Initial commit
This commit is contained in:
201
skills/typer-patterns/SKILL.md
Normal file
201
skills/typer-patterns/SKILL.md
Normal file
@@ -0,0 +1,201 @@
|
||||
---
|
||||
name: typer-patterns
|
||||
description: Modern type-safe Typer CLI patterns with type hints, Enums, and sub-apps. Use when building CLI applications, creating Typer commands, implementing type-safe CLIs, or when user mentions Typer, CLI patterns, type hints, Enums, sub-apps, or command-line interfaces.
|
||||
allowed-tools: Read, Write, Edit, Bash
|
||||
---
|
||||
|
||||
# typer-patterns
|
||||
|
||||
Provides modern type-safe Typer CLI patterns including type hints, Enum usage, sub-app composition, and Typer() instance patterns for building maintainable command-line applications.
|
||||
|
||||
## Core Patterns
|
||||
|
||||
### 1. Type-Safe Commands with Type Hints
|
||||
|
||||
Use Python type hints for automatic validation and better IDE support:
|
||||
|
||||
```python
|
||||
import typer
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
@app.command()
|
||||
def process(
|
||||
input_file: Path = typer.Argument(..., help="Input file path"),
|
||||
output: Optional[Path] = typer.Option(None, help="Output file path"),
|
||||
verbose: bool = typer.Option(False, "--verbose", "-v"),
|
||||
count: int = typer.Option(10, help="Number of items to process")
|
||||
) -> None:
|
||||
"""Process files with type-safe parameters."""
|
||||
if verbose:
|
||||
typer.echo(f"Processing {input_file}")
|
||||
```
|
||||
|
||||
### 2. Enum-Based Options
|
||||
|
||||
Use Enums for constrained choices with autocomplete:
|
||||
|
||||
```python
|
||||
from enum import Enum
|
||||
|
||||
class OutputFormat(str, Enum):
|
||||
json = "json"
|
||||
yaml = "yaml"
|
||||
text = "text"
|
||||
|
||||
@app.command()
|
||||
def export(
|
||||
format: OutputFormat = typer.Option(OutputFormat.json, help="Output format")
|
||||
) -> None:
|
||||
"""Export with enum-based format selection."""
|
||||
typer.echo(f"Exporting as {format.value}")
|
||||
```
|
||||
|
||||
### 3. Sub-Application Composition
|
||||
|
||||
Organize complex CLIs with sub-apps:
|
||||
|
||||
```python
|
||||
app = typer.Typer()
|
||||
db_app = typer.Typer()
|
||||
app.add_typer(db_app, name="db", help="Database commands")
|
||||
|
||||
@db_app.command("migrate")
|
||||
def db_migrate() -> None:
|
||||
"""Run database migrations."""
|
||||
pass
|
||||
|
||||
@db_app.command("seed")
|
||||
def db_seed() -> None:
|
||||
"""Seed database with test data."""
|
||||
pass
|
||||
```
|
||||
|
||||
### 4. Typer() Instance Pattern
|
||||
|
||||
Use Typer() instances for better organization and testing:
|
||||
|
||||
```python
|
||||
def create_app() -> typer.Typer:
|
||||
"""Factory function for creating Typer app."""
|
||||
app = typer.Typer(
|
||||
name="myapp",
|
||||
help="My CLI application",
|
||||
add_completion=True,
|
||||
no_args_is_help=True
|
||||
)
|
||||
|
||||
@app.command()
|
||||
def hello(name: str) -> None:
|
||||
typer.echo(f"Hello {name}")
|
||||
|
||||
return app
|
||||
|
||||
app = create_app()
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
```
|
||||
|
||||
## Usage Workflow
|
||||
|
||||
1. **Identify pattern need**: Determine which Typer pattern fits your use case
|
||||
2. **Select template**: Choose from templates/ based on complexity
|
||||
3. **Customize**: Adapt type hints, Enums, and sub-apps to your domain
|
||||
4. **Validate**: Run validation script to check type safety
|
||||
5. **Test**: Use example tests as reference
|
||||
|
||||
## Template Selection Guide
|
||||
|
||||
- **basic-typed-command.py**: Single command with type hints
|
||||
- **enum-options.py**: Commands with Enum-based options
|
||||
- **sub-app-structure.py**: Multi-command CLI with sub-apps
|
||||
- **typer-instance.py**: Factory pattern for testable CLIs
|
||||
- **advanced-validation.py**: Custom validators and callbacks
|
||||
|
||||
## Validation
|
||||
|
||||
Run the type safety validation:
|
||||
|
||||
```bash
|
||||
./scripts/validate-types.sh path/to/cli.py
|
||||
```
|
||||
|
||||
Checks:
|
||||
- All parameters have type hints
|
||||
- Return types specified
|
||||
- Enums used for constrained choices
|
||||
- Proper Typer decorators
|
||||
|
||||
## Examples
|
||||
|
||||
See `examples/` for complete working CLIs:
|
||||
- `examples/basic-cli/`: Simple typed CLI
|
||||
- `examples/enum-cli/`: Enum-based options
|
||||
- `examples/subapp-cli/`: Multi-command with sub-apps
|
||||
- `examples/factory-cli/`: Testable Typer factory pattern
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always use type hints**: Enables auto-validation and IDE support
|
||||
2. **Prefer Enums over strings**: For constrained choices
|
||||
3. **Use Path for file paths**: Better validation than str
|
||||
4. **Document with docstrings**: Typer uses them for help text
|
||||
5. **Keep commands focused**: One command = one responsibility
|
||||
6. **Use sub-apps for grouping**: Organize related commands together
|
||||
7. **Test with factory pattern**: Makes CLIs unit-testable
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Callback for Global Options
|
||||
|
||||
```python
|
||||
@app.callback()
|
||||
def main(
|
||||
verbose: bool = typer.Option(False, "--verbose", "-v"),
|
||||
ctx: typer.Context = typer.Context
|
||||
) -> None:
|
||||
"""Global options applied to all commands."""
|
||||
ctx.obj = {"verbose": verbose}
|
||||
```
|
||||
|
||||
### Custom Validators
|
||||
|
||||
```python
|
||||
def validate_port(value: int) -> int:
|
||||
if not 1024 <= value <= 65535:
|
||||
raise typer.BadParameter("Port must be between 1024-65535")
|
||||
return value
|
||||
|
||||
@app.command()
|
||||
def serve(port: int = typer.Option(8000, callback=validate_port)) -> None:
|
||||
"""Serve with validated port."""
|
||||
pass
|
||||
```
|
||||
|
||||
### Rich Output Integration
|
||||
|
||||
```python
|
||||
from rich.console import Console
|
||||
|
||||
console = Console()
|
||||
|
||||
@app.command()
|
||||
def status() -> None:
|
||||
"""Show status with rich formatting."""
|
||||
console.print("[bold green]System online[/bold green]")
|
||||
```
|
||||
|
||||
## Integration Points
|
||||
|
||||
- Use with `cli-structure` skill for overall CLI architecture
|
||||
- Combine with `testing-patterns` for CLI test coverage
|
||||
- Integrate with `packaging` skill for distribution
|
||||
|
||||
## References
|
||||
|
||||
- Templates: `templates/`
|
||||
- Scripts: `scripts/validate-types.sh`, `scripts/generate-cli.sh`
|
||||
- Examples: `examples/*/`
|
||||
Reference in New Issue
Block a user