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.
Files changed (25) hide show
  1. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/PKG-INFO +1 -1
  2. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/pyproject.toml +1 -1
  3. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/pyproject.toml.orig +1 -1
  4. hexastack_cli-0.6.0/src/hexastack_cli/__init__.py +12 -0
  5. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/adapters/presenter.py +28 -5
  6. hexastack_cli-0.6.0/src/hexastack_cli/domain/__init__.py +11 -0
  7. hexastack_cli-0.6.0/src/hexastack_cli/domain/options.py +25 -0
  8. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/__init__.py +6 -0
  9. hexastack_cli-0.6.0/src/hexastack_cli/infra/options.py +73 -0
  10. hexastack_cli-0.4.0/src/hexastack_cli/__init__.py +0 -6
  11. hexastack_cli-0.4.0/src/hexastack_cli/domain/__init__.py +0 -0
  12. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/README.md +0 -0
  13. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/adapters/__init__.py +0 -0
  14. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/adapters/routing.py +0 -0
  15. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/domain/config.py +0 -0
  16. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/app.py +0 -0
  17. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/autodiscovery.py +0 -0
  18. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/bootstrap.py +0 -0
  19. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/config.py +0 -0
  20. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/infra/decorators.py +0 -0
  21. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/py.typed +0 -0
  22. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/__init__.py +0 -0
  23. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/events.py +0 -0
  24. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/narrator.py +0 -0
  25. {hexastack_cli-0.4.0 → hexastack_cli-0.6.0}/src/hexastack_cli/testing/terminal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hexastack-cli
3
- Version: 0.4.0
3
+ Version: 0.6.0
4
4
  Summary: Hexastack CLI presentation adapter with Typer and Rich
5
5
  Author: Richard West
6
6
  Author-email: Richard West <dopplereffect.us@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hexastack-cli"
3
- version = "0.4.0"
3
+ version = "0.6.0"
4
4
  description = "Hexastack CLI presentation adapter with Typer and Rich"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hexastack-cli"
3
- version = "0.4.0"
3
+ version = "0.6.0"
4
4
  description = "Hexastack CLI presentation adapter with Typer and Rich"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.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
- mode = (format_mode or "table").lower()
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 == "json":
124
+ if mode == OutputFormat.JSON.value:
104
125
  return self._present_json(data)
105
- if mode == "plain":
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)
@@ -1,6 +0,0 @@
1
- from hexastack_cli import adapters, infra
2
-
3
- __all__ = [
4
- "adapters",
5
- "infra",
6
- ]
File without changes
File without changes