{"id":41555930,"url":"https://github.com/asterkin/taew-py","last_synced_at":"2026-01-24T05:10:46.486Z","repository":{"id":321787359,"uuid":"1080504199","full_name":"asterkin/taew-py","owner":"asterkin","description":"Ports \u0026 Adapters foundation library for Python applications","archived":false,"fork":false,"pushed_at":"2025-10-31T13:32:53.000Z","size":3063,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-31T15:25:30.032Z","etag":null,"topics":["ai-native","clean-architecture","cli-framework","dependency-injection","hexagonal-architecture","ports-and-adapters","protocol-oriented","python","python3","taew","type-safety"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asterkin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-10-21T13:14:02.000Z","updated_at":"2025-10-31T13:32:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/asterkin/taew-py","commit_stats":null,"previous_names":["asterkin/taew-py"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/asterkin/taew-py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asterkin%2Ftaew-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asterkin%2Ftaew-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asterkin%2Ftaew-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asterkin%2Ftaew-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asterkin","download_url":"https://codeload.github.com/asterkin/taew-py/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asterkin%2Ftaew-py/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28712841,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T05:01:10.984Z","status":"ssl_error","status_checked_at":"2026-01-24T04:59:18.328Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-native","clean-architecture","cli-framework","dependency-injection","hexagonal-architecture","ports-and-adapters","protocol-oriented","python","python3","taew","type-safety"],"created_at":"2026-01-24T05:10:45.662Z","updated_at":"2026-01-24T05:10:46.480Z","avatar_url":"https://github.com/asterkin.png","language":"Python","readme":"# taew-py\n\n![taew-py banner](docs/images/banner.jpg)\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python](https://img.shields.io/badge/python-3.14+-blue.svg)](https://www.python.org/downloads/)\n[![Platform](https://img.shields.io/badge/platform-linux-blue.svg)](https://www.kernel.org/)\n[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)\n\n**Ports \u0026 Adapters foundation library for Python applications**\n\n`taew-py` is a Python foundation library that supports rapid development of evolvable MVPs without premature technology lock-in. By implementing the Ports \u0026 Adapters (Hexagonal Architecture) pattern, it enables you to build applications where core business logic remains independent of external technologies and frameworks.\n\nThe name **taew** comes from the Elvish word for \"socket\" - a [programmable port](https://www.elfdict.com/w/taew) that adapts to different needs.\n\n## The Problem\n\nWhen building MVPs, developers face a dilemma:\n- **Move fast** by coupling directly to specific technologies (databases, frameworks, cloud providers)\n- **Move carefully** by building extensive abstractions upfront\n\nThe first approach leads to **technology lock-in** that becomes increasingly painful to change. The second creates **upfront complexity** that slows initial development.\n\n## The Solution\n\n`taew-py` provides a third path: **write business logic against protocol-based ports or ABCs, then plug in adapters as needed**. This enables:\n\n- **Rapid prototyping** with simple adapters (in-memory, standard library)\n- **Gradual evolution** by swapping adapters without changing core logic\n- **Technology freedom** through clean separation of concerns\n- **Type safety** via Python protocols and strict type checking\n\nStart with Python standard library adapters (this repository), then add technology-specific adapters (AWS, databases, web frameworks) from separate repositories as your needs evolve.\n\n## Architecture Rationale\n\nThe `taew-py` library organizes code into three fundamental layers:\n\n**Domain Data Structures**\n- Pure data classes and types\n- No behavior or logic - just data representation\n- Foundation for all operations across the system\n\n**Ports**\n- Interfaces describing operations on domain structures\n- Defined as Protocols (preferred) or ABCs when inheritance is needed\n- No implementation - only contracts\n- A **port** is a group of related interfaces bound to the same technology concern (e.g., read/write operations, send/receive operations)\n\n**Adapters**\n- Concrete implementations of ports built on specific technologies\n- Bridge between abstract ports and real-world tools (databases, APIs, file systems, etc.)\n- Each adapter targets a specific technology stack\n\n### Core Components\n\n**Domain Layer** (`taew/domain/`)\n- Pure domain data structures\n- Configuration types for port and application setup\n\n**Ports Layer** (`taew/ports/`)\n- Protocol-based or ABC-based interface definitions\n- Examples: binding interfaces, browsing code trees, building parsers, serializing objects\n\n**Adapters Layer** (`taew/adapters/`)\n- Python standard library-based implementations\n- CLI adapters for command-line interface support\n- Launch-time adapters for dependency injection and instantiation\n\n**Utils** (`taew/utils/`)\n- Minimal common utilities - kept as small as possible\n\n### Configuration-Driven Wiring\n\nAdapters are selected at runtime through Python data structures (`AppConfiguration` and `PortsMapping`):\n\n```python\nfrom taew.domain.configuration import AppConfiguration, PortConfiguration\n\nconfig = AppConfiguration(\n    ports={\n        ports.for_serializing_objects: PortConfiguration(\n            adapter_module=\"taew.adapters.python.pprint.for_serializing_objects\"\n        ),\n        ports.for_browsing_code_tree: PortConfiguration(\n            adapter_module=\"taew.adapters.python.inspect.for_browsing_code_tree\"\n        ),\n    }\n)\n```\n\nConfiguration is encoded in Python data structures for maximum flexibility. Helper `Configure` classes are provided for all `taew` adapters to enable automatic generation when needed.\n\nThis design enables:\n- **Zero code changes** when swapping implementations\n- **Testing flexibility** using lightweight adapters (e.g., in-memory vs. database)\n- **Gradual migration** from simple to sophisticated technologies\n\n## Key Design Principles\n\n### Application Layer Separation\n\n`taew-py` promotes clean architecture through strict import boundaries:\n\n1. **Application Domain** - No `taew` imports\n   - Pure domain data structures and business logic\n   - Completely independent of the framework\n\n2. **Application Ports** - No `taew` imports (only application domain)\n   - Interface definitions using Protocols or ABCs\n   - May reference domain data structures\n\n3. **Application Workflows** - No specific adapters or `taew` imports\n   - Orchestrates domain logic through port interfaces\n   - Only depends on application domain and ports\n\n4. **Application Adapters** - `taew` imports allowed\n   - Customizations of generic `taew` adapters\n   - Implements application port interfaces\n\n5. **Application Configuration** - `taew` imports allowed\n   - Wires adapters to ports\n   - Python data structures for maximum flexibility\n   - Helper `Configure` classes provided for all `taew` adapters\n\n### Framework Philosophy\n\n- **Not Opinionated** - `taew` does not enforce any specific interpretation of Ports \u0026 Adapters\n- **Good Practices Made Easy** - Aims to make sound architectural patterns straightforward to apply\n- **Standard Library First** - Prefers Python stdlib interfaces (collections, protocols) whenever possible; in many ways, `taew-py` extends them for Ports \u0026 Adapters development\n- **Type Safety** - Python 3.14+ with full utilization of strong type annotations\n- **AI-Friendly from Day One** - Once domain structures and ports are defined (can be brainstormed with AI), developing specific technology adapters becomes a straightforward process that's easy and safe to delegate completely to AI agents\n- **CLI First MVP** - close to zero code conversion of application workflows to CLI commands\n\n## Sample Application\n\nSee [bz-taew-py](https://github.com/asterkin/bz-taew-py) - a complete CLI application for parking zone payment validation demonstrating real-world usage of taew-py's ports and adapters architecture.\n\n### Evolvable Applications\n\nStart with simple adapters, evolve as needed:\n\n1. **Prototype** - Use in-memory adapters for quick validation\n2. **MVP** - Switch to SQLite or local file storage\n3. **Scale** - Migrate to cloud databases without changing business logic\n4. **Optimize** - Add caching layers or specialized storage\n\nEach transition requires only adapter changes, not core logic rewrites.\n\n## Technology-Specific Adapters\n\nWhile this repository contains Python standard library adapters, technology-specific adapters are developed in separate repositories:\n\n- Cloud adapters (Buckets, Functions, etc.) - e.g. `taew-adapters-aws`\n- 3rd Party Database adapters (PostgreSQL, MySQL, MongoDB) - e.g.`taew-adapters-pg`\n- Web framework adapters (FastAPI, Flask, Django) - `taew-adapters-flask`\n\nThis separation enables:\n- **Minimal dependencies** - Only include what you need\n- **Independent evolution** - Adapters update on their own schedules\n- **Technology-specific testing** - Each adapter suite tests against real services\n\n## User Guide\n\n### Installation\n\ntaew-py requires Python 3.14+ and is currently distributed via GitHub. We recommend using `uv` for dependency management.\n\n#### Install uv (if not already installed)\n\n```bash\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n```\n\n#### Add taew-py to your project\n\n```bash\n# Initialize a new project\nmkdir my-app\ncd my-app\nuv init my-app\n\n# Add taew-py as a dependency\nuv add \"taew @ git+https://github.com/asterkin/taew-py.git@main\"\n```\n\n#### Configure in pyproject.toml\n\n```toml\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\nrequires-python = \"\u003e=3.14\"\ndependencies = [\n    \"taew\",\n]\n\n[tool.uv.sources]\ntaew = { git = \"https://github.com/asterkin/taew-py.git\", branch = \"main\" }\n```\n\n### Minimal Configuration\n\nCreate `configuration.py` with minimal setup:\n\n```python\nfrom taew.utils.cli import configure\n\nadapters = configure()\n```\n\n### CLI Entry Point Shim\n\nCreate executable `bin/my-app`:\n\n```python\n#!/usr/bin/env python3\n\nimport sys\nfrom collections.abc import Sequence\nfrom pathlib import Path\n\n# Add project root to PYTHONPATH\nsys.path.insert(0, str(Path(__file__).parent.parent))\n\nfrom taew.ports.for_starting_programs import Main\nfrom taew.adapters.launch_time.for_binding_interfaces import bind\nfrom configuration import adapters\n\ndef main(cmd_args: Sequence[str]) -\u003e None:\n    \"\"\"CLI entry point for testing and production use.\n\n    Args:\n        cmd_args: Command line arguments (typically sys.argv)\n    \"\"\"\n    try:\n        # Dynamically bind the Main interface\n        _main = bind(Main, adapters=adapters)\n\n        # Run with command line arguments\n        _main(cmd_args)\n\n    except Exception as e:\n        print(f\"Error: {e}\", file=sys.stderr)\n        sys.exit(1)\n\nif __name__ == \"__main__\":\n    main(sys.argv)\n```\n\nMake it executable: `chmod +x bin/my-app`\n\n### Workflow Configurator Template\n\nFor workflow packages, create `workflows/\u003cpackage\u003e/for_configuring_adapters.py`:\n\n```python\nfrom dataclasses import dataclass\nfrom taew.adapters.python.dataclass.for_configuring_adapters import (\n    Configure as ConfigureBase,\n)\n\n@dataclass(eq=False, frozen=True)\nclass Configure(ConfigureBase):\n    _root_marker: str = \"workflows\"\n    _ports: str = \"ports\"\n\n    def __post_init__(self) -\u003e None:\n        object.__setattr__(self, \"_package\", __package__)\n        object.__setattr__(self, \"_file\", __file__)\n```\n\n### Application Structure\n\n```\nmy-app/\n├── domain/              # Pure business data structures\n├── ports/               # Protocol interfaces for your capabilities\n├── workflows/           # Business logic orchestrating ports\n│   └── \u003cpackage\u003e/\n│       ├── __init__.py\n│       ├── for_configuring_adapters.py\n│       └── \u003cworkflow\u003e.py\n├── adapters/            # Port implementations\n│   ├── cli/             # CLI commands (auto-discovered)\n│   ├── ram/             # In-memory adapters (for prototyping)\n│   └── \u003ctechnology\u003e/    # Technology-specific adapters\n├── configuration.py     # Dependency injection wiring\n├── bin/\n│   └── my-app           # CLI entry point\n└── pyproject.toml\n```\n\n### AI-Native Learning\n\n**taew-py is designed for AI-assisted development.** The best way to learn is through hands-on experience with an AI assistant like Claude Code CLI.\n\nSee [HELLO_TAEW_PY.md](HELLO_TAEW_PY.md) for a step-by-step guided tutorial. Send the proposed prompts one by one to Claude Code CLI and observe the results as you build a complete \"Hello World\" application through 8 progressive steps:\n\n1. **Project bootstrapping** - Initialize project, add dependencies, create minimal configuration and CLI shim\n2. **Simple command** - Add a basic CLI command without full architecture\n3. **Full architecture** - Implement ports, workflows, and adapters pattern\n4. **Extension practice** - Add new functionality following established patterns\n5. **Initial documentation** - Generate architecture documentation\n6. **Template repository** - Add data abstraction layer with repository pattern using string.Template\n7. **Base class and logging** - Extract shared dependencies and add cross-cutting concerns\n8. **Final documentation** - Update architecture docs with advanced patterns\n\nEach prompt includes verification steps to confirm correct behavior.\n\n**See the results:** [docs/HELLO_TAEW_CALUDE.md](docs/HELLO_TAEW_CALUDE.md) contains the complete CLAUDE.md file generated by executing all 8 prompts with Claude Code CLI. This comprehensive architecture document demonstrates how well AI assistants can understand and document the Ports \u0026 Adapters pattern, including:\n- Four-layer architecture breakdown (domain, ports, workflows, adapters)\n- Complete flow from CLI entry point through dependency injection to workflow execution\n- Detailed explanation of Repository Pattern, Template Method Pattern, and base class patterns\n- Guidelines for adding new functionality\n- Testing strategies and development workflows\n\n### Real-World Example\n\nSee [bz-taew-py](https://github.com/asterkin/bz-taew-py) for a complete application demonstrating:\n- Complex domain models (parking tickets, payment cards, zones)\n- Multiple workflows (car drivers, parking inspectors)\n- Various adapters (RAM, directory-based storage, CLI)\n- Configuration with variants (date formatting)\n- Full test suite with 100% coverage\n\n### Next Steps\n\n- Study [bz-taew-py](https://github.com/asterkin/bz-taew-py) for real-world patterns\n- Read [CLAUDE.md](CLAUDE.md) for system architecture details\n- Review [CONTRIBUTING.md](CONTRIBUTING.md) for AI-native development workflow\n- Explore adapter implementations in `taew/adapters/python/`\n\n## Project Structure\n\n```\ntaew-py/\n├── taew/                    # Core library\n│   ├── domain/              # Pure data structures\n│   │   ├── configuration.py # Port and adapter configuration types\n│   │   ├── argument.py      # Function argument metadata\n│   │   └── function.py      # Function metadata structures\n│   ├── ports/               # Protocol-based interfaces\n│   │   ├── for_binding_interfaces.py\n│   │   ├── for_browsing_code_tree.py\n│   │   ├── for_building_command_parsers.py\n│   │   ├── for_stringizing_objects.py\n│   │   ├── for_marshalling_objects.py\n│   │   └── ...              # Additional port definitions\n│   ├── adapters/            # Concrete implementations\n│   │   ├── python/          # Python stdlib adapters\n│   │   │   ├── argparse/    # CLI argument parsing\n│   │   │   ├── dataclass/   # Dataclass support\n│   │   │   ├── json/        # JSON serialization\n│   │   │   ├── pprint/      # Pretty printing\n│   │   │   ├── pickle/      # Binary serialization\n│   │   │   ├── inspect/     # Code introspection\n│   │   │   └── ...          # 30+ stdlib adapters\n│   │   ├── cli/             # CLI command framework\n│   │   │   └── for_starting_programs/\n│   │   └── launch_time/     # Dependency injection\n│   │       └── for_binding_interfaces/\n│   └── utils/               # Minimal utilities\n│       ├── cli.py           # CLI bootstrap helpers\n│       └── configure.py     # Configuration utilities\n├── test/                    # Test suite\n├── bin/                     # Sample CLI applications\n├── CLAUDE.md                # System architecture (AI context)\n├── GEMINI.md                # Quick reference (AI context)\n├── AGENTS.md                # Cross-agent patterns (AI context)\n├── CONTRIBUTING.md          # Contribution guidelines\n└── README.md                # This file\n```\n\n**Key Directories:**\n\n- **domain/** - Pure data classes with no behavior or dependencies\n- **ports/** - Protocol definitions named by capability (e.g., `for_stringizing_objects`)\n- **adapters/python/** - 30+ adapters built on Python standard library (argparse, json, pickle, dataclass, inspect, typing, etc.)\n- **adapters/cli/** - Command-line interface framework with automatic command discovery\n- **adapters/launch_time/** - Stateless dependency injection via `bind()` and `create_instance()`\n- **utils/** - Minimal helper functions for configuration and bootstrapping\n\nSee [CLAUDE.md](CLAUDE.md) for detailed system architecture and [CONTRIBUTING.md](CONTRIBUTING.md) for development guidance.\n\n## Contributing\n\nWe welcome contributions! This project is designed as an **AI-Native** codebase, optimized for development with AI assistants like Claude Code CLI.\n\nPlease read [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines on:\n- AI-native development workflow\n- Using Claude Code CLI slash commands (`/issue-new`, `/issue-close`)\n- Code quality standards and testing requirements\n- Architectural patterns and the configurator system\n- Pull request process\n\n### Quick Start for Contributors\n\nThis project follows strict type checking and formatting standards:\n\n1. **Python 3.14+** - Full utilization of modern type annotations\n2. All code must pass `mypy` and `pyright` with zero errors\n3. Use `ruff` for formatting (run `make ruff-format`)\n4. Maintain 100% test coverage for new features\n5. Write tests against protocols, not implementations\n\n### Development Setup\n\nThis project uses `uv` for dependency management and `make` for task automation.\n\n```bash\n# Clone the repository\ngit clone https://github.com/asterkin/taew-py.git\ncd taew-py\n\n# Create and activate virtual environment\nuv venv\nsource .venv/bin/activate  # or .venv\\Scripts\\activate on Windows\n\n# Install dependencies\nuv sync\n\n# Run the full verification suite\nmake all\n```\n\n### Common Commands\n\n- `make all` - Run complete pipeline (static analysis + tests with coverage)\n- `make static` - Run ruff, mypy, and pyright\n- `make coverage` - Run tests with coverage analysis\n- `make test-unit` - Run unit tests only\n- `make ruff-format` - Format code\n\n### Testing Strategy\n\nTests are written against port protocols, not concrete implementations:\n\n```python\nfrom taew.ports.for_stringizing_objects import Dumps as DumpsProtocol\n\ndef _get_stringizer() -\u003e DumpsProtocol:\n    from taew.adapters.python.pprint.for_stringizing_objects import Dumps\n    return Dumps()\n\nclass TestStringizing(unittest.TestCase):\n    def test_stringation_dict(self):\n        dumps = _get_stringizer()\n        result = dumps({\"key\": \"value\"})\n        self.assertIn(\"key\", result)\n```\n\nThis approach ensures adapters are truly interchangeable.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## References\n\n- **Ports \u0026 Adapters Pattern**: [Alistair Cockburn's original article](https://alistair.cockburn.us/hexagonal-architecture/)\n- **Focus on Core Value and Keep Cloud Infrastructure Flexible**: [Asher Sterkin's article on applying Ports \u0026 Adapters in cloud environments](https://medium.com/@asher-sterkin/focus-on-core-value-and-keep-cloud-infrastructure-flexible-with-ports-adapters-af79c5fa1e56)\n- **Dependency Inversion Principle**: Part of SOLID principles\n- **Protocol-based programming in Python**: [PEP 544](https://peps.python.org/pep-0544/)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasterkin%2Ftaew-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasterkin%2Ftaew-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasterkin%2Ftaew-py/lists"}