hexdag 0.5.0.dev1__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 (261) hide show
  1. hexdag/__init__.py +116 -0
  2. hexdag/__main__.py +30 -0
  3. hexdag/adapters/executors/__init__.py +5 -0
  4. hexdag/adapters/executors/local_executor.py +316 -0
  5. hexdag/builtin/__init__.py +6 -0
  6. hexdag/builtin/adapters/__init__.py +51 -0
  7. hexdag/builtin/adapters/anthropic/__init__.py +5 -0
  8. hexdag/builtin/adapters/anthropic/anthropic_adapter.py +151 -0
  9. hexdag/builtin/adapters/database/__init__.py +6 -0
  10. hexdag/builtin/adapters/database/csv/csv_adapter.py +249 -0
  11. hexdag/builtin/adapters/database/pgvector/__init__.py +5 -0
  12. hexdag/builtin/adapters/database/pgvector/pgvector_adapter.py +478 -0
  13. hexdag/builtin/adapters/database/sqlalchemy/sqlalchemy_adapter.py +252 -0
  14. hexdag/builtin/adapters/database/sqlite/__init__.py +5 -0
  15. hexdag/builtin/adapters/database/sqlite/sqlite_adapter.py +410 -0
  16. hexdag/builtin/adapters/local/README.md +59 -0
  17. hexdag/builtin/adapters/local/__init__.py +7 -0
  18. hexdag/builtin/adapters/local/local_observer_manager.py +696 -0
  19. hexdag/builtin/adapters/memory/__init__.py +47 -0
  20. hexdag/builtin/adapters/memory/file_memory_adapter.py +297 -0
  21. hexdag/builtin/adapters/memory/in_memory_memory.py +216 -0
  22. hexdag/builtin/adapters/memory/schemas.py +57 -0
  23. hexdag/builtin/adapters/memory/session_memory.py +178 -0
  24. hexdag/builtin/adapters/memory/sqlite_memory_adapter.py +215 -0
  25. hexdag/builtin/adapters/memory/state_memory.py +280 -0
  26. hexdag/builtin/adapters/mock/README.md +89 -0
  27. hexdag/builtin/adapters/mock/__init__.py +15 -0
  28. hexdag/builtin/adapters/mock/hexdag.toml +50 -0
  29. hexdag/builtin/adapters/mock/mock_database.py +225 -0
  30. hexdag/builtin/adapters/mock/mock_embedding.py +223 -0
  31. hexdag/builtin/adapters/mock/mock_llm.py +177 -0
  32. hexdag/builtin/adapters/mock/mock_tool_adapter.py +192 -0
  33. hexdag/builtin/adapters/mock/mock_tool_router.py +232 -0
  34. hexdag/builtin/adapters/openai/__init__.py +5 -0
  35. hexdag/builtin/adapters/openai/openai_adapter.py +634 -0
  36. hexdag/builtin/adapters/secret/__init__.py +7 -0
  37. hexdag/builtin/adapters/secret/local_secret_adapter.py +248 -0
  38. hexdag/builtin/adapters/unified_tool_router.py +280 -0
  39. hexdag/builtin/macros/__init__.py +17 -0
  40. hexdag/builtin/macros/conversation_agent.py +390 -0
  41. hexdag/builtin/macros/llm_macro.py +151 -0
  42. hexdag/builtin/macros/reasoning_agent.py +423 -0
  43. hexdag/builtin/macros/tool_macro.py +380 -0
  44. hexdag/builtin/nodes/__init__.py +38 -0
  45. hexdag/builtin/nodes/_discovery.py +123 -0
  46. hexdag/builtin/nodes/agent_node.py +696 -0
  47. hexdag/builtin/nodes/base_node_factory.py +242 -0
  48. hexdag/builtin/nodes/composite_node.py +926 -0
  49. hexdag/builtin/nodes/data_node.py +201 -0
  50. hexdag/builtin/nodes/expression_node.py +487 -0
  51. hexdag/builtin/nodes/function_node.py +454 -0
  52. hexdag/builtin/nodes/llm_node.py +491 -0
  53. hexdag/builtin/nodes/loop_node.py +920 -0
  54. hexdag/builtin/nodes/mapped_input.py +518 -0
  55. hexdag/builtin/nodes/port_call_node.py +269 -0
  56. hexdag/builtin/nodes/tool_call_node.py +195 -0
  57. hexdag/builtin/nodes/tool_utils.py +390 -0
  58. hexdag/builtin/prompts/__init__.py +68 -0
  59. hexdag/builtin/prompts/base.py +422 -0
  60. hexdag/builtin/prompts/chat_prompts.py +303 -0
  61. hexdag/builtin/prompts/error_correction_prompts.py +320 -0
  62. hexdag/builtin/prompts/tool_prompts.py +160 -0
  63. hexdag/builtin/tools/builtin_tools.py +84 -0
  64. hexdag/builtin/tools/database_tools.py +164 -0
  65. hexdag/cli/__init__.py +17 -0
  66. hexdag/cli/__main__.py +7 -0
  67. hexdag/cli/commands/__init__.py +27 -0
  68. hexdag/cli/commands/build_cmd.py +812 -0
  69. hexdag/cli/commands/create_cmd.py +208 -0
  70. hexdag/cli/commands/docs_cmd.py +293 -0
  71. hexdag/cli/commands/generate_types_cmd.py +252 -0
  72. hexdag/cli/commands/init_cmd.py +188 -0
  73. hexdag/cli/commands/pipeline_cmd.py +494 -0
  74. hexdag/cli/commands/plugin_dev_cmd.py +529 -0
  75. hexdag/cli/commands/plugins_cmd.py +441 -0
  76. hexdag/cli/commands/studio_cmd.py +101 -0
  77. hexdag/cli/commands/validate_cmd.py +221 -0
  78. hexdag/cli/main.py +84 -0
  79. hexdag/core/__init__.py +83 -0
  80. hexdag/core/config/__init__.py +20 -0
  81. hexdag/core/config/loader.py +479 -0
  82. hexdag/core/config/models.py +150 -0
  83. hexdag/core/configurable.py +294 -0
  84. hexdag/core/context/__init__.py +37 -0
  85. hexdag/core/context/execution_context.py +378 -0
  86. hexdag/core/docs/__init__.py +26 -0
  87. hexdag/core/docs/extractors.py +678 -0
  88. hexdag/core/docs/generators.py +890 -0
  89. hexdag/core/docs/models.py +120 -0
  90. hexdag/core/domain/__init__.py +10 -0
  91. hexdag/core/domain/dag.py +1225 -0
  92. hexdag/core/exceptions.py +234 -0
  93. hexdag/core/expression_parser.py +569 -0
  94. hexdag/core/logging.py +449 -0
  95. hexdag/core/models/__init__.py +17 -0
  96. hexdag/core/models/base.py +138 -0
  97. hexdag/core/orchestration/__init__.py +46 -0
  98. hexdag/core/orchestration/body_executor.py +481 -0
  99. hexdag/core/orchestration/components/__init__.py +97 -0
  100. hexdag/core/orchestration/components/adapter_lifecycle_manager.py +113 -0
  101. hexdag/core/orchestration/components/checkpoint_manager.py +134 -0
  102. hexdag/core/orchestration/components/execution_coordinator.py +360 -0
  103. hexdag/core/orchestration/components/health_check_manager.py +176 -0
  104. hexdag/core/orchestration/components/input_mapper.py +143 -0
  105. hexdag/core/orchestration/components/lifecycle_manager.py +583 -0
  106. hexdag/core/orchestration/components/node_executor.py +377 -0
  107. hexdag/core/orchestration/components/secret_manager.py +202 -0
  108. hexdag/core/orchestration/components/wave_executor.py +158 -0
  109. hexdag/core/orchestration/constants.py +17 -0
  110. hexdag/core/orchestration/events/README.md +312 -0
  111. hexdag/core/orchestration/events/__init__.py +104 -0
  112. hexdag/core/orchestration/events/batching.py +330 -0
  113. hexdag/core/orchestration/events/decorators.py +139 -0
  114. hexdag/core/orchestration/events/events.py +573 -0
  115. hexdag/core/orchestration/events/observers/__init__.py +30 -0
  116. hexdag/core/orchestration/events/observers/core_observers.py +690 -0
  117. hexdag/core/orchestration/events/observers/models.py +111 -0
  118. hexdag/core/orchestration/events/taxonomy.py +269 -0
  119. hexdag/core/orchestration/hook_context.py +237 -0
  120. hexdag/core/orchestration/hooks.py +437 -0
  121. hexdag/core/orchestration/models.py +418 -0
  122. hexdag/core/orchestration/orchestrator.py +910 -0
  123. hexdag/core/orchestration/orchestrator_factory.py +275 -0
  124. hexdag/core/orchestration/port_wrappers.py +327 -0
  125. hexdag/core/orchestration/prompt/__init__.py +32 -0
  126. hexdag/core/orchestration/prompt/template.py +332 -0
  127. hexdag/core/pipeline_builder/__init__.py +21 -0
  128. hexdag/core/pipeline_builder/component_instantiator.py +386 -0
  129. hexdag/core/pipeline_builder/include_tag.py +265 -0
  130. hexdag/core/pipeline_builder/pipeline_config.py +133 -0
  131. hexdag/core/pipeline_builder/py_tag.py +223 -0
  132. hexdag/core/pipeline_builder/tag_discovery.py +268 -0
  133. hexdag/core/pipeline_builder/yaml_builder.py +1196 -0
  134. hexdag/core/pipeline_builder/yaml_validator.py +569 -0
  135. hexdag/core/ports/__init__.py +65 -0
  136. hexdag/core/ports/api_call.py +133 -0
  137. hexdag/core/ports/database.py +489 -0
  138. hexdag/core/ports/embedding.py +215 -0
  139. hexdag/core/ports/executor.py +237 -0
  140. hexdag/core/ports/file_storage.py +117 -0
  141. hexdag/core/ports/healthcheck.py +87 -0
  142. hexdag/core/ports/llm.py +551 -0
  143. hexdag/core/ports/memory.py +70 -0
  144. hexdag/core/ports/observer_manager.py +130 -0
  145. hexdag/core/ports/secret.py +145 -0
  146. hexdag/core/ports/tool_router.py +94 -0
  147. hexdag/core/ports_builder.py +623 -0
  148. hexdag/core/protocols.py +273 -0
  149. hexdag/core/resolver.py +304 -0
  150. hexdag/core/schema/__init__.py +9 -0
  151. hexdag/core/schema/generator.py +742 -0
  152. hexdag/core/secrets.py +242 -0
  153. hexdag/core/types.py +413 -0
  154. hexdag/core/utils/async_warnings.py +206 -0
  155. hexdag/core/utils/schema_conversion.py +78 -0
  156. hexdag/core/utils/sql_validation.py +86 -0
  157. hexdag/core/validation/secure_json.py +148 -0
  158. hexdag/core/yaml_macro.py +517 -0
  159. hexdag/mcp_server.py +3120 -0
  160. hexdag/studio/__init__.py +10 -0
  161. hexdag/studio/build_ui.py +92 -0
  162. hexdag/studio/server/__init__.py +1 -0
  163. hexdag/studio/server/main.py +100 -0
  164. hexdag/studio/server/routes/__init__.py +9 -0
  165. hexdag/studio/server/routes/execute.py +208 -0
  166. hexdag/studio/server/routes/export.py +558 -0
  167. hexdag/studio/server/routes/files.py +207 -0
  168. hexdag/studio/server/routes/plugins.py +419 -0
  169. hexdag/studio/server/routes/validate.py +220 -0
  170. hexdag/studio/ui/index.html +13 -0
  171. hexdag/studio/ui/package-lock.json +2992 -0
  172. hexdag/studio/ui/package.json +31 -0
  173. hexdag/studio/ui/postcss.config.js +6 -0
  174. hexdag/studio/ui/public/hexdag.svg +5 -0
  175. hexdag/studio/ui/src/App.tsx +251 -0
  176. hexdag/studio/ui/src/components/Canvas.tsx +408 -0
  177. hexdag/studio/ui/src/components/ContextMenu.tsx +187 -0
  178. hexdag/studio/ui/src/components/FileBrowser.tsx +123 -0
  179. hexdag/studio/ui/src/components/Header.tsx +181 -0
  180. hexdag/studio/ui/src/components/HexdagNode.tsx +193 -0
  181. hexdag/studio/ui/src/components/NodeInspector.tsx +512 -0
  182. hexdag/studio/ui/src/components/NodePalette.tsx +262 -0
  183. hexdag/studio/ui/src/components/NodePortsSection.tsx +403 -0
  184. hexdag/studio/ui/src/components/PluginManager.tsx +347 -0
  185. hexdag/studio/ui/src/components/PortsEditor.tsx +481 -0
  186. hexdag/studio/ui/src/components/PythonEditor.tsx +195 -0
  187. hexdag/studio/ui/src/components/ValidationPanel.tsx +105 -0
  188. hexdag/studio/ui/src/components/YamlEditor.tsx +196 -0
  189. hexdag/studio/ui/src/components/index.ts +8 -0
  190. hexdag/studio/ui/src/index.css +92 -0
  191. hexdag/studio/ui/src/main.tsx +10 -0
  192. hexdag/studio/ui/src/types/index.ts +123 -0
  193. hexdag/studio/ui/src/vite-env.d.ts +1 -0
  194. hexdag/studio/ui/tailwind.config.js +29 -0
  195. hexdag/studio/ui/tsconfig.json +37 -0
  196. hexdag/studio/ui/tsconfig.node.json +13 -0
  197. hexdag/studio/ui/vite.config.ts +35 -0
  198. hexdag/visualization/__init__.py +69 -0
  199. hexdag/visualization/dag_visualizer.py +1020 -0
  200. hexdag-0.5.0.dev1.dist-info/METADATA +369 -0
  201. hexdag-0.5.0.dev1.dist-info/RECORD +261 -0
  202. hexdag-0.5.0.dev1.dist-info/WHEEL +4 -0
  203. hexdag-0.5.0.dev1.dist-info/entry_points.txt +4 -0
  204. hexdag-0.5.0.dev1.dist-info/licenses/LICENSE +190 -0
  205. hexdag_plugins/.gitignore +43 -0
  206. hexdag_plugins/README.md +73 -0
  207. hexdag_plugins/__init__.py +1 -0
  208. hexdag_plugins/azure/LICENSE +21 -0
  209. hexdag_plugins/azure/README.md +414 -0
  210. hexdag_plugins/azure/__init__.py +21 -0
  211. hexdag_plugins/azure/azure_blob_adapter.py +450 -0
  212. hexdag_plugins/azure/azure_cosmos_adapter.py +383 -0
  213. hexdag_plugins/azure/azure_keyvault_adapter.py +314 -0
  214. hexdag_plugins/azure/azure_openai_adapter.py +415 -0
  215. hexdag_plugins/azure/pyproject.toml +107 -0
  216. hexdag_plugins/azure/tests/__init__.py +1 -0
  217. hexdag_plugins/azure/tests/test_azure_blob_adapter.py +350 -0
  218. hexdag_plugins/azure/tests/test_azure_cosmos_adapter.py +323 -0
  219. hexdag_plugins/azure/tests/test_azure_keyvault_adapter.py +330 -0
  220. hexdag_plugins/azure/tests/test_azure_openai_adapter.py +329 -0
  221. hexdag_plugins/hexdag_etl/README.md +168 -0
  222. hexdag_plugins/hexdag_etl/__init__.py +53 -0
  223. hexdag_plugins/hexdag_etl/examples/01_simple_pandas_transform.py +270 -0
  224. hexdag_plugins/hexdag_etl/examples/02_simple_pandas_only.py +149 -0
  225. hexdag_plugins/hexdag_etl/examples/03_file_io_pipeline.py +109 -0
  226. hexdag_plugins/hexdag_etl/examples/test_pandas_transform.py +84 -0
  227. hexdag_plugins/hexdag_etl/hexdag.toml +25 -0
  228. hexdag_plugins/hexdag_etl/hexdag_etl/__init__.py +48 -0
  229. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/__init__.py +13 -0
  230. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/api_extract.py +230 -0
  231. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/base_node_factory.py +181 -0
  232. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/file_io.py +415 -0
  233. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/outlook.py +492 -0
  234. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/pandas_transform.py +563 -0
  235. hexdag_plugins/hexdag_etl/hexdag_etl/nodes/sql_extract_load.py +112 -0
  236. hexdag_plugins/hexdag_etl/pyproject.toml +82 -0
  237. hexdag_plugins/hexdag_etl/test_transform.py +54 -0
  238. hexdag_plugins/hexdag_etl/tests/test_plugin_integration.py +62 -0
  239. hexdag_plugins/mysql_adapter/LICENSE +21 -0
  240. hexdag_plugins/mysql_adapter/README.md +224 -0
  241. hexdag_plugins/mysql_adapter/__init__.py +6 -0
  242. hexdag_plugins/mysql_adapter/mysql_adapter.py +408 -0
  243. hexdag_plugins/mysql_adapter/pyproject.toml +93 -0
  244. hexdag_plugins/mysql_adapter/tests/test_mysql_adapter.py +259 -0
  245. hexdag_plugins/storage/README.md +184 -0
  246. hexdag_plugins/storage/__init__.py +19 -0
  247. hexdag_plugins/storage/file/__init__.py +5 -0
  248. hexdag_plugins/storage/file/local.py +325 -0
  249. hexdag_plugins/storage/ports/__init__.py +5 -0
  250. hexdag_plugins/storage/ports/vector_store.py +236 -0
  251. hexdag_plugins/storage/sql/__init__.py +7 -0
  252. hexdag_plugins/storage/sql/base.py +187 -0
  253. hexdag_plugins/storage/sql/mysql.py +27 -0
  254. hexdag_plugins/storage/sql/postgresql.py +27 -0
  255. hexdag_plugins/storage/tests/__init__.py +1 -0
  256. hexdag_plugins/storage/tests/test_local_file_storage.py +161 -0
  257. hexdag_plugins/storage/tests/test_sql_adapters.py +212 -0
  258. hexdag_plugins/storage/vector/__init__.py +7 -0
  259. hexdag_plugins/storage/vector/chromadb.py +223 -0
  260. hexdag_plugins/storage/vector/in_memory.py +285 -0
  261. hexdag_plugins/storage/vector/pgvector.py +502 -0
