hexastack-cli 0.1.0__tar.gz → 0.3.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 (22) hide show
  1. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/PKG-INFO +3 -3
  2. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/README.md +2 -2
  3. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/pyproject.toml +22 -1
  4. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/pyproject.toml.orig +26 -1
  5. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/adapters/__init__.py +0 -2
  6. {hexastack_cli-0.1.0/src/hexastack_cli/infra → hexastack_cli-0.3.0/src/hexastack_cli/domain}/config.py +0 -20
  7. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/infra/__init__.py +2 -0
  8. {hexastack_cli-0.1.0/src/hexastack_cli/adapters → hexastack_cli-0.3.0/src/hexastack_cli/infra}/app.py +1 -1
  9. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/infra/bootstrap.py +1 -1
  10. hexastack_cli-0.3.0/src/hexastack_cli/infra/config.py +19 -0
  11. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/infra/decorators.py +6 -3
  12. hexastack_cli-0.3.0/src/hexastack_cli/py.typed +0 -0
  13. hexastack_cli-0.3.0/src/hexastack_cli/testing/__init__.py +9 -0
  14. hexastack_cli-0.3.0/src/hexastack_cli/testing/events.py +16 -0
  15. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/testing/narrator.py +1 -9
  16. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/testing/terminal.py +1 -1
  17. hexastack_cli-0.1.0/src/hexastack_cli/testing/__init__.py +0 -7
  18. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/__init__.py +0 -0
  19. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/adapters/presenter.py +0 -0
  20. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/adapters/routing.py +0 -0
  21. /hexastack_cli-0.1.0/src/hexastack_cli/py.typed → /hexastack_cli-0.3.0/src/hexastack_cli/domain/__init__.py +0 -0
  22. {hexastack_cli-0.1.0 → hexastack_cli-0.3.0}/src/hexastack_cli/infra/autodiscovery.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hexastack-cli
3
- Version: 0.1.0
3
+ Version: 0.3.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>
@@ -43,8 +43,8 @@ Description-Content-Type: text/markdown
43
43
  ```
44
44
  hexastack_cli/
45
45
  ├── domain/ # CliContext, OutputFormat enum
46
- ├── adapters/ # create_cli_app, Rich presenters, Typer command runners
47
- └── infra/ # CliBootstrapper (order=30), @cli_command, @cli_query, @cli_group, @feature_flag_command
46
+ ├── adapters/ # Rich presenters, Typer command runners
47
+ └── infra/ # create_cli_app, CliBootstrapper (order=40), @cli_command, @cli_query, @cli_group, @feature_flag_command
48
48
  ```
49
49
 
50
50
  ### Key Exports
@@ -27,8 +27,8 @@
27
27
  ```
28
28
  hexastack_cli/
29
29
  ├── domain/ # CliContext, OutputFormat enum
30
- ├── adapters/ # create_cli_app, Rich presenters, Typer command runners
31
- └── infra/ # CliBootstrapper (order=30), @cli_command, @cli_query, @cli_group, @feature_flag_command
30
+ ├── adapters/ # Rich presenters, Typer command runners
31
+ └── infra/ # create_cli_app, CliBootstrapper (order=40), @cli_command, @cli_query, @cli_group, @feature_flag_command
32
32
  ```
33
33
 
34
34
  ### Key Exports
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hexastack-cli"
3
- version = "0.1.0"
3
+ version = "0.3.0"
4
4
  description = "Hexastack CLI presentation adapter with Typer and Rich"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -34,3 +34,24 @@ workspace = true
34
34
 
35
35
  [tool.importlinter]
36
36
  root_packages = ["hexastack_cli"]
37
+
38
+ [[tool.importlinter.contracts]]
39
+ name = "Hexagonal architecture layer hierarchy"
40
+ type = "layers"
41
+ containers = ["hexastack_cli"]
42
+ layers = [
43
+ "infra",
44
+ "adapters",
45
+ ]
46
+
47
+ [[tool.importlinter.contracts]]
48
+ name = "Forbidden imports for adapters"
49
+ type = "forbidden"
50
+ source_modules = ["hexastack_cli.adapters"]
51
+ forbidden_modules = ["hexastack_cli.testing"]
52
+
53
+ [[tool.importlinter.contracts]]
54
+ name = "Forbidden imports for infra"
55
+ type = "forbidden"
56
+ source_modules = ["hexastack_cli.infra"]
57
+ forbidden_modules = ["hexastack_cli.testing"]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hexastack-cli"
3
- version = "0.1.0"
3
+ version = "0.3.0"
4
4
  description = "Hexastack CLI presentation adapter with Typer and Rich"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -33,3 +33,28 @@ hexastack-cqrs = { workspace = true }
