Type Definitions & Protocols
Relevant source files
The following files were used as context for generating this wiki page:
- src/flext_cli/_typings/base.py
- src/flext_cli/_protocols/domain.py
- src/flext_cli/_protocols/_base_parts/flextcliprotocolsbase_part_03.py
- src/flext_cli/_protocols/_base_parts/flextcliprotocolsbase_part_04.py
- src/flext_cli/_protocols/_base_parts/flextcliprotocolsbase_part_05.py
- tests/unit/test_typings.py
The flext-cli project utilizes a rigorous type system and structural protocols to ensure consistency across CLI commands, service layers, and data models. This architecture relies on Python's typing.Protocol for structural subtyping and Pydantic-based adapters for runtime validation.
The primary goal of these definitions is to create a decoupled boundary between the public CLI facade and internal implementations. By using protocols, the system allows for modular service replacements (e.g., authentication, command execution) while maintaining strict type safety for JSON payloads and CLI parameters.
Core Type Aliases
The project defines a set of base type aliases in FlextCliTypesBase to standardize data structures used for tabular output, TOML/YAML processing, and CLI configuration.
Data Structures and Tabular Types
These types define the shape of data processed for display or persistence.
| Type Name | Definition / Composition | Description |
|---|---|---|
TableMappingRow | t.MappingKV[str, t.JsonPayload] | A single row in a table represented as a dictionary. |
TableSequenceRow | t.SequenceOf[t.JsonPayload] | A single row in a table represented as a sequence. |
TabularData | TableMappingRow | t.SequenceOf[TableRow] | The standard input for table-rendering services. |
JsonMapping | MappingKV[str, JsonValue] | A standard JSON-compatible dictionary. |
CliValue | t.Scalar | t.StrSequence | DefaultMapping | Permitted values for CLI configuration and options. |
Sources: src/flext_cli/_typings/base.py:25-41, src/flext_cli/_typings/base.py:46
Specialized Adapters
Standard Pydantic TypeAdapter instances are exposed for immediate reuse in validation logic.
STR_SEQUENCE_ADAPTER: ClassVar[t.ValueAdapter[t.StrSequence]] = t.str_sequence_adapter()
JSON_VALUE_ADAPTER: ClassVar[t.ValueAdapter[t.JsonValue]] = t.json_value_adapter()
JSON_MAPPING_ADAPTER: ClassVar[t.ValueAdapter[t.JsonMapping]] = t.json_mapping_adapter()
Sources: src/flext_cli/_typings/base.py:73-77
Service Protocols
Structural protocols define the "contracts" that various CLI services must fulfill. These are categorized into base execution parts and domain-specific logic.
Command Execution (CommandRunner)
The CommandRunner protocol specifies how external processes are invoked and how their results (stdout, stderr, exit codes) are captured.
Authentication Service (AuthService)
The AuthService protocol manages the lifecycle of credentials and tokens.
- validate_credentials: Validates direct username/password pairs.
- save_auth_token / fetch_auth_token: Manages persistence of session tokens.
- authenticate: Orchestrates high-level authentication flows using mixed inputs.
- clear_auth_tokens: Security cleanup of stored session data.
Sources: src/flext_cli/_protocols/_base_parts/flextcliprotocolsbase_part_04.py:47-67
Model-Driven CLI Protocols
flext-cli heavily utilizes model-driven design where Pydantic models define the expected input for CLI commands.
Result Command Handlers
A core pattern is the ResultCommandHandler, which consumes a Pydantic model and returns a flext_core.p.Result object. This supports "Railway Oriented Programming" within the CLI.
Domain Protocols
Higher-level contracts define the integration points for the workspace orchestrator and declarative rules.
- JsonValueProcessor: A simple transformation protocol for JSON data.
- CommandEntry: Defines how a command name is mapped to a handler.
- SummaryStats: A contract for the result of batch operations, including fields like
verb,total,success,failed, andelapsed.
Sources: src/flext_cli/_protocols/domain.py:19-25, src/flext_cli/_protocols/domain.py:38-42, src/flext_cli/_protocols/domain.py:74-81
Protocol Implementation Hierarchy
The base protocols are implemented using a "part" pattern (mixins) to organize large protocol interfaces into manageable segments.
Validation and Runtime Checking
Protocols are marked with @runtime_checkable, allowing for isinstance() checks at runtime. This is verified in the test suite to ensure that implementations correctly satisfy the structural requirements.
@runtime_checkable
class Test(Protocol):
def operation(self, data: t.StrSequence) -> t.JsonMapping: ...
class Implementation:
def operation(self, data: t.StrSequence) -> t.JsonMapping:
return {"processed": [item.upper() for item in data], "count": len(data)}
# Runtime check
impl: Test = Implementation()
assert isinstance(impl, Test)
Sources: tests/unit/test_typings.py:61-75
Summary
The type system in flext-cli provides a robust framework for building enterprise-grade CLI tools. By combining static type aliases (for data shapes) with structural protocols (for service behaviors), the project ensures that components like the CommandRunner, AuthService, and DataManager remain interchangeable and testable. The use of p.Result within these protocols enforces a consistent error-handling strategy across the entire application lifecycle.