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.
- nld/business/__init__.py +16 -0
- nld/business/dictionary.py +37 -0
- nld/business/lookup.py +146 -0
- nld/business/task/__init__.py +5 -0
- nld/business/task/business_dictionary_find_task.py +112 -0
- nld/cli/business/__init__.py +0 -0
- nld/cli/business/main_business.py +47 -0
- nld/cli/business/params_business.py +54 -0
- nld/cli/cli_events.py +28 -0
- nld/cli/cli_exceptions.py +9 -0
- nld/cli/cli_utils.py +24 -0
- nld/cli/connection/main_connection.py +69 -0
- nld/cli/connection/params_connection.py +25 -0
- nld/cli/flow/main_flow.py +190 -0
- nld/cli/flow/params_flow.py +352 -0
- nld/cli/flow/requires_flow.py +300 -0
- nld/cli/flow/state_flow.py +187 -0
- nld/cli/main.py +75 -0
- nld/cli/params.py +85 -0
- nld/cli/project/main_project.py +41 -0
- nld/cli/project/params_project.py +18 -0
- nld/cli/requires.py +140 -0
- nld/cli/requires_wrapper.py +56 -0
- nld/cli/sql/__init__.py +0 -0
- nld/cli/sql/main_sql.py +35 -0
- nld/cli/sql/params_sql.py +22 -0
- nld/cli/structure/main_structure.py +112 -0
- nld/cli/structure/params_structure.py +109 -0
- nld/cli/utils/execution_params_def_utils.py +25 -0
- nld/cli/utils/mutually_exclusive_option.py +98 -0
- nld/connector/azure_blob_storage/__init__.py +27 -0
- nld/connector/azure_blob_storage/azure_blob_storage_connection.py +44 -0
- nld/connector/azure_blob_storage/azure_blob_storage_connector.py +99 -0
- nld/connector/azure_blob_storage/azure_blob_storage_credential.py +23 -0
- nld/connector/azure_blob_storage/azure_blob_storage_utils.py +64 -0
- nld/connector/base/__init__.py +72 -0
- nld/connector/base/config.py +171 -0
- nld/connector/base/config_default.py +37 -0
- nld/connector/base/config_loader.py +123 -0
- nld/connector/base/config_source.py +288 -0
- nld/connector/base/connection.py +96 -0
- nld/connector/base/connector.py +628 -0
- nld/connector/base/credential.py +82 -0
- nld/connector/base/events.py +80 -0
- nld/connector/base/exceptions.py +84 -0
- nld/connector/base/plugin.py +61 -0
- nld/connector/base/query.py +483 -0
- nld/connector/base/query_exec_result_formatter.py +197 -0
- nld/connector/base/sql.py +25 -0
- nld/connector/base/structure_reader.py +73 -0
- nld/connector/bigquery/__init__.py +30 -0
- nld/connector/bigquery/bigquery_connection.py +73 -0
- nld/connector/bigquery/bigquery_connector.py +921 -0
- nld/connector/bigquery/bigquery_credential.py +29 -0
- nld/connector/bigquery/bigquery_data_type.py +20 -0
- nld/connector/bigquery/bigquery_structure.py +19 -0
- nld/connector/bigquery/pydantic/__init__.py +7 -0
- nld/connector/bigquery/pydantic/model_manager.py +431 -0
- nld/connector/bigquery/pydantic/structure_mapper.py +178 -0
- nld/connector/bigquery/query_wrapper.py +40 -0
- nld/connector/bigquery/service/__init__.py +7 -0
- nld/connector/bigquery/service/structure_diff_ddl_generator.py +208 -0
- nld/connector/bigquery/service/structure_reader.py +277 -0
- nld/connector/bigquery/sqlglot/__init__.py +7 -0
- nld/connector/bigquery/sqlglot/ddl.py +181 -0
- nld/connector/bigquery/sqlglot/dml.py +13 -0
- nld/connector/duckdb/__init__.py +46 -0
- nld/connector/duckdb/constants.py +3 -0
- nld/connector/duckdb/duckdb_credential.py +16 -0
- nld/connector/duckdb/duckdb_data_type.py +53 -0
- nld/connector/duckdb/duckdb_engine.py +262 -0
- nld/connector/duckdb/duckdb_structure.py +19 -0
- nld/connector/duckdb/engine/__init__.py +0 -0
- nld/connector/duckdb/engine/duckdb_native/__init__.py +0 -0
- nld/connector/duckdb/engine/duckdb_native/adapter/__init__.py +0 -0
- nld/connector/duckdb/engine/duckdb_native/adapter/pydantic/__init__.py +7 -0
- nld/connector/duckdb/engine/duckdb_native/adapter/pydantic/model_manager.py +333 -0
- nld/connector/duckdb/engine/duckdb_native/adapter/pydantic/structure_mapper.py +209 -0
- nld/connector/duckdb/engine/duckdb_native/connection.py +95 -0
- nld/connector/duckdb/engine/duckdb_native/connector.py +627 -0
- nld/connector/duckdb/engine/duckdb_native/query_wrapper.py +92 -0
- nld/connector/duckdb/engine/duckdb_native/utils.py +107 -0
- nld/connector/duckdb/service/__init__.py +7 -0
- nld/connector/duckdb/service/structure_diff_ddl_generator.py +462 -0
- nld/connector/duckdb/service/structure_reader.py +543 -0
- nld/connector/duckdb/sqlglot/__init__.py +7 -0
- nld/connector/duckdb/sqlglot/ddl.py +74 -0
- nld/connector/duckdb/sqlglot/dml.py +57 -0
- nld/connector/local/__init__.py +17 -0
- nld/connector/local/local_connection.py +23 -0
- nld/connector/local/local_connector.py +80 -0
- nld/connector/local/local_credential.py +12 -0
- nld/connector/local/local_utils.py +1 -0
- nld/connector/manager/__init__.py +6 -0
- nld/connector/manager/events.py +37 -0
- nld/connector/manager/factory.py +189 -0
- nld/connector/manager/manager.py +49 -0
- nld/connector/postgresql/__init__.py +42 -0
- nld/connector/postgresql/engine/psycopg2/__init__.py +11 -0
- nld/connector/postgresql/engine/psycopg2/adapter/__init__.py +0 -0
- nld/connector/postgresql/engine/psycopg2/adapter/pandas/__init__.py +11 -0
- nld/connector/postgresql/engine/psycopg2/adapter/pandas/dataframe_manager.py +101 -0
- nld/connector/postgresql/engine/psycopg2/adapter/pandas/structure_mapper.py +34 -0
- nld/connector/postgresql/engine/psycopg2/adapter/pydantic/__init__.py +11 -0
- nld/connector/postgresql/engine/psycopg2/adapter/pydantic/model_manager.py +576 -0
- nld/connector/postgresql/engine/psycopg2/adapter/pydantic/structure_mapper.py +247 -0
- nld/connector/postgresql/engine/psycopg2/connection.py +89 -0
- nld/connector/postgresql/engine/psycopg2/connector.py +790 -0
- nld/connector/postgresql/engine/psycopg2/query_wrapper.py +42 -0
- nld/connector/postgresql/engine/psycopg2/utils.py +123 -0
- nld/connector/postgresql/postgresql_credential.py +34 -0
- nld/connector/postgresql/postgresql_data_type.py +51 -0
- nld/connector/postgresql/postgresql_structure.py +19 -0
- nld/connector/postgresql/service/__init__.py +7 -0
- nld/connector/postgresql/service/structure_diff_ddl_generator.py +439 -0
- nld/connector/postgresql/service/structure_reader.py +577 -0
- nld/connector/postgresql/sqlglot/__init__.py +7 -0
- nld/connector/postgresql/sqlglot/ddl.py +13 -0
- nld/connector/postgresql/sqlglot/dml.py +13 -0
- nld/connector/s3_blob_storage/__init__.py +29 -0
- nld/connector/s3_blob_storage/s3_object_storage_connection.py +102 -0
- nld/connector/s3_blob_storage/s3_object_storage_connector.py +262 -0
- nld/connector/s3_blob_storage/s3_object_storage_credential.py +23 -0
- nld/connector/s3_blob_storage/s3_object_storage_utils.py +556 -0
- nld/connector/s3_blob_storage/s3_structure.py +41 -0
- nld/connector/s3_blob_storage/s3_utils.py +1 -0
- nld/connector/snowflake/__init__.py +29 -0
- nld/connector/snowflake/pydantic/__init__.py +7 -0
- nld/connector/snowflake/pydantic/model_manager.py +344 -0
- nld/connector/snowflake/pydantic/structure_mapper.py +170 -0
- nld/connector/snowflake/query_wrapper.py +43 -0
- nld/connector/snowflake/service/__init__.py +7 -0
- nld/connector/snowflake/service/structure_diff_ddl_generator.py +339 -0
- nld/connector/snowflake/service/structure_reader.py +135 -0
- nld/connector/snowflake/snowflake_connection.py +111 -0
- nld/connector/snowflake/snowflake_connector.py +653 -0
- nld/connector/snowflake/snowflake_credential.py +43 -0
- nld/connector/snowflake/snowflake_data_type.py +18 -0
- nld/connector/snowflake/snowflake_utils.py +107 -0
- nld/connector/snowflake/sqlglot/__init__.py +7 -0
- nld/connector/snowflake/sqlglot/ddl.py +213 -0
- nld/connector/snowflake/sqlglot/dml.py +56 -0
- nld/connector/task/__init__.py +13 -0
- nld/connector/task/connection_debug.py +47 -0
- nld/connector/task/connection_export_env_var.py +105 -0
- nld/connector/task/connection_get_structure.py +158 -0
- nld/connector/task/connection_list.py +51 -0
- nld/engine/__init__.py +1 -0
- nld/engine/pyarrow/__init__.py +11 -0
- nld/engine/pyarrow/pydantic_structure_mapper.py +181 -0
- nld/engine/pyarrow/utils.py +158 -0
- nld/exceptions.py +184 -0
- nld/flow/__init__.py +25 -0
- nld/flow/backend/__init__.py +5 -0
- nld/flow/backend/bigquery/__init__.py +0 -0
- nld/flow/backend/bigquery/backend_mixin.py +37 -0
- nld/flow/backend/bigquery/utils.py +6 -0
- nld/flow/backend/duckdb/__init__.py +3 -0
- nld/flow/backend/duckdb/backend_mixin.py +37 -0
- nld/flow/backend/duckdb/utils.py +6 -0
- nld/flow/backend/local/__init__.py +3 -0
- nld/flow/backend/local/backend_mixin.py +62 -0
- nld/flow/backend/postgresql/__init__.py +5 -0
- nld/flow/backend/postgresql/backend_mixin.py +33 -0
- nld/flow/backend/postgresql/utils.py +6 -0
- nld/flow/backend/s3_blob_storage/__init__.py +5 -0
- nld/flow/backend/s3_blob_storage/backend_mixin.py +115 -0
- nld/flow/backend/snowflake/__init__.py +0 -0
- nld/flow/backend/snowflake/backend_mixin.py +29 -0
- nld/flow/backend/snowflake/utils.py +6 -0
- nld/flow/backend/utils.py +8 -0
- nld/flow/config/__init__.py +7 -0
- nld/flow/config/flow_config.py +94 -0
- nld/flow/definition/__init__.py +21 -0
- nld/flow/definition/field_lineage.py +97 -0
- nld/flow/definition/flow_definition.py +724 -0
- nld/flow/definition/sql_config.py +28 -0
- nld/flow/deploy/__init__.py +54 -0
- nld/flow/deploy/flow_definition_hash.py +154 -0
- nld/flow/deploy/flow_deploy_diff.py +17 -0
- nld/flow/deploy/flow_deploy_executor.py +1006 -0
- nld/flow/deploy/flow_deploy_manifest.py +67 -0
- nld/flow/deploy/flow_deploy_metadata_manager.py +333 -0
- nld/flow/deploy/flow_deploy_metadata_models.py +100 -0
- nld/flow/deploy/flow_deploy_planner.py +599 -0
- nld/flow/deploy/flow_manifest_discovery.py +38 -0
- nld/flow/events.py +26 -0
- nld/flow/exceptions.py +65 -0
- nld/flow/execution/__init__.py +24 -0
- nld/flow/execution/backend/bigquery_with_pydantic.py +228 -0
- nld/flow/execution/backend/duckdb_with_pydantic.py +233 -0
- nld/flow/execution/backend/local_with_duckdb.py +330 -0
- nld/flow/execution/backend/local_with_pydantic.py +140 -0
- nld/flow/execution/backend/migrations/s3_blob_storage_to_parquet.py +224 -0
- nld/flow/execution/backend/postgresql_with_pydantic.py +331 -0
- nld/flow/execution/backend/s3_blob_storage_base.py +20 -0
- nld/flow/execution/backend/s3_blob_storage_with_duckdb.py +378 -0
- nld/flow/execution/backend/s3_blob_storage_with_pydantic.py +388 -0
- nld/flow/execution/backend/snowflake_with_pydantic.py +228 -0
- nld/flow/execution/batch_execution_info.py +39 -0
- nld/flow/execution/decorator.py +116 -0
- nld/flow/execution/events.py +73 -0
- nld/flow/execution/execution_info.py +215 -0
- nld/flow/execution/factory.py +288 -0
- nld/flow/execution/manager.py +522 -0
- nld/flow/execution/schema.py +55 -0
- nld/flow/execution/utils.py +4 -0
- nld/flow/graph/__init__.py +25 -0
- nld/flow/graph/data_flow_graph.py +436 -0
- nld/flow/graph/scoped_data_flow_graph.py +78 -0
- nld/flow/graph/serializers.py +125 -0
- nld/flow/incremental/__init__.py +0 -0
- nld/flow/incremental/backend/__init__.py +0 -0
- nld/flow/incremental/backend/plan.py +97 -0
- nld/flow/incremental/backend/postgresql/__init__.py +9 -0
- nld/flow/incremental/backend/postgresql/backend_mixin.py +128 -0
- nld/flow/incremental/backend/s3_blob_storage/__init__.py +15 -0
- nld/flow/incremental/backend/s3_blob_storage/backend_mixin.py +234 -0
- nld/flow/incremental/backend/s3_blob_storage/schema.py +13 -0
- nld/flow/incremental/base/__init__.py +11 -0
- nld/flow/incremental/base/manager.py +758 -0
- nld/flow/incremental/base/sql_filter_manager.py +21 -0
- nld/flow/incremental/impl/__init__.py +39 -0
- nld/flow/incremental/impl/by_key/__init__.py +33 -0
- nld/flow/incremental/impl/by_key/backend/base_with_duckdb.py +19 -0
- nld/flow/incremental/impl/by_key/backend/base_with_pydantic.py +26 -0
- nld/flow/incremental/impl/by_key/backend/bigquery_with_pydantic.py +328 -0
- nld/flow/incremental/impl/by_key/backend/duckdb_with_pydantic.py +327 -0
- nld/flow/incremental/impl/by_key/backend/local_with_duckdb.py +252 -0
- nld/flow/incremental/impl/by_key/backend/local_with_pydantic.py +220 -0
- nld/flow/incremental/impl/by_key/backend/postgresql_with_pydantic.py +538 -0
- nld/flow/incremental/impl/by_key/backend/s3_blob_storage_base.py +237 -0
- nld/flow/incremental/impl/by_key/backend/s3_blob_storage_with_duckdb.py +297 -0
- nld/flow/incremental/impl/by_key/backend/s3_blob_storage_with_pydantic.py +258 -0
- nld/flow/incremental/impl/by_key/logic.py +168 -0
- nld/flow/incremental/impl/by_key/manager.py +301 -0
- nld/flow/incremental/impl/by_key/schema.py +35 -0
- nld/flow/incremental/impl/by_key/sql_filter_manager.py +88 -0
- nld/flow/incremental/impl/by_key/state.py +162 -0
- nld/flow/incremental/impl/by_source_tst/__init__.py +27 -0
- nld/flow/incremental/impl/by_source_tst/backend/__init__.py +0 -0
- nld/flow/incremental/impl/by_source_tst/backend/base_with_pydantic.py +26 -0
- nld/flow/incremental/impl/by_source_tst/backend/bigquery_with_pydantic.py +216 -0
- nld/flow/incremental/impl/by_source_tst/backend/duckdb_with_pydantic.py +215 -0
- nld/flow/incremental/impl/by_source_tst/backend/local_with_pydantic.py +114 -0
- nld/flow/incremental/impl/by_source_tst/backend/postgresql_with_pydantic.py +387 -0
- nld/flow/incremental/impl/by_source_tst/backend/snowflake_with_pydantic.py +216 -0
- nld/flow/incremental/impl/by_source_tst/logic.py +143 -0
- nld/flow/incremental/impl/by_source_tst/manager.py +165 -0
- nld/flow/incremental/impl/by_source_tst/sql_filter_manager.py +81 -0
- nld/flow/incremental/impl/by_source_tst/state.py +98 -0
- nld/flow/incremental/impl/no_increment/__init__.py +27 -0
- nld/flow/incremental/impl/no_increment/backend/base_with_duckdb.py +19 -0
- nld/flow/incremental/impl/no_increment/backend/base_with_pydantic.py +43 -0
- nld/flow/incremental/impl/no_increment/logic.py +64 -0
- nld/flow/incremental/impl/no_increment/manager.py +78 -0
- nld/flow/incremental/impl/no_increment/sql_filter_manager.py +15 -0
- nld/flow/incremental/impl/no_increment/state.py +44 -0
- nld/flow/incremental/models/__init__.py +83 -0
- nld/flow/incremental/models/config.py +9 -0
- nld/flow/incremental/models/constants.py +2 -0
- nld/flow/incremental/models/events.py +131 -0
- nld/flow/incremental/models/logic.py +179 -0
- nld/flow/incremental/models/manifest.py +60 -0
- nld/flow/incremental/models/plan.py +88 -0
- nld/flow/incremental/models/referential.py +94 -0
- nld/flow/incremental/models/request.py +261 -0
- nld/flow/incremental/models/state.py +34 -0
- nld/flow/incremental/services/__init__.py +11 -0
- nld/flow/incremental/services/factory.py +384 -0
- nld/flow/incremental/services/registry.py +58 -0
- nld/flow/seed/__init__.py +11 -0
- nld/flow/seed/connector/__init__.py +0 -0
- nld/flow/seed/connector/bigquery.py +135 -0
- nld/flow/seed/connector/duckdb.py +158 -0
- nld/flow/seed/connector/postgresql.py +158 -0
- nld/flow/seed/connector/snowflake.py +135 -0
- nld/flow/seed/seed_file_resolver.py +68 -0
- nld/flow/seed/seed_flow_task.py +157 -0
- nld/flow/seed/seed_write_strategy.py +180 -0
- nld/flow/sql/__init__.py +55 -0
- nld/flow/sql/sql_file_resolver.py +96 -0
- nld/flow/sql/sql_flow_task.py +446 -0
- nld/flow/sql/sql_glot_utils.py +45 -0
- nld/flow/sql/sql_query_resolver.py +118 -0
- nld/flow/sql/sql_rendering.py +120 -0
- nld/flow/sql/sql_step_converter.py +88 -0
- nld/flow/sql/sql_write_strategy.py +476 -0
- nld/flow/sql/task/__init__.py +9 -0
- nld/flow/sql/task/sql_rendering_exec_task.py +154 -0
- nld/flow/sql/task/sql_rendering_executor.py +67 -0
- nld/flow/sql/task/sql_rendering_flow_task.py +93 -0
- nld/flow/sql/transformation/__init__.py +17 -0
- nld/flow/sql/transformation/base.py +30 -0
- nld/flow/sql/transformation/base_resolver.py +74 -0
- nld/flow/sql/transformation/deduplicated_select/__init__.py +5 -0
- nld/flow/sql/transformation/deduplicated_select/connector/__init__.py +0 -0
- nld/flow/sql/transformation/deduplicated_select/resolver.py +21 -0
- nld/flow/sql/transformation/deduplicated_select/transformation.py +323 -0
- nld/flow/sql/transformation/registry.py +139 -0
- nld/flow/sql/transformation/select/__init__.py +5 -0
- nld/flow/sql/transformation/select/connector/__init__.py +0 -0
- nld/flow/sql/transformation/select/resolver.py +19 -0
- nld/flow/sql/transformation/select/transformation.py +193 -0
- nld/flow/state/__init__.py +11 -0
- nld/flow/state/config/__init__.py +11 -0
- nld/flow/state/config/state_backend_connector.py +105 -0
- nld/flow/state/events.py +46 -0
- nld/flow/state/factory.py +173 -0
- nld/flow/state/manager/__init__.py +11 -0
- nld/flow/state/manager/base.py +278 -0
- nld/flow/state/manager/by_key.py +23 -0
- nld/flow/state/manager/by_source_tst.py +26 -0
- nld/flow/state/manager/no_increment.py +23 -0
- nld/flow/state/state_backend_connector_resolver.py +170 -0
- nld/flow/task/__init__.py +29 -0
- nld/flow/task/data_flow_dependency_graph.py +164 -0
- nld/flow/task/data_flow_deploy_execute_task.py +177 -0
- nld/flow/task/data_flow_deploy_plan_task.py +3 -0
- nld/flow/task/data_flow_exec_task.py +345 -0
- nld/flow/task/data_flow_executor.py +389 -0
- nld/flow/task/data_flow_info.py +280 -0
- nld/flow/task/data_flow_state_renderers.py +387 -0
- nld/flow/task/data_flow_state_task.py +667 -0
- nld/flow/task/data_flow_step.py +45 -0
- nld/flow/task/data_flow_task.py +720 -0
- nld/flow/task/utils.py +0 -0
- nld/flow/utils/__init__.py +25 -0
- nld/flow/utils/flow_execution_params.py +23 -0
- nld/flow/utils/flow_loading_strategy.py +24 -0
- nld/flow/utils/flow_update_strategy.py +24 -0
- nld/flow/utils/flow_utils.py +4 -0
- nld/logging/__init__.py +53 -0
- nld/logging/base.py +90 -0
- nld/logging/events.py +124 -0
- nld/logging/logger.py +152 -0
- nld/parameters/__init__.py +17 -0
- nld/parameters/execution_params.py +221 -0
- nld/parameters/execution_params_def.py +10 -0
- nld/parameters/parser.py +151 -0
- nld/parameters/utils.py +25 -0
- nld/project/__init__.py +13 -0
- nld/project/additional_entity_config.py +78 -0
- nld/project/default_project.py +16 -0
- nld/project/project.py +242 -0
- nld/project/project_events.py +90 -0
- nld/project/project_exceptions.py +43 -0
- nld/project/project_variables.py +16 -0
- nld/project/task/__init__.py +9 -0
- nld/project/task/project_entity_info_task.py +81 -0
- nld/project/task/project_info_task.py +187 -0
- nld/py.typed +0 -0
- nld/pydantic/__init__.py +30 -0
- nld/pydantic/backend/__init__.py +11 -0
- nld/pydantic/backend/base_model_manager.py +240 -0
- nld/pydantic/backend/base_structure_mapper.py +63 -0
- nld/pydantic/base_model.py +400 -0
- nld/pydantic/entity_reference.py +109 -0
- nld/pydantic/field_utils.py +2 -0
- nld/pydantic/named_base_model.py +578 -0
- nld/pydantic/namespace.py +120 -0
- nld/pydantic/namespaced_base_model_wrapper.py +53 -0
- nld/pydantic/utils.py +55 -0
- nld/service/__init__.py +37 -0
- nld/service/entity_definition.py +91 -0
- nld/service/entity_definition_wrapper.py +126 -0
- nld/service/entity_provider.py +1060 -0
- nld/service/events.py +34 -0
- nld/service/exceptions.py +14 -0
- nld/service/file_output_service.py +145 -0
- nld/service/jinja_renderer.py +133 -0
- nld/service/model_read_util.py +303 -0
- nld/service/nld_entities.py +23 -0
- nld/service/nld_entity_registry.py +915 -0
- nld/structure/__init__.py +67 -0
- nld/structure/config/__init__.py +9 -0
- nld/structure/config/structure_config.py +51 -0
- nld/structure/deploy/__init__.py +67 -0
- nld/structure/deploy/structure_deploy_executor.py +437 -0
- nld/structure/deploy/structure_deploy_manager.py +328 -0
- nld/structure/deploy/structure_deploy_manifest.py +40 -0
- nld/structure/deploy/structure_deploy_planner.py +235 -0
- nld/structure/deploy/structure_diff.py +54 -0
- nld/structure/deploy/structure_diff_computer.py +262 -0
- nld/structure/deploy/structure_diff_ddl_generator.py +67 -0
- nld/structure/deploy/structure_manifest_discovery.py +38 -0
- nld/structure/deploy/structure_metadata_backend_manager.py +258 -0
- nld/structure/deploy/structure_metadata_models.py +88 -0
- nld/structure/deploy/structure_schema_history.py +220 -0
- nld/structure/events.py +56 -0
- nld/structure/exceptions.py +36 -0
- nld/structure/field/__init__.py +36 -0
- nld/structure/field/field.py +237 -0
- nld/structure/field/field_adapter.py +326 -0
- nld/structure/field/field_characterisation.py +63 -0
- nld/structure/field/field_characterisation_def.py +205 -0
- nld/structure/field/field_data_type.py +49 -0
- nld/structure/field/field_format_adapter.py +127 -0
- nld/structure/field/field_template.py +167 -0
- nld/structure/service/__init__.py +5 -0
- nld/structure/service/sql_renderer_wrapper.py +92 -0
- nld/structure/service/sql_template_wrapper.py +56 -0
- nld/structure/service/structure_builder.py +28 -0
- nld/structure/service/structure_characterisation_adapter.py +34 -0
- nld/structure/service/structure_sql_renderer.py +151 -0
- nld/structure/structure/__init__.py +39 -0
- nld/structure/structure/structure.py +884 -0
- nld/structure/structure/structure_adapter.py +239 -0
- nld/structure/structure/structure_characterisation.py +34 -0
- nld/structure/structure/structure_characterisation_def.py +100 -0
- nld/structure/structure/structure_definition.py +6 -0
- nld/structure/structure/structure_options.py +21 -0
- nld/structure/structure/structure_referential.py +22 -0
- nld/structure/structure/structure_template.py +38 -0
- nld/structure/structure_model/__init__.py +10 -0
- nld/structure/structure_model/structure_model.py +113 -0
- nld/structure/structure_model/structure_model_cardinality.py +14 -0
- nld/structure/structure_model/structure_model_link.py +51 -0
- nld/structure/task/__init__.py +31 -0
- nld/structure/task/structure_adapt_task.py +66 -0
- nld/structure/task/structure_build_task.py +58 -0
- nld/structure/task/structure_deploy_execute_task.py +3 -0
- nld/structure/task/structure_deploy_plan_task.py +3 -0
- nld/structure/task/structure_deploy_task.py +292 -0
- nld/structure/task/structure_info_task.py +241 -0
- nld/structure/task/structure_sql_renderer_task.py +69 -0
- nld/task/__init__.py +25 -0
- nld/task/base/__init__.py +4 -0
- nld/task/base/base_step.py +44 -0
- nld/task/base/base_task.py +112 -0
- nld/task/base/std_task.py +42 -0
- nld/task/context/__init__.py +9 -0
- nld/task/context/context.py +211 -0
- nld/task/context/env_var.py +4 -0
- nld/task/context/request.py +129 -0
- nld/task/context/variables.py +26 -0
- nld/task/execution.py +82 -0
- nld/task/task_events.py +69 -0
- nld/task/task_module_execution.py +191 -0
- nld/task/task_utils.py +49 -0
- nld/utils/__init__.py +21 -0
- nld/utils/datetime_util.py +262 -0
- nld/utils/decorator_utils.py +16 -0
- nld/utils/enum_utils.py +14 -0
- nld/utils/exception_utils.py +27 -0
- nld/utils/file_util.py +434 -0
- nld/utils/import_utils.py +57 -0
- nld/utils/inspect_utils.py +128 -0
- nld/utils/jinja_utils.py +57 -0
- nld/utils/mixin.py +45 -0
- nld/utils/module_loader.py +193 -0
- nld/utils/requestor_utils.py +9 -0
- nld/utils/requests_util.py +25 -0
- nld/utils/sqlglot/__init__.py +27 -0
- nld/utils/sqlglot/base_ddl.py +340 -0
- nld/utils/sqlglot/base_dml.py +349 -0
- nld/utils/sqlglot/utils.py +99 -0
- nld/utils/string_utils.py +21 -0
- nld/utils/user_display.py +205 -0
- nld/utils/variable_utils.py +24 -0
- nld/utils/yaml_util.py +38 -0
- nld_core-0.1.1a1.dist-info/METADATA +185 -0
- nld_core-0.1.1a1.dist-info/RECORD +467 -0
- nld_core-0.1.1a1.dist-info/WHEEL +5 -0
- nld_core-0.1.1a1.dist-info/entry_points.txt +2 -0
- nld_core-0.1.1a1.dist-info/licenses/LICENSE.md +201 -0
- nld_core-0.1.1a1.dist-info/top_level.txt +1 -0
nld/business/__init__.py
ADDED
|
@@ -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,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
|
+
)
|