nld-core 0.1.1a1__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 (467) hide show
  1. nld/business/__init__.py +16 -0
  2. nld/business/dictionary.py +37 -0
  3. nld/business/lookup.py +146 -0
  4. nld/business/task/__init__.py +5 -0
  5. nld/business/task/business_dictionary_find_task.py +112 -0
  6. nld/cli/business/__init__.py +0 -0
  7. nld/cli/business/main_business.py +47 -0
  8. nld/cli/business/params_business.py +54 -0
  9. nld/cli/cli_events.py +28 -0
  10. nld/cli/cli_exceptions.py +9 -0
  11. nld/cli/cli_utils.py +24 -0
  12. nld/cli/connection/main_connection.py +69 -0
  13. nld/cli/connection/params_connection.py +25 -0
  14. nld/cli/flow/main_flow.py +190 -0
  15. nld/cli/flow/params_flow.py +352 -0
  16. nld/cli/flow/requires_flow.py +300 -0
  17. nld/cli/flow/state_flow.py +187 -0
  18. nld/cli/main.py +75 -0
  19. nld/cli/params.py +85 -0
  20. nld/cli/project/main_project.py +41 -0
  21. nld/cli/project/params_project.py +18 -0
  22. nld/cli/requires.py +140 -0
  23. nld/cli/requires_wrapper.py +56 -0
  24. nld/cli/sql/__init__.py +0 -0
  25. nld/cli/sql/main_sql.py +35 -0
  26. nld/cli/sql/params_sql.py +22 -0
  27. nld/cli/structure/main_structure.py +112 -0
  28. nld/cli/structure/params_structure.py +109 -0
  29. nld/cli/utils/execution_params_def_utils.py +25 -0
  30. nld/cli/utils/mutually_exclusive_option.py +98 -0
  31. nld/connector/azure_blob_storage/__init__.py +27 -0
  32. nld/connector/azure_blob_storage/azure_blob_storage_connection.py +44 -0
  33. nld/connector/azure_blob_storage/azure_blob_storage_connector.py +99 -0
  34. nld/connector/azure_blob_storage/azure_blob_storage_credential.py +23 -0
  35. nld/connector/azure_blob_storage/azure_blob_storage_utils.py +64 -0
  36. nld/connector/base/__init__.py +72 -0
  37. nld/connector/base/config.py +171 -0
  38. nld/connector/base/config_default.py +37 -0
  39. nld/connector/base/config_loader.py +123 -0
  40. nld/connector/base/config_source.py +288 -0
  41. nld/connector/base/connection.py +96 -0
  42. nld/connector/base/connector.py +628 -0
  43. nld/connector/base/credential.py +82 -0
  44. nld/connector/base/events.py +80 -0
  45. nld/connector/base/exceptions.py +84 -0
  46. nld/connector/base/plugin.py +61 -0
  47. nld/connector/base/query.py +483 -0
  48. nld/connector/base/query_exec_result_formatter.py +197 -0
  49. nld/connector/base/sql.py +25 -0
  50. nld/connector/base/structure_reader.py +73 -0
  51. nld/connector/bigquery/__init__.py +30 -0
  52. nld/connector/bigquery/bigquery_connection.py +73 -0
  53. nld/connector/bigquery/bigquery_connector.py +921 -0
  54. nld/connector/bigquery/bigquery_credential.py +29 -0
  55. nld/connector/bigquery/bigquery_data_type.py +20 -0
  56. nld/connector/bigquery/bigquery_structure.py +19 -0
  57. nld/connector/bigquery/pydantic/__init__.py +7 -0
  58. nld/connector/bigquery/pydantic/model_manager.py +431 -0
  59. nld/connector/bigquery/pydantic/structure_mapper.py +178 -0
  60. nld/connector/bigquery/query_wrapper.py +40 -0
  61. nld/connector/bigquery/service/__init__.py +7 -0
  62. nld/connector/bigquery/service/structure_diff_ddl_generator.py +208 -0
  63. nld/connector/bigquery/service/structure_reader.py +277 -0
  64. nld/connector/bigquery/sqlglot/__init__.py +7 -0
  65. nld/connector/bigquery/sqlglot/ddl.py +181 -0
  66. nld/connector/bigquery/sqlglot/dml.py +13 -0
  67. nld/connector/duckdb/__init__.py +46 -0
  68. nld/connector/duckdb/constants.py +3 -0
  69. nld/connector/duckdb/duckdb_credential.py +16 -0
  70. nld/connector/duckdb/duckdb_data_type.py +53 -0
  71. nld/connector/duckdb/duckdb_engine.py +262 -0
  72. nld/connector/duckdb/duckdb_structure.py +19 -0
  73. nld/connector/duckdb/engine/__init__.py +0 -0
  74. nld/connector/duckdb/engine/duckdb_native/__init__.py +0 -0
  75. nld/connector/duckdb/engine/duckdb_native/adapter/__init__.py +0 -0
  76. nld/connector/duckdb/engine/duckdb_native/adapter/pydantic/__init__.py +7 -0
  77. nld/connector/duckdb/engine/duckdb_native/adapter/pydantic/model_manager.py +333 -0
  78. nld/connector/duckdb/engine/duckdb_native/adapter/pydantic/structure_mapper.py +209 -0
  79. nld/connector/duckdb/engine/duckdb_native/connection.py +95 -0
  80. nld/connector/duckdb/engine/duckdb_native/connector.py +627 -0
  81. nld/connector/duckdb/engine/duckdb_native/query_wrapper.py +92 -0
  82. nld/connector/duckdb/engine/duckdb_native/utils.py +107 -0
  83. nld/connector/duckdb/service/__init__.py +7 -0
  84. nld/connector/duckdb/service/structure_diff_ddl_generator.py +462 -0
  85. nld/connector/duckdb/service/structure_reader.py +543 -0
  86. nld/connector/duckdb/sqlglot/__init__.py +7 -0
  87. nld/connector/duckdb/sqlglot/ddl.py +74 -0
  88. nld/connector/duckdb/sqlglot/dml.py +57 -0
  89. nld/connector/local/__init__.py +17 -0
  90. nld/connector/local/local_connection.py +23 -0
  91. nld/connector/local/local_connector.py +80 -0
  92. nld/connector/local/local_credential.py +12 -0
  93. nld/connector/local/local_utils.py +1 -0
  94. nld/connector/manager/__init__.py +6 -0
  95. nld/connector/manager/events.py +37 -0
  96. nld/connector/manager/factory.py +189 -0
  97. nld/connector/manager/manager.py +49 -0
  98. nld/connector/postgresql/__init__.py +42 -0
  99. nld/connector/postgresql/engine/psycopg2/__init__.py +11 -0
  100. nld/connector/postgresql/engine/psycopg2/adapter/__init__.py +0 -0
  101. nld/connector/postgresql/engine/psycopg2/adapter/pandas/__init__.py +11 -0
  102. nld/connector/postgresql/engine/psycopg2/adapter/pandas/dataframe_manager.py +101 -0
  103. nld/connector/postgresql/engine/psycopg2/adapter/pandas/structure_mapper.py +34 -0
  104. nld/connector/postgresql/engine/psycopg2/adapter/pydantic/__init__.py +11 -0
  105. nld/connector/postgresql/engine/psycopg2/adapter/pydantic/model_manager.py +576 -0
  106. nld/connector/postgresql/engine/psycopg2/adapter/pydantic/structure_mapper.py +247 -0
  107. nld/connector/postgresql/engine/psycopg2/connection.py +89 -0
  108. nld/connector/postgresql/engine/psycopg2/connector.py +790 -0
  109. nld/connector/postgresql/engine/psycopg2/query_wrapper.py +42 -0
  110. nld/connector/postgresql/engine/psycopg2/utils.py +123 -0
  111. nld/connector/postgresql/postgresql_credential.py +34 -0
  112. nld/connector/postgresql/postgresql_data_type.py +51 -0
  113. nld/connector/postgresql/postgresql_structure.py +19 -0
  114. nld/connector/postgresql/service/__init__.py +7 -0
  115. nld/connector/postgresql/service/structure_diff_ddl_generator.py +439 -0
  116. nld/connector/postgresql/service/structure_reader.py +577 -0
  117. nld/connector/postgresql/sqlglot/__init__.py +7 -0
  118. nld/connector/postgresql/sqlglot/ddl.py +13 -0
  119. nld/connector/postgresql/sqlglot/dml.py +13 -0
  120. nld/connector/s3_blob_storage/__init__.py +29 -0
  121. nld/connector/s3_blob_storage/s3_object_storage_connection.py +102 -0
  122. nld/connector/s3_blob_storage/s3_object_storage_connector.py +262 -0
  123. nld/connector/s3_blob_storage/s3_object_storage_credential.py +23 -0
  124. nld/connector/s3_blob_storage/s3_object_storage_utils.py +556 -0
  125. nld/connector/s3_blob_storage/s3_structure.py +41 -0
  126. nld/connector/s3_blob_storage/s3_utils.py +1 -0
  127. nld/connector/snowflake/__init__.py +29 -0
  128. nld/connector/snowflake/pydantic/__init__.py +7 -0
  129. nld/connector/snowflake/pydantic/model_manager.py +344 -0
  130. nld/connector/snowflake/pydantic/structure_mapper.py +170 -0
  131. nld/connector/snowflake/query_wrapper.py +43 -0
  132. nld/connector/snowflake/service/__init__.py +7 -0
  133. nld/connector/snowflake/service/structure_diff_ddl_generator.py +339 -0
  134. nld/connector/snowflake/service/structure_reader.py +135 -0
  135. nld/connector/snowflake/snowflake_connection.py +111 -0
  136. nld/connector/snowflake/snowflake_connector.py +653 -0
  137. nld/connector/snowflake/snowflake_credential.py +43 -0
  138. nld/connector/snowflake/snowflake_data_type.py +18 -0
  139. nld/connector/snowflake/snowflake_utils.py +107 -0
  140. nld/connector/snowflake/sqlglot/__init__.py +7 -0
  141. nld/connector/snowflake/sqlglot/ddl.py +213 -0
  142. nld/connector/snowflake/sqlglot/dml.py +56 -0
  143. nld/connector/task/__init__.py +13 -0
  144. nld/connector/task/connection_debug.py +47 -0
  145. nld/connector/task/connection_export_env_var.py +105 -0
  146. nld/connector/task/connection_get_structure.py +158 -0
  147. nld/connector/task/connection_list.py +51 -0
  148. nld/engine/__init__.py +1 -0
  149. nld/engine/pyarrow/__init__.py +11 -0
  150. nld/engine/pyarrow/pydantic_structure_mapper.py +181 -0
  151. nld/engine/pyarrow/utils.py +158 -0
  152. nld/exceptions.py +184 -0
  153. nld/flow/__init__.py +25 -0
  154. nld/flow/backend/__init__.py +5 -0
  155. nld/flow/backend/bigquery/__init__.py +0 -0
  156. nld/flow/backend/bigquery/backend_mixin.py +37 -0
  157. nld/flow/backend/bigquery/utils.py +6 -0
  158. nld/flow/backend/duckdb/__init__.py +3 -0
  159. nld/flow/backend/duckdb/backend_mixin.py +37 -0
  160. nld/flow/backend/duckdb/utils.py +6 -0
  161. nld/flow/backend/local/__init__.py +3 -0
  162. nld/flow/backend/local/backend_mixin.py +62 -0
  163. nld/flow/backend/postgresql/__init__.py +5 -0
  164. nld/flow/backend/postgresql/backend_mixin.py +33 -0
  165. nld/flow/backend/postgresql/utils.py +6 -0
  166. nld/flow/backend/s3_blob_storage/__init__.py +5 -0
  167. nld/flow/backend/s3_blob_storage/backend_mixin.py +115 -0
  168. nld/flow/backend/snowflake/__init__.py +0 -0
  169. nld/flow/backend/snowflake/backend_mixin.py +29 -0
  170. nld/flow/backend/snowflake/utils.py +6 -0
  171. nld/flow/backend/utils.py +8 -0
  172. nld/flow/config/__init__.py +7 -0
  173. nld/flow/config/flow_config.py +94 -0
  174. nld/flow/definition/__init__.py +21 -0
  175. nld/flow/definition/field_lineage.py +97 -0
  176. nld/flow/definition/flow_definition.py +724 -0
  177. nld/flow/definition/sql_config.py +28 -0
  178. nld/flow/deploy/__init__.py +54 -0
  179. nld/flow/deploy/flow_definition_hash.py +154 -0
  180. nld/flow/deploy/flow_deploy_diff.py +17 -0
  181. nld/flow/deploy/flow_deploy_executor.py +1006 -0
  182. nld/flow/deploy/flow_deploy_manifest.py +67 -0
  183. nld/flow/deploy/flow_deploy_metadata_manager.py +333 -0
  184. nld/flow/deploy/flow_deploy_metadata_models.py +100 -0
  185. nld/flow/deploy/flow_deploy_planner.py +599 -0
  186. nld/flow/deploy/flow_manifest_discovery.py +38 -0
  187. nld/flow/events.py +26 -0
  188. nld/flow/exceptions.py +65 -0
  189. nld/flow/execution/__init__.py +24 -0
  190. nld/flow/execution/backend/bigquery_with_pydantic.py +228 -0
  191. nld/flow/execution/backend/duckdb_with_pydantic.py +233 -0
  192. nld/flow/execution/backend/local_with_duckdb.py +330 -0
  193. nld/flow/execution/backend/local_with_pydantic.py +140 -0
  194. nld/flow/execution/backend/migrations/s3_blob_storage_to_parquet.py +224 -0
  195. nld/flow/execution/backend/postgresql_with_pydantic.py +331 -0
  196. nld/flow/execution/backend/s3_blob_storage_base.py +20 -0
  197. nld/flow/execution/backend/s3_blob_storage_with_duckdb.py +378 -0
  198. nld/flow/execution/backend/s3_blob_storage_with_pydantic.py +388 -0
  199. nld/flow/execution/backend/snowflake_with_pydantic.py +228 -0
  200. nld/flow/execution/batch_execution_info.py +39 -0
  201. nld/flow/execution/decorator.py +116 -0
  202. nld/flow/execution/events.py +73 -0
  203. nld/flow/execution/execution_info.py +215 -0
  204. nld/flow/execution/factory.py +288 -0
  205. nld/flow/execution/manager.py +522 -0
  206. nld/flow/execution/schema.py +55 -0
  207. nld/flow/execution/utils.py +4 -0
  208. nld/flow/graph/__init__.py +25 -0
  209. nld/flow/graph/data_flow_graph.py +436 -0
  210. nld/flow/graph/scoped_data_flow_graph.py +78 -0
  211. nld/flow/graph/serializers.py +125 -0
  212. nld/flow/incremental/__init__.py +0 -0
  213. nld/flow/incremental/backend/__init__.py +0 -0
  214. nld/flow/incremental/backend/plan.py +97 -0
  215. nld/flow/incremental/backend/postgresql/__init__.py +9 -0
  216. nld/flow/incremental/backend/postgresql/backend_mixin.py +128 -0
  217. nld/flow/incremental/backend/s3_blob_storage/__init__.py +15 -0
  218. nld/flow/incremental/backend/s3_blob_storage/backend_mixin.py +234 -0
  219. nld/flow/incremental/backend/s3_blob_storage/schema.py +13 -0
  220. nld/flow/incremental/base/__init__.py +11 -0
  221. nld/flow/incremental/base/manager.py +758 -0
  222. nld/flow/incremental/base/sql_filter_manager.py +21 -0
  223. nld/flow/incremental/impl/__init__.py +39 -0
  224. nld/flow/incremental/impl/by_key/__init__.py +33 -0
  225. nld/flow/incremental/impl/by_key/backend/base_with_duckdb.py +19 -0
  226. nld/flow/incremental/impl/by_key/backend/base_with_pydantic.py +26 -0
  227. nld/flow/incremental/impl/by_key/backend/bigquery_with_pydantic.py +328 -0
  228. nld/flow/incremental/impl/by_key/backend/duckdb_with_pydantic.py +327 -0
  229. nld/flow/incremental/impl/by_key/backend/local_with_duckdb.py +252 -0
  230. nld/flow/incremental/impl/by_key/backend/local_with_pydantic.py +220 -0
  231. nld/flow/incremental/impl/by_key/backend/postgresql_with_pydantic.py +538 -0
  232. nld/flow/incremental/impl/by_key/backend/s3_blob_storage_base.py +237 -0
  233. nld/flow/incremental/impl/by_key/backend/s3_blob_storage_with_duckdb.py +297 -0
  234. nld/flow/incremental/impl/by_key/backend/s3_blob_storage_with_pydantic.py +258 -0
  235. nld/flow/incremental/impl/by_key/logic.py +168 -0
  236. nld/flow/incremental/impl/by_key/manager.py +301 -0
  237. nld/flow/incremental/impl/by_key/schema.py +35 -0
  238. nld/flow/incremental/impl/by_key/sql_filter_manager.py +88 -0
  239. nld/flow/incremental/impl/by_key/state.py +162 -0
  240. nld/flow/incremental/impl/by_source_tst/__init__.py +27 -0
  241. nld/flow/incremental/impl/by_source_tst/backend/__init__.py +0 -0
  242. nld/flow/incremental/impl/by_source_tst/backend/base_with_pydantic.py +26 -0
  243. nld/flow/incremental/impl/by_source_tst/backend/bigquery_with_pydantic.py +216 -0
  244. nld/flow/incremental/impl/by_source_tst/backend/duckdb_with_pydantic.py +215 -0
  245. nld/flow/incremental/impl/by_source_tst/backend/local_with_pydantic.py +114 -0
  246. nld/flow/incremental/impl/by_source_tst/backend/postgresql_with_pydantic.py +387 -0
  247. nld/flow/incremental/impl/by_source_tst/backend/snowflake_with_pydantic.py +216 -0
  248. nld/flow/incremental/impl/by_source_tst/logic.py +143 -0
  249. nld/flow/incremental/impl/by_source_tst/manager.py +165 -0
  250. nld/flow/incremental/impl/by_source_tst/sql_filter_manager.py +81 -0
  251. nld/flow/incremental/impl/by_source_tst/state.py +98 -0
  252. nld/flow/incremental/impl/no_increment/__init__.py +27 -0
  253. nld/flow/incremental/impl/no_increment/backend/base_with_duckdb.py +19 -0
  254. nld/flow/incremental/impl/no_increment/backend/base_with_pydantic.py +43 -0
  255. nld/flow/incremental/impl/no_increment/logic.py +64 -0
  256. nld/flow/incremental/impl/no_increment/manager.py +78 -0
  257. nld/flow/incremental/impl/no_increment/sql_filter_manager.py +15 -0
  258. nld/flow/incremental/impl/no_increment/state.py +44 -0
  259. nld/flow/incremental/models/__init__.py +83 -0
  260. nld/flow/incremental/models/config.py +9 -0
  261. nld/flow/incremental/models/constants.py +2 -0
  262. nld/flow/incremental/models/events.py +131 -0
  263. nld/flow/incremental/models/logic.py +179 -0
  264. nld/flow/incremental/models/manifest.py +60 -0
  265. nld/flow/incremental/models/plan.py +88 -0
  266. nld/flow/incremental/models/referential.py +94 -0
  267. nld/flow/incremental/models/request.py +261 -0
  268. nld/flow/incremental/models/state.py +34 -0
  269. nld/flow/incremental/services/__init__.py +11 -0
  270. nld/flow/incremental/services/factory.py +384 -0
  271. nld/flow/incremental/services/registry.py +58 -0
  272. nld/flow/seed/__init__.py +11 -0
  273. nld/flow/seed/connector/__init__.py +0 -0
  274. nld/flow/seed/connector/bigquery.py +135 -0
  275. nld/flow/seed/connector/duckdb.py +158 -0
  276. nld/flow/seed/connector/postgresql.py +158 -0
  277. nld/flow/seed/connector/snowflake.py +135 -0
  278. nld/flow/seed/seed_file_resolver.py +68 -0
  279. nld/flow/seed/seed_flow_task.py +157 -0
  280. nld/flow/seed/seed_write_strategy.py +180 -0
  281. nld/flow/sql/__init__.py +55 -0
  282. nld/flow/sql/sql_file_resolver.py +96 -0
  283. nld/flow/sql/sql_flow_task.py +446 -0
  284. nld/flow/sql/sql_glot_utils.py +45 -0
  285. nld/flow/sql/sql_query_resolver.py +118 -0
  286. nld/flow/sql/sql_rendering.py +120 -0
  287. nld/flow/sql/sql_step_converter.py +88 -0
  288. nld/flow/sql/sql_write_strategy.py +476 -0
  289. nld/flow/sql/task/__init__.py +9 -0
  290. nld/flow/sql/task/sql_rendering_exec_task.py +154 -0
  291. nld/flow/sql/task/sql_rendering_executor.py +67 -0
  292. nld/flow/sql/task/sql_rendering_flow_task.py +93 -0
  293. nld/flow/sql/transformation/__init__.py +17 -0
  294. nld/flow/sql/transformation/base.py +30 -0
  295. nld/flow/sql/transformation/base_resolver.py +74 -0
  296. nld/flow/sql/transformation/deduplicated_select/__init__.py +5 -0
  297. nld/flow/sql/transformation/deduplicated_select/connector/__init__.py +0 -0
  298. nld/flow/sql/transformation/deduplicated_select/resolver.py +21 -0
  299. nld/flow/sql/transformation/deduplicated_select/transformation.py +323 -0
  300. nld/flow/sql/transformation/registry.py +139 -0
  301. nld/flow/sql/transformation/select/__init__.py +5 -0
  302. nld/flow/sql/transformation/select/connector/__init__.py +0 -0
  303. nld/flow/sql/transformation/select/resolver.py +19 -0
  304. nld/flow/sql/transformation/select/transformation.py +193 -0
  305. nld/flow/state/__init__.py +11 -0
  306. nld/flow/state/config/__init__.py +11 -0
  307. nld/flow/state/config/state_backend_connector.py +105 -0
  308. nld/flow/state/events.py +46 -0
  309. nld/flow/state/factory.py +173 -0
  310. nld/flow/state/manager/__init__.py +11 -0
  311. nld/flow/state/manager/base.py +278 -0
  312. nld/flow/state/manager/by_key.py +23 -0
  313. nld/flow/state/manager/by_source_tst.py +26 -0
  314. nld/flow/state/manager/no_increment.py +23 -0
  315. nld/flow/state/state_backend_connector_resolver.py +170 -0
  316. nld/flow/task/__init__.py +29 -0
  317. nld/flow/task/data_flow_dependency_graph.py +164 -0
  318. nld/flow/task/data_flow_deploy_execute_task.py +177 -0
  319. nld/flow/task/data_flow_deploy_plan_task.py +3 -0
  320. nld/flow/task/data_flow_exec_task.py +345 -0
  321. nld/flow/task/data_flow_executor.py +389 -0
  322. nld/flow/task/data_flow_info.py +280 -0
  323. nld/flow/task/data_flow_state_renderers.py +387 -0
  324. nld/flow/task/data_flow_state_task.py +667 -0
  325. nld/flow/task/data_flow_step.py +45 -0
  326. nld/flow/task/data_flow_task.py +720 -0
  327. nld/flow/task/utils.py +0 -0
  328. nld/flow/utils/__init__.py +25 -0
  329. nld/flow/utils/flow_execution_params.py +23 -0
  330. nld/flow/utils/flow_loading_strategy.py +24 -0
  331. nld/flow/utils/flow_update_strategy.py +24 -0
  332. nld/flow/utils/flow_utils.py +4 -0
  333. nld/logging/__init__.py +53 -0
  334. nld/logging/base.py +90 -0
  335. nld/logging/events.py +124 -0
  336. nld/logging/logger.py +152 -0
  337. nld/parameters/__init__.py +17 -0
  338. nld/parameters/execution_params.py +221 -0
  339. nld/parameters/execution_params_def.py +10 -0
  340. nld/parameters/parser.py +151 -0
  341. nld/parameters/utils.py +25 -0
  342. nld/project/__init__.py +13 -0
  343. nld/project/additional_entity_config.py +78 -0
  344. nld/project/default_project.py +16 -0
  345. nld/project/project.py +242 -0
  346. nld/project/project_events.py +90 -0
  347. nld/project/project_exceptions.py +43 -0
  348. nld/project/project_variables.py +16 -0
  349. nld/project/task/__init__.py +9 -0
  350. nld/project/task/project_entity_info_task.py +81 -0
  351. nld/project/task/project_info_task.py +187 -0
  352. nld/py.typed +0 -0
  353. nld/pydantic/__init__.py +30 -0
  354. nld/pydantic/backend/__init__.py +11 -0
  355. nld/pydantic/backend/base_model_manager.py +240 -0
  356. nld/pydantic/backend/base_structure_mapper.py +63 -0
  357. nld/pydantic/base_model.py +400 -0
  358. nld/pydantic/entity_reference.py +109 -0
  359. nld/pydantic/field_utils.py +2 -0
  360. nld/pydantic/named_base_model.py +578 -0
  361. nld/pydantic/namespace.py +120 -0
  362. nld/pydantic/namespaced_base_model_wrapper.py +53 -0
  363. nld/pydantic/utils.py +55 -0
  364. nld/service/__init__.py +37 -0
  365. nld/service/entity_definition.py +91 -0
  366. nld/service/entity_definition_wrapper.py +126 -0
  367. nld/service/entity_provider.py +1060 -0
  368. nld/service/events.py +34 -0
  369. nld/service/exceptions.py +14 -0
  370. nld/service/file_output_service.py +145 -0
  371. nld/service/jinja_renderer.py +133 -0
  372. nld/service/model_read_util.py +303 -0
  373. nld/service/nld_entities.py +23 -0
  374. nld/service/nld_entity_registry.py +915 -0
  375. nld/structure/__init__.py +67 -0
  376. nld/structure/config/__init__.py +9 -0
  377. nld/structure/config/structure_config.py +51 -0
  378. nld/structure/deploy/__init__.py +67 -0
  379. nld/structure/deploy/structure_deploy_executor.py +437 -0
  380. nld/structure/deploy/structure_deploy_manager.py +328 -0
  381. nld/structure/deploy/structure_deploy_manifest.py +40 -0
  382. nld/structure/deploy/structure_deploy_planner.py +235 -0
  383. nld/structure/deploy/structure_diff.py +54 -0
  384. nld/structure/deploy/structure_diff_computer.py +262 -0
  385. nld/structure/deploy/structure_diff_ddl_generator.py +67 -0
  386. nld/structure/deploy/structure_manifest_discovery.py +38 -0
  387. nld/structure/deploy/structure_metadata_backend_manager.py +258 -0
  388. nld/structure/deploy/structure_metadata_models.py +88 -0
  389. nld/structure/deploy/structure_schema_history.py +220 -0
  390. nld/structure/events.py +56 -0
  391. nld/structure/exceptions.py +36 -0
  392. nld/structure/field/__init__.py +36 -0
  393. nld/structure/field/field.py +237 -0
  394. nld/structure/field/field_adapter.py +326 -0
  395. nld/structure/field/field_characterisation.py +63 -0
  396. nld/structure/field/field_characterisation_def.py +205 -0
  397. nld/structure/field/field_data_type.py +49 -0
  398. nld/structure/field/field_format_adapter.py +127 -0
  399. nld/structure/field/field_template.py +167 -0
  400. nld/structure/service/__init__.py +5 -0
  401. nld/structure/service/sql_renderer_wrapper.py +92 -0
  402. nld/structure/service/sql_template_wrapper.py +56 -0
  403. nld/structure/service/structure_builder.py +28 -0
  404. nld/structure/service/structure_characterisation_adapter.py +34 -0
  405. nld/structure/service/structure_sql_renderer.py +151 -0
  406. nld/structure/structure/__init__.py +39 -0
  407. nld/structure/structure/structure.py +884 -0
  408. nld/structure/structure/structure_adapter.py +239 -0
  409. nld/structure/structure/structure_characterisation.py +34 -0
  410. nld/structure/structure/structure_characterisation_def.py +100 -0
  411. nld/structure/structure/structure_definition.py +6 -0
  412. nld/structure/structure/structure_options.py +21 -0
  413. nld/structure/structure/structure_referential.py +22 -0
  414. nld/structure/structure/structure_template.py +38 -0
  415. nld/structure/structure_model/__init__.py +10 -0
  416. nld/structure/structure_model/structure_model.py +113 -0
  417. nld/structure/structure_model/structure_model_cardinality.py +14 -0
  418. nld/structure/structure_model/structure_model_link.py +51 -0
  419. nld/structure/task/__init__.py +31 -0
  420. nld/structure/task/structure_adapt_task.py +66 -0
  421. nld/structure/task/structure_build_task.py +58 -0
  422. nld/structure/task/structure_deploy_execute_task.py +3 -0
  423. nld/structure/task/structure_deploy_plan_task.py +3 -0
  424. nld/structure/task/structure_deploy_task.py +292 -0
  425. nld/structure/task/structure_info_task.py +241 -0
  426. nld/structure/task/structure_sql_renderer_task.py +69 -0
  427. nld/task/__init__.py +25 -0
  428. nld/task/base/__init__.py +4 -0
  429. nld/task/base/base_step.py +44 -0
  430. nld/task/base/base_task.py +112 -0
  431. nld/task/base/std_task.py +42 -0
  432. nld/task/context/__init__.py +9 -0
  433. nld/task/context/context.py +211 -0
  434. nld/task/context/env_var.py +4 -0
  435. nld/task/context/request.py +129 -0
  436. nld/task/context/variables.py +26 -0
  437. nld/task/execution.py +82 -0
  438. nld/task/task_events.py +69 -0
  439. nld/task/task_module_execution.py +191 -0
  440. nld/task/task_utils.py +49 -0
  441. nld/utils/__init__.py +21 -0
  442. nld/utils/datetime_util.py +262 -0
  443. nld/utils/decorator_utils.py +16 -0
  444. nld/utils/enum_utils.py +14 -0
  445. nld/utils/exception_utils.py +27 -0
  446. nld/utils/file_util.py +434 -0
  447. nld/utils/import_utils.py +57 -0
  448. nld/utils/inspect_utils.py +128 -0
  449. nld/utils/jinja_utils.py +57 -0
  450. nld/utils/mixin.py +45 -0
  451. nld/utils/module_loader.py +193 -0
  452. nld/utils/requestor_utils.py +9 -0
  453. nld/utils/requests_util.py +25 -0
  454. nld/utils/sqlglot/__init__.py +27 -0
  455. nld/utils/sqlglot/base_ddl.py +340 -0
  456. nld/utils/sqlglot/base_dml.py +349 -0
  457. nld/utils/sqlglot/utils.py +99 -0
  458. nld/utils/string_utils.py +21 -0
  459. nld/utils/user_display.py +205 -0
  460. nld/utils/variable_utils.py +24 -0
  461. nld/utils/yaml_util.py +38 -0
  462. nld_core-0.1.1a1.dist-info/METADATA +185 -0
  463. nld_core-0.1.1a1.dist-info/RECORD +467 -0
  464. nld_core-0.1.1a1.dist-info/WHEEL +5 -0
  465. nld_core-0.1.1a1.dist-info/entry_points.txt +2 -0
  466. nld_core-0.1.1a1.dist-info/licenses/LICENSE.md +201 -0
  467. nld_core-0.1.1a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,16 @@
