Examples
"""Simple Sequential Workflow Example"""
import asyncio
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner
class DataFetchStep(ZumaActionStep):
async def execute(self, context):
return {"data": "fetched_data"}
class ProcessingStep(ZumaActionStep):
async def execute(self, context):
data = context.get("data")
return {"processed": f"processed_{data}"}
if __name__ == "__main__":
asyncio.run(
ZumaRunner().run_workflow(
ZumaWorkflow(
"Simple Workflow",
steps=[
DataFetchStep(),
ProcessingStep(),
],
)
)
)
"""Parallel Processing Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaParallelAction, ZumaRunner
from typing import Dict, Any
import asyncio
class DataProcessStep(ZumaActionStep):
"""Processes a single file"""
def __init__(self, name: str, file_type: str):
super().__init__(name)
self.file_type = file_type
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
valid_files = context.get("valid_files", [])
our_files = [f for f in valid_files if f.endswith(self.file_type)]
results = []
for file in our_files:
print(f"[{self.name}] Processing {file}...")
await asyncio.sleep(0.5) # Simulate processing
results.append({
"file": file,
"processor": self.name
})
return {"processed_files": len(results), "results": results}
async def run_parallel_workflow():
# Define parallel data processing
parallel_processing = ZumaParallelAction(
"Parallel Processing",
steps=[
DataProcessStep("Process CSV", file_type=".csv"),
DataProcessStep("Process JSON", file_type=".json"),
DataProcessStep("Process XML", file_type=".xml")
],
max_concurrency=2 # Process 2 file types at a time
)
# Create workflow
workflow = ZumaWorkflow(
"Parallel Processing Workflow",
steps=[parallel_processing]
)
# Run workflow
runner = ZumaRunner()
result = await runner.run_workflow(workflow)
runner.print_execution_summary(result)
return result
if __name__ == "__main__":
asyncio.run(run_parallel_workflow())
"""Conditional Workflow Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaConditionalStep, ZumaRunner
from typing import Dict, Any
import asyncio
def check_data_size(context: Dict[str, Any]) -> bool:
"""Determines processing path based on data size"""
return context.get("data_size", 0) > 1000
class DataLoadStep(ZumaActionStep):
"""Loads and measures the size of input data"""
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
data = context.get("input_data", list(range(2000)))
print(f"[{self.name}] Loading {len(data)} items...")
await asyncio.sleep(0.5)
return {"data": data, "data_size": len(data)}
class BatchProcessingStep(ZumaActionStep):
"""Handles large dataset processing in batches"""
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
data = context.get("data", [])
batch_size = 100
print(f"[{self.name}] Processing {len(data)} items in batches...")
processed = []
for i in range(0, len(data), batch_size):
batch = data[i : i + batch_size]
await asyncio.sleep(0.1) # Simulate batch processing
processed.extend([f"processed_{item}" for item in batch])
return {
"processed_items": len(processed),
"processing_type": "batch",
"results": processed,
}
class SimpleProcessingStep(ZumaActionStep):
"""Handles small dataset processing"""
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
data = context.get("data", [])
print(f"[{self.name}] Processing {len(data)} items directly...")
await asyncio.sleep(0.5) # Simulate processing
processed = [f"processed_{item}" for item in data]
return {
"processed_items": len(processed),
"processing_type": "simple",
"results": processed,
}
async def run_conditional_workflow():
workflow = ZumaWorkflow(
"Conditional Processing Workflow",
steps=[
DataLoadStep("Load Data"),
ZumaConditionalStep(
"Processing Path Decision",
condition=check_data_size,
true_component=BatchProcessingStep("Batch Process"),
false_component=SimpleProcessingStep("Simple Process"),
),
],
)
# Run workflow with sample data
initial_context = {"input_data": list(range(2000))} # Large dataset
runner = ZumaRunner()
result = await runner.run_workflow(workflow, context=initial_context)
runner.print_execution_summary(result)
return result
if __name__ == "__main__":
asyncio.run(run_conditional_workflow())
"""Error Handling Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner, ZumaExecutionError
from typing import Dict, Any
import asyncio
class ValidatingStep(ZumaActionStep):
"""Step that validates input data"""
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
data = context.get("data")
print(f"[{self.name}] Validating data: {data}")
if not self.validate_data(data):
raise ZumaExecutionError("Data validation failed")
return {"validated": True, "data": data}
def validate_data(self, data):
return isinstance(data, str) and len(data) > 0
async def run_error_workflow():
workflow = ZumaWorkflow(
"Error Handling Workflow",
steps=[
ValidatingStep(
"Validate Data",
description="Validates input data format",
retries=3
)
],
continue_on_failure=True
)
runner = ZumaRunner()
result = await runner.run_workflow(workflow)
runner.print_execution_summary(result)
return result
if __name__ == "__main__":
asyncio.run(run_error_workflow())
"""Retry Mechanism Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner, ZumaExecutionError
from typing import Dict, Any
import asyncio
import random
class UnreliableAPIStep(ZumaActionStep):
def __init__(self, name: str):
super().__init__(
name=name,
retries=3, # Try up to 3 times
retry_delay=1.0 # Wait 1 second between retries
)
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
# Simulated API call that might fail
if random.random() < 0.7: # 70% chance of failure
raise ZumaExecutionError("API request failed")
return {"api_response": "success"}
async def run_retry_example():
workflow = ZumaWorkflow(
"Retry Mechanism Demo",
steps=[UnreliableAPIStep("API Call")]
)
runner = ZumaRunner()
result = await runner.run_workflow(
workflow,
generate_diagram=True,
diagram_output="retry_mechanism"
)
return result
if __name__ == "__main__":
asyncio.run(run_retry_example())
"""Workflow Composition Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner
from typing import Dict, Any
import asyncio
class DataFetchStep(ZumaActionStep):
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
print(f"[{self.name}] Fetching data...")
await asyncio.sleep(0.5)
return {"data": "raw_data"}
class ValidationWorkflow(ZumaWorkflow):
def __init__(self):
super().__init__(
"Data Validation Workflow",
steps=[
DataValidationStep("Format Check"),
SchemaValidationStep("Schema Check")
]
)
class ProcessingWorkflow(ZumaWorkflow):
def __init__(self):
super().__init__(
"Data Processing Workflow",
steps=[
DataTransformStep("Transform"),
DataEnrichStep("Enrich")
]
)
async def run_composed_workflow():
# Create main workflow that combines other workflows
workflow = ZumaWorkflow(
"Main Workflow",
steps=[
DataFetchStep("Fetch Data"),
ValidationWorkflow(),
ProcessingWorkflow()
]
)
runner = ZumaRunner()
result = await runner.run_workflow(workflow)
runner.print_execution_summary(result)
return result
if __name__ == "__main__":
asyncio.run(run_composed_workflow())
"""Dynamic Workflow Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner
from typing import Dict, Any, List
import asyncio
class DynamicStep(ZumaActionStep):
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
# Generate steps based on context
data_types = context.get("data_types", [])
steps = []
for data_type in data_types:
steps.append(
ProcessingStep(f"Process {data_type}", data_type)
)
# Create and run dynamic workflow
workflow = ZumaWorkflow(
"Dynamic Sub-Workflow",
steps=steps
)
runner = ZumaRunner()
result = await runner.run_workflow(workflow, context)
return result.context
async def run_dynamic_workflow():
workflow = ZumaWorkflow(
"Dynamic Workflow",
steps=[
DynamicStep("Generate Steps")
]
)
# Run with different data types
context = {"data_types": ["CSV", "JSON", "XML"]}
runner = ZumaRunner()
result = await runner.run_workflow(workflow, context)
runner.print_execution_summary(result)
return result
if __name__ == "__main__":
asyncio.run(run_dynamic_workflow())
"""Custom Actions Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner
from typing import Dict, Any
import asyncio
class CustomRetryStep(ZumaActionStep):
def __init__(self, name: str, max_retries: int = 3):
super().__init__(
name=name,
retries=max_retries,
retry_delay=1.0
)
self.attempt = 0
async def before_retry(self, error: Exception) -> None:
self.attempt += 1
print(f"Retry attempt {self.attempt} after error: {error}")
async def after_retry(self, result: Dict[str, Any]) -> None:
print(f"Retry succeeded on attempt {self.attempt}")
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
# Custom retry logic
if self.attempt < 2: # Succeed on third try
raise Exception("Simulated failure")
return {"status": "success"}
async def run_custom_workflow():
workflow = ZumaWorkflow(
"Custom Actions Workflow",
steps=[CustomRetryStep("Custom Retry")]
)
runner = ZumaRunner()
result = await runner.run_workflow(workflow)
runner.print_execution_summary(result)
return result
if __name__ == "__main__":
asyncio.run(run_custom_workflow())
"""Workflow Visualization Example"""
from zuma import ZumaWorkflow, ZumaActionStep, ZumaRunner, ZumaExecutionError
from typing import Dict, Any
import asyncio
import random
class UnreliableAPIStep(ZumaActionStep):
def __init__(self, name: str):
super().__init__(
name=name,
retries=3, # Try up to 3 times
retry_delay=1.0 # Wait 1 second between retries
)
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
# Simulated API call that might fail
if random.random() < 0.7: # 70% chance of failure
raise ZumaExecutionError("API request failed")
return {"api_response": "success"}
class DataProcessingStep(ZumaActionStep):
async def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
api_response = context.get("api_response")
print(f"[{self.name}] Processing response: {api_response}")
await asyncio.sleep(0.5) # Simulate processing
return {"processed_data": f"processed_{api_response}"}
async def run_visualization_example():
# Create a workflow with multiple steps to demonstrate visualization
workflow = ZumaWorkflow(
"Visualization Demo",
steps=[
UnreliableAPIStep("API Call"),
DataProcessingStep("Process Data")
]
)
runner = ZumaRunner()
# Generate visualization diagram
result = await runner.run_workflow(
workflow,
generate_diagram=True,
diagram_output="workflow_diagram"
)
# The diagram will be generated as a Mermaid flowchart
# showing the workflow structure, retries, and error paths
return result
if __name__ == "__main__":
asyncio.run(run_visualization_example())