kailash 0.3.0__py3-none-any.whl → 0.3.2__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.
Files changed (113) hide show
  1. kailash/access_control.py +40 -39
  2. kailash/api/auth.py +26 -32
  3. kailash/api/custom_nodes.py +29 -29
  4. kailash/api/custom_nodes_secure.py +35 -35
  5. kailash/api/database.py +17 -17
  6. kailash/api/gateway.py +19 -19
  7. kailash/api/mcp_integration.py +24 -23
  8. kailash/api/studio.py +45 -45
  9. kailash/api/workflow_api.py +8 -8
  10. kailash/cli/commands.py +5 -8
  11. kailash/manifest.py +42 -42
  12. kailash/mcp/__init__.py +1 -1
  13. kailash/mcp/ai_registry_server.py +20 -20
  14. kailash/mcp/client.py +9 -11
  15. kailash/mcp/client_new.py +10 -10
  16. kailash/mcp/server.py +1 -2
  17. kailash/mcp/server_enhanced.py +449 -0
  18. kailash/mcp/servers/ai_registry.py +6 -6
  19. kailash/mcp/utils/__init__.py +31 -0
  20. kailash/mcp/utils/cache.py +267 -0
  21. kailash/mcp/utils/config.py +263 -0
  22. kailash/mcp/utils/formatters.py +293 -0
  23. kailash/mcp/utils/metrics.py +418 -0
  24. kailash/nodes/ai/agents.py +9 -9
  25. kailash/nodes/ai/ai_providers.py +33 -34
  26. kailash/nodes/ai/embedding_generator.py +31 -32
  27. kailash/nodes/ai/intelligent_agent_orchestrator.py +62 -66
  28. kailash/nodes/ai/iterative_llm_agent.py +48 -48
  29. kailash/nodes/ai/llm_agent.py +32 -33
  30. kailash/nodes/ai/models.py +13 -13
  31. kailash/nodes/ai/self_organizing.py +44 -44
  32. kailash/nodes/api/auth.py +11 -11
  33. kailash/nodes/api/graphql.py +13 -13
  34. kailash/nodes/api/http.py +19 -19
  35. kailash/nodes/api/monitoring.py +20 -20
  36. kailash/nodes/api/rate_limiting.py +9 -13
  37. kailash/nodes/api/rest.py +29 -29
  38. kailash/nodes/api/security.py +44 -47
  39. kailash/nodes/base.py +21 -23
  40. kailash/nodes/base_async.py +7 -7
  41. kailash/nodes/base_cycle_aware.py +12 -12
  42. kailash/nodes/base_with_acl.py +5 -5
  43. kailash/nodes/code/python.py +66 -57
  44. kailash/nodes/data/directory.py +6 -6
  45. kailash/nodes/data/event_generation.py +10 -10
  46. kailash/nodes/data/file_discovery.py +28 -31
  47. kailash/nodes/data/readers.py +8 -8
  48. kailash/nodes/data/retrieval.py +10 -10
  49. kailash/nodes/data/sharepoint_graph.py +17 -17
  50. kailash/nodes/data/sources.py +5 -5
  51. kailash/nodes/data/sql.py +13 -13
  52. kailash/nodes/data/streaming.py +25 -25
  53. kailash/nodes/data/vector_db.py +22 -22
  54. kailash/nodes/data/writers.py +7 -7
  55. kailash/nodes/logic/async_operations.py +17 -17
  56. kailash/nodes/logic/convergence.py +11 -11
  57. kailash/nodes/logic/loop.py +4 -4
  58. kailash/nodes/logic/operations.py +11 -11
  59. kailash/nodes/logic/workflow.py +8 -9
  60. kailash/nodes/mixins/mcp.py +17 -17
  61. kailash/nodes/mixins.py +8 -10
  62. kailash/nodes/transform/chunkers.py +3 -3
  63. kailash/nodes/transform/formatters.py +7 -7
  64. kailash/nodes/transform/processors.py +10 -10
  65. kailash/runtime/access_controlled.py +18 -18
  66. kailash/runtime/async_local.py +17 -19
  67. kailash/runtime/docker.py +20 -22
  68. kailash/runtime/local.py +16 -16
  69. kailash/runtime/parallel.py +23 -23
  70. kailash/runtime/parallel_cyclic.py +27 -27
  71. kailash/runtime/runner.py +6 -6
  72. kailash/runtime/testing.py +20 -20
  73. kailash/sdk_exceptions.py +0 -58
  74. kailash/security.py +14 -26
  75. kailash/tracking/manager.py +38 -38
  76. kailash/tracking/metrics_collector.py +15 -14
  77. kailash/tracking/models.py +53 -53
  78. kailash/tracking/storage/base.py +7 -17
  79. kailash/tracking/storage/database.py +22 -23
  80. kailash/tracking/storage/filesystem.py +38 -40
  81. kailash/utils/export.py +21 -21
  82. kailash/utils/templates.py +2 -3
  83. kailash/visualization/api.py +30 -34
  84. kailash/visualization/dashboard.py +17 -17
  85. kailash/visualization/performance.py +16 -16
  86. kailash/visualization/reports.py +25 -27
  87. kailash/workflow/builder.py +8 -8
  88. kailash/workflow/convergence.py +13 -12
  89. kailash/workflow/cycle_analyzer.py +30 -32
  90. kailash/workflow/cycle_builder.py +12 -12
  91. kailash/workflow/cycle_config.py +16 -15
  92. kailash/workflow/cycle_debugger.py +40 -40
  93. kailash/workflow/cycle_exceptions.py +29 -29
  94. kailash/workflow/cycle_profiler.py +21 -21
  95. kailash/workflow/cycle_state.py +20 -22
  96. kailash/workflow/cyclic_runner.py +44 -44
  97. kailash/workflow/graph.py +40 -40
  98. kailash/workflow/mermaid_visualizer.py +9 -11
  99. kailash/workflow/migration.py +22 -22
  100. kailash/workflow/mock_registry.py +6 -6
  101. kailash/workflow/runner.py +9 -9
  102. kailash/workflow/safety.py +12 -13
  103. kailash/workflow/state.py +8 -11
  104. kailash/workflow/templates.py +19 -19
  105. kailash/workflow/validation.py +14 -14
  106. kailash/workflow/visualization.py +22 -22
  107. {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/METADATA +53 -5
  108. kailash-0.3.2.dist-info/RECORD +136 -0
  109. kailash-0.3.0.dist-info/RECORD +0 -130
  110. {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/WHEEL +0 -0
  111. {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/entry_points.txt +0 -0
  112. {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/licenses/LICENSE +0 -0
  113. {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/top_level.txt +0 -0
kailash/runtime/runner.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Main runner for workflow execution."""
2
2
 
3
3
  import logging
4
- from typing import Any, Dict, Optional, Tuple
4
+ from typing import Any
5
5
 
6
6
  from kailash.runtime.local import LocalRuntime
7
7
  from kailash.tracking import TaskManager
@@ -11,7 +11,7 @@ from kailash.workflow import Workflow
11
11
  class WorkflowRunner:
12
12
  """High-level interface for running workflows."""
13
13
 
14
- def __init__(self, debug: bool = False, task_manager: Optional[TaskManager] = None):
14
+ def __init__(self, debug: bool = False, task_manager: TaskManager | None = None):
15
15
  """Initialize the workflow runner.
16
16
 
17
17
  Args:
@@ -36,9 +36,9 @@ class WorkflowRunner:
36
36
  def run(
37
37
  self,
38
38
  workflow: Workflow,
39
- parameters: Optional[Dict[str, Dict[str, Any]]] = None,
39
+ parameters: dict[str, dict[str, Any]] | None = None,
40
40
  runtime_type: str = "local",
41
- ) -> Tuple[Dict[str, Any], str]:
41
+ ) -> tuple[dict[str, Any], str]:
42
42
  """Run a workflow.
43
43
 
44
44
  Args:
@@ -82,7 +82,7 @@ class WorkflowRunner:
82
82
  runtime = LocalRuntime(debug=self.debug)
83
83
  return runtime.validate_workflow(workflow)
84
84
 
85
- def get_run_status(self, run_id: str) -> Dict[str, Any]:
85
+ def get_run_status(self, run_id: str) -> dict[str, Any]:
86
86
  """Get status of a workflow run.
87
87
 
88
88
  Args:
@@ -94,7 +94,7 @@ class WorkflowRunner:
94
94
  return self.task_manager.get_run_status(run_id)
95
95
 
96
96
  def get_run_history(
97
- self, workflow_name: Optional[str] = None, limit: int = 10
97
+ self, workflow_name: str | None = None, limit: int = 10
98
98
  ) -> list:
99
99
  """Get run history.
100
100
 
@@ -1,7 +1,7 @@
1
1
  """Testing utilities for Kailash workflows and nodes."""
2
2
 
3
3
  import json
4
- from typing import Any, Dict, List, Optional, Tuple, Union
4
+ from typing import Any
5
5
 
6
6
  from kailash.nodes.base import Node, NodeParameter
7
7
  from kailash.runtime.local import LocalRuntime
@@ -21,7 +21,7 @@ class MockNode(Node):
21
21
  self._fail_message = kwargs.get("fail_message", "Mock failure")
22
22
  self._execution_count = 0
23
23
 
24
- def get_parameters(self) -> Dict[str, NodeParameter]:
24
+ def get_parameters(self) -> dict[str, NodeParameter]:
25
25
  """Define mock parameters."""
26
26
  return {
27
27
  "input": NodeParameter(
@@ -43,7 +43,7 @@ class MockNode(Node):
43
43
  ),
44
44
  }
45
45
 
46
- def run(self, **kwargs) -> Dict[str, Any]:
46
+ def run(self, **kwargs) -> dict[str, Any]:
47
47
  """Execute mock node logic."""
48
48
  self._execution_count += 1
49
49
 
@@ -64,8 +64,8 @@ class TestDataGenerator:
64
64
 
65
65
  @staticmethod
66
66
  def generate_csv_data(
67
- rows: int = 10, columns: List[str] = None
68
- ) -> List[Dict[str, Any]]:
67
+ rows: int = 10, columns: list[str] = None
68
+ ) -> list[dict[str, Any]]:
69
69
  """Generate mock CSV data."""
70
70
  if columns is None:
71
71
  columns = ["id", "name", "value", "category"]
@@ -88,7 +88,7 @@ class TestDataGenerator:
88
88
  return data
89
89
 
90
90
  @staticmethod
91
- def generate_json_data(structure: str = "simple") -> Union[Dict, List]:
91
+ def generate_json_data(structure: str = "simple") -> dict | list:
92
92
  """Generate mock JSON data."""
93
93
  if structure == "simple":
94
94
  return {
@@ -154,8 +154,8 @@ class WorkflowTestHelper:
154
154
  self,
155
155
  workflow: Workflow,
156
156
  with_tracking: bool = True,
157
- parameters: Optional[Dict] = None,
158
- ) -> Tuple[Dict[str, Any], Optional[str]]:
157
+ parameters: dict | None = None,
158
+ ) -> tuple[dict[str, Any], str | None]:
159
159
  """Run a workflow with optional tracking."""
160
160
  if with_tracking:
161
161
  self.task_manager = TaskManager()
@@ -165,7 +165,7 @@ class WorkflowTestHelper:
165
165
  return self.runtime.execute(workflow, self.task_manager, parameters)
166
166
 
167
167
  def assert_workflow_success(
168
- self, workflow: Workflow, expected_nodes: Optional[List[str]] = None
168
+ self, workflow: Workflow, expected_nodes: list[str] | None = None
169
169
  ):
170
170
  """Assert that a workflow runs successfully."""
171
171
  results, run_id = self.run_workflow(workflow)
@@ -182,10 +182,10 @@ class WorkflowTestHelper:
182
182
 
183
183
  def assert_node_output(
184
184
  self,
185
- results: Dict[str, Any],
185
+ results: dict[str, Any],
186
186
  node_id: str,
187
- expected_keys: List[str],
188
- expected_values: Optional[Dict] = None,
187
+ expected_keys: list[str],
188
+ expected_values: dict | None = None,
189
189
  ):
190
190
  """Assert that a node produced expected output."""
191
191
  assert node_id in results, f"Node {node_id} not found in results"
@@ -208,7 +208,7 @@ class NodeTestHelper:
208
208
  """Helper class for testing individual nodes."""
209
209
 
210
210
  @staticmethod
211
- def test_node_parameters(node: Node, expected_params: Dict[str, type]):
211
+ def test_node_parameters(node: Node, expected_params: dict[str, type]):
212
212
  """Test that a node has expected parameters."""
213
213
  params = node.get_parameters()
214
214
 
@@ -222,10 +222,10 @@ class NodeTestHelper:
222
222
  @staticmethod
223
223
  def test_node_execution(
224
224
  node: Node,
225
- inputs: Dict[str, Any],
226
- expected_keys: List[str],
225
+ inputs: dict[str, Any],
226
+ expected_keys: list[str],
227
227
  should_fail: bool = False,
228
- ) -> Dict[str, Any]:
228
+ ) -> dict[str, Any]:
229
229
  """Test node execution with given inputs."""
230
230
  if should_fail:
231
231
  try:
@@ -244,7 +244,7 @@ class NodeTestHelper:
244
244
 
245
245
  @staticmethod
246
246
  def test_node_validation(
247
- node: Node, valid_inputs: Dict[str, Any], invalid_inputs: List[Dict[str, Any]]
247
+ node: Node, valid_inputs: dict[str, Any], invalid_inputs: list[dict[str, Any]]
248
248
  ):
249
249
  """Test node input validation."""
250
250
  # Test valid inputs
@@ -269,7 +269,7 @@ class TestReporter:
269
269
  """Initialize reporter with task manager."""
270
270
  self.task_manager = task_manager
271
271
 
272
- def generate_run_report(self, run_id: str) -> Dict[str, Any]:
272
+ def generate_run_report(self, run_id: str) -> dict[str, Any]:
273
273
  """Generate a detailed report for a workflow run."""
274
274
  run = self.task_manager.get_run_summary(run_id)
275
275
  tasks = self.task_manager.list_tasks(run_id)
@@ -305,7 +305,7 @@ class TestReporter:
305
305
 
306
306
  return report
307
307
 
308
- def save_report(self, report: Dict[str, Any], output_path: str):
308
+ def save_report(self, report: dict[str, Any], output_path: str):
309
309
  """Save report to file."""
310
310
  with open(output_path, "w") as f:
311
311
  json.dump(report, f, indent=2, default=str)
@@ -325,7 +325,7 @@ def create_test_node(node_type: str = "MockNode", **config) -> Node:
325
325
 
326
326
 
327
327
  def create_test_workflow(
328
- name: str = "test_workflow", nodes: Optional[List[Dict]] = None
328
+ name: str = "test_workflow", nodes: list[dict] | None = None
329
329
  ) -> Workflow:
330
330
  """Create a test workflow with specified nodes."""
331
331
  workflow = Workflow(name=name)
kailash/sdk_exceptions.py CHANGED
@@ -77,15 +77,11 @@ See Also:
77
77
  class KailashException(Exception):
78
78
  """Base exception for all Kailash SDK errors."""
79
79
 
80
- pass
81
-
82
80
 
83
81
  # Node-related exceptions
84
82
  class NodeException(KailashException):
85
83
  """Base exception for node-related errors."""
86
84
 
87
- pass
88
-
89
85
 
90
86
  class NodeValidationError(NodeException):
91
87
  """Raised when node validation fails.
@@ -96,8 +92,6 @@ class NodeValidationError(NodeException):
96
92
  - Configuration is invalid
97
93
  """
98
94
 
99
- pass
100
-
101
95
 
102
96
  class NodeExecutionError(NodeException):
103
97
  """Raised when node execution fails.
@@ -108,8 +102,6 @@ class NodeExecutionError(NodeException):
108
102
  - Data transformation fails
109
103
  """
110
104
 
111
- pass
112
-
113
105
 
114
106
  class NodeConfigurationError(NodeException):
115
107
  """Raised when node configuration is invalid.
@@ -120,8 +112,6 @@ class NodeConfigurationError(NodeException):
120
112
  - Required environment variables are missing
121
113
  """
122
114
 
123
- pass
124
-
125
115
 
126
116
  class SafetyViolationError(NodeException):
127
117
  """Raised when code safety validation fails.
@@ -132,15 +122,11 @@ class SafetyViolationError(NodeException):
132
122
  - Malicious code patterns are detected
133
123
  """
134
124
 
135
- pass
136
-
137
125
 
138
126
  # Workflow-related exceptions
139
127
  class WorkflowException(KailashException):
140
128
  """Base exception for workflow-related errors."""
141
129
 
142
- pass
143
-
144
130
 
145
131
  class WorkflowValidationError(WorkflowException):
146
132
  """Raised when workflow validation fails.
@@ -151,8 +137,6 @@ class WorkflowValidationError(WorkflowException):
151
137
  - Workflow structure is invalid
152
138
  """
153
139
 
154
- pass
155
-
156
140
 
157
141
  class WorkflowExecutionError(WorkflowException):
158
142
  """Raised when workflow execution fails.
@@ -163,8 +147,6 @@ class WorkflowExecutionError(WorkflowException):
163
147
  - Runtime resources are exhausted
164
148
  """
165
149
 
166
- pass
167
-
168
150
 
169
151
  class CyclicDependencyError(WorkflowException):
170
152
  """Raised when a cyclic dependency is detected in the workflow graph.
@@ -173,8 +155,6 @@ class CyclicDependencyError(WorkflowException):
173
155
  making it impossible to determine execution order.
174
156
  """
175
157
 
176
- pass
177
-
178
158
 
179
159
  class ConnectionError(WorkflowException):
180
160
  """Raised when node connections are invalid.
@@ -185,8 +165,6 @@ class ConnectionError(WorkflowException):
185
165
  - Node not found in workflow
186
166
  """
187
167
 
188
- pass
189
-
190
168
 
191
169
  class CycleConfigurationError(WorkflowException):
192
170
  """Raised when cycle configuration is invalid.
@@ -202,15 +180,11 @@ class CycleConfigurationError(WorkflowException):
202
180
  - Missing source/target nodes before build()
203
181
  """
204
182
 
205
- pass
206
-
207
183
 
208
184
  # Runtime-related exceptions
209
185
  class RuntimeException(KailashException):
210
186
  """Base exception for runtime-related errors."""
211
187
 
212
- pass
213
-
214
188
 
215
189
  class RuntimeExecutionError(RuntimeException):
216
190
  """Raised when runtime execution fails.
@@ -221,15 +195,11 @@ class RuntimeExecutionError(RuntimeException):
221
195
  - Execution is interrupted
222
196
  """
223
197
 
224
- pass
225
-
226
198
 
227
199
  # Task tracking exceptions
228
200
  class TaskException(KailashException):
229
201
  """Base exception for task tracking errors."""
230
202
 
231
- pass
232
-
233
203
 
234
204
  class TaskStateError(TaskException):
235
205
  """Raised when task state operations fail.
@@ -240,15 +210,11 @@ class TaskStateError(TaskException):
240
210
  - Concurrent modification conflicts occur
241
211
  """
242
212
 
243
- pass
244
-
245
213
 
246
214
  # Storage exceptions
247
215
  class StorageException(KailashException):
248
216
  """Base exception for storage-related errors."""
249
217
 
250
- pass
251
-
252
218
 
253
219
  class KailashStorageError(StorageException):
254
220
  """Raised when storage operations fail.
@@ -260,8 +226,6 @@ class KailashStorageError(StorageException):
260
226
  - Data formatting is incorrect
261
227
  """
262
228
 
263
- pass
264
-
265
229
 
266
230
  # Import/Export exceptions
267
231
  class ExportException(KailashException):
@@ -273,8 +237,6 @@ class ExportException(KailashException):
273
237
  - Serialization fails
274
238
  """
275
239
 
276
- pass
277
-
278
240
 
279
241
  class ImportException(KailashException):
280
242
  """Raised when import operations fail.
@@ -285,8 +247,6 @@ class ImportException(KailashException):
285
247
  - Deserialization fails
286
248
  """
287
249
 
288
- pass
289
-
290
250
 
291
251
  # Configuration exceptions
292
252
  class ConfigurationException(KailashException):
@@ -298,8 +258,6 @@ class ConfigurationException(KailashException):
298
258
  - Configuration schema is invalid
299
259
  """
300
260
 
301
- pass
302
-
303
261
 
304
262
  class KailashConfigError(ConfigurationException):
305
263
  """Raised when configuration is invalid (legacy name).
@@ -307,8 +265,6 @@ class KailashConfigError(ConfigurationException):
307
265
  This is an alias for ConfigurationException for backward compatibility.
308
266
  """
309
267
 
310
- pass
311
-
312
268
 
313
269
  # Manifest exceptions
314
270
  class ManifestError(KailashException):
@@ -320,8 +276,6 @@ class ManifestError(KailashException):
320
276
  - Version incompatibility
321
277
  """
322
278
 
323
- pass
324
-
325
279
 
326
280
  # CLI exceptions
327
281
  class CLIException(KailashException):
@@ -333,8 +287,6 @@ class CLIException(KailashException):
333
287
  - Command execution fails
334
288
  """
335
289
 
336
- pass
337
-
338
290
 
339
291
  # Visualization exceptions
340
292
  class VisualizationError(KailashException):
@@ -346,8 +298,6 @@ class VisualizationError(KailashException):
346
298
  - Output format is unsupported
347
299
  """
348
300
 
349
- pass
350
-
351
301
 
352
302
  # Template exceptions
353
303
  class TemplateError(KailashException):
@@ -359,8 +309,6 @@ class TemplateError(KailashException):
359
309
  - Variable substitution fails
360
310
  """
361
311
 
362
- pass
363
-
364
312
 
365
313
  # Code execution exceptions
366
314
  # (SafetyViolationError already defined above - removing duplicate)
@@ -375,8 +323,6 @@ class CodeExecutionError(NodeException):
375
323
  - Import or dependency issues
376
324
  """
377
325
 
378
- pass
379
-
380
326
 
381
327
  # Resource exceptions
382
328
  class KailashNotFoundException(KailashException):
@@ -388,8 +334,6 @@ class KailashNotFoundException(KailashException):
388
334
  - A file or resource is missing
389
335
  """
390
336
 
391
- pass
392
-
393
337
 
394
338
  # Workflow-specific exceptions
395
339
  class KailashWorkflowException(WorkflowException):
@@ -398,8 +342,6 @@ class KailashWorkflowException(WorkflowException):
398
342
  This is an alias for WorkflowException for consistency.
399
343
  """
400
344
 
401
- pass
402
-
403
345
 
404
346
  # Legacy exception name compatibility for tests and backwards compatibility
405
347
  KailashRuntimeError = RuntimeExecutionError
kailash/security.py CHANGED
@@ -118,7 +118,7 @@ import tempfile
118
118
  import time
119
119
  from contextlib import contextmanager
120
120
  from pathlib import Path
121
- from typing import Any, Dict, List, Optional, Union
121
+ from typing import Any
122
122
 
123
123
  logger = logging.getLogger(__name__)
124
124
 
@@ -126,43 +126,33 @@ logger = logging.getLogger(__name__)
126
126
  class SecurityError(Exception):
127
127
  """Raised when a security policy violation is detected."""
128
128
 
129
- pass
130
-
131
129
 
132
130
  class PathTraversalError(SecurityError):
133
131
  """Raised when path traversal attempt is detected."""
134
132
 
135
- pass
136
-
137
133
 
138
134
  class CommandInjectionError(SecurityError):
139
135
  """Raised when command injection attempt is detected."""
140
136
 
141
- pass
142
-
143
137
 
144
138
  class ExecutionTimeoutError(SecurityError):
145
139
  """Raised when execution exceeds allowed time limit."""
146
140
 
147
- pass
148
-
149
141
 
150
142
  class MemoryLimitError(SecurityError):
151
143
  """Raised when memory usage exceeds allowed limit."""
152
144
 
153
- pass
154
-
155
145
 
156
146
  class SecurityConfig:
157
147
  """Configuration for security policies and limits."""
158
148
 
159
149
  def __init__(
160
150
  self,
161
- allowed_directories: Optional[List[str]] = None,
151
+ allowed_directories: list[str] | None = None,
162
152
  max_file_size: int = 100 * 1024 * 1024, # 100MB
163
153
  execution_timeout: float = 300.0, # 5 minutes
164
154
  memory_limit: int = 512 * 1024 * 1024, # 512MB
165
- allowed_file_extensions: Optional[List[str]] = None,
155
+ allowed_file_extensions: list[str] | None = None,
166
156
  enable_audit_logging: bool = True,
167
157
  enable_path_validation: bool = True,
168
158
  enable_command_validation: bool = True,
@@ -242,8 +232,8 @@ def set_security_config(config: SecurityConfig) -> None:
242
232
 
243
233
 
244
234
  def validate_file_path(
245
- file_path: Union[str, Path],
246
- config: Optional[SecurityConfig] = None,
235
+ file_path: str | Path,
236
+ config: SecurityConfig | None = None,
247
237
  operation: str = "access",
248
238
  ) -> Path:
249
239
  """
@@ -343,9 +333,9 @@ def validate_file_path(
343
333
 
344
334
 
345
335
  def safe_open(
346
- file_path: Union[str, Path],
336
+ file_path: str | Path,
347
337
  mode: str = "r",
348
- config: Optional[SecurityConfig] = None,
338
+ config: SecurityConfig | None = None,
349
339
  **kwargs,
350
340
  ):
351
341
  """
@@ -391,9 +381,7 @@ def safe_open(
391
381
  return open(validated_path, mode, **kwargs)
392
382
 
393
383
 
394
- def validate_command_string(
395
- command: str, config: Optional[SecurityConfig] = None
396
- ) -> str:
384
+ def validate_command_string(command: str, config: SecurityConfig | None = None) -> str:
397
385
  """
398
386
  Validate command strings to prevent injection attacks.
399
387
 
@@ -445,7 +433,7 @@ def validate_command_string(
445
433
 
446
434
  @contextmanager
447
435
  def execution_timeout(
448
- timeout: Optional[float] = None, config: Optional[SecurityConfig] = None
436
+ timeout: float | None = None, config: SecurityConfig | None = None
449
437
  ):
450
438
  """
451
439
  Context manager to enforce execution timeouts.
@@ -485,8 +473,8 @@ def execution_timeout(
485
473
  def sanitize_input(
486
474
  value: Any,
487
475
  max_length: int = 10000,
488
- allowed_types: Optional[List[type]] = None,
489
- config: Optional[SecurityConfig] = None,
476
+ allowed_types: list[type] | None = None,
477
+ config: SecurityConfig | None = None,
490
478
  ) -> Any:
491
479
  """
492
480
  Sanitize input values to prevent injection attacks.
@@ -776,7 +764,7 @@ def sanitize_input(
776
764
 
777
765
 
778
766
  def create_secure_temp_dir(
779
- prefix: str = "kailash_", config: Optional[SecurityConfig] = None
767
+ prefix: str = "kailash_", config: SecurityConfig | None = None
780
768
  ) -> Path:
781
769
  """
782
770
  Create a secure temporary directory.
@@ -804,8 +792,8 @@ def create_secure_temp_dir(
804
792
 
805
793
 
806
794
  def validate_node_parameters(
807
- parameters: Dict[str, Any], config: Optional[SecurityConfig] = None
808
- ) -> Dict[str, Any]:
795
+ parameters: dict[str, Any], config: SecurityConfig | None = None
796
+ ) -> dict[str, Any]:
809
797
  """
810
798
  Validate and sanitize node parameters.
811
799