dhis2w-cli 0.5.2__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.
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: dhis2w-cli
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: dhis2 command-line interface (Typer) — mounts plugins from dhis2-core.
|
|
5
|
+
Author: Morten Hansen
|
|
6
|
+
Author-email: Morten Hansen <morten@winterop.com>
|
|
7
|
+
Requires-Dist: dhis2w-core>=0.5.0,<0.6
|
|
8
|
+
Requires-Dist: typer>=0.24
|
|
9
|
+
Requires-Dist: rich>=15
|
|
10
|
+
Requires-Dist: dhis2w-browser>=0.5.0,<0.6 ; extra == 'browser'
|
|
11
|
+
Requires-Python: >=3.13
|
|
12
|
+
Provides-Extra: browser
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dhis2w-cli"
|
|
3
|
+
version = "0.5.2"
|
|
4
|
+
description = "dhis2 command-line interface (Typer) — mounts plugins from dhis2-core."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Morten Hansen", email = "morten@winterop.com" }]
|
|
7
|
+
requires-python = ">=3.13"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"dhis2w-core>=0.5.0,<0.6",
|
|
10
|
+
"typer>=0.24",
|
|
11
|
+
"rich>=15",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
browser = ["dhis2w-browser>=0.5.0,<0.6"]
|
|
16
|
+
|
|
17
|
+
[project.scripts]
|
|
18
|
+
dhis2 = "dhis2w_cli.main:main"
|
|
19
|
+
|
|
20
|
+
[build-system]
|
|
21
|
+
requires = ["uv_build>=0.11.7,<0.12.0"]
|
|
22
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Typer console script entrypoint for dhis2."""
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Typer root for the `dhis2` CLI — discovers plugins and mounts them."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
from dhis2w_core.cli_errors import run_app
|
|
11
|
+
from dhis2w_core.cli_output import JSON_OUTPUT
|
|
12
|
+
from dhis2w_core.plugin import discover_plugins
|
|
13
|
+
from dhis2w_core.rich_console import STDERR_CONSOLE
|
|
14
|
+
from rich.logging import RichHandler
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _enable_debug_logging() -> None:
|
|
18
|
+
"""Turn on dhis2-client HTTP traces + dhis2-core debug logs on stderr.
|
|
19
|
+
|
|
20
|
+
Uses `rich.logging.RichHandler` tied to the shared `STDERR_CONSOLE` so log
|
|
21
|
+
lines render above any active Rich `Progress` / `Status` display instead
|
|
22
|
+
of tearing through it.
|
|
23
|
+
"""
|
|
24
|
+
handler = RichHandler(
|
|
25
|
+
console=STDERR_CONSOLE,
|
|
26
|
+
show_path=False,
|
|
27
|
+
show_time=True,
|
|
28
|
+
markup=False,
|
|
29
|
+
rich_tracebacks=False,
|
|
30
|
+
log_time_format="%H:%M:%S",
|
|
31
|
+
)
|
|
32
|
+
handler.setLevel(logging.DEBUG)
|
|
33
|
+
root = logging.getLogger()
|
|
34
|
+
root.addHandler(handler)
|
|
35
|
+
for name in ("dhis2w_client", "dhis2w_core"):
|
|
36
|
+
logging.getLogger(name).setLevel(logging.DEBUG)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def build_app() -> typer.Typer:
|
|
40
|
+
"""Build a fresh Typer app with every discovered plugin mounted.
|
|
41
|
+
|
|
42
|
+
Every call returns a new app, which keeps unit tests hermetic and lets
|
|
43
|
+
callers introspect the mounted surface without side effects.
|
|
44
|
+
|
|
45
|
+
`pretty_exceptions_enable=False` so our `run_app` wrapper (invoked from
|
|
46
|
+
`main()` below) sees uncaught exceptions and can render them cleanly.
|
|
47
|
+
"""
|
|
48
|
+
app = typer.Typer(
|
|
49
|
+
help="dhis2 — command-line interface for DHIS2 (discovers plugins from dhis2-core).",
|
|
50
|
+
no_args_is_help=True,
|
|
51
|
+
add_completion=False,
|
|
52
|
+
pretty_exceptions_enable=False,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@app.callback()
|
|
56
|
+
def _root(
|
|
57
|
+
profile: Annotated[
|
|
58
|
+
str | None,
|
|
59
|
+
typer.Option(
|
|
60
|
+
"--profile",
|
|
61
|
+
"-p",
|
|
62
|
+
help="DHIS2 profile name (overrides DHIS2_PROFILE env + TOML default).",
|
|
63
|
+
),
|
|
64
|
+
] = None,
|
|
65
|
+
debug: Annotated[
|
|
66
|
+
bool,
|
|
67
|
+
typer.Option(
|
|
68
|
+
"--debug",
|
|
69
|
+
"-d",
|
|
70
|
+
help="Verbose output on stderr — HTTP method/URL/status/elapsed for every request.",
|
|
71
|
+
),
|
|
72
|
+
] = False,
|
|
73
|
+
json_: Annotated[
|
|
74
|
+
bool,
|
|
75
|
+
typer.Option(
|
|
76
|
+
"--json",
|
|
77
|
+
"-j",
|
|
78
|
+
help="Emit raw JSON to stdout instead of Rich tables (uniform across all commands).",
|
|
79
|
+
),
|
|
80
|
+
] = False,
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Set the active DHIS2 profile + optional debug logging + output mode for this invocation."""
|
|
83
|
+
if profile:
|
|
84
|
+
os.environ["DHIS2_PROFILE"] = profile
|
|
85
|
+
if debug:
|
|
86
|
+
_enable_debug_logging()
|
|
87
|
+
# Always set, not just when True — `CliRunner` reuses the same
|
|
88
|
+
# process across `invoke` calls, so a stale `True` from a previous
|
|
89
|
+
# invocation must not leak into the next one.
|
|
90
|
+
JSON_OUTPUT.set(json_)
|
|
91
|
+
|
|
92
|
+
for plugin in discover_plugins():
|
|
93
|
+
plugin.register_cli(app)
|
|
94
|
+
return app
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
app = build_app()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def main() -> None:
|
|
101
|
+
"""Console-script entrypoint — wraps the Typer app with clean error rendering."""
|
|
102
|
+
run_app(app)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
main()
|
|
File without changes
|