snowflake-data-exchange-agent 1.2.0__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.
Files changed (158) hide show
  1. snowflake_data_exchange_agent-1.2.0/.gitignore +126 -0
  2. snowflake_data_exchange_agent-1.2.0/PKG-INFO +556 -0
  3. snowflake_data_exchange_agent-1.2.0/README.md +498 -0
  4. snowflake_data_exchange_agent-1.2.0/pyproject.toml +189 -0
  5. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/__init__.py +8 -0
  6. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/__version__.py +23 -0
  7. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/__init__.py +9 -0
  8. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/base_config.py +9 -0
  9. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/cli.py +49 -0
  10. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/default.py +30 -0
  11. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/manager.py +133 -0
  12. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/__init__.py +27 -0
  13. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/application.py +85 -0
  14. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/base_section_config.py +104 -0
  15. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/bulk_utilities/__init__.py +16 -0
  16. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/bulk_utilities/base.py +19 -0
  17. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/bulk_utilities/bcp.py +70 -0
  18. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/bulk_utilities/bulk_utility_registry.py +10 -0
  19. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/__init__.py +24 -0
  20. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/base.py +19 -0
  21. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/__init__.py +28 -0
  22. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/base.py +19 -0
  23. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/s3.py +106 -0
  24. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/snowflake/__init__.py +24 -0
  25. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/snowflake/authenticator_type.py +40 -0
  26. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/snowflake/base.py +172 -0
  27. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/snowflake/connection_name.py +47 -0
  28. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/snowflake/external_browser.py +43 -0
  29. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/cloud_storages/snowflake/password.py +52 -0
  30. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/connection_registry.py +10 -0
  31. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/jdbc/__init__.py +18 -0
  32. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/jdbc/base.py +151 -0
  33. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/jdbc/postgresql.py +56 -0
  34. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/connections/jdbc/sqlserver.py +91 -0
  35. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/server.py +42 -0
  36. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/task_sources/__init__.py +14 -0
  37. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/task_sources/api.py +39 -0
  38. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/task_sources/snowflake_stored_procedure.py +45 -0
  39. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/task_sources/task_source.py +21 -0
  40. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/sections/task_sources/task_source_registry.py +10 -0
  41. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/config/toml.py +171 -0
  42. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/configuration_example.toml +39 -0
  43. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/__init__.py +6 -0
  44. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/cloud_storage_types.py +27 -0
  45. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/config_defaults.py +8 -0
  46. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/config_keys.py +41 -0
  47. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/connection_types.py +60 -0
  48. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/container_keys.py +7 -0
  49. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/data_source_types.py +38 -0
  50. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/paths.py +72 -0
  51. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/task_keys.py +12 -0
  52. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/constants/task_source_types.py +26 -0
  53. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/container.py +122 -0
  54. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/custom_exceptions.py +7 -0
  55. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/__init__.py +19 -0
  56. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/base.py +41 -0
  57. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/bcp_data_source.py +289 -0
  58. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/bulk_utility_types.py +22 -0
  59. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/data_source_registry.py +10 -0
  60. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/database_engines.py +87 -0
  61. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_data_source.py +306 -0
  62. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_jar.py +124 -0
  63. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_jar_dict.py +172 -0
  64. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_mappers/README.md +6 -0
  65. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_mappers/__init__.py +13 -0
  66. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_mappers/base_jdbc_mapper.py +41 -0
  67. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_mappers/byte_array_mapper.py +48 -0
  68. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/jdbc_mappers/date_time_offset_mapper.py +46 -0
  69. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/sf_connection.py +323 -0
  70. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/sql_command_type.py +28 -0
  71. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/data_sources/sql_parser.py +69 -0
  72. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/enums/task_status.py +17 -0
  73. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/interfaces/__init__.py +14 -0
  74. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/interfaces/data_source.py +90 -0
  75. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/interfaces/task_queue.py +148 -0
  76. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/interfaces/task_source_adapter.py +55 -0
  77. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/interfaces/uploader.py +114 -0
  78. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/interfaces/wsgi_server.py +17 -0
  79. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/main.py +64 -0
  80. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/providers/storageProvider.py +77 -0
  81. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/queues/__init__.py +6 -0
  82. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/queues/deque_task_queue.py +155 -0
  83. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/queues/sqlite_task_queue.py +340 -0
  84. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/servers/__init__.py +6 -0
  85. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/servers/flask_app.py +216 -0
  86. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/servers/waitress_app.py +64 -0
  87. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/task_sources/__init__.py +21 -0
  88. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/task_sources/api.py +108 -0
  89. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/task_sources/snowflake_stored_procedure.py +193 -0
  90. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/task_sources/task_source_adapter_registry.py +10 -0
  91. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/tasks/__init__.py +6 -0
  92. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/tasks/lease_refresher.py +170 -0
  93. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/tasks/manager.py +334 -0
  94. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/tasks/task.py +32 -0
  95. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/uploaders/amazon_s3_uploader.py +141 -0
  96. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/uploaders/azure_blob_uploader.py +182 -0
  97. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/uploaders/sf_stage_uploader.py +157 -0
  98. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/utils/__init__.py +11 -0
  99. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/utils/base_registry.py +79 -0
  100. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/utils/decorators.py +113 -0
  101. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/utils/file_system.py +69 -0
  102. snowflake_data_exchange_agent-1.2.0/src/data_exchange_agent/utils/sf_logger.py +184 -0
  103. snowflake_data_exchange_agent-1.2.0/tests/README.md +200 -0
  104. snowflake_data_exchange_agent-1.2.0/tests/__init__.py +0 -0
  105. snowflake_data_exchange_agent-1.2.0/tests/assets/test_db/Step1_create_db.sql +205 -0
  106. snowflake_data_exchange_agent-1.2.0/tests/assets/test_db/Step2_scale_db.sql +219 -0
  107. snowflake_data_exchange_agent-1.2.0/tests/config/__init__.py +1 -0
  108. snowflake_data_exchange_agent-1.2.0/tests/config/sections/__init__.py +1 -0
  109. snowflake_data_exchange_agent-1.2.0/tests/config/sections/bulk_utilities/__init__.py +1 -0
  110. snowflake_data_exchange_agent-1.2.0/tests/config/sections/bulk_utilities/test_bcp_bulk_utility_config.py +260 -0
  111. snowflake_data_exchange_agent-1.2.0/tests/config/sections/bulk_utilities/test_bulk_utility_registry.py +162 -0
  112. snowflake_data_exchange_agent-1.2.0/tests/config/sections/connections/cloud_storages/test_s3_connection_config.py +482 -0
  113. snowflake_data_exchange_agent-1.2.0/tests/config/sections/connections/jdbc/test_jdbc_connection_config.py +393 -0
  114. snowflake_data_exchange_agent-1.2.0/tests/config/sections/connections/jdbc/test_postgresql_connection_config.py +378 -0
  115. snowflake_data_exchange_agent-1.2.0/tests/config/sections/connections/jdbc/test_sqlserver_connection_config.py +488 -0
  116. snowflake_data_exchange_agent-1.2.0/tests/config/sections/test_application_config.py +260 -0
  117. snowflake_data_exchange_agent-1.2.0/tests/config/sections/test_base_config.py +382 -0
  118. snowflake_data_exchange_agent-1.2.0/tests/config/sections/test_server_config.py +280 -0
  119. snowflake_data_exchange_agent-1.2.0/tests/config/test_cli_config.py +262 -0
  120. snowflake_data_exchange_agent-1.2.0/tests/config/test_config_manager.py +269 -0
  121. snowflake_data_exchange_agent-1.2.0/tests/config/test_default_config.py +258 -0
  122. snowflake_data_exchange_agent-1.2.0/tests/config/test_toml_config.py +460 -0
  123. snowflake_data_exchange_agent-1.2.0/tests/constants/__init__.py +1 -0
  124. snowflake_data_exchange_agent-1.2.0/tests/constants/test_data_source_types.py +104 -0
  125. snowflake_data_exchange_agent-1.2.0/tests/constants/test_paths.py +239 -0
  126. snowflake_data_exchange_agent-1.2.0/tests/data_sources/jdbc_mappers/__init__.py +1 -0
  127. snowflake_data_exchange_agent-1.2.0/tests/data_sources/jdbc_mappers/test_byte_array_mapper.py +134 -0
  128. snowflake_data_exchange_agent-1.2.0/tests/data_sources/jdbc_mappers/test_date_time_offset_mapper.py +208 -0
  129. snowflake_data_exchange_agent-1.2.0/tests/data_sources/test_base_data_source.py +180 -0
  130. snowflake_data_exchange_agent-1.2.0/tests/data_sources/test_bcp_data_source.py +559 -0
  131. snowflake_data_exchange_agent-1.2.0/tests/data_sources/test_bulk_utility_types.py +160 -0
  132. snowflake_data_exchange_agent-1.2.0/tests/data_sources/test_data_source_registry.py +257 -0
  133. snowflake_data_exchange_agent-1.2.0/tests/data_sources/test_jdbc_data_source.py +802 -0
  134. snowflake_data_exchange_agent-1.2.0/tests/data_sources/test_sql_parser.py +236 -0
  135. snowflake_data_exchange_agent-1.2.0/tests/task_sources/test_snowflake_stored_procedure.py +564 -0
  136. snowflake_data_exchange_agent-1.2.0/tests/tasks/test_task.py +297 -0
  137. snowflake_data_exchange_agent-1.2.0/tests/test_amazon_s3_uploader.py +287 -0
  138. snowflake_data_exchange_agent-1.2.0/tests/test_api_manager.py +203 -0
  139. snowflake_data_exchange_agent-1.2.0/tests/test_azure_blob_uploader.py +354 -0
  140. snowflake_data_exchange_agent-1.2.0/tests/test_constants.py +120 -0
  141. snowflake_data_exchange_agent-1.2.0/tests/test_container.py +298 -0
  142. snowflake_data_exchange_agent-1.2.0/tests/test_data_sources_interfaces.py +250 -0
  143. snowflake_data_exchange_agent-1.2.0/tests/test_deque_task_queue.py +259 -0
  144. snowflake_data_exchange_agent-1.2.0/tests/test_enums.py +97 -0
  145. snowflake_data_exchange_agent-1.2.0/tests/test_flask_app.py +359 -0
  146. snowflake_data_exchange_agent-1.2.0/tests/test_integration.py +274 -0
  147. snowflake_data_exchange_agent-1.2.0/tests/test_jdbc_jar.py +322 -0
  148. snowflake_data_exchange_agent-1.2.0/tests/test_jdbc_jar_dict.py +486 -0
  149. snowflake_data_exchange_agent-1.2.0/tests/test_main.py +163 -0
  150. snowflake_data_exchange_agent-1.2.0/tests/test_runner.py +79 -0
  151. snowflake_data_exchange_agent-1.2.0/tests/test_sf_stage_uploader.py +472 -0
  152. snowflake_data_exchange_agent-1.2.0/tests/test_sqlite_task_queue.py +441 -0
  153. snowflake_data_exchange_agent-1.2.0/tests/test_storage_provider.py +256 -0
  154. snowflake_data_exchange_agent-1.2.0/tests/test_task_manager.py +464 -0
  155. snowflake_data_exchange_agent-1.2.0/tests/test_uploader_interface.py +221 -0
  156. snowflake_data_exchange_agent-1.2.0/tests/test_waitress_app.py +176 -0
  157. snowflake_data_exchange_agent-1.2.0/tests/utils/test_decorators.py +284 -0
  158. snowflake_data_exchange_agent-1.2.0/tests/utils/test_sf_logger.py +374 -0
