hexastack-cli 0.4.0__tar.gz → 0.6.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.
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/PKG-INFO +1 -1
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/pyproject.toml +1 -1
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/pyproject.toml.orig +1 -1
- hexastack_cli-0.6.0/src/hexastack_cli/__init__.py +12 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/adapters/presenter.py +28 -5
- hexastack_cli-0.6.0/src/hexastack_cli/domain/__init__.py +11 -0
- hexastack_cli-0.6.0/src/hexastack_cli/domain/options.py +25 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/__init__.py +6 -0
- hexastack_cli-0.6.0/src/hexastack_cli/infra/options.py +73 -0
- hexastack_cli-0.4.0/src/hexastack_cli/__init__.py +0 -6
- hexastack_cli-0.4.0/src/hexastack_cli/domain/__init__.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/README.md +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/adapters/__init__.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/adapters/routing.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/domain/config.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/app.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/autodiscovery.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/bootstrap.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/config.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/decorators.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/py.typed +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/__init__.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/events.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/narrator.py +0 -0
- {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/terminal.py +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from hexastack_cli import adapters, domain, infra
|
|
2
|
+
from hexastack_cli.domain.options import OutputFormat
|
|
3
|
+
from hexastack_cli.infra.options import format_option, resolve_format
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"adapters",
|
|
7
|
+
"domain",
|
|
8
|
+
"format_option",
|
|
9
|
+
"infra",
|
|
10
|
+
"OutputFormat",
|
|
11
|
+
"resolve_format",
|
|
12
|
+
]
|
|
@@ -8,6 +8,7 @@ from rich.console import Console
|
|
|
8
8
|
from rich.panel import Panel
|
|
9
9
|
from rich.table import Table
|
|
10
10
|
|
|
11
|
+
from hexastack_cli.domain.options import OutputFormat
|
|
11
12
|
from hexastack_core.domain import Generic
|
|
12
13
|
from hexastack_core.ports.presenter import PresenterPort
|
|
13
14
|
|
|
@@ -79,16 +80,33 @@ class RichTerminalPresenter(PresenterPort):
|
|
|
79
80
|
self._console.print(f"[bold green]{data}[/bold green]")
|
|
80
81
|
return data
|
|
81
82
|
|
|
83
|
+
def _present_markdown(self, instance: Generic, data: Any) -> Any:
|
|
84
|
+
"""Render markdown formatted representation to stdout."""
|
|
85
|
+
if isinstance(data, dict):
|
|
86
|
+
title = type(instance).__name__
|
|
87
|
+
lines = [f"### {title}", "", "| Field | Value |", "|---|---|"]
|
|
88
|
+
for k, v in data.items():
|
|
89
|
+
val_str = json.dumps(v) if isinstance(v, dict | list) else str(v)
|
|
90
|
+
lines.append(f"| {k} | {val_str} |")
|
|
91
|
+
sys.stdout.write("\n".join(lines) + "\n")
|
|
92
|
+
elif isinstance(data, list):
|
|
93
|
+
lines = [f"- {item}" for item in data]
|
|
94
|
+
sys.stdout.write("\n".join(lines) + "\n")
|
|
95
|
+
else:
|
|
96
|
+
sys.stdout.write(f"**{data}**\n")
|
|
97
|
+
sys.stdout.flush()
|
|
98
|
+
return data
|
|
99
|
+
|
|
82
100
|
def present(
|
|
83
101
|
self,
|
|
84
102
|
instance: Generic,
|
|
85
|
-
format_mode: str | None = None,
|
|
103
|
+
format_mode: str | OutputFormat | None = None,
|
|
86
104
|
) -> Any:
|
|
87
105
|
"""Format and print a domain Generic instance to stdout based on requested format mode.
|
|
88
106
|
|
|
89
107
|
Args:
|
|
90
108
|
instance: Domain Generic or DTO model instance.
|
|
91
|
-
format_mode: Optional format mode ('table', 'json', 'plain').
|
|
109
|
+
format_mode: Optional format mode ('table', 'json', 'plain', 'markdown').
|
|
92
110
|
|
|
93
111
|
Returns:
|
|
94
112
|
The presented raw data representation.
|
|
@@ -98,12 +116,17 @@ class RichTerminalPresenter(PresenterPort):
|
|
|
98
116
|
"""
|
|
99
117
|
data = instance.model_dump() if isinstance(instance, BaseModel) else instance
|
|
100
118
|
|
|
101
|
-
|
|
119
|
+
if isinstance(format_mode, OutputFormat):
|
|
120
|
+
mode = format_mode.value
|
|
121
|
+
else:
|
|
122
|
+
mode = (format_mode or OutputFormat.TABLE.value).lower().strip()
|
|
102
123
|
|
|
103
|
-
if mode ==
|
|
124
|
+
if mode == OutputFormat.JSON.value:
|
|
104
125
|
return self._present_json(data)
|
|
105
|
-
if mode ==
|
|
126
|
+
if mode == OutputFormat.PLAIN.value:
|
|
106
127
|
return self._present_plain(data)
|
|
128
|
+
if mode == OutputFormat.MARKDOWN.value:
|
|
129
|
+
return self._present_markdown(instance, data)
|
|
107
130
|
return self._present_table(instance, data)
|
|
108
131
|
|
|
109
132
|
def print_error(self, message: str) -> None:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Domain models and enumerations for Hexastack CLI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from hexastack_cli.domain.config import HexastackCliConfig
|
|
6
|
+
from hexastack_cli.domain.options import OutputFormat
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"HexastackCliConfig",
|
|
10
|
+
"OutputFormat",
|
|
11
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Domain representations for CLI output presentation formats.
|
|
2
|
+
|
|
3
|
+
Notes/Architectural Intent:
|
|
4
|
+
Defines the canonical output format enumeration shared across CLI presenters,
|
|
5
|
+
command runners, and reporting bridges. Fulfills the cross-ecosystem CLI alignment invariant.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from enum import StrEnum
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"OutputFormat",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class OutputFormat(StrEnum):
|
|
18
|
+
"""Supported output presentation formats for CLI commands."""
|
|
19
|
+
|
|
20
|
+
AUTO = "auto"
|
|
21
|
+
JSON = "json"
|
|
22
|
+
MARKDOWN = "markdown"
|
|
23
|
+
PLAIN = "plain"
|
|
24
|
+
RICH = "rich"
|
|
25
|
+
TABLE = "table"
|
|
@@ -15,6 +15,10 @@ from hexastack_cli.infra.decorators import (
|
|
|
15
15
|
cli_group,
|
|
16
16
|
cli_query,
|
|
17
17
|
)
|
|
18
|
+
from hexastack_cli.infra.options import (
|
|
19
|
+
format_option,
|
|
20
|
+
resolve_format,
|
|
21
|
+
)
|
|
18
22
|
|
|
19
23
|
__all__ = [
|
|
20
24
|
"autodiscover_cli_commands",
|
|
@@ -25,7 +29,9 @@ __all__ = [
|
|
|
25
29
|
"CliMetadata",
|
|
26
30
|
"create_cli_app",
|
|
27
31
|
"create_cli_visitor",
|
|
32
|
+
"format_option",
|
|
28
33
|
"GroupMetadata",
|
|
29
34
|
"HexastackCliConfig",
|
|
30
35
|
"register_cli_config",
|
|
36
|
+
"resolve_format",
|
|
31
37
|
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""CLI option factories and formatting resolvers for Hexastack CLI applications.
|
|
2
|
+
|
|
3
|
+
Notes/Architectural Intent:
|
|
4
|
+
Provides standardized Typer option factories and stdout pipe-detection routines.
|
|
5
|
+
When format is 'auto', automatically routes to structured JSON when piped into
|
|
6
|
+
downstream Unix utilities (jq, grep) or styled Rich/table output when attached to an
|
|
7
|
+
interactive TTY. Aligns with the Hexa ecosystem CLI standards.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import typer
|
|
17
|
+
|
|
18
|
+
from hexastack_cli.domain.options import OutputFormat
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"format_option",
|
|
22
|
+
"resolve_format",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def resolve_format(
|
|
27
|
+
format_type: str | OutputFormat,
|
|
28
|
+
default_tty: str = "table",
|
|
29
|
+
default_pipe: str = "json",
|
|
30
|
+
) -> str:
|
|
31
|
+
"""Resolve an output format string, handling auto-detection for pipes.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
format_type: The format chosen by user or default ('auto', 'table', 'json', etc.).
|
|
35
|
+
default_tty: Default format when connected to an interactive terminal.
|
|
36
|
+
default_pipe: Default format when stdout is piped or redirected.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Normalized lowercase format string (e.g. 'table', 'json', 'rich').
|
|
40
|
+
|
|
41
|
+
Notes/Architectural Intent:
|
|
42
|
+
When format_type is 'auto', inspects sys.stdout.isatty() to choose between
|
|
43
|
+
structured machine-readable format for pipelines or visual format for humans.
|
|
44
|
+
"""
|
|
45
|
+
raw = (
|
|
46
|
+
format_type.value
|
|
47
|
+
if isinstance(format_type, Enum)
|
|
48
|
+
else str(format_type).lower().strip()
|
|
49
|
+
)
|
|
50
|
+
if raw == OutputFormat.AUTO.value:
|
|
51
|
+
if not sys.stdout.isatty():
|
|
52
|
+
return default_pipe
|
|
53
|
+
return default_tty
|
|
54
|
+
return raw
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def format_option(
|
|
58
|
+
default: str = "table",
|
|
59
|
+
help_text: str = "Output presentation format (table, json, markdown, rich, plain, auto).",
|
|
60
|
+
) -> Any:
|
|
61
|
+
"""Construct a standardized Typer option for format selection.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
default: Default format option value.
|
|
65
|
+
help_text: Help string to render in CLI usage catalogs.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Configured Typer Option specification.
|
|
69
|
+
|
|
70
|
+
Notes/Architectural Intent:
|
|
71
|
+
Standardizes '-f' / '--format' flag across all Hexastack CLI commands.
|
|
72
|
+
"""
|
|
73
|
+
return typer.Option(default, "-f", "--format", help=help_text)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|