fdc-shared-kernel 0.0.197__tar.gz → 0.0.199__tar.gz
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.
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/PKG-INFO +1 -1
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/PKG-INFO +1 -1
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/SOURCES.txt +5 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/pyproject.toml +1 -1
- fdc_shared_kernel-0.0.199/shared_kernel/aws/athena_client.py +27 -0
- fdc_shared_kernel-0.0.199/shared_kernel/data_warehouse_handlers/connections/csv_warehouse_connection.py +161 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/fabric_sql_warehouse_connection.py +1 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/mssql_warehouse_connection.py +1 -1
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/mysql_warehouse_connection.py +2 -1
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/postgresql_warehouse_connection.py +1 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.py +1 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py +2 -0
- fdc_shared_kernel-0.0.199/shared_kernel/data_warehouse_handlers/csv_handler.py +53 -0
- fdc_shared_kernel-0.0.199/shared_kernel/data_warehouse_handlers/query_executors/csv_query_executor.py +105 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py +2 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/dataclasses/warehouse_configs.py +13 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/__init__.py +1 -0
- fdc_shared_kernel-0.0.199/shared_kernel/datatype_mappings/connectors_to_system/csv.py +23 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/enums/connection_engine.py +1 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/schema_onboarding_tracker.py +11 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/task_manager.py +36 -0
- fdc_shared_kernel-0.0.199/shared_kernel/tests/utils/__init__.py +0 -0
- fdc_shared_kernel-0.0.197/shared_kernel/datatype_mappings/connectors_to_system/csv.py +0 -1
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/README.md +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/README_pypi.md +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/dependency_links.txt +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/requires.txt +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/top_level.txt +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/requirements.txt +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/setup.cfg +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/agent_communication_channel/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/agent_communication_channel/agent_channel.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/agent_communication_channel/contexts.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/agent_communication_channel/event_channel.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/ai_audit_log/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/ai_chat_persistence/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/ai_chat_persistence/chat_persistence.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/async_task_executor/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/async_task_executor/async_task_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/auth/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/auth/jwt_helper.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/auth/token_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/auth/workbook_permission_handler.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/batch_job → fdc_shared_kernel-0.0.199/shared_kernel/aws}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/batch_job/job_handlers → fdc_shared_kernel-0.0.199/shared_kernel/batch_job}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/batch_job_status_tracker/container_job_status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/batch_job/job_storage_managers → fdc_shared_kernel-0.0.199/shared_kernel/batch_job/job_handlers}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_handlers/aws_batch_job_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_handlers/azure_apps_job_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_handlers/job_handler_factory.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_handlers/job_status_mapper.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/dataclasses → fdc_shared_kernel-0.0.199/shared_kernel/batch_job/job_storage_managers}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_storage_managers/azure_blob_storage_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_storage_managers/job_storage_manager_factory.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/batch_job/job_storage_managers/s3_job_storage_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/config/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/constants/constants.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/base_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/custom_query_builders/databricks_query.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/databricks_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/fabric_sql_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/factory.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/jdbc_driver_registry.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/jdbc_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/mssql_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/mysql_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/odbc_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/postgresql_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/databricks_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/fabric_sql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/mssql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/mysql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/postgresql_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/redshift_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/query_executors/snowflake_query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/redshift_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/snowflake_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/data_warehouse_handlers/utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/database/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/datatype_mappings → fdc_shared_kernel-0.0.199/shared_kernel/dataclasses}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/dataclasses/aws_batch_job_context.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/dataclasses/azure_container_app_job_context.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/dataclasses/event_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/dataclasses/job_context.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/dataclasses/job_record_dataclasses.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/models → fdc_shared_kernel-0.0.199/shared_kernel/datatype_mappings}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/databricks.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/db2.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/jdbc.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/jira.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/mssql.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/mysql.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/oracle.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/postgres.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/redshift.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/salesforce.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/snowflake.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/connectors_to_system/sqlalchemy.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/system_to_warehouse/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/system_to_warehouse/postgres.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/datatype_mappings/system_to_warehouse/redshift.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/enums/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/enums/async_task_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/enums/status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/event_executor/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/event_executor/event_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/event_executor/job_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/event_executor/utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/batch_job_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/configuration_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/custom_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/data_validation_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/http_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/infrastructure_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/operational_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/security_exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/exceptions/user_intervention_exception.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/http/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/http/httpx_http_client.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/http/request_http_client.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/base_job_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/data_warehouse_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/databus.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/encryption.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/http.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/keyvault.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/query_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/storage_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/interfaces/warehouse_connection.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/logger/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/aws_databus.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/azure_databus.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/http_databus.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/nats_databus.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/nats_publisher.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/nats_test.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/utils/aws_utility.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/utils/azure_utility.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/messaging/utils/event_messages.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/metrics/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/metrics/status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/storage_handlers → fdc_shared_kernel-0.0.199/shared_kernel/models}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/registries/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/registries/schema_onboarding_event_registry.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/registries/service_event_registry.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/base_tracker.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/enums.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/exceptions.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/run_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/shared_helpers.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/task_determination.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/task_helpers.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/template_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/schema_onboarding_tracker/utility_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/encryption/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/encryption/manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/encryption/providers.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/key_vault/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/key_vault/aws_secret_manager.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/security/key_vault/azure_keyvault.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/status_tracker/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/status_tracker/status_tracker.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/tests → fdc_shared_kernel-0.0.199/shared_kernel/storage_handlers}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/storage_handlers/blob_file_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/storage_handlers/s3_storage_handler.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/tests/config → fdc_shared_kernel-0.0.199/shared_kernel/tests}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/tests/logger → fdc_shared_kernel-0.0.199/shared_kernel/tests/config}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/config/test_config.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/tests/messaging → fdc_shared_kernel-0.0.199/shared_kernel/tests/logger}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/logger/test_logger.py +0 -0
- {fdc_shared_kernel-0.0.197/shared_kernel/tests/utils → fdc_shared_kernel-0.0.199/shared_kernel/tests/messaging}/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/messaging/test_aws_databus.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/messaging/test_event_executor.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/messaging/test_nats_interface.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/security/test_encryption.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/utils/test_data_validators.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/utils/test_date_format_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/tests/utils/test_string_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/traceability/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/traceability/traceability_handler.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/data_validators_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/date_format_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/date_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/logging_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/request_id.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/string_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/template_renderer.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/thread_debug_utils.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/thread_local_storage.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/utils/thread_log_traker.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/tests/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/tests/messaging/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/tests/messaging/utils/__init__.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/tests/messaging/utils/test_aws_utility.py +0 -0
- {fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/tests/test_job_executor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fdc_shared_kernel
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.199
|
|
4
4
|
Summary: Shared library for microservice
|
|
5
5
|
Author-email: Shikhil S <shikhil.s@dbizsolution.com>, Ahammed Akdham N <ahammedakdham.n@dbizsolution.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fdc_shared_kernel
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.199
|
|
4
4
|
Summary: Shared library for microservice
|
|
5
5
|
Author-email: Shikhil S <shikhil.s@dbizsolution.com>, Ahammed Akdham N <ahammedakdham.n@dbizsolution.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
{fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/SOURCES.txt
RENAMED
|
@@ -21,6 +21,8 @@ shared_kernel/auth/__init__.py
|
|
|
21
21
|
shared_kernel/auth/jwt_helper.py
|
|
22
22
|
shared_kernel/auth/token_handler.py
|
|
23
23
|
shared_kernel/auth/workbook_permission_handler.py
|
|
24
|
+
shared_kernel/aws/__init__.py
|
|
25
|
+
shared_kernel/aws/athena_client.py
|
|
24
26
|
shared_kernel/batch_job/__init__.py
|
|
25
27
|
shared_kernel/batch_job/batch_job_status_tracker/container_job_status_tracker.py
|
|
26
28
|
shared_kernel/batch_job/job_handlers/__init__.py
|
|
@@ -36,6 +38,7 @@ shared_kernel/config/__init__.py
|
|
|
36
38
|
shared_kernel/constants/constants.py
|
|
37
39
|
shared_kernel/data_warehouse_handlers/__init__.py
|
|
38
40
|
shared_kernel/data_warehouse_handlers/base_executor.py
|
|
41
|
+
shared_kernel/data_warehouse_handlers/csv_handler.py
|
|
39
42
|
shared_kernel/data_warehouse_handlers/databricks_handler.py
|
|
40
43
|
shared_kernel/data_warehouse_handlers/fabric_sql_handler.py
|
|
41
44
|
shared_kernel/data_warehouse_handlers/factory.py
|
|
@@ -49,6 +52,7 @@ shared_kernel/data_warehouse_handlers/redshift_handler.py
|
|
|
49
52
|
shared_kernel/data_warehouse_handlers/snowflake_handler.py
|
|
50
53
|
shared_kernel/data_warehouse_handlers/utils.py
|
|
51
54
|
shared_kernel/data_warehouse_handlers/warehouse_handlers_map.py
|
|
55
|
+
shared_kernel/data_warehouse_handlers/connections/csv_warehouse_connection.py
|
|
52
56
|
shared_kernel/data_warehouse_handlers/connections/databricks_warehouse_connection.py
|
|
53
57
|
shared_kernel/data_warehouse_handlers/connections/fabric_sql_warehouse_connection.py
|
|
54
58
|
shared_kernel/data_warehouse_handlers/connections/jdbc_warehouse_connection.py
|
|
@@ -58,6 +62,7 @@ shared_kernel/data_warehouse_handlers/connections/postgresql_warehouse_connectio
|
|
|
58
62
|
shared_kernel/data_warehouse_handlers/connections/redshift_warehouse_connection.py
|
|
59
63
|
shared_kernel/data_warehouse_handlers/connections/snowflake_warehouse_connection.py
|
|
60
64
|
shared_kernel/data_warehouse_handlers/custom_query_builders/databricks_query.py
|
|
65
|
+
shared_kernel/data_warehouse_handlers/query_executors/csv_query_executor.py
|
|
61
66
|
shared_kernel/data_warehouse_handlers/query_executors/databricks_query_executor.py
|
|
62
67
|
shared_kernel/data_warehouse_handlers/query_executors/fabric_sql_query_executor.py
|
|
63
68
|
shared_kernel/data_warehouse_handlers/query_executors/jdbc_query_executor.py
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import boto3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_assumed_role_credentials(role_arn: str, service_name: str) -> dict:
|
|
5
|
+
sts_client = boto3.client("sts")
|
|
6
|
+
assumed_role = sts_client.assume_role(
|
|
7
|
+
RoleArn=role_arn, RoleSessionName=f"{str(service_name).capitalize()}Session"
|
|
8
|
+
)
|
|
9
|
+
return assumed_role["Credentials"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def build_aws_client(service_name: str, role_arn: str = None, region: str = None):
|
|
13
|
+
"""Build a boto3 client for `service_name`, optionally assuming `role_arn`."""
|
|
14
|
+
if role_arn:
|
|
15
|
+
credentials = get_assumed_role_credentials(role_arn, service_name)
|
|
16
|
+
return boto3.client(
|
|
17
|
+
service_name,
|
|
18
|
+
aws_access_key_id=credentials["AccessKeyId"],
|
|
19
|
+
aws_secret_access_key=credentials["SecretAccessKey"],
|
|
20
|
+
aws_session_token=credentials["SessionToken"],
|
|
21
|
+
region_name=region,
|
|
22
|
+
)
|
|
23
|
+
return boto3.client(service_name, region_name=region) if region else boto3.client(service_name)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_athena_client(role_arn: str = None, region: str = None):
|
|
27
|
+
return build_aws_client("athena", role_arn=role_arn, region=region)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
|
|
4
|
+
from shared_kernel.aws.athena_client import build_athena_client, build_aws_client
|
|
5
|
+
from shared_kernel.config import Config
|
|
6
|
+
from shared_kernel.dataclasses.warehouse_configs import CSVConfig
|
|
7
|
+
from shared_kernel.exceptions.http_exceptions import BadRequest
|
|
8
|
+
from shared_kernel.interfaces.warehouse_connection import DataWarehouseConnection, cancel_check_connection
|
|
9
|
+
from shared_kernel.logger import Logger
|
|
10
|
+
|
|
11
|
+
config = Config()
|
|
12
|
+
logger = Logger(config.get("APP_NAME"))
|
|
13
|
+
|
|
14
|
+
TERMINAL_STATES = ("SUCCEEDED", "FAILED", "CANCELLED")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AthenaCursor:
|
|
18
|
+
"""Cursor-like adapter over boto3 Athena start_query_execution/poll/get_query_results,
|
|
19
|
+
so Athena's async query model can be used behind the same cursor-shaped contract.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
athena_client,
|
|
25
|
+
database: str,
|
|
26
|
+
output_location: str,
|
|
27
|
+
role_arn: str = None,
|
|
28
|
+
region: str = None,
|
|
29
|
+
poll_interval: float = 1.0,
|
|
30
|
+
):
|
|
31
|
+
self._client = athena_client
|
|
32
|
+
self._database = database
|
|
33
|
+
self._output_location = output_location
|
|
34
|
+
self._role_arn = role_arn
|
|
35
|
+
self._region = region
|
|
36
|
+
self._poll_interval = poll_interval
|
|
37
|
+
self._columns = []
|
|
38
|
+
self._column_types = []
|
|
39
|
+
self._rows = []
|
|
40
|
+
self._exec_id = None
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def description(self):
|
|
44
|
+
# DB-API-shaped: (name, type_code, ...) — type_code holds the Athena/
|
|
45
|
+
# Presto native type string (e.g. "varchar", "bigint")
|
|
46
|
+
return [
|
|
47
|
+
(name, type_code, None, None, None, None, None)
|
|
48
|
+
for name, type_code in zip(self._columns, self._column_types)
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
def execute(self, query: str, params: tuple = None):
|
|
52
|
+
exec_response = self._client.start_query_execution(
|
|
53
|
+
QueryString=query,
|
|
54
|
+
QueryExecutionContext={"Database": self._database},
|
|
55
|
+
ResultConfiguration={"OutputLocation": self._output_location},
|
|
56
|
+
WorkGroup="primary",
|
|
57
|
+
)
|
|
58
|
+
self._exec_id = exec_response["QueryExecutionId"]
|
|
59
|
+
|
|
60
|
+
while True:
|
|
61
|
+
stats = self._client.get_query_execution(QueryExecutionId=self._exec_id)
|
|
62
|
+
state = stats["QueryExecution"]["Status"]["State"]
|
|
63
|
+
if state in TERMINAL_STATES:
|
|
64
|
+
break
|
|
65
|
+
time.sleep(self._poll_interval)
|
|
66
|
+
|
|
67
|
+
if state != "SUCCEEDED":
|
|
68
|
+
reason = stats["QueryExecution"]["Status"].get("StateChangeReason", "Unknown error")
|
|
69
|
+
raise Exception(f"Athena query {state.lower()}: {reason}")
|
|
70
|
+
|
|
71
|
+
response = self._client.get_query_results(QueryExecutionId=self._exec_id, MaxResults=1000)
|
|
72
|
+
column_info = response["ResultSet"]["ResultSetMetadata"]["ColumnInfo"]
|
|
73
|
+
self._columns = [c.get("Name", "") for c in column_info]
|
|
74
|
+
self._column_types = [c.get("Type", "varchar") for c in column_info]
|
|
75
|
+
|
|
76
|
+
# Athena's first result row echoes the column headers (as VarCharValue),
|
|
77
|
+
# skip it — real column names/order already come from ColumnInfo above.
|
|
78
|
+
rows_data = response["ResultSet"]["Rows"]
|
|
79
|
+
data_rows = rows_data[1:] if rows_data else []
|
|
80
|
+
self._rows = [
|
|
81
|
+
tuple(c.get("VarCharValue", "") for c in r["Data"]) for r in data_rows
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
self._delete_output()
|
|
85
|
+
return self
|
|
86
|
+
|
|
87
|
+
def _delete_output(self):
|
|
88
|
+
try:
|
|
89
|
+
s3_client = build_aws_client("s3", role_arn=self._role_arn, region=self._region)
|
|
90
|
+
bucket, prefix = _parse_s3_location(self._output_location)
|
|
91
|
+
s3_client.delete_object(Bucket=bucket, Key=f"{prefix}{self._exec_id}.csv")
|
|
92
|
+
s3_client.delete_object(Bucket=bucket, Key=f"{prefix}{self._exec_id}.csv.metadata")
|
|
93
|
+
except Exception as e:
|
|
94
|
+
logger.warning(f"Failed to delete Athena output for {self._exec_id}: {e}")
|
|
95
|
+
|
|
96
|
+
def fetchall(self):
|
|
97
|
+
return self._rows
|
|
98
|
+
|
|
99
|
+
def fetchone(self):
|
|
100
|
+
return self._rows[0] if self._rows else None
|
|
101
|
+
|
|
102
|
+
def cancel(self):
|
|
103
|
+
if self._exec_id:
|
|
104
|
+
self._client.stop_query_execution(QueryExecutionId=self._exec_id)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _parse_s3_location(s3_uri: str):
|
|
108
|
+
without_scheme = s3_uri.replace("s3://", "", 1)
|
|
109
|
+
bucket, _, prefix = without_scheme.partition("/")
|
|
110
|
+
if prefix and not prefix.endswith("/"):
|
|
111
|
+
prefix += "/"
|
|
112
|
+
return bucket, prefix
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class CSVWarehouseConnection(DataWarehouseConnection):
|
|
116
|
+
"""Athena/Glue-backed connection for the CSV data source.
|
|
117
|
+
|
|
118
|
+
Athena is stateless and per-query (no persistent session), so unlike the
|
|
119
|
+
SQLAlchemy-pooled connections this class has no engine/connection to keep
|
|
120
|
+
alive between queries.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
def __init__(self, source_config: CSVConfig):
|
|
124
|
+
if source_config is None:
|
|
125
|
+
raise ValueError("Missing required parameter: source_config (CSVConfig)")
|
|
126
|
+
self._config = source_config
|
|
127
|
+
self._client = None
|
|
128
|
+
|
|
129
|
+
def _get_client(self):
|
|
130
|
+
if self._client is None:
|
|
131
|
+
self._client = build_athena_client(
|
|
132
|
+
role_arn=self._config.athena_cross_account_role_arn,
|
|
133
|
+
region=self._config.region,
|
|
134
|
+
)
|
|
135
|
+
return self._client
|
|
136
|
+
|
|
137
|
+
@contextmanager
|
|
138
|
+
@cancel_check_connection
|
|
139
|
+
def get_connection(self, retries: int = 3, delay: int = 5, query_timeout: int = 30):
|
|
140
|
+
cursor = AthenaCursor(
|
|
141
|
+
athena_client=self._get_client(),
|
|
142
|
+
database=self._config.glue_database,
|
|
143
|
+
output_location=self._config.athena_output_location,
|
|
144
|
+
role_arn=self._config.athena_cross_account_role_arn,
|
|
145
|
+
region=self._config.region,
|
|
146
|
+
)
|
|
147
|
+
yield cursor
|
|
148
|
+
|
|
149
|
+
def is_valid_connection(self) -> bool:
|
|
150
|
+
return True
|
|
151
|
+
|
|
152
|
+
def close_connection(self):
|
|
153
|
+
self._client = None
|
|
154
|
+
|
|
155
|
+
def test_connection(self) -> bool:
|
|
156
|
+
try:
|
|
157
|
+
with self.get_connection(retries=1) as cursor:
|
|
158
|
+
cursor.execute("SELECT 1")
|
|
159
|
+
return True
|
|
160
|
+
except Exception as e:
|
|
161
|
+
raise BadRequest(f"Athena/Glue connection test failed: {str(e)}") from e
|
|
@@ -69,6 +69,7 @@ class FabricSQLWarehouseConnection(DataWarehouseConnection):
|
|
|
69
69
|
f"DATABASE={cfg.database};"
|
|
70
70
|
"Encrypt=yes;"
|
|
71
71
|
"TrustServerCertificate=no;"
|
|
72
|
+
"Connection Timeout=10;"
|
|
72
73
|
)
|
|
73
74
|
# We use odbc_connect query param to prevent SQLAlchemy dialect from auto-injecting
|
|
74
75
|
# conflicting credentials/parameters (avoiding error FA005).
|
|
@@ -60,7 +60,7 @@ class MSSQLWarehouseConnection(DataWarehouseConnection):
|
|
|
60
60
|
connection_string = get_constant("mssql", "CONNECTION_STRING").format(
|
|
61
61
|
cfg.username, password, cfg.host, int(cfg.port), cfg.database
|
|
62
62
|
)
|
|
63
|
-
connect_args = {}
|
|
63
|
+
connect_args = {"timeout": 10}
|
|
64
64
|
|
|
65
65
|
pool_size = int(Config.get("MSSQL_POOL_SIZE", 10))
|
|
66
66
|
|
|
@@ -64,6 +64,7 @@ class PostgreSQLWarehouseConnection(DataWarehouseConnection):
|
|
|
64
64
|
pool_size = int(Config.get("POSTGRES_POOL_SIZE", 10))
|
|
65
65
|
self._engines[key] = create_engine(
|
|
66
66
|
url,
|
|
67
|
+
connect_args={"connect_timeout": 10},
|
|
67
68
|
pool_size=pool_size,
|
|
68
69
|
max_overflow=5,
|
|
69
70
|
pool_timeout=30,
|
|
@@ -197,6 +197,7 @@ class RedshiftWarehouseConnection(DataWarehouseConnection):
|
|
|
197
197
|
pool_size = int(Config.get("REDSHIFT_POOL_SIZE", 10))
|
|
198
198
|
self._engines[key] = create_engine(
|
|
199
199
|
url,
|
|
200
|
+
connect_args={"timeout": 10},
|
|
200
201
|
pool_size=pool_size,
|
|
201
202
|
max_overflow=5,
|
|
202
203
|
pool_timeout=30,
|
|
@@ -63,6 +63,7 @@ class SnowflakeWarehouseConnection(DataWarehouseConnection):
|
|
|
63
63
|
schema=cfg.schema,
|
|
64
64
|
private_key=pkb,
|
|
65
65
|
authenticator="snowflake_jwt",
|
|
66
|
+
validate_default_parameters=True,
|
|
66
67
|
)
|
|
67
68
|
else:
|
|
68
69
|
self._conn = snowflake.connector.connect(
|
|
@@ -71,6 +72,7 @@ class SnowflakeWarehouseConnection(DataWarehouseConnection):
|
|
|
71
72
|
account=cfg.account,
|
|
72
73
|
database=cfg.database,
|
|
73
74
|
schema=cfg.schema,
|
|
75
|
+
validate_default_parameters=True,
|
|
74
76
|
)
|
|
75
77
|
self._cursor = self._conn.cursor()
|
|
76
78
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from pypika import Query
|
|
2
|
+
|
|
3
|
+
from shared_kernel.data_warehouse_handlers.connections.csv_warehouse_connection import CSVWarehouseConnection
|
|
4
|
+
from shared_kernel.data_warehouse_handlers.query_executors.csv_query_executor import CSVQueryExecutor
|
|
5
|
+
from shared_kernel.dataclasses.warehouse_configs import CSVConfig
|
|
6
|
+
from shared_kernel.interfaces.data_warehouse_handler import WarehouseHandler
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CSVWarehouseHandler(WarehouseHandler):
|
|
10
|
+
|
|
11
|
+
def get_config(self) -> CSVConfig:
|
|
12
|
+
required = ("glue_database", "region", "s3_bucket", "s3_prefix", "athena_output_location")
|
|
13
|
+
missing = [f for f in required if not self.payload.get(f)]
|
|
14
|
+
if missing:
|
|
15
|
+
raise ValueError(f"CSV payload is missing required fields: {missing}.")
|
|
16
|
+
|
|
17
|
+
return CSVConfig(
|
|
18
|
+
glue_database=str(self.payload.get("glue_database")).strip(),
|
|
19
|
+
region=str(self.payload.get("region")).strip(),
|
|
20
|
+
s3_bucket=str(self.payload.get("s3_bucket")).strip(),
|
|
21
|
+
s3_prefix=str(self.payload.get("s3_prefix")).strip(),
|
|
22
|
+
athena_output_location=str(self.payload.get("athena_output_location")).strip(),
|
|
23
|
+
athena_cross_account_role_arn=self.payload.get("athena_cross_account_role_arn"),
|
|
24
|
+
schema=self.payload.get("schema"),
|
|
25
|
+
schema_list=self.payload.get("schema_list"),
|
|
26
|
+
pagination=self.pagination,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def _build_connection(self) -> CSVWarehouseConnection:
|
|
30
|
+
"""Internal — not exposed to callers."""
|
|
31
|
+
return CSVWarehouseConnection(source_config=self.get_config())
|
|
32
|
+
|
|
33
|
+
def get_executor(self) -> CSVQueryExecutor:
|
|
34
|
+
return CSVQueryExecutor(warehouse_connection=self._build_connection())
|
|
35
|
+
|
|
36
|
+
def get_query_object(self) -> Query:
|
|
37
|
+
return Query
|
|
38
|
+
|
|
39
|
+
def create_records_and_count_query(
|
|
40
|
+
self,
|
|
41
|
+
query: str,
|
|
42
|
+
limit: str,
|
|
43
|
+
page: str,
|
|
44
|
+
) -> tuple[str, str]:
|
|
45
|
+
count_query = f"SELECT COUNT(*) FROM ({query}) AS _count"
|
|
46
|
+
|
|
47
|
+
if limit:
|
|
48
|
+
query = f"{query} LIMIT {int(limit)}"
|
|
49
|
+
if page:
|
|
50
|
+
offset = (int(page) - 1) * int(limit)
|
|
51
|
+
query = f"{query} OFFSET {offset}"
|
|
52
|
+
|
|
53
|
+
return count_query, query
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
from shared_kernel.config import Config
|
|
6
|
+
from shared_kernel.data_warehouse_handlers.base_executor import BaseQueryExecutor, cancel_check
|
|
7
|
+
from shared_kernel.interfaces.warehouse_connection import DataWarehouseConnection
|
|
8
|
+
from shared_kernel.logger import Logger
|
|
9
|
+
|
|
10
|
+
config = Config()
|
|
11
|
+
logger = Logger(config.get("APP_NAME"))
|
|
12
|
+
MAX_QUERY_CONCURRENCY = 5
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CSVQueryExecutor(BaseQueryExecutor):
|
|
16
|
+
"""Query executor for the Athena/Glue-backed CSV data source."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, warehouse_connection: DataWarehouseConnection) -> None:
|
|
19
|
+
self.warehouse_connection = warehouse_connection
|
|
20
|
+
|
|
21
|
+
@cancel_check
|
|
22
|
+
def execute_query(
|
|
23
|
+
self,
|
|
24
|
+
query: str,
|
|
25
|
+
params: Optional[tuple] = None,
|
|
26
|
+
) -> List[Dict[str, Any]]:
|
|
27
|
+
with self.warehouse_connection.get_connection() as cursor:
|
|
28
|
+
self.active_connections.add(cursor)
|
|
29
|
+
try:
|
|
30
|
+
logger.info(f"Executing Athena query: {query}")
|
|
31
|
+
start = time.perf_counter()
|
|
32
|
+
cursor.execute(query, params)
|
|
33
|
+
elapsed = time.perf_counter() - start
|
|
34
|
+
logger.info(f"Athena query executed in {elapsed:.6f}s")
|
|
35
|
+
|
|
36
|
+
columns = [col[0] for col in cursor.description]
|
|
37
|
+
return [dict(zip(columns, row)) for row in cursor.fetchall()]
|
|
38
|
+
except Exception as e:
|
|
39
|
+
logger.error(f"Athena query failed: {query} — {e}", exc_info=True)
|
|
40
|
+
raise Exception(f"Query execution failed: {str(e)}") from e
|
|
41
|
+
finally:
|
|
42
|
+
self.active_connections.discard(cursor)
|
|
43
|
+
|
|
44
|
+
def execute_queries(
|
|
45
|
+
self,
|
|
46
|
+
queries: List[str],
|
|
47
|
+
) -> List[List[Dict[str, Any]]]:
|
|
48
|
+
if not queries:
|
|
49
|
+
return []
|
|
50
|
+
|
|
51
|
+
indexed: List[Tuple[int, str]] = list(enumerate(queries))
|
|
52
|
+
results: List[Optional[List[Dict[str, Any]]]] = [None] * len(queries)
|
|
53
|
+
|
|
54
|
+
with ThreadPoolExecutor(max_workers=MAX_QUERY_CONCURRENCY) as pool:
|
|
55
|
+
future_to_index = {
|
|
56
|
+
pool.submit(self.execute_query, query): idx
|
|
57
|
+
for idx, query in indexed
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for future in as_completed(future_to_index):
|
|
61
|
+
idx = future_to_index[future]
|
|
62
|
+
try:
|
|
63
|
+
results[idx] = future.result()
|
|
64
|
+
except Exception as e:
|
|
65
|
+
for pending in future_to_index:
|
|
66
|
+
if not pending.done():
|
|
67
|
+
pending.cancel()
|
|
68
|
+
raise Exception(
|
|
69
|
+
f"Parallel query execution failed on query index {idx}: {e}"
|
|
70
|
+
) from e
|
|
71
|
+
|
|
72
|
+
return results
|
|
73
|
+
|
|
74
|
+
@cancel_check
|
|
75
|
+
def execute_query_with_column_types(
|
|
76
|
+
self,
|
|
77
|
+
query: str,
|
|
78
|
+
params: Optional[tuple] = None,
|
|
79
|
+
) -> Tuple[List[Dict[str, Any]], List[Tuple]]:
|
|
80
|
+
with self.warehouse_connection.get_connection() as cursor:
|
|
81
|
+
self.active_connections.add(cursor)
|
|
82
|
+
try:
|
|
83
|
+
logger.info(f"Executing Athena query with column types: {query}")
|
|
84
|
+
start = time.perf_counter()
|
|
85
|
+
cursor.execute(query, params)
|
|
86
|
+
elapsed = time.perf_counter() - start
|
|
87
|
+
logger.info(f"Athena query executed in {elapsed:.6f}s")
|
|
88
|
+
|
|
89
|
+
description = cursor.description or []
|
|
90
|
+
if not description:
|
|
91
|
+
return [], []
|
|
92
|
+
|
|
93
|
+
columns = [col[0] for col in description]
|
|
94
|
+
rows = [dict(zip(columns, row)) for row in cursor.fetchall()]
|
|
95
|
+
return rows, description
|
|
96
|
+
except Exception as e:
|
|
97
|
+
logger.error(f"Athena query failed: {query} — {e}", exc_info=True)
|
|
98
|
+
raise Exception(f"Query execution failed: {str(e)}") from e
|
|
99
|
+
finally:
|
|
100
|
+
self.active_connections.discard(cursor)
|
|
101
|
+
|
|
102
|
+
def cancel(self) -> None:
|
|
103
|
+
logger.warning(f"Cancelling {len(self.active_connections)} active Athena query cursor(s).")
|
|
104
|
+
for cursor in list(self.active_connections):
|
|
105
|
+
self._cancel_connection(cursor)
|
|
@@ -8,6 +8,7 @@ from shared_kernel.data_warehouse_handlers.redshift_handler import RedshiftWareh
|
|
|
8
8
|
from shared_kernel.data_warehouse_handlers.snowflake_handler import SnowflakeWarehouseHandler
|
|
9
9
|
from shared_kernel.data_warehouse_handlers.jdbc_handler import JDBCWarehouseHandler
|
|
10
10
|
from shared_kernel.data_warehouse_handlers.fabric_sql_handler import FabricSQLWarehouseHandler
|
|
11
|
+
from shared_kernel.data_warehouse_handlers.csv_handler import CSVWarehouseHandler
|
|
11
12
|
from shared_kernel.enums.connection_engine import ConnectionEngine
|
|
12
13
|
|
|
13
14
|
|
|
@@ -22,4 +23,5 @@ warehouse_handlers = {
|
|
|
22
23
|
ConnectionEngine.DATABRICKS.value: DatabricksWarehouseHandler,
|
|
23
24
|
ConnectionEngine.JDBC.value: JDBCWarehouseHandler,
|
|
24
25
|
ConnectionEngine.FABRIC_SQL.value: FabricSQLWarehouseHandler,
|
|
26
|
+
ConnectionEngine.CSV.value: CSVWarehouseHandler,
|
|
25
27
|
}
|
|
@@ -112,6 +112,19 @@ class SnowflakeConfig(BaseConfig):
|
|
|
112
112
|
default_schema: str = "PUBLIC"
|
|
113
113
|
|
|
114
114
|
|
|
115
|
+
@dataclass
|
|
116
|
+
class CSVConfig(BaseConfig):
|
|
117
|
+
"""Configuration for the AWS Glue/Athena-backed CSV data source."""
|
|
118
|
+
|
|
119
|
+
glue_database: str
|
|
120
|
+
region: str
|
|
121
|
+
s3_bucket: str
|
|
122
|
+
s3_prefix: str
|
|
123
|
+
athena_output_location: str
|
|
124
|
+
athena_cross_account_role_arn: Optional[str] = None
|
|
125
|
+
default_schema: Optional[str] = None
|
|
126
|
+
|
|
127
|
+
|
|
115
128
|
@dataclass
|
|
116
129
|
class JDBCConfig(BaseConfig):
|
|
117
130
|
"""Configuration for JDBC-based connections."""
|
|
@@ -5,4 +5,5 @@ from shared_kernel.datatype_mappings.connectors_to_system.databricks import data
|
|
|
5
5
|
from shared_kernel.datatype_mappings.connectors_to_system.mysql import mysql_to_system
|
|
6
6
|
from shared_kernel.datatype_mappings.connectors_to_system.snowflake import snowflake_to_system
|
|
7
7
|
from shared_kernel.datatype_mappings.connectors_to_system.sqlalchemy import sqlalchemy_to_system
|
|
8
|
+
from shared_kernel.datatype_mappings.connectors_to_system.csv import csv_to_system
|
|
8
9
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
csv_to_system = {
|
|
2
|
+
"VARCHAR": "string",
|
|
3
|
+
"CHAR": "string",
|
|
4
|
+
"STRING": "string",
|
|
5
|
+
"BOOLEAN": "boolean",
|
|
6
|
+
"TINYINT": "integer",
|
|
7
|
+
"SMALLINT": "integer",
|
|
8
|
+
"INTEGER": "integer",
|
|
9
|
+
"INT": "integer",
|
|
10
|
+
"BIGINT": "integer",
|
|
11
|
+
"REAL": "double",
|
|
12
|
+
"FLOAT": "double",
|
|
13
|
+
"DOUBLE": "double",
|
|
14
|
+
"DECIMAL": "numeric",
|
|
15
|
+
"DATE": "date",
|
|
16
|
+
"TIMESTAMP": "timestamp",
|
|
17
|
+
"TIMESTAMP WITH TIME ZONE": "timestamp",
|
|
18
|
+
"VARBINARY": "binary",
|
|
19
|
+
"JSON": "json",
|
|
20
|
+
"ARRAY": "array",
|
|
21
|
+
"MAP": "json",
|
|
22
|
+
"ROW": "json",
|
|
23
|
+
}
|
|
@@ -157,6 +157,17 @@ class SchemaOnboardingTracker(BaseSchemaOnboardingTracker):
|
|
|
157
157
|
task_id, status, output, error, error_message, metadata
|
|
158
158
|
)
|
|
159
159
|
|
|
160
|
+
def claim_task(
|
|
161
|
+
self, task_id: str, expected_status: TaskStatus, claimed_status: TaskStatus = TaskStatus.RUNNING
|
|
162
|
+
) -> bool:
|
|
163
|
+
"""
|
|
164
|
+
Atomically transitions a task from expected_status to claimed_status.
|
|
165
|
+
Returns True only if this call won the transition — see
|
|
166
|
+
TaskManager.claim_task for why this exists (fan-in double-dispatch
|
|
167
|
+
prevention).
|
|
168
|
+
"""
|
|
169
|
+
return self._task_manager.claim_task(task_id, expected_status, claimed_status)
|
|
170
|
+
|
|
160
171
|
def increment_task_attempts(self, task_id: str) -> Dict[str, Any]:
|
|
161
172
|
"""
|
|
162
173
|
Increment attempts for retries.
|
|
@@ -87,6 +87,42 @@ class TaskManager(BaseSchemaOnboardingTracker):
|
|
|
87
87
|
|
|
88
88
|
return self._make_request("UPDATE_TASK_STATUS", payload)
|
|
89
89
|
|
|
90
|
+
def claim_task(
|
|
91
|
+
self, task_id: str, expected_status: TaskStatus, claimed_status: TaskStatus = TaskStatus.RUNNING
|
|
92
|
+
) -> bool:
|
|
93
|
+
"""
|
|
94
|
+
Atomically transitions a task from expected_status to claimed_status,
|
|
95
|
+
returning True only if this call won the transition.
|
|
96
|
+
|
|
97
|
+
Used to prevent a task from being dispatched twice when multiple
|
|
98
|
+
upstream branches of a fan-in join (e.g. two entities' chains both
|
|
99
|
+
feeding a shared downstream task) complete concurrently and each
|
|
100
|
+
independently decides the joined task is now eligible — a plain
|
|
101
|
+
update_task_status() call is not conditional and both callers would
|
|
102
|
+
otherwise "succeed".
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
task_id (str): Task ID
|
|
106
|
+
expected_status (TaskStatus): Status the task must currently be in
|
|
107
|
+
claimed_status (TaskStatus): Status to set if the claim succeeds
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
bool: True if this call won the claim, False if a concurrent
|
|
111
|
+
caller already claimed it first (or the task was already past
|
|
112
|
+
expected_status for any other reason).
|
|
113
|
+
"""
|
|
114
|
+
self._validate_task_id(task_id)
|
|
115
|
+
|
|
116
|
+
payload = {
|
|
117
|
+
"task_id": task_id,
|
|
118
|
+
"status": claimed_status.value,
|
|
119
|
+
"expected_status": expected_status.value,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
response = self._make_request("UPDATE_TASK_STATUS", payload)
|
|
123
|
+
data = self._get_data_from_response(response) or {}
|
|
124
|
+
return bool(data.get("claimed"))
|
|
125
|
+
|
|
90
126
|
def increment_task_attempts(self, task_id: str) -> Dict[str, Any]:
|
|
91
127
|
"""
|
|
92
128
|
Increment attempts for retries.
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
csv_to_system = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/requires.txt
RENAMED
|
File without changes
|
{fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/fdc_shared_kernel.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fdc_shared_kernel-0.0.197 → fdc_shared_kernel-0.0.199}/shared_kernel/ai_audit_log/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|