@@ -0,0 +1,126 @@
1
+ __pycache__/
2
+ *.py[codz]
3
+ *$py.class
4
+ *.so
5
+
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ share/python-wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ *.manifest
26
+ *.spec
27
+
28
+ pip-log.txt
29
+ pip-delete-this-directory.txt
30
+
31
+ htmlcov/
32
+ .tox/
33
+ .nox/
34
+ .coverage
35
+ .coverage.*
36
+ .cache
37
+ nosetests.xml
38
+ coverage.xml
39
+ *.cover
40
+ *.py.cover
41
+ .hypothesis/
42
+ .pytest_cache/
43
+ cover/
44
+
45
+ *.mo
46
+ *.pot
47
+
48
+ *.log
49
+ local_settings.py
50
+ db.sqlite3
51
+ db.sqlite3-journal
52
+
53
+ instance/
54
+ .webassets-cache
55
+
56
+ .scrapy
57
+
58
+ docs/_build/
59
+
60
+ .pybuilder/
61
+ target/
62
+
63
+ .ipynb_checkpoints
64
+
65
+ profile_default/
66
+ ipython_config.py
67
+
68
+ .pdm-python
69
+ .pdm-build/
70
+ .pixi
71
+ __pypackages__/
72
+
73
+ celerybeat-schedule
74
+ celerybeat.pid
75
+
76
+ *.rdb
77
+ *.aof
78
+ *.pid
79
+
80
+ mnesia/
81
+ rabbitmq/
82
+ rabbitmq-data/
83
+ activemq-data/
84
+
85
+ *.sage.py
86
+
87
+ .env
88
+ .envrc
89
+ .venv
90
+ env/
91
+ venv/
92
+ ENV/
93
+ env.bak/
94
+ venv.bak/
95
+
96
+ .spyderproject
97
+ .spyproject
98
+ .ropeproject
99
+
100
+ /site
101
+
102
+ .mypy_cache/
103
+ .dmypy.json
104
+ dmypy.json
105
+ .pyre/
106
+ .pytype/
107
+
108
+ cython_debug/
109
+ .abstra/
110
+ .ruff_cache/
111
+ .pypirc
112
+
113
+ marimo/_static/
114
+ marimo/_lsp/
115
+ __marimo__/
116
+
117
+ .streamlit/secrets.toml
118
+
119
+ .DS_Store
120
+ .AppleDouble
121
+ .LSOverride
122
+ ._*
123
+
124
+ configuration.toml
125
+ src/mocked_api/*
126
+ *.code-workspace
@@ -0,0 +1,556 @@
1
+ Metadata-Version: 2.4
2
+ Name: snowflake-data-exchange-agent
3
+ Version: 1.2.0
4
+ Summary: Data exchange agent for migrations and validation
5
+ Project-URL: Bug Tracker, https://github.com/snowflakedb/migrations-data-validation/issues
6
+ Project-URL: Source code, https://github.com/snowflakedb/migrations-data-validation/
7
+ Project-URL: homepage, https://www.snowflake.com/
8
+ Author-email: "Snowflake, Inc." <snowflake-python-libraries-dl@snowflake.com>
9
+ License: Apache License, Version 2.0
10
+ Keywords: Snowflake,analytics,cloud,data,data-analysis,data-analytics,data-engineering,data-management,data-processing,data-science,data-visualization,data-warehouse,database
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Environment :: Other Environment
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Intended Audience :: Information Technology
17
+ Classifier: Intended Audience :: System Administrators
18
+ Classifier: License :: OSI Approved :: Apache Software License
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: SQL
22
+ Classifier: Topic :: Database
23
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
24
+ Classifier: Topic :: Software Development
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
27
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
+ Requires-Python: <3.13,>=3.10
29
+ Requires-Dist: azure-identity==1.25.0
30
+ Requires-Dist: azure-storage-blob==12.26.0
31
+ Requires-Dist: boto3==1.40.41
32
+ Requires-Dist: dependency-injector==4.48.2
33
+ Requires-Dist: flask==3.1.2
34
+ Requires-Dist: jaydebeapi==1.2.3
35
+ Requires-Dist: psutil==7.1.0
36
+ Requires-Dist: psycopg2-binary==2.9.10
37
+ Requires-Dist: py4j==0.10.9.9
38
+ Requires-Dist: pyarrow==22.0.0
39
+ Requires-Dist: requests==2.32.5
40
+ Requires-Dist: snowflake-connector-python==4.0.0
41
+ Requires-Dist: sqlparse==0.5.4
42
+ Requires-Dist: toml==0.10.2
43
+ Requires-Dist: urllib3==2.6.3
44
+ Requires-Dist: waitress==3.0.2
45
+ Provides-Extra: all
46
+ Requires-Dist: parameterized>=0.9.0; extra == 'all'
47
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
48
+ Requires-Dist: pytest-mock>=3.10.0; extra == 'all'
49
+ Requires-Dist: pytest>=7.0.0; extra == 'all'
50
+ Requires-Dist: ruff>=0.1.0; extra == 'all'
51
+ Provides-Extra: development
52
+ Requires-Dist: parameterized>=0.9.0; extra == 'development'
53
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'development'
54
+ Requires-Dist: pytest-mock>=3.10.0; extra == 'development'
55
+ Requires-Dist: pytest>=7.0.0; extra == 'development'
56
+ Requires-Dist: ruff>=0.1.0; extra == 'development'
57
+ Description-Content-Type: text/markdown
58
+
59
+ # Snowflake Data Exchange Agent
60
+
61
+ [![License Apache-2.0](https://img.shields.io/:license-Apache%202-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.txt)
62
+ [![Python](https://img.shields.io/badge/python-3.10--3.12-blue)](https://www.python.org/downloads/)
63
+
64
+ A REST API service for database migrations and data validation. Supports multiple databases including Snowflake, PostgreSQL, and SQL Server with queue-based task processing.
65
+
66
+ ## Quick Start
67
+
68
+ ```bash
69
+ # Install
70
+ pip install snowflake-data-exchange-agent
71
+
72
+ # Run
73
+ data-exchange-agent --port 8080
74
+
75
+ # Test
76
+ curl http://localhost:8080/health
77
+ ```
78
+
79
+ ## Installation
80
+
81
+ ### From PyPI (Production)
82
+ ```bash
83
+ pip install snowflake-data-exchange-agent
84
+ ```
85
+
86
+ ### Requirements & Dependencies
87
+
88
+ **Python Version**: 3.10, 3.11, or 3.12 (3.13 not yet supported)
89
+
90
+ **Available dependency groups**:
91
+ - `development`: Testing and development tools (pytest, ruff, etc.)
92
+ - `all`: Includes all development dependencies
93
+
94
+ **Core dependencies include**:
95
+ - Snowflake Connector for Python
96
+ - PySpark for data processing
97
+ - Flask + Waitress for REST API
98
+ - PostgreSQL support (psycopg2-binary)
99
+ - AWS SDK (boto3)
100
+
101
+ ## Configuration
102
+
103
+ Create `src/data_exchange_agent/configuration.toml`:
104
+
105
+ ```toml
106
+ selected_task_source = "api"
107
+
108
+ [application]
109
+ workers = 4
110
+ task_fetch_interval = 5
111
+ debug_mode = false
112
+
113
+ [task_source.api]
114
+ key = "api-key"
115
+
116
+ [connections.source.<sqlserver|postgresql|teradata>]
117
+ username = "username"
118
+ password = "password"
119
+ database = "database_name"
120
+ host = "127.0.0.1"
121
+ port = <1433|5432|1025>
122
+
123
+ [connections.target.snowflake_connection_name]
124
+ connection_name = "connection_name"
125
+
126
+ [connections.target.s3]
127
+ profile_name = "profile_name"
128
+ bucket_name = "bucket_name"
129
+
130
+ [connections.target.blob]
131
+ connection_string = "DefaultEndpointsProtocol=https;AccountName=account_name;AccountKey=account_key;EndpointSuffix=core.windows.net"
132
+ container_name = "container_name"
133
+ # Optional: Account name and use_default_credential if not using connection string
134
+ account_name="storage_account_name"
135
+ use_default_credential=<True|False>
136
+ ```
137
+
138
+ For Snowflake, create `~/.snowflake/config.toml`:
139
+
140
+ ```toml
141
+ [connections.default]
142
+ account = "your_account.region"
143
+ user = "your_username"
144
+ password = "your_password"
145
+ warehouse = "COMPUTE_WH"
146
+ database = "PRODUCTION_DB"
147
+ ```
148
+
149
+ ## API Usage
150
+
151
+ ### Command Line
152
+ ```bash
153
+ # Basic usage
154
+ data-exchange-agent
155
+
156
+ # Production settings
157
+ data-exchange-agent --workers 8 --port 8080
158
+
159
+ # Debug mode
160
+ data-exchange-agent --debug --port 5001
161
+ ```
162
+
163
+ ### Health Check
164
+ ```http
165
+ GET /health
166
+ ```
167
+ ```json
168
+ {
169
+ "status": "healthy",
170
+ "version": "0.0.18",
171
+ "database_connections": {
172
+ "snowflake": "connected"
173
+ }
174
+ }
175
+ ```
176
+
177
+ ### Task Management
178
+ ```http
179
+ # Start processing
180
+ GET /handle_tasks
181
+
182
+ # Stop processing
183
+ GET /stop
184
+
185
+ # Get status
186
+ GET /get_handling_tasks_status
187
+
188
+ # Task count
189
+ GET /get_tasks_count
190
+ ```
191
+
192
+ ### Add Task
193
+ ```http
194
+ POST /tasks
195
+ Content-Type: application/json
196
+ ```
197
+ ```json
198
+ {
199
+ "task_type": "data_extraction",
200
+ "source_config": {
201
+ "database": "postgresql",
202
+ "query": "SELECT * FROM users"
203
+ },
204
+ "destination_config": {
205
+ "type": "snowflake_stage",
206
+ "stage": "@data_stage/users/"
207
+ }
208
+ }
209
+ ```
210
+
211
+ ## Development
212
+
213
+ ### Setup
214
+ ```bash
215
+ git clone https://github.com/snowflakedb/migrations-data-validation.git
216
+ cd migrations-data-validation/data-exchange-agent
217
+ pip install -e .[development]
218
+ ```
219
+
220
+ ### Testing
221
+ ```bash
222
+ # Run all tests
223
+ pytest
224
+
225
+ # With coverage
226
+ pytest --cov=src/data_exchange_agent
227
+
228
+ # Run specific test types
229
+ pytest tests/unit/ # Unit tests only
230
+ pytest -m "not integration" # Non-integration tests
231
+ ```
232
+
233
+ ### Code Quality
234
+ ```bash
235
+ # Format code
236
+ ruff format .
237
+
238
+ # Lint code
239
+ ruff check .
240
+
241
+ # Auto-fix linting issues
242
+ ruff check --fix .
243
+ ```
244
+ ## 🐳 Docker
245
+
246
+ The Data Exchange Agent can be run in a Docker container with configuration injected via environment variables at runtime.
247
+
248
+ ### Building the Image
249
+
250
+ ```bash
251
+ cd data-exchange-agent
252
+ docker build -t data-exchange-agent .
253
+ ```
254
+
255
+ ### How It Works
256
+
257
+ The Dockerfile uses configuration templates that are processed at container startup:
258
+
259
+ 1. **`docker-artifacts/configuration.template.toml`** - Agent configuration template
260
+ 2. **`docker-artifacts/snowflake.config.template.toml`** - Snowflake connection template
261
+ 3. **`docker-artifacts/docker-entrypoint.sh`** - Entrypoint script that uses `envsubst` to substitute environment variables into the templates before starting the agent
262
+
263
+ This approach ensures that sensitive credentials (passwords) are never baked into the Docker image—they are only injected at runtime.
264
+
265
+ ### Environment Variables
266
+
267
+ #### Data Source Configuration (Required for database connections)
268
+
269
+ | Variable | Description | Default |
270
+ |----------|-------------|---------|
271
+ | `DATA_SOURCE_USERNAME` | Username for the source database | - |
272
+ | `DATA_SOURCE_PASSWORD` | Password for the source database | - |
273
+ | `DATA_SOURCE_HOST` | Hostname of the source database | - |
274
+ | `DATA_SOURCE_PORT` | Port of the source database | `1433` |
275
+ | `DATA_SOURCE_DATABASE` | Database name on the source | - |
276
+
277
+ #### Snowflake Connection Configuration (Required for Snowflake integration)
278
+
279
+ | Variable | Description | Default |
280
+ |----------|-------------|---------|
281
+ | `SNOWFLAKE_ACCOUNT` | Snowflake account identifier (e.g., `myaccount.us-west-2.aws`) | - |
282
+ | `SNOWFLAKE_USER` | Snowflake username | - |
283
+ | `SNOWFLAKE_PASSWORD` | Snowflake password | - |
284
+ | `SNOWFLAKE_WAREHOUSE` | Snowflake warehouse name | - |
285
+ | `SNOWFLAKE_ROLE` | Snowflake role | - |
286
+ | `SNOWFLAKE_DATABASE` | Default Snowflake database | - |
287
+ | `SNOWFLAKE_SCHEMA` | Default Snowflake schema | - |
288
+
289
+ #### Application Configuration
290
+
291
+ | Variable | Description | Default |
292
+ |----------|-------------|---------|
293
+ | `AGENT_AFFINITY` | Agent affinity label for task routing (required) | - |
294
+ | `WORKER_COUNT` | Number of worker threads | `1` |
295
+
296
+ ### Running the Container
297
+
298
+ ```bash
299
+ docker run -p 5000:5000 \
300
+ -e DATA_SOURCE_USERNAME="db_user" \
301
+ -e DATA_SOURCE_PASSWORD="db_password" \
302
+ -e DATA_SOURCE_HOST="db.example.com" \
303
+ -e DATA_SOURCE_PORT="1433" \
304
+ -e DATA_SOURCE_DATABASE="mydb" \
305
+ -e SNOWFLAKE_ACCOUNT="myaccount.us-west-2.aws" \
306
+ -e SNOWFLAKE_USER="snowflake_user" \
307
+ -e SNOWFLAKE_PASSWORD="snowflake_password" \
308
+ -e SNOWFLAKE_WAREHOUSE="COMPUTE_WH" \
309
+ -e SNOWFLAKE_ROLE="DATA_ENGINEER" \
310
+ -e SNOWFLAKE_DATABASE="PROD_DB" \
311
+ -e SNOWFLAKE_SCHEMA="PUBLIC" \
312
+ -e AGENT_AFFINITY="blue" \
313
+ -e WORKER_COUNT="8" \
314
+ data-exchange-agent
315
+ ```
316
+
317
+ You can also pass additional arguments to the agent:
318
+
319
+ ```bash
320
+ docker run -p 8080:8080 \
321
+ -e DATA_SOURCE_PASSWORD="secret" \
322
+ -e SNOWFLAKE_PASSWORD="secret" \
323
+ # ... other env vars ...
324
+ data-exchange-agent --port 8080 --debug
325
+ ```
326
+
327
+ ### Running in Snowpark Container Services (SPCS)
328
+
329
+ When deploying the Data Exchange Agent in [Snowpark Container Services](https://docs.snowflake.com/en/developer-guide/snowpark-container-services/overview), you can use the special `@SPCS_CONNECTION` connection name to automatically use Snowflake-provided credentials.
330
+
331
+ #### How It Works
332
+
333
+ When running in SPCS, Snowflake automatically provides:
334
+ - An **OAuth token** at `/snowflake/session/token`
335
+ - **Environment variables**: `SNOWFLAKE_HOST`, `SNOWFLAKE_ACCOUNT`, `SNOWFLAKE_DATABASE`, `SNOWFLAKE_SCHEMA`
336
+
337
+ The `@SPCS_CONNECTION` feature reads these credentials automatically, so you don't need to configure Snowflake passwords or account details manually.
338
+
339
+ > **Note**: `SNOWFLAKE_WAREHOUSE` is **not** provided by SPCS. You can set it manually via environment variable or use the `QUERY_WAREHOUSE` parameter when creating the service.
340
+
341
+ #### Configuration
342
+
343
+ By default, the Docker image uses `@SPCS_CONNECTION`. No additional Snowflake configuration is needed:
344
+
345
+ ```toml
346
+ [task_source.snowflake_stored_procedure]
347
+ connection_name = "@SPCS_CONNECTION"
348
+
349
+ [connections.target.snowflake_connection_name]
350
+ connection_name = "@SPCS_CONNECTION"
351
+ ```
352
+
353
+ #### Environment Variables for SPCS
354
+
355
+ | Variable | Description | Default |
356
+ |----------|-------------|---------|
357
+ | `SNOWFLAKE_CONNECTION_NAME` | Connection mode: `@SPCS_CONNECTION` for SPCS credentials, or a named connection from `~/.snowflake/config.toml` | `@SPCS_CONNECTION` |
358
+ | `SNOWFLAKE_WAREHOUSE` | Warehouse for queries (not provided by SPCS, must be set manually) | - |
359
+
360
+ #### Switching to Manual Credentials
361
+
362
+ If you need to use traditional Snowflake credentials instead of SPCS-provided ones (e.g., for testing outside SPCS), set the `SNOWFLAKE_CONNECTION_NAME` environment variable:
363
+
364
+ ```bash
365
+ # Use a named connection from ~/.snowflake/config.toml
366
+ docker run \
367
+ -e SNOWFLAKE_CONNECTION_NAME="MY_SNOWFLAKE_CONNECTION" \
368
+ -e SNOWFLAKE_ACCOUNT="myaccount.us-west-2.aws" \
369
+ -e SNOWFLAKE_USER="user" \
370
+ -e SNOWFLAKE_PASSWORD="password" \
371
+ # ... other env vars ...
372
+ data-exchange-agent
373
+ ```
374
+
375
+ #### Example SPCS Service Definition
376
+
377
+ ```sql
378
+ CREATE SERVICE data_exchange_agent
379
+ IN COMPUTE POOL my_compute_pool
380
+ QUERY_WAREHOUSE = MY_WAREHOUSE
381
+ FROM SPECIFICATION $$
382
+ spec:
383
+ containers:
384
+ - name: agent
385
+ image: /my_db/my_schema/my_repo/data-exchange-agent:latest
386
+ env:
387
+ DATA_SOURCE_HOST: "source-db.example.com"
388
+ DATA_SOURCE_PORT: "1433"
389
+ DATA_SOURCE_DATABASE: "mydb"
390
+ DATA_SOURCE_USERNAME: "user"
391
+ AGENT_AFFINITY: "spcs-agent"
392
+ WORKER_COUNT: "4"
393
+ secrets:
394
+ - snowflakeSecret: my_db_password_secret
395
+ secretKeyRef: password
396
+ envVarName: DATA_SOURCE_PASSWORD
397
+ $$;
398
+ ```
399
+
400
+ For more details, see the [Snowflake SPCS documentation](https://docs.snowflake.com/en/developer-guide/snowpark-container-services/spcs-execute-sql).
401
+
402
+ ## 🔌 Extending the System
403
+
404
+ ### Adding a New Bulk Utility
405
+
406
+ Bulk utilities are command-line tools used to efficiently export data from databases (e.g., BCP for SQL Server). Follow these steps to add a new bulk utility:
407
+
408
+ #### 1. Define the Bulk Utility Type
409
+
410
+ Add your new utility to the `BulkUtilityType` enum in `src/data_exchange_agent/data_sources/bulk_utility_types.py`:
411
+
412
+ ```python
413
+ class BulkUtilityType(str, Enum):
414
+ BCP = "bcp"
415
+ YOUR_UTILITY = "your_utility_name" # Add this line
416
+ ```
417
+
418
+ #### 2. Create Configuration Class
419
+
420
+ Create a new configuration class in `src/data_exchange_agent/config/sections/bulk_utilities/your_utility.py`:
421
+
422
+ ```python
423
+ from data_exchange_agent.config.sections.bulk_utilities.base import BaseBulkUtilityConfig
424
+
425
+ class YourUtilityConfig(BaseBulkUtilityConfig):
426
+ """Configuration class for YourUtility bulk utility settings."""
427
+
428
+ def __init__(
429
+ self,
430
+ # Add utility-specific parameters
431
+ utility_specific_parameter: str = "default_param",
432
+ ) -> None:
433
+ """Initialize YourUtility configuration."""
434
+ self.utility_specific_parameter = utility_specific_parameter
435
+
436
+ def _custom_validation(self) -> str | None:
437
+ """Validate configuration parameters."""
438
+ if not self.utility_specific_parameter:
439
+ return "Utility specific parameter cannot be empty."
440
+ return None
441
+
442
+ def __repr__(self) -> str:
443
+ """Return string representation."""
444
+ return f"YourUtilityConfig(utility_specific_parameter='{self.utility_specific_parameter}')"
445
+ ```
446
+
447
+ #### 3. Register the Bulk Utility
448
+
449
+ Register your utility in `src/data_exchange_agent/config/sections/bulk_utilities/__init__.py`:
450
+
451
+ ```python
452
+ from data_exchange_agent.config.sections.bulk_utilities.your_utility import YourUtilityConfig
453
+ from data_exchange_agent.constants.connection_types import ConnectionType
454
+
455
+ # Add to registry
456
+ BulkUtilityRegistry.register(ConnectionType.YOUR_UTILITY, YourUtilityConfig) # Add this
457
+
458
+ # Add to __all__
459
+ __all__ = [
460
+ "BaseBulkUtilityConfig",
461
+ "BulkUtilityRegistry",
462
+ "BCPBulkUtilityConfig",
463
+ "YourUtilityConfig", # Add this
464
+ ]
465
+ ```
466
+
467
+ #### 4. Update ConnectionType Enum
468
+
469
+ Add your utility type to `src/data_exchange_agent/constants/connection_types.py`:
470
+
471
+ ```python
472
+ class ConnectionType(str, Enum):
473
+ # Bulk utilities
474
+ BCP = BulkUtilityType.BCP.value
475
+ YOUR_UTILITY = BulkUtilityType.YOUR_UTILITY.value # Add this
476
+ ```
477
+
478
+ #### 5. Create Data Source Implementation
479
+
480
+ Create the data source class in `src/data_exchange_agent/data_sources/your_utility_data_source.py`:
481
+
482
+ ```python
483
+ from data_exchange_agent.data_sources.base import BaseDataSource
484
+ from data_exchange_agent.data_sources.bulk_utility_types import BulkUtilityType
485
+
486
+ class YourUtilityDataSource(BaseDataSource):
487
+ """Data source implementation for YourUtility."""
488
+
489
+ @inject
490
+ def __init__(
491
+ self,
492
+ engine: str,
493
+ statement: str,
494
+ results_folder_path: str = None,
495
+ base_file_name: str = "result",
496
+ logger: SFLogger = Provide[container_keys.SF_LOGGER],
497
+ program_config: ConfigManager = Provide[container_keys.PROGRAM_CONFIG],
498
+ ) -> None:
499
+ """Initialize YourUtilityDataSource."""
500
+ self.logger = logger
501
+ self._statement = statement
502
+
503
+ # Get configuration
504
+ bulk_utility_config = program_config[config_keys.BULK_UTILITY]
505
+ utility_config = bulk_utility_config.get(BulkUtilityType.YOUR_UTILITY, None)
506
+
507
+ # Use config values or defaults
508
+ self.utility_specific_parameter = utility_config.utility_specific_parameter if utility_config else "default_param"
509
+
510
+ def export_data(self) -> bool:
511
+ """Export data using your utility command."""
512
+ # Implement the export logic
513
+ pass
514
+ ```
515
+
516
+ #### 6. Add Configuration to TOML
517
+
518
+ Users can now configure your bulk utility in `configuration.toml`:
519
+
520
+ ```toml
521
+ [bulk_utility.your_utility_name]
522
+ # Add your custom parameters
523
+ utility_specific_parameter = "param"
524
+ ```
525
+
526
+ #### 7. Write Tests
527
+
528
+ Create tests in `tests/data_sources/test_your_utility_data_source.py` to verify functionality.
529
+
530
+ ### Example: BCP Implementation
531
+
532
+ See the existing BCP implementation for reference:
533
+ - Config: `src/data_exchange_agent/config/sections/bulk_utilities/bcp.py`
534
+ - Data Source: `src/data_exchange_agent/data_sources/bcp_data_source.py`
535
+ - Configuration example in `configuration_example.toml`
536
+
537
+ ---
538
+
539
+ ## 🤝 Contributing
540
+
541
+ We welcome contributions! See our [Contributing Guide](../CONTRIBUTING.md) for details on how to collaborate, set up your development environment, and submit PRs.
542
+
543
+ ---
544
+
545
+ ## 📄 License
546
+
547
+ This project is licensed under the Apache License 2.0. See the [LICENSE](../LICENSE) file for details.
548
+
549
+ ## 🆘 Support
550
+
551
+ - **Documentation**: [Full documentation](https://github.com/snowflakedb/migrations-data-validation)
552
+ - **Issues**: [GitHub Issues](https://github.com/snowflakedb/migrations-data-validation/issues)
553
+
554
+ ---
555
+
556
+ **Developed with ❄️ by Snowflake**