33
33
 
34
34
  [tool.importlinter]
35
35
  root_packages = ["hexastack_cli"]
36
+
37
+ [[tool.importlinter.contracts]]
38
+ name = "Hexagonal architecture layer hierarchy"
39
+ type = "layers"
40
+ containers = ["hexastack_cli"]
41
+ layers = [
42
+ "infra",
43
+ "adapters",
44
+ ]
45
+
46
+ [[tool.importlinter.contracts]]
47
+ name = "Forbidden imports for adapters"
48
+ type = "forbidden"
49
+ source_modules = ["hexastack_cli.adapters"]
50
+ forbidden_modules = [
51
+ "hexastack_cli.testing",
52
+ ]
53
+
54
+ [[tool.importlinter.contracts]]
55
+ name = "Forbidden imports for infra"
56
+ type = "forbidden"
57
+ source_modules = ["hexastack_cli.infra"]
58
+ forbidden_modules = [
59
+ "hexastack_cli.testing",
60
+ ]
@@ -1,4 +1,3 @@
1
- from hexastack_cli.adapters.app import create_cli_app
2
1
  from hexastack_cli.adapters.presenter import RichTerminalPresenter
3
2
  from hexastack_cli.adapters.routing import (
4
3
  register_cqrs_command,
@@ -6,7 +5,6 @@ from hexastack_cli.adapters.routing import (
6
5
  )
7
6
 
8
7
  __all__ = [
9
- "create_cli_app",
10
8
  "register_cqrs_command",
11
9
  "register_cqrs_query",
12
10
  "RichTerminalPresenter",
@@ -1,10 +1,6 @@
1
1
  from pydantic import BaseModel, Field
2
2
 
3
- from hexastack_core.infra.decorators import config_section
4
- from hexastack_core.infra.registries.config import ConfigRegistry
5
3
 
6
-
7
- @config_section("cli")
8
4
  class HexastackCliConfig(BaseModel):
9
5
  """Configuration schema for Hexastack CLI presentation adapter.
10
6
 
@@ -24,20 +20,4 @@ class HexastackCliConfig(BaseModel):
24
20
 
25
21
  __all__ = [
26
22
  "HexastackCliConfig",
27
- "register_cli_config",
28
23
  ]
29
-
30
-
31
- def register_cli_config(registry: ConfigRegistry) -> None:
32
- """Register CLI configuration schema with a ConfigRegistry under 'cli'.
33
-
34
- Args:
35
- registry: Target ConfigRegistry instance.
36
-
37
- Returns:
38
- None.
39
-
40
- Raises:
41
- None.
42
- """
43
- registry.register_config_section("cli", HexastackCliConfig)
@@ -1,3 +1,4 @@
1
+ from hexastack_cli.infra.app import create_cli_app
1
2
  from hexastack_cli.infra.autodiscovery import (
2
3
  autodiscover_cli_commands,
3
4
  create_cli_visitor,
@@ -22,6 +23,7 @@ __all__ = [
22
23
  "cli_query",
23
24
  "CliBootstrapper",
24
25
  "CliMetadata",
26
+ "create_cli_app",
25
27
  "create_cli_visitor",
26
28
  "GroupMetadata",
27
29
  "HexastackCliConfig",
@@ -51,7 +51,7 @@ def create_cli_app(
51
51
  def _version_callback(value: bool) -> None:
52
52
  if value:
53
53
  active_console.print(f"{cfg.app_name} {cfg.version}")
54
- raise typer.Exit()
54
+ raise typer.Exit
55
55
 
56
56
  # Establish root callback to enforce multi-command structure and handle --version
57
57
  @app.callback()
@@ -34,7 +34,7 @@ class CliBootstrapper(BootstrapperPort):
34
34
  Raises:
35
35
  None.
36
36
  """
37
- from hexastack_cli.adapters.app import create_cli_app
37
+ from hexastack_cli.infra.app import create_cli_app
38
38
  from hexastack_cli.infra.autodiscovery import create_cli_visitor
39
39
 
40
40
  cfg = HexastackCliConfig()
@@ -0,0 +1,19 @@
1
+ from hexastack_cli.domain.config import HexastackCliConfig
2
+ from hexastack_core.infra.decorators import config_section
3
+ from hexastack_core.infra.registries.config import ConfigRegistry
4
+
5
+ config_section("cli")(HexastackCliConfig)
6
+
7
+ __all__ = [
8
+ "HexastackCliConfig",
9
+ "register_cli_config",
10
+ ]
11
+
12
+
13
+ def register_cli_config(registry: ConfigRegistry) -> None:
14
+ """Register CLI configuration schema with a ConfigRegistry under 'cli'.
15
+
16
+ Args:
17
+ registry: Target ConfigRegistry instance.
18
+ """
19
+ registry.register_config_section("cli", HexastackCliConfig)
@@ -1,9 +1,12 @@
1
1
  from collections.abc import Callable, Sequence
2
2
  from dataclasses import dataclass, field
3
- from typing import Any, Literal
3
+ from typing import Any, Literal, TypeVar
4
4
 
5
5
  from hexastack_core.domain import Command, Query
6
6
 
7
+ TCommand = TypeVar("TCommand", bound=Command)
8
+ TQuery = TypeVar("TQuery", bound=Query)
9
+
7
10
  _CLI_METADATA_ATTR = "__hexastack_cli__"
8
11
  _CLI_GROUP_ATTR = "__hexastack_cli_group__"
9
12
 
@@ -58,7 +61,7 @@ def _normalize_tokens(tokens: Sequence[str] | str | None) -> tuple[str, ...]:
58
61
  return tuple(str(t).strip() for t in tokens if str(t).strip())
59
62
 
60
63
 
61
- def cli_command[TCommand: Command](
64
+ def cli_command(
62
65
  name: str | None = None,
63
66
  *,
64
67
  positional: Sequence[str] | str | None = None,
@@ -129,7 +132,7 @@ def cli_group(
129
132
  return decorator
130
133
 
131
134
 
132
- def cli_query[TQuery: Query](
135
+ def cli_query(
133
136
  name: str | None = None,
134
137
  *,
135
138
  positional: Sequence[str] | str | None = None,
File without changes
@@ -0,0 +1,9 @@
1
+ from hexastack_cli.testing.events import TerminalEvent
2
+ from hexastack_cli.testing.narrator import CliNarrator
3
+ from hexastack_cli.testing.terminal import render_cli_demo_video
4
+
5
+ __all__ = [
6
+ "CliNarrator",
7
+ "render_cli_demo_video",
8
+ "TerminalEvent",
9
+ ]
@@ -0,0 +1,16 @@
1
+ """Domain models and data contracts for CLI testing and narrative demonstration."""
2
+
3
+ from dataclasses import dataclass
4
+
5
+ __all__ = [
6
+ "TerminalEvent",
7
+ ]
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class TerminalEvent:
12
+ """A discrete timestamped event within a CLI demo recording session."""
13
+
14
+ event_type: str # "step" | "input" | "output"
15
+ payload: str
16
+ timestamp: float
@@ -4,20 +4,12 @@ from __future__ import annotations
4
4
 
5
5
  import os
6
6
  import time
7
- from dataclasses import dataclass
8
7
  from pathlib import Path
9
8
  from typing import Any
10
9
 
11
10
  from typer.testing import CliRunner, Result
12
11
 
13
-
14
- @dataclass(frozen=True)
15
- class TerminalEvent:
16
- """A discrete timestamped event within a CLI demo recording session."""
17
-
18
- event_type: str # "step" | "input" | "output"
19
- payload: str
20
- timestamp: float
12
+ from hexastack_cli.testing.events import TerminalEvent
21
13
 
22
14
 
23
15
  class CliNarrator:
@@ -9,7 +9,7 @@ import re
9
9
  import shutil
10
10
  from pathlib import Path
11
11
 
12
- from hexastack_cli.testing.narrator import TerminalEvent
12
+ from hexastack_cli.testing.events import TerminalEvent
13
13
  from hexastack_core.domain.exceptions import MissingDependencyError
14
14
 
15
15
  TERMINAL_HTML_TEMPLATE = """<!DOCTYPE html>
@@ -1,7 +0,0 @@
1
- """Testing utilities and demo recording engine for CLI applications."""
2
-
3
- from hexastack_cli.testing.narrator import CliNarrator
4
-
5
- __all__ = [
6
- "CliNarrator",
7
- ]