@@ -0,0 +1,82 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "hexdag-etl"
7
+ version = "0.1.0"
8
+ description = "ETL infrastructure for hexDAG pipelines"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ authors = [{ name = "hexDAG Team" }]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3.12",
17
+ ]
18
+ keywords = ["etl", "data-pipeline", "hexdag", "plugin"]
19
+ requires-python = ">=3.12"
20
+ dependencies = [
21
+ "pandas>=2.0.0",
22
+ "aiohttp>=3.8.0",
23
+ "hexdag", # <-- plain dependency name
24
+ ]
25
+
26
+ [project.optional-dependencies]
27
+ dev = [
28
+ "pytest>=7.0.0",
29
+ "pytest-asyncio>=0.21.0",
30
+ "pytest-cov>=4.0.0",
31
+ "ruff>=0.1.0",
32
+ "mypy>=1.0.0",
33
+ ]
34
+
35
+ [tool.hatch.metadata]
36
+ allow-direct-references = true # now harmless but not strictly needed
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["hexdag_etl"]
40
+
41
+ [tool.hatch.build.targets.sdist]
42
+ include = ["/hexdag_etl", "/tests", "/examples", "/README.md"]
43
+
44
+ [tool.uv.sources]
45
+ hexdag = { path = "../.." } # <-- tell uv to take hexdag from repo root
46
+
47
+ [tool.ruff]
48
+ target-version = "py312"
49
+ line-length = 120
50
+
51
+ [tool.ruff.lint]
52
+ select = [
53
+ "E", # pycodestyle errors
54
+ "W", # pycodestyle warnings
55
+ "F", # pyflakes
56
+ "I", # isort
57
+ "UP", # pyupgrade
58
+ ]
59
+ ignore = [
60
+ "E501", # line too long
61
+ "SIM105", # contextlib.suppress doesn't work with async
62
+ "E402", # module import not at top of file (test files)
63
+ ]
64
+
65
+ [tool.mypy]
66
+ python_version = "3.12"
67
+ warn_return_any = true
68
+ warn_unused_configs = true
69
+ disallow_untyped_defs = true
70
+ disallow_incomplete_defs = true
71
+ check_untyped_defs = true
72
+ disallow_untyped_decorators = true
73
+ no_implicit_optional = true
74
+ warn_redundant_casts = true
75
+ warn_unused_ignores = true
76
+ warn_no_return = true
77
+ warn_unreachable = true
78
+ strict_equality = true
79
+
80
+ [[tool.mypy.overrides]]
81
+ module = "tests.*"
82
+ disallow_untyped_defs = false
@@ -0,0 +1,54 @@
1
+ """Test the pandas transform step by step."""
2
+
3
+ import sys
4
+
5
+ sys.path.insert(0, "/Users/jankwapisz/Documents/Praca/Omniviser/hexdag")
6
+ sys.path.insert(0, "/Users/jankwapisz/Documents/Praca/Omniviser/hexdag/hexdag_plugins")
7
+
8
+ import pandas as pd
9
+
10
+ from hexdag_etl.nodes.pandas_transform import PandasTransformNode
11
+
12
+ # Create the node
13
+ node_factory = PandasTransformNode()
14
+
15
+ # Build operations
16
+ operations = [
17
+ {"type": "transform", "method": "pandas.DataFrame.sort_values", "kwargs": {"by": "amount", "ascending": False}},
18
+ {
19
+ "type": "transform",
20
+ "method": "pandas.DataFrame.assign",
21
+ "kwargs": {"amount_doubled": "{{ lambda df: df['amount'] * 2 }}"},
22
+ },
23
+ {"type": "transform", "method": "pandas.DataFrame.head", "args": [3]},
24
+ ]
25
+
26
+ # Create node spec
27
+ node_spec = node_factory(name="test_transform", operations=operations)
28
+
29
+ # Test input
30
+ df = pd.DataFrame(
31
+ {
32
+ "customer_id": ["C001", "C002", "C003", "C004", "C005"],
33
+ "name": ["Alice", "Bob", "Carol", "David", "Emma"],
34
+ "amount": [150.0, 299.99, 150.0, 29.99, 299.99],
35
+ "category": ["A", "B", "A", "C", "B"],
36
+ }
37
+ )
38
+
39
+ print("Input DataFrame:")
40
+ print(df)
41
+ print()
42
+
43
+ # Try to run the function
44
+ import asyncio
45
+
46
+
47
+ async def test():
48
+ result = await node_spec.fn({"data": df})
49
+ print("Output:")
50
+ print(result)
51
+ return result
52
+
53
+
54
+ asyncio.run(test())
@@ -0,0 +1,62 @@
1
+ """Test hexDAG ETL plugin integration."""
2
+
3
+ from hexdag.core.domain.dag import NodeSpec
4
+ from hexdag.core.registry import registry
5
+
6
+
7
+ def test_plugin_components_registered():
8
+ """Test that all ETL plugin components are properly registered."""
9
+
10
+ # Test artifact storage adapter
11
+ artifact_adapter = registry.get("local", namespace="etl")
12
+ assert artifact_adapter is not None, "Local artifact adapter should be registered"
13
+
14
+ # Test nodes
15
+
16
+ # Note: Nodes are factory classes, not directly in registry like adapters
17
+ # They're registered as node factories that create NodeSpecs
18
+ pandas_transform_factory = registry.get("pandas_transform", namespace="etl")
19
+ assert pandas_transform_factory is not None, "Pandas transform node should be registered"
20
+
21
+ api_extract_factory = registry.get("api_extract", namespace="etl")
22
+ assert api_extract_factory is not None, "API extract node should be registered"
23
+
24
+ sql_extract_factory = registry.get("sql_extract", namespace="etl")
25
+ assert sql_extract_factory is not None, "SQL extract node should be registered"
26
+
27
+ sql_load_factory = registry.get("sql_load", namespace="etl")
28
+ assert sql_load_factory is not None, "SQL load node should be registered"
29
+
30
+
31
+ def test_artifact_adapter_instantiation():
32
+ """Test that artifact adapter can be instantiated."""
33
+ from hexdag.core.registry import registry
34
+
35
+ adapter_cls = registry.get("local", namespace="etl")
36
+ assert adapter_cls is not None
37
+
38
+ adapter = adapter_cls(base_path="/tmp/test_artifacts")
39
+ assert adapter is not None
40
+ assert hasattr(adapter, "write")
41
+ assert hasattr(adapter, "read")
42
+ assert hasattr(adapter, "list")
43
+
44
+
45
+ def test_pandas_transform_node_creation():
46
+ """Test that pandas transform node can be created."""
47
+ from hexdag.core.registry import registry
48
+
49
+ factory_cls = registry.get("pandas_transform", namespace="etl")
50
+ assert factory_cls is not None
51
+
52
+ factory = factory_cls()
53
+
54
+ # Create a simple node spec
55
+ node_spec = factory(
56
+ name="test_transform",
57
+ operations=[{"type": "transform", "method": "pandas.DataFrame.head", "kwargs": {"n": 5}}],
58
+ )
59
+
60
+ assert isinstance(node_spec, NodeSpec)
61
+ assert node_spec.name == "test_transform"
62
+ assert "operations" in node_spec.params
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 HexDAG Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,224 @@
1
+ # HexDAG MySQL Adapter
2
+
3
+ A production-ready MySQL database adapter plugin for the hexDAG framework.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Production-Ready**: Built for high-performance production deployments
8
+ - 📦 **JSON Document Storage**: Leverage MySQL's native JSON support
9
+ - 🔄 **Async Operations**: Full async/await support for all operations
10
+ - 🔒 **Transaction Support**: ACID compliance with proper transaction handling
11
+ - 🎯 **Type-Safe**: Full type hints and Pydantic validation
12
+ - 🔌 **Plugin Architecture**: Seamlessly integrates with hexDAG's plugin system
13
+
14
+ ## Installation
15
+
16
+ ### Local Development
17
+
18
+ For local development within the hexDAG project:
19
+
20
+ ```bash
21
+ # Using uv (recommended for hexDAG development)
22
+ uv pip install -e hexdag_plugins/mysql_adapter/
23
+
24
+ # Or using pip
25
+ uv pip install -e hexdag_plugins/mysql_adapter/
26
+ ```
27
+
28
+ ### With development dependencies
29
+
30
+ ```bash
31
+ pip install -e "hexdag_plugins/mysql_adapter/[dev]"
32
+ ```
33
+
34
+ ## Configuration
35
+
36
+ ### Environment Variables
37
+
38
+ Set these environment variables for default connection:
39
+
40
+ ```bash
41
+ export MYSQL_HOST=localhost
42
+ export MYSQL_PORT=3306
43
+ export MYSQL_USER=your_user
44
+ export MYSQL_PASSWORD=your_password
45
+ export MYSQL_DATABASE=hexdag
46
+ ```
47
+
48
+ ### Programmatic Configuration
49
+
50
+ ```python
51
+ from hexdag_plugins.mysql_adapter import MySQLAdapter
52
+
53
+ adapter = MySQLAdapter(
54
+ host="your-mysql-host",
55
+ port=3306,
56
+ user="your-user",
57
+ password="your-password",
58
+ database="hexdag",
59
+ charset="utf8mb4"
60
+ )
61
+ ```
62
+
63
+ ## Usage
64
+
65
+ ### Basic Operations
66
+
67
+ ```python
68
+ import asyncio
69
+ from hexdag_plugins.mysql_adapter import MySQLAdapter
70
+
71
+ async def main():
72
+ # Initialize adapter
73
+ adapter = MySQLAdapter(
74
+ host="localhost",
75
+ user="root",
76
+ password="password",
77
+ database="hexdag"
78
+ )
79
+
80
+ # Insert document
81
+ doc_id = await adapter.ainsert("users", {
82
+ "name": "John Doe",
83
+ "email": "john@example.com",
84
+ "metadata": {
85
+ "role": "admin",
86
+ "permissions": ["read", "write", "delete"]
87
+ }
88
+ })
89
+
90
+ # Query documents
91
+ users = await adapter.aquery(
92
+ "users",
93
+ filter={"metadata.role": "admin"}
94
+ )
95
+
96
+ # Update document
97
+ await adapter.aupdate("users", doc_id, {
98
+ "last_login": "2024-01-01T12:00:00Z"
99
+ })
100
+
101
+ # Delete document
102
+ await adapter.adelete("users", doc_id)
103
+
104
+ asyncio.run(main())
105
+ ```
106
+
107
+ ### Integration with hexDAG
108
+
109
+ The adapter automatically registers with hexDAG's registry system:
110
+
111
+ ```python
112
+ from hexdag.core.bootstrap import bootstrap_registry
113
+ from hexdag.core.registry import registry
114
+
115
+ # Bootstrap with MySQL plugin
116
+ bootstrap_registry()
117
+
118
+ # Get MySQL adapter from registry
119
+ mysql_info = registry.get_info("mysql", namespace="plugin")
120
+ adapter = mysql_info.get_instance(
121
+ host="localhost",
122
+ user="root",
123
+ password="password"
124
+ )
125
+ ```
126
+
127
+ ## Database Schema
128
+
129
+ The adapter creates a flexible document store schema:
130
+
131
+ ```sql
132
+ CREATE TABLE hexdag_documents (
133
+ id VARCHAR(255) PRIMARY KEY,
134
+ collection VARCHAR(255) NOT NULL,
135
+ document JSON NOT NULL,
136
+ metadata JSON,
137
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
138
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
139
+ INDEX idx_collection (collection),
140
+ INDEX idx_created (created_at),
141
+ INDEX idx_updated (updated_at)
142
+ );
143
+ ```
144
+
145
+ ## Advanced Features
146
+
147
+ ### JSON Path Queries
148
+
149
+ Leverage MySQL's JSON functions for complex queries:
150
+
151
+ ```python
152
+ # Query nested JSON fields
153
+ results = await adapter.aquery(
154
+ "products",
155
+ filter={
156
+ "specs.memory": "16GB",
157
+ "price": {"$lt": 1000}
158
+ }
159
+ )
160
+ ```
161
+
162
+ ### Concurrent Operations
163
+
164
+ The adapter supports concurrent operations safely:
165
+
166
+ ```python
167
+ import asyncio
168
+
169
+ async def bulk_insert(adapter, collection, documents):
170
+ tasks = [
171
+ adapter.ainsert(collection, doc)
172
+ for doc in documents
173
+ ]
174
+ return await asyncio.gather(*tasks)
175
+ ```
176
+
177
+ ### Connection Pooling
178
+
179
+ The adapter uses PyMySQL with connection management for optimal performance.
180
+
181
+ ## Testing
182
+
183
+ ### Run Tests
184
+
185
+ ```bash
186
+ pytest tests/
187
+ ```
188
+
189
+ ### Test with Docker MySQL
190
+
191
+ ```bash
192
+ # Start MySQL container
193
+ docker run -d \
194
+ --name mysql-test \
195
+ -e MYSQL_ROOT_PASSWORD=test \
196
+ -e MYSQL_DATABASE=hexdag_test \
197
+ -p 3306:3306 \
198
+ mysql:8.0
199
+
200
+ # Run tests
201
+ MYSQL_TEST_HOST=localhost \
202
+ MYSQL_TEST_USER=root \
203
+ MYSQL_TEST_PASSWORD=test \
204
+ MYSQL_TEST_DATABASE=hexdag_test \
205
+ pytest tests/
206
+ ```
207
+
208
+ ## Requirements
209
+
210
+ - Python 3.12+
211
+ - MySQL 5.7+ (8.0+ recommended for full JSON support)
212
+ - PyMySQL 1.1.0+
213
+
214
+ ## License
215
+
216
+ MIT License - see LICENSE file for details.
217
+
218
+ ## Contributing
219
+
220
+ Contributions are welcome! Please feel free to submit a Pull Request.
221
+
222
+ ## Support
223
+
224
+ For issues and questions, please use the GitHub issue tracker.
@@ -0,0 +1,6 @@
1
+ """MySQL adapter plugin for hexDAG framework."""
2
+
3
+ from hexdag_plugins.mysql_adapter.mysql_adapter import MySQLAdapter
4
+
5
+ __version__ = "1.0.0"
6
+ __all__ = ["MySQLAdapter"]