kailash 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kailash/__init__.py +31 -0
- kailash/__main__.py +11 -0
- kailash/cli/__init__.py +5 -0
- kailash/cli/commands.py +563 -0
- kailash/manifest.py +778 -0
- kailash/nodes/__init__.py +23 -0
- kailash/nodes/ai/__init__.py +26 -0
- kailash/nodes/ai/agents.py +417 -0
- kailash/nodes/ai/models.py +488 -0
- kailash/nodes/api/__init__.py +52 -0
- kailash/nodes/api/auth.py +567 -0
- kailash/nodes/api/graphql.py +480 -0
- kailash/nodes/api/http.py +598 -0
- kailash/nodes/api/rate_limiting.py +572 -0
- kailash/nodes/api/rest.py +665 -0
- kailash/nodes/base.py +1032 -0
- kailash/nodes/base_async.py +128 -0
- kailash/nodes/code/__init__.py +32 -0
- kailash/nodes/code/python.py +1021 -0
- kailash/nodes/data/__init__.py +125 -0
- kailash/nodes/data/readers.py +496 -0
- kailash/nodes/data/sharepoint_graph.py +623 -0
- kailash/nodes/data/sql.py +380 -0
- kailash/nodes/data/streaming.py +1168 -0
- kailash/nodes/data/vector_db.py +964 -0
- kailash/nodes/data/writers.py +529 -0
- kailash/nodes/logic/__init__.py +6 -0
- kailash/nodes/logic/async_operations.py +702 -0
- kailash/nodes/logic/operations.py +551 -0
- kailash/nodes/transform/__init__.py +5 -0
- kailash/nodes/transform/processors.py +379 -0
- kailash/runtime/__init__.py +6 -0
- kailash/runtime/async_local.py +356 -0
- kailash/runtime/docker.py +697 -0
- kailash/runtime/local.py +434 -0
- kailash/runtime/parallel.py +557 -0
- kailash/runtime/runner.py +110 -0
- kailash/runtime/testing.py +347 -0
- kailash/sdk_exceptions.py +307 -0
- kailash/tracking/__init__.py +7 -0
- kailash/tracking/manager.py +885 -0
- kailash/tracking/metrics_collector.py +342 -0
- kailash/tracking/models.py +535 -0
- kailash/tracking/storage/__init__.py +0 -0
- kailash/tracking/storage/base.py +113 -0
- kailash/tracking/storage/database.py +619 -0
- kailash/tracking/storage/filesystem.py +543 -0
- kailash/utils/__init__.py +0 -0
- kailash/utils/export.py +924 -0
- kailash/utils/templates.py +680 -0
- kailash/visualization/__init__.py +62 -0
- kailash/visualization/api.py +732 -0
- kailash/visualization/dashboard.py +951 -0
- kailash/visualization/performance.py +808 -0
- kailash/visualization/reports.py +1471 -0
- kailash/workflow/__init__.py +15 -0
- kailash/workflow/builder.py +245 -0
- kailash/workflow/graph.py +827 -0
- kailash/workflow/mermaid_visualizer.py +628 -0
- kailash/workflow/mock_registry.py +63 -0
- kailash/workflow/runner.py +302 -0
- kailash/workflow/state.py +238 -0
- kailash/workflow/visualization.py +588 -0
- kailash-0.1.0.dist-info/METADATA +710 -0
- kailash-0.1.0.dist-info/RECORD +69 -0
- kailash-0.1.0.dist-info/WHEEL +5 -0
- kailash-0.1.0.dist-info/entry_points.txt +2 -0
- kailash-0.1.0.dist-info/licenses/LICENSE +21 -0
- kailash-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
"""Asynchronous base node class extension for the Kailash SDK.
|
2
|
+
|
3
|
+
This module extends the base Node class with asynchronous execution capabilities,
|
4
|
+
allowing for more efficient handling of I/O-bound operations in workflows.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from datetime import datetime, timezone
|
8
|
+
from typing import Any, Dict
|
9
|
+
|
10
|
+
from kailash.nodes.base import Node
|
11
|
+
from kailash.sdk_exceptions import NodeExecutionError, NodeValidationError
|
12
|
+
|
13
|
+
|
14
|
+
class AsyncNode(Node):
|
15
|
+
"""Base class for asynchronous nodes in the Kailash system.
|
16
|
+
|
17
|
+
This class extends the standard Node class with async execution capabilities,
|
18
|
+
providing a clean interface for implementing asynchronous operations in
|
19
|
+
workflow nodes. It's particularly useful for:
|
20
|
+
|
21
|
+
1. API calls and network operations
|
22
|
+
2. Database queries
|
23
|
+
3. File operations
|
24
|
+
4. External service integrations
|
25
|
+
5. LLM/AI model inference
|
26
|
+
|
27
|
+
Design Philosophy:
|
28
|
+
- Maintain backward compatibility with synchronous nodes
|
29
|
+
- Support both sync and async execution methods
|
30
|
+
- Provide clear error handling and logging for async operations
|
31
|
+
- Enable efficient parallel execution in workflows
|
32
|
+
|
33
|
+
Usage Pattern:
|
34
|
+
- Override async_run() instead of run() for async functionality
|
35
|
+
- Default async_run() implementation calls run() for backward compatibility
|
36
|
+
- Node configurtion and validation remain the same as standard nodes
|
37
|
+
|
38
|
+
Upstream components:
|
39
|
+
- Workflow: Creates and manages node instances
|
40
|
+
- AsyncWorkflowExecutor: Executes nodes in parallel where possible
|
41
|
+
- AsyncLocalRuntime: Runs workflows with async support
|
42
|
+
|
43
|
+
Downstream usage:
|
44
|
+
- Custom AsyncNodes: Implement async_run() for I/O-bound operations
|
45
|
+
- TaskManager: Tracks node execution status
|
46
|
+
"""
|
47
|
+
|
48
|
+
async def async_run(self, **kwargs) -> Dict[str, Any]:
|
49
|
+
"""Asynchronous execution method for the node.
|
50
|
+
|
51
|
+
This method should be overridden by subclasses that require asynchronous
|
52
|
+
execution. The default implementation calls the synchronous run() method.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
**kwargs: Input parameters for node execution
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
Dictionary of outputs matching the node's output schema
|
59
|
+
|
60
|
+
Raises:
|
61
|
+
NodeExecutionError: If execution fails
|
62
|
+
"""
|
63
|
+
# Default implementation calls the synchronous run() method
|
64
|
+
return self.run(**kwargs)
|
65
|
+
|
66
|
+
async def execute_async(self, **runtime_inputs) -> Dict[str, Any]:
|
67
|
+
"""Execute the node asynchronously with validation and error handling.
|
68
|
+
|
69
|
+
This method follows the same pattern as execute() but supports asynchronous
|
70
|
+
execution. It performs:
|
71
|
+
|
72
|
+
1. Input validation
|
73
|
+
2. Execution via async_run()
|
74
|
+
3. Output validation
|
75
|
+
4. Error handling and logging
|
76
|
+
|
77
|
+
Args:
|
78
|
+
**runtime_inputs: Runtime inputs for node execution
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
Dictionary of validated outputs
|
82
|
+
|
83
|
+
Raises:
|
84
|
+
NodeValidationError: If inputs or outputs are invalid
|
85
|
+
NodeExecutionError: If execution fails
|
86
|
+
"""
|
87
|
+
start_time = datetime.now(timezone.utc)
|
88
|
+
try:
|
89
|
+
self.logger.info(f"Executing node {self.id} asynchronously")
|
90
|
+
|
91
|
+
# Merge runtime inputs with config (runtime inputs take precedence)
|
92
|
+
merged_inputs = {**self.config, **runtime_inputs}
|
93
|
+
|
94
|
+
# Handle nested config case (for nodes that store parameters in config['config'])
|
95
|
+
if "config" in merged_inputs and isinstance(merged_inputs["config"], dict):
|
96
|
+
# Extract nested config
|
97
|
+
nested_config = merged_inputs["config"]
|
98
|
+
merged_inputs.update(nested_config)
|
99
|
+
# Don't remove the config key as some nodes might need it
|
100
|
+
|
101
|
+
# Validate inputs
|
102
|
+
validated_inputs = self.validate_inputs(**merged_inputs)
|
103
|
+
self.logger.debug(f"Validated inputs for {self.id}: {validated_inputs}")
|
104
|
+
|
105
|
+
# Execute node logic asynchronously
|
106
|
+
outputs = await self.async_run(**validated_inputs)
|
107
|
+
|
108
|
+
# Validate outputs
|
109
|
+
validated_outputs = self.validate_outputs(outputs)
|
110
|
+
|
111
|
+
execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
|
112
|
+
self.logger.info(
|
113
|
+
f"Node {self.id} executed successfully in {execution_time:.3f}s"
|
114
|
+
)
|
115
|
+
return validated_outputs
|
116
|
+
|
117
|
+
except NodeValidationError:
|
118
|
+
# Re-raise validation errors as-is
|
119
|
+
raise
|
120
|
+
except NodeExecutionError:
|
121
|
+
# Re-raise execution errors as-is
|
122
|
+
raise
|
123
|
+
except Exception as e:
|
124
|
+
# Wrap any other exception in NodeExecutionError
|
125
|
+
self.logger.error(f"Node {self.id} execution failed: {e}", exc_info=True)
|
126
|
+
raise NodeExecutionError(
|
127
|
+
f"Node '{self.id}' execution failed: {type(e).__name__}: {e}"
|
128
|
+
) from e
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"""Code execution nodes for running arbitrary Python code.
|
2
|
+
|
3
|
+
This module enables users to write custom Python code as functions or classes
|
4
|
+
and automatically wrap them as Kailash nodes. This provides maximum flexibility
|
5
|
+
for users who need custom processing logic that doesn't fit into predefined nodes.
|
6
|
+
|
7
|
+
Key Features:
|
8
|
+
1. Function wrapping - Convert any Python function into a node
|
9
|
+
2. Class wrapping - Convert Python classes into stateful nodes
|
10
|
+
3. Dynamic execution - Run arbitrary Python code safely
|
11
|
+
4. Type inference - Automatically detect inputs/outputs
|
12
|
+
5. Error handling - Graceful error management during execution
|
13
|
+
|
14
|
+
Example:
|
15
|
+
# Define a custom function
|
16
|
+
def process_data(data: pd.DataFrame, threshold: float) -> pd.DataFrame:
|
17
|
+
return data[data['value'] > threshold]
|
18
|
+
|
19
|
+
# Wrap it as a node
|
20
|
+
custom_node = PythonCodeNode.from_function(
|
21
|
+
func=process_data,
|
22
|
+
name="threshold_filter",
|
23
|
+
description="Filter data by threshold"
|
24
|
+
)
|
25
|
+
|
26
|
+
# Use in workflow
|
27
|
+
workflow.add_node(custom_node)
|
28
|
+
"""
|
29
|
+
|
30
|
+
from .python import ClassWrapper, CodeExecutor, FunctionWrapper, PythonCodeNode
|
31
|
+
|
32
|
+
__all__ = ["PythonCodeNode", "CodeExecutor", "FunctionWrapper", "ClassWrapper"]
|