kailash 0.4.2__py3-none-any.whl → 0.6.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 +1 -1
- kailash/client/__init__.py +12 -0
- kailash/client/enhanced_client.py +306 -0
- kailash/core/actors/__init__.py +16 -0
- kailash/core/actors/connection_actor.py +566 -0
- kailash/core/actors/supervisor.py +364 -0
- kailash/edge/__init__.py +16 -0
- kailash/edge/compliance.py +834 -0
- kailash/edge/discovery.py +659 -0
- kailash/edge/location.py +582 -0
- kailash/gateway/__init__.py +33 -0
- kailash/gateway/api.py +289 -0
- kailash/gateway/enhanced_gateway.py +357 -0
- kailash/gateway/resource_resolver.py +217 -0
- kailash/gateway/security.py +227 -0
- kailash/middleware/auth/models.py +2 -2
- kailash/middleware/database/base_models.py +1 -7
- kailash/middleware/database/repositories.py +3 -1
- kailash/middleware/gateway/__init__.py +22 -0
- kailash/middleware/gateway/checkpoint_manager.py +398 -0
- kailash/middleware/gateway/deduplicator.py +382 -0
- kailash/middleware/gateway/durable_gateway.py +417 -0
- kailash/middleware/gateway/durable_request.py +498 -0
- kailash/middleware/gateway/event_store.py +459 -0
- kailash/nodes/admin/audit_log.py +364 -6
- kailash/nodes/admin/permission_check.py +817 -33
- kailash/nodes/admin/role_management.py +1242 -108
- kailash/nodes/admin/schema_manager.py +438 -0
- kailash/nodes/admin/user_management.py +1209 -681
- kailash/nodes/api/http.py +95 -71
- kailash/nodes/base.py +281 -164
- kailash/nodes/base_async.py +30 -31
- kailash/nodes/code/__init__.py +8 -1
- kailash/nodes/code/async_python.py +1035 -0
- kailash/nodes/code/python.py +1 -0
- kailash/nodes/data/async_sql.py +12 -25
- kailash/nodes/data/sql.py +20 -11
- kailash/nodes/data/workflow_connection_pool.py +643 -0
- kailash/nodes/rag/__init__.py +1 -4
- kailash/resources/__init__.py +40 -0
- kailash/resources/factory.py +533 -0
- kailash/resources/health.py +319 -0
- kailash/resources/reference.py +288 -0
- kailash/resources/registry.py +392 -0
- kailash/runtime/async_local.py +711 -302
- kailash/testing/__init__.py +34 -0
- kailash/testing/async_test_case.py +353 -0
- kailash/testing/async_utils.py +345 -0
- kailash/testing/fixtures.py +458 -0
- kailash/testing/mock_registry.py +495 -0
- kailash/utils/resource_manager.py +420 -0
- kailash/workflow/__init__.py +8 -0
- kailash/workflow/async_builder.py +621 -0
- kailash/workflow/async_patterns.py +766 -0
- kailash/workflow/builder.py +93 -10
- kailash/workflow/cyclic_runner.py +111 -41
- kailash/workflow/graph.py +7 -2
- kailash/workflow/resilience.py +11 -1
- {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/METADATA +12 -7
- {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/RECORD +64 -28
- {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/WHEEL +0 -0
- {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/entry_points.txt +0 -0
- {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/top_level.txt +0 -0
kailash/nodes/code/python.py
CHANGED
kailash/nodes/data/async_sql.py
CHANGED
@@ -34,7 +34,8 @@ from decimal import Decimal
|
|
34
34
|
from enum import Enum
|
35
35
|
from typing import Any, AsyncIterator, Optional, Union
|
36
36
|
|
37
|
-
from kailash.nodes.base import
|
37
|
+
from kailash.nodes.base import NodeParameter, register_node
|
38
|
+
from kailash.nodes.base_async import AsyncNode
|
38
39
|
from kailash.sdk_exceptions import NodeExecutionError, NodeValidationError
|
39
40
|
|
40
41
|
|
@@ -204,16 +205,22 @@ class PostgreSQLAdapter(DatabaseAdapter):
|
|
204
205
|
query_params.append(value)
|
205
206
|
params = query_params
|
206
207
|
|
208
|
+
# Ensure params is a list/tuple for asyncpg
|
209
|
+
if params is None:
|
210
|
+
params = []
|
211
|
+
elif not isinstance(params, (list, tuple)):
|
212
|
+
params = [params]
|
213
|
+
|
207
214
|
if fetch_mode == FetchMode.ONE:
|
208
|
-
row = await conn.fetchrow(query, *
|
215
|
+
row = await conn.fetchrow(query, *params)
|
209
216
|
return self._convert_row(dict(row)) if row else None
|
210
217
|
elif fetch_mode == FetchMode.ALL:
|
211
|
-
rows = await conn.fetch(query, *
|
218
|
+
rows = await conn.fetch(query, *params)
|
212
219
|
return [self._convert_row(dict(row)) for row in rows]
|
213
220
|
elif fetch_mode == FetchMode.MANY:
|
214
221
|
if not fetch_size:
|
215
222
|
raise ValueError("fetch_size required for MANY mode")
|
216
|
-
rows = await conn.fetch(query, *
|
223
|
+
rows = await conn.fetch(query, *params)
|
217
224
|
return [self._convert_row(dict(row)) for row in rows[:fetch_size]]
|
218
225
|
elif fetch_mode == FetchMode.ITERATOR:
|
219
226
|
raise NotImplementedError("Iterator mode not yet implemented")
|
@@ -425,7 +432,7 @@ class SQLiteAdapter(DatabaseAdapter):
|
|
425
432
|
|
426
433
|
|
427
434
|
@register_node()
|
428
|
-
class AsyncSQLDatabaseNode(
|
435
|
+
class AsyncSQLDatabaseNode(AsyncNode):
|
429
436
|
"""Asynchronous SQL database node for high-concurrency database operations.
|
430
437
|
|
431
438
|
This node provides non-blocking database operations with connection pooling,
|
@@ -713,26 +720,6 @@ class AsyncSQLDatabaseNode(Node):
|
|
713
720
|
except Exception as e:
|
714
721
|
raise NodeExecutionError(f"Database query failed: {str(e)}")
|
715
722
|
|
716
|
-
def run(self, **inputs) -> dict[str, Any]:
|
717
|
-
"""Synchronous run method - delegates to async_run."""
|
718
|
-
import asyncio
|
719
|
-
|
720
|
-
import nest_asyncio
|
721
|
-
|
722
|
-
try:
|
723
|
-
# Check if we're already in an event loop
|
724
|
-
loop = asyncio.get_running_loop()
|
725
|
-
|
726
|
-
# Apply nest_asyncio to allow nested event loops
|
727
|
-
nest_asyncio.apply()
|
728
|
-
|
729
|
-
# Now we can safely run even in an existing event loop
|
730
|
-
return asyncio.run(self.async_run(**inputs))
|
731
|
-
|
732
|
-
except RuntimeError:
|
733
|
-
# No event loop running, we can use asyncio.run() directly
|
734
|
-
return asyncio.run(self.async_run(**inputs))
|
735
|
-
|
736
723
|
async def process(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
737
724
|
"""Async process method for middleware compatibility."""
|
738
725
|
return await self.async_run(**inputs)
|
kailash/nodes/data/sql.py
CHANGED
@@ -288,10 +288,10 @@ class SQLDatabaseNode(Node):
|
|
288
288
|
),
|
289
289
|
"parameters": NodeParameter(
|
290
290
|
name="parameters",
|
291
|
-
type=list
|
291
|
+
type=Any, # Allow both list and dict for parameters
|
292
292
|
required=False,
|
293
|
-
default=
|
294
|
-
description="Query parameters for parameterized queries",
|
293
|
+
default=None,
|
294
|
+
description="Query parameters for parameterized queries (list for positional, dict for named)",
|
295
295
|
),
|
296
296
|
"result_format": NodeParameter(
|
297
297
|
name="result_format",
|
@@ -367,7 +367,7 @@ class SQLDatabaseNode(Node):
|
|
367
367
|
"""
|
368
368
|
# Extract validated inputs
|
369
369
|
query = kwargs.get("query")
|
370
|
-
parameters = kwargs.get("parameters"
|
370
|
+
parameters = kwargs.get("parameters")
|
371
371
|
result_format = kwargs.get("result_format", "dict")
|
372
372
|
user_context = kwargs.get("user_context")
|
373
373
|
|
@@ -757,19 +757,28 @@ class SQLDatabaseNode(Node):
|
|
757
757
|
|
758
758
|
import re
|
759
759
|
|
760
|
-
# Remove potential passwords from error messages
|
760
|
+
# Remove potential passwords from error messages, but be more selective
|
761
761
|
patterns_to_mask = [
|
762
762
|
# Connection string passwords
|
763
763
|
(r"://[^:]+:[^@]+@", "://***:***@"),
|
764
|
-
#
|
765
|
-
(r"'[^']*'", "'***'"),
|
766
|
-
#
|
767
|
-
(
|
764
|
+
# Password fields in SQL (case insensitive)
|
765
|
+
(r"password\s*=\s*['\"][^'\"]*['\"]", "password='***'", re.IGNORECASE),
|
766
|
+
# API keys and tokens in SQL
|
767
|
+
(
|
768
|
+
r"(api_key|token|secret)\s*=\s*['\"][^'\"]*['\"]",
|
769
|
+
r"\1='***'",
|
770
|
+
re.IGNORECASE,
|
771
|
+
),
|
768
772
|
]
|
769
773
|
|
770
774
|
sanitized = error_message
|
771
|
-
for
|
772
|
-
|
775
|
+
for pattern_info in patterns_to_mask:
|
776
|
+
if len(pattern_info) == 3:
|
777
|
+
pattern, replacement, flags = pattern_info
|
778
|
+
sanitized = re.sub(pattern, replacement, sanitized, flags=flags)
|
779
|
+
else:
|
780
|
+
pattern, replacement = pattern_info
|
781
|
+
sanitized = re.sub(pattern, replacement, sanitized)
|
773
782
|
|
774
783
|
return sanitized
|
775
784
|
|