CodeUChain provides a powerful framework for chaining processing links with hook support and flexible states.
pip install codeuchainZero external dependencies - pure Python!
This package supports the llm.txt standard for easy AI/LLM integration. See llm-full.txt for comprehensive documentation.
- State: Immutable by default, mutable for flexibility—embracing Python's dynamism.
- Link: Selfless processors, async and ecosystem-rich.
- Chain: Harmonious connectors with conditional flows.
- Hook: Gentle enhancers, optional and forgiving.
- Error Handling: Compassionate routing and retries.
- Typed Features: Optional static typing with TypedDict and generics for type safety.
import asyncio
from codeuchain import State, Chain, MathLink, LoggingHook
async def main():
chain = Chain()
chain.add_link("math", MathLink("sum"))
chain.use_hook(LoggingHook())
ctx = State({"numbers": [1, 2, 3]})
result = await chain.run(ctx)
print(result.get("result")) # 6
asyncio.run(main())CodeUChain supports optional static typing for enhanced type safety and better IDE support:
from typing import TypedDict
from codeuchain import State, Link, Chain
class InputData(TypedDict):
numbers: list[int]
operation: str
class OutputData(InputData):
result: float
class SumLink(Link[InputData, OutputData]):
async def call(self, ctx: State[InputData]) -> State[OutputData]:
numbers = ctx.get("numbers") or []
total = sum(numbers)
return ctx.insert_as("result", float(total))
# Usage
async def main():
chain: Chain[InputData, OutputData] = Chain()
chain.add_link(SumLink(), "sum")
data: InputData = {"numbers": [1, 2, 3], "operation": "sum"}
ctx: State[InputData] = State(data)
result: State[OutputData] = await chain.run(ctx)
print(result.get("result")) # 6.0
asyncio.run(main())The insert_as() method enables clean type evolution without casting:
class UserInput(TypedDict):
name: str
email: str
class UserWithProfile(TypedDict):
name: str
email: str
age: int
preferences: dict
# Clean type evolution
ctx = State[UserInput]({"name": "Alice", "email": "alice@example.com"})
evolved_ctx = (
ctx
.insert_as("age", 30)
.insert_as("preferences", {"theme": "dark"})
)Use Untyped (Default):
- Prototyping and exploration
- Dynamic data structures
- Simple scripts
- Maximum flexibility
Use Typed (Optional):
- Production systems
- Complex workflows
- Team collaboration
- Long-term maintenance
- Enhanced IDE support
Both approaches work together—you can mix typed and untyped components in the same chain!
Need HTTP functionality? See examples/http_examples/ for implementations:
# Copy from examples/http_examples/http_links.py
from your_project.simple_http import SimpleHttpLink
link = SimpleHttpLink("https://api.example.com/data")# Requires: pip install aiohttp
from your_project.aio_http import AioHttpLink
link = AioHttpLink("https://api.example.com/data", method="POST")See the examples/ directory for comprehensive demonstrations:
typed_vs_untyped_comparison.py- Side-by-side comparison of approachestyped_workflow_patterns.py- Common patterns for typed workflowsinsert_as_method_demo.py- Type evolution demonstrationssimple_math.py- Basic untyped usage
Optimized for Python's strengths—dynamic, ecosystem-integrated, and developer-friendly. Start fresh, build powerful processing pipelines.