1
+ from .dictionary import (
2
+ BusinessDictionary,
3
+ NamespacedBusinessDictionary,
4
+ Term,
5
+ )
6
+ from .lookup import FindMatch, find_by_synonym, find_terms, resolve_term
7
+
8
+ __all__ = [
9
+ "BusinessDictionary",
10
+ "FindMatch",
11
+ "NamespacedBusinessDictionary",
12
+ "Term",
13
+ "find_by_synonym",
14
+ "find_terms",
15
+ "resolve_term",
16
+ ]
@@ -0,0 +1,37 @@
1
+ from pydantic import Field as PydanticField
2
+
3
+ from nld.pydantic import NldBaseModel, NldNamedBaseModel, NldNamespacedBaseModelWrapper
4
+
5
+
6
+ class Term(NldBaseModel):
7
+ """A single business term with synonyms, description, and cross-references."""
8
+
9
+ name: str = PydanticField(description="Canonical term name")
10
+ description: str = PydanticField(
11
+ description="Detailed description of the business meaning",
12
+ )
13
+ synonyms: list[str] = PydanticField(
14
+ default_factory=list,
15
+ description="Alternative names referring to the same concept",
16
+ )
17
+ examples: list[str] = PydanticField(
18
+ default_factory=list,
19
+ description="Example usages, e.g. sample column or table names",
20
+ )
21
+ related_terms: list[str] = PydanticField(
22
+ default_factory=list,
23
+ description="Names of related terms in the dictionary",
24
+ )
25
+
26
+
27
+ class BusinessDictionary(NldNamedBaseModel):
28
+ """Namespaced business vocabulary used by agents to name tables and fields."""
29
+
30
+ terms: dict[str, Term] = PydanticField(
31
+ default_factory=dict,
32
+ description="Terms indexed by canonical term name",
33
+ )
34
+
35
+
36
+ class NamespacedBusinessDictionary(NldNamespacedBaseModelWrapper[BusinessDictionary]):
37
+ """BusinessDictionary wrapped with namespace information."""
nld/business/lookup.py ADDED
@@ -0,0 +1,146 @@
1
+ from typing import TYPE_CHECKING, Literal
2
+
3
+ from nld.pydantic import NldBaseModel, NldNamespace
4
+
5
+ from .dictionary import BusinessDictionary, Term
6
+
7
+ if TYPE_CHECKING:
8
+ from nld.service.nld_entity_registry import NldEntityRegistry
9
+
10
+
11
+ BUSINESS_DICTIONARY_ENTITY_TYPE = "business_dictionary"
12
+
13
+ MatchedOn = Literal["name", "synonym", "related_term"]
14
+
15
+
16
+ class FindMatch(NldBaseModel):
17
+ """A single term match produced by `find_terms`."""
18
+
19
+ term: Term
20
+ matched_on: MatchedOn
21
+ source_namespace: str
22
+
23
+
24
+ def _get_dictionaries_in_hierarchy(
25
+ registry: "NldEntityRegistry",
26
+ namespace: str | None,
27
+ ) -> list[tuple[NldNamespace, BusinessDictionary]]:
28
+ """Return `(namespace, dictionary)` pairs along the namespace hierarchy.
29
+
30
+ Ordered from deepest (closest to the given namespace) to root so that
31
+ namespace overrides are consumed before the general dictionary.
32
+ """
33
+ target = NldNamespace(namespace) if namespace is not None else NldNamespace(".")
34
+
35
+ if BUSINESS_DICTIONARY_ENTITY_TYPE not in registry.entities:
36
+ return []
37
+
38
+ storage = registry.entities[BUSINESS_DICTIONARY_ENTITY_TYPE]
39
+
40
+ pairs: list[tuple[NldNamespace, BusinessDictionary]] = []
41
+ for level_namespace in target.hierarchy:
42
+ namespace_entries = storage.get(level_namespace, {})
43
+ for model in namespace_entries.values():
44
+ if isinstance(model, BusinessDictionary):
45
+ pairs.append((level_namespace, model))
46
+
47
+ pairs.sort(key=lambda item: item[0].depth, reverse=True)
48
+ return pairs
49
+
50
+
51
+ def resolve_term(
52
+ registry: "NldEntityRegistry",
53
+ term_name: str,
54
+ namespace: str | None = None,
55
+ ) -> Term | None:
56
+ """Resolve a term by name, walking the namespace hierarchy upward.
57
+
58
+ The closest namespace definition wins; the root dictionary acts as the
59
+ general fallback.
60
+ """
61
+ for _, dictionary in _get_dictionaries_in_hierarchy(
62
+ registry=registry,
63
+ namespace=namespace,
64
+ ):
65
+ term = dictionary.terms.get(term_name)
66
+ if term is not None:
67
+ return term
68
+ return None
69
+
70
+
71
+ def find_by_synonym(
72
+ registry: "NldEntityRegistry",
73
+ synonym: str,
74
+ namespace: str | None = None,
75
+ ) -> Term | None:
76
+ """Find a term by matching one of its synonyms or its canonical name.
77
+
78
+ Walks the namespace hierarchy from the given namespace up to root and
79
+ returns the first match found, so namespace overrides win over general.
80
+ """
81
+ normalized = synonym.lower()
82
+ for _, dictionary in _get_dictionaries_in_hierarchy(
83
+ registry=registry,
84
+ namespace=namespace,
85
+ ):
86
+ for term in dictionary.terms.values():
87
+ if term.name.lower() == normalized:
88
+ return term
89
+ if any(candidate.lower() == normalized for candidate in term.synonyms):
90
+ return term
91
+ return None
92
+
93
+
94
+ def find_terms(
95
+ registry: "NldEntityRegistry",
96
+ query: str,
97
+ match_name: bool = True,
98
+ match_synonym: bool = False,
99
+ match_related: bool = False,
100
+ namespace: str | None = None,
101
+ ) -> list[FindMatch]:
102
+ """Search dictionaries in the hierarchy and return every term matching `query`.
103
+
104
+ The scope flags control which Term fields participate in the match:
105
+ canonical `name`, `synonyms`, and/or `related_terms`. Matching is a
106
+ case-insensitive exact string equality against each enabled field.
107
+
108
+ When the same term name appears in multiple namespaces the deepest
109
+ (most specific) definition wins, preserving the `parents` override
110
+ semantics used by `resolve_term` and `find_by_synonym`.
111
+ """
112
+ normalized = query.lower()
113
+ seen_names: set[str] = set()
114
+ results: list[FindMatch] = []
115
+
116
+ for source_namespace, dictionary in _get_dictionaries_in_hierarchy(
117
+ registry=registry,
118
+ namespace=namespace,
119
+ ):
120
+ for term in dictionary.terms.values():
121
+ if term.name in seen_names:
122
+ continue
123
+
124
+ matched_on: MatchedOn | None = None
125
+ if match_name and term.name.lower() == normalized:
126
+ matched_on = "name"
127
+ elif match_synonym and any(
128
+ candidate.lower() == normalized for candidate in term.synonyms
129
+ ):
130
+ matched_on = "synonym"
131
+ elif match_related and any(
132
+ candidate.lower() == normalized for candidate in term.related_terms
133
+ ):
134
+ matched_on = "related_term"
135
+
136
+ if matched_on is not None:
137
+ results.append(
138
+ FindMatch(
139
+ term=term,
140
+ matched_on=matched_on,
141
+ source_namespace=str(source_namespace),
142
+ ),
143
+ )
144
+ seen_names.add(term.name)
145
+
146
+ return results
@@ -0,0 +1,5 @@
1
+ from .business_dictionary_find_task import BusinessDictionaryFindTask
2
+
3
+ __all__ = [
4
+ "BusinessDictionaryFindTask",
5
+ ]
@@ -0,0 +1,112 @@
1
+ import json
2
+ import os
3
+ import sys
4
+ from typing import Any
5
+
6
+ from nld.business import find_terms
7
+ from nld.parameters.execution_params_def import ExecutionParameterDefinition
8
+ from nld.service import FileOutputService
9
+ from nld.task import BaseRunStatus, StandardTask
10
+ from nld.task.context import NldExecutionContext
11
+
12
+ BUSINESS_DICTIONARY_FIND_FILE_NAME = "business_dictionary_find.json"
13
+
14
+
15
+ class BusinessDictionaryFindTask(StandardTask):
16
+ """Look up business dictionary terms and emit the results as JSON.
17
+
18
+ The scope flags (`match_name`, `match_synonym`, `match_related`) control
19
+ which Term fields participate in the match. At least one scope must be
20
+ enabled; defaults to name-only matching.
21
+ """
22
+
23
+ init_params = [
24
+ ExecutionParameterDefinition(name="term", mandatory=True),
25
+ ExecutionParameterDefinition(name="synonym", mandatory=False, data_type="bool"),
26
+ ExecutionParameterDefinition(
27
+ name="related_terms",
28
+ mandatory=False,
29
+ data_type="bool",
30
+ ),
31
+ ExecutionParameterDefinition(name="namespace", mandatory=False),
32
+ ExecutionParameterDefinition(
33
+ name="output",
34
+ mandatory=False,
35
+ data_type="bool",
36
+ ),
37
+ ExecutionParameterDefinition(
38
+ name="override_output_folder_path",
39
+ mandatory=False,
40
+ ),
41
+ ]
42
+ run_params = []
43
+
44
+ def __init__(
45
+ self,
46
+ term: str,
47
+ synonym: bool = False,
48
+ related_terms: bool = False,
49
+ namespace: str | None = None,
50
+ output: bool = False,
51
+ override_output_folder_path: str | None = None,
52
+ **kwargs: Any,
53
+ ) -> None:
54
+ super().__init__(**kwargs)
55
+ self.execution_context = NldExecutionContext.require_current()
56
+ self.namespace = namespace
57
+ self.output = output
58
+ self.override_output_folder_path = override_output_folder_path
59
+ self.query = term
60
+ self.scope_name = True
61
+ self.scope_related = related_terms
62
+ self.scope_synonym = synonym
63
+
64
+ def run(self, **kwargs: Any) -> bool:
65
+ run_status = BaseRunStatus.SUCCESS.value
66
+
67
+ self.execution_context.load_entities()
68
+ registry = self.execution_context.entity_registry
69
+
70
+ matches = find_terms(
71
+ registry=registry,
72
+ query=self.query,
73
+ match_name=self.scope_name,
74
+ match_synonym=self.scope_synonym,
75
+ match_related=self.scope_related,
76
+ namespace=self.namespace,
77
+ )
78
+
79
+ payload = {
80
+ "query": self.query,
81
+ "namespace": self.namespace or ".",
82
+ "scope": {
83
+ "term": self.scope_name,
84
+ "synonym": self.scope_synonym,
85
+ "related_terms": self.scope_related,
86
+ },
87
+ "matches": [match.model_dump() for match in matches],
88
+ }
89
+
90
+ if self.output or self.override_output_folder_path is not None:
91
+ file_output_service = FileOutputService(
92
+ root_folder_path=self.execution_context.get_nld_root_folder_path(),
93
+ override_output_folder_path=self.override_output_folder_path,
94
+ )
95
+ file_output_service.write_json_file(
96
+ file_name=BUSINESS_DICTIONARY_FIND_FILE_NAME,
97
+ data=payload,
98
+ )
99
+ output_path = os.path.join(
100
+ file_output_service.determine_output_folder_path(),
101
+ BUSINESS_DICTIONARY_FIND_FILE_NAME,
102
+ )
103
+ self.log_info(
104
+ f"Wrote {len(matches)} match(es) to {output_path}",
105
+ )
106
+ else:
107
+ sys.stdout.write(
108
+ json.dumps(payload, indent=2, ensure_ascii=False) + "\n",
109
+ )
110
+ sys.stdout.flush()
111
+
112
+ return run_status
File without changes
@@ -0,0 +1,47 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from nld.business.task import BusinessDictionaryFindTask
6
+ from nld.cli import params, requires_wrapper
7
+ from nld.cli.business import params_business
8
+ from nld.task.task_utils import execute_task
9
+
10
+
11
+ @click.group(name="dict", no_args_is_help=True)
12
+ @click.pass_context
13
+ def dictionary(ctx: click.Context, /, **kwargs: Any) -> None:
14
+ """Business dictionary commands."""
15
+
16
+
17
+ @requires_wrapper.nld_command(
18
+ group=dictionary,
19
+ command_name="find",
20
+ with_project=True,
21
+ )
22
+ @params.nld_root_folder_path
23
+ @params_business.term
24
+ @params_business.synonym
25
+ @params_business.related_terms
26
+ @params_business.namespace
27
+ @params_business.output
28
+ @params_business.override_output_folder_path
29
+ def find(ctx: click.Context, **kwargs: Any) -> bool:
30
+ """Look up business dictionary terms and emit the results as JSON.
31
+
32
+ By default the query is matched against each term's canonical name.
33
+ Add `--synonym` to also match against synonyms, and `--related-terms`
34
+ to also match against related_terms. The flags compose.
35
+
36
+ Examples:
37
+
38
+ nld business dict find --term customer
39
+
40
+ nld business dict find --term counterparty --synonym --namespace finance
41
+
42
+ nld business dict find --term customer --synonym --output
43
+
44
+ nld business dict find --term customer --synonym --related-terms \\
45
+ --override-output-folder-path ./out
46
+ """
47
+ return execute_task(BusinessDictionaryFindTask) # type: ignore[no-any-return]
@@ -0,0 +1,54 @@
1
+ import click
2
+
3
+ term = click.option(
4
+ "--term",
5
+ type=str,
6
+ required=True,
7
+ help="Query string to look up in the business dictionary.",
8
+ )
9
+
10
+ synonym = click.option(
11
+ "--synonym",
12
+ is_flag=True,
13
+ default=False,
14
+ help="Also match the query against each term's synonyms.",
15
+ )
16
+
17
+ related_terms = click.option(
18
+ "--related-terms",
19
+ "related_terms",
20
+ is_flag=True,
21
+ default=False,
22
+ help="Also match the query against each term's related_terms.",
23
+ )
24
+
25
+ namespace = click.option(
26
+ "--namespace",
27
+ type=str,
28
+ required=False,
29
+ default=None,
30
+ help="Namespace to scope the lookup; walks parents up to root.",
31
+ )
32
+
33
+ output = click.option(
34
+ "--output",
35
+ is_flag=True,
36
+ default=False,
37
+ help=(
38
+ "Write the JSON result to a file instead of printing to stdout. "
39
+ "When set without `--override-output-folder-path`, the file is "
40
+ "written to a timestamped folder under `output/`."
41
+ ),
42
+ )
43
+
44
+ override_output_folder_path = click.option(
45
+ "--override-output-folder-path",
46
+ "override_output_folder_path",
47
+ type=click.Path(file_okay=False, writable=True),
48
+ required=False,
49
+ default=None,
50
+ help=(
51
+ "Folder to write the JSON result into; implies `--output`. The "
52
+ "file is named `business_dictionary_find.json`."
53
+ ),
54
+ )
nld/cli/cli_events.py ADDED
@@ -0,0 +1,28 @@
1
+ from nld.logging import ErrorEvent, InfoEvent
2
+ from nld.task import ExecutionInfo
3
+
4
+
5
+ class CommandCompleted(InfoEvent):
6
+ def __init__(self, exec_info: ExecutionInfo):
7
+ super().__init__()
8
+ self.exec_info = exec_info
9
+
10
+ def code(self) -> str:
11
+ return "CMD-002"
12
+
13
+ def message(self) -> str:
14
+ return self.exec_info.get_completion_message()
15
+
16
+
17
+ class CommandRuntimeError(ErrorEvent):
18
+ def __init__(self, e: Exception):
19
+ self.e = e
20
+
21
+ def code(self) -> str:
22
+ return "CMD-091"
23
+
24
+ def message(self) -> str:
25
+ error_message = (
26
+ str(self.e.message) if hasattr(self.e, "message") else str(self.e)
27
+ )
28
+ return f"Runtime Error: {error_message}"
@@ -0,0 +1,9 @@
1
+ from click.exceptions import ClickException
2
+
3
+
4
+ class ExceptionExit(ClickException):
5
+ """Wraps exceptions without results thrown while invoking nld commands."""
6
+
7
+ def __init__(self, exception: Exception) -> None:
8
+ super().__init__(exception.__str__())
9
+ self.exception = exception
nld/cli/cli_utils.py ADDED
@@ -0,0 +1,24 @@
1
+ from types import ModuleType
2
+
3
+ import click
4
+ import click.core
5
+
6
+ from nld.utils.inspect_utils import (
7
+ extract_functions_from_command_module,
8
+ )
9
+
10
+
11
+ def add_commands_from_modules(
12
+ cli: click.core.Group, command_module: ModuleType, command_prefix: str = ""
13
+ ) -> None:
14
+ commands = extract_functions_from_command_module(
15
+ command_module, command_prefix, click.core.Command
16
+ )
17
+ groups = extract_functions_from_command_module(
18
+ command_module, command_prefix, click.core.Group
19
+ )
20
+
21
+ for method in commands + groups:
22
+ if method.name == cli.name:
23
+ continue
24
+ cli.add_command(method)
@@ -0,0 +1,69 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from nld.cli import params, requires_wrapper
6
+ from nld.cli.connection import params_connection
7
+ from nld.connector.task import (
8
+ ConnectionDebugTask,
9
+ ConnectionExportEnvironmentVariablesTask,
10
+ ConnectionGetStructureTask,
11
+ ConnectionListTask,
12
+ )
13
+ from nld.task.task_utils import execute_task
14
+
15
+
16
+ @requires_wrapper.nld_command("debug")
17
+ @params.specific_connection_params
18
+ def debug(ctx: click.Context, **kwargs: Any) -> bool:
19
+ """Test the connection availability and status"""
20
+ return execute_task(ConnectionDebugTask) # type: ignore[no-any-return]
21
+
22
+
23
+ @requires_wrapper.nld_command("export-env-var")
24
+ @params.specific_connection_params
25
+ def export_env_var(ctx: click.Context, **kwargs: Any) -> bool:
26
+ """
27
+ Export environment variables for a connection to the parent terminal.
28
+
29
+ To load variables into your current shell, use eval:
30
+
31
+ eval "$(nld connection export-env-var --connection-name <name>)"
32
+
33
+ With a specific profile:
34
+
35
+ eval "$(nld connection export-env-var \
36
+ --connection-name <name> --profile-name <profile>)"
37
+ """
38
+ return execute_task(ConnectionExportEnvironmentVariablesTask) # type: ignore[no-any-return]
39
+
40
+
41
+ @requires_wrapper.nld_command("get-structure")
42
+ @params.specific_connection_params
43
+ @params_connection.database
44
+ @params.namespace
45
+ @params_connection.schema
46
+ @params_connection.object_name
47
+ def get_structure(ctx: click.Context, **kwargs: Any) -> bool:
48
+ """Extract database structure from a connection.
49
+
50
+ Extracts metadata about tables, views, columns, primary keys, and
51
+ unique constraints. Output is in YAML format.
52
+
53
+ Examples:
54
+
55
+ nld connection get-structure --connection-name my_conn
56
+
57
+ nld connection get-structure --connection-name my_conn --schema public
58
+
59
+ nld connection get-structure --connection-name my_conn --namespace source.raw
60
+
61
+ nld connection get-structure --connection-name my_conn --object users
62
+ """
63
+ return execute_task(ConnectionGetStructureTask) # type: ignore[no-any-return]
64
+
65
+
66
+ @requires_wrapper.nld_command("list")
67
+ def list_connections(ctx: click.Context, **kwargs: Any) -> bool:
68
+ """List all available connections"""
69
+ return execute_task(ConnectionListTask) # type: ignore[no-any-return]
@@ -0,0 +1,25 @@
1
+ import click
2
+
3
+ database = click.option(
4
+ "--database",
5
+ type=str,
6
+ required=False,
7
+ default=None,
8
+ help="Database name (validates against connection, uses connection DB if omitted)",
9
+ )
10
+
11
+ schema = click.option(
12
+ "--schema",
13
+ type=str,
14
+ required=False,
15
+ default=None,
16
+ help="Filter by schema name",
17
+ )
18
+
19
+ object_name = click.option(
20
+ "--object",
21
+ type=str,
22
+ required=False,
23
+ default=None,
24
+ help="Filter by table/view name",
25
+ )