castor-extractor 0.24.36__tar.gz → 0.24.40__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.

Potentially problematic release.


This version of castor-extractor might be problematic. Click here for more details.

Files changed (437) hide show
  1. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/CHANGELOG.md +18 -0
  2. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/PKG-INFO +19 -1
  3. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/upload.py +10 -0
  4. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/__init__.py +1 -0
  5. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/constant.py +5 -1
  6. castor_extractor-0.24.40/castor_extractor/uploader/enums.py +8 -0
  7. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/settings.py +2 -0
  8. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/upload.py +26 -5
  9. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/upload_test.py +5 -3
  10. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/client.py +2 -1
  11. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/assets.py +3 -0
  12. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/client/client.py +42 -5
  13. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/client/endpoints.py +17 -0
  14. castor_extractor-0.24.40/castor_extractor/visualization/sigma/client/sources_transformer.py +94 -0
  15. castor_extractor-0.24.40/castor_extractor/visualization/sigma/client/sources_transformer_test.py +101 -0
  16. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/extract.py +17 -1
  17. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/client.py +4 -5
  18. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/client_test.py +2 -1
  19. castor_extractor-0.24.40/castor_extractor/warehouse/databricks/queries/column_lineage.sql +25 -0
  20. castor_extractor-0.24.40/castor_extractor/warehouse/databricks/queries/table_lineage.sql +23 -0
  21. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/sql_client.py +14 -11
  22. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/extract.py +3 -1
  23. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/queries/column.sql +3 -3
  24. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/queries/schema.sql +7 -2
  25. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/queries/table.sql +1 -1
  26. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/pyproject.toml +1 -1
  27. castor_extractor-0.24.36/castor_extractor/warehouse/databricks/lineage.py +0 -69
  28. castor_extractor-0.24.36/castor_extractor/warehouse/databricks/lineage_test.py +0 -89
  29. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/Dockerfile +0 -0
  30. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/DockerfileUsage.md +0 -0
  31. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/LICENCE +0 -0
  32. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/README.md +0 -0
  33. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/__init__.py +0 -0
  34. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/__init__.py +0 -0
  35. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_bigquery.py +0 -0
  36. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_confluence.py +0 -0
  37. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_databricks.py +0 -0
  38. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_domo.py +0 -0
  39. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_looker.py +0 -0
  40. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_looker_studio.py +0 -0
  41. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_metabase_api.py +0 -0
  42. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_metabase_db.py +0 -0
  43. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_mode.py +0 -0
  44. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_mysql.py +0 -0
  45. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_notion.py +0 -0
  46. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_postgres.py +0 -0
  47. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_powerbi.py +0 -0
  48. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_qlik.py +0 -0
  49. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_redshift.py +0 -0
  50. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_salesforce.py +0 -0
  51. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_salesforce_reporting.py +0 -0
  52. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_sigma.py +0 -0
  53. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_snowflake.py +0 -0
  54. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_sqlserver.py +0 -0
  55. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_strategy.py +0 -0
  56. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_tableau.py +0 -0
  57. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/extract_thoughtspot.py +0 -0
  58. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/commands/file_check.py +0 -0
  59. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/__init__.py +0 -0
  60. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/column.py +0 -0
  61. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/column_test.py +0 -0
  62. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/constants.py +0 -0
  63. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/enums.py +0 -0
  64. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/file.py +0 -0
  65. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/file_test.py +0 -0
  66. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/file_test_users.csv +0 -0
  67. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/file_test_users_valid.csv +0 -0
  68. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/templates/__init__.py +0 -0
  69. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/file_checker/templates/generic_warehouse.py +0 -0
  70. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/__init__.py +0 -0
  71. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/__init__.py +0 -0
  72. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/assets.py +0 -0
  73. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/client/__init__.py +0 -0
  74. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/client/client.py +0 -0
  75. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/client/client_test.py +0 -0
  76. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/client/credentials.py +0 -0
  77. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/client/endpoints.py +0 -0
  78. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/client/pagination.py +0 -0
  79. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/extract.py +0 -0
  80. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/utils.py +0 -0
  81. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/confluence/utils_test.py +0 -0
  82. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/__init__.py +0 -0
  83. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/assets.py +0 -0
  84. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/__init__.py +0 -0
  85. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/client.py +0 -0
  86. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/client_test.py +0 -0
  87. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/constants.py +0 -0
  88. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/credentials.py +0 -0
  89. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/endpoints.py +0 -0
  90. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/client/pagination.py +0 -0
  91. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/knowledge/notion/extract.py +0 -0
  92. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/logger.py +0 -0
  93. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/__init__.py +0 -0
  94. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/__init__.py +0 -0
  95. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/assets.py +0 -0
  96. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/client/__init__.py +0 -0
  97. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/client/client.py +0 -0
  98. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/client/credentials.py +0 -0
  99. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/client/endpoints.py +0 -0
  100. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/quality/soda/client/pagination.py +0 -0
  101. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/__init__.py +0 -0
  102. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/__init__.py +0 -0
  103. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/assets.py +0 -0
  104. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/client/__init__.py +0 -0
  105. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/client/client.py +0 -0
  106. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/client/credentials.py +0 -0
  107. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/client/endpoint.py +0 -0
  108. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/coalesce/client/pagination.py +0 -0
  109. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/dbt/__init__.py +0 -0
  110. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/dbt/assets.py +0 -0
  111. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/dbt/client.py +0 -0
  112. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/dbt/client_test.py +0 -0
  113. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/transformation/dbt/credentials.py +0 -0
  114. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/types.py +0 -0
  115. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/env.py +0 -0
  116. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/env_test.py +0 -0
  117. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/uploader/utils.py +0 -0
  118. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/__init__.py +0 -0
  119. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/argument_parser.py +0 -0
  120. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/argument_parser_test.py +0 -0
  121. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/batch.py +0 -0
  122. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/batch_test.py +0 -0
  123. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/__init__.py +0 -0
  124. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/abstract.py +0 -0
  125. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/__init__.py +0 -0
  126. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/auth.py +0 -0
  127. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/auth_test.py +0 -0
  128. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/client.py +0 -0
  129. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/client_test.py +0 -0
  130. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/pagination.py +0 -0
  131. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/pagination_test.py +0 -0
  132. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/safe_request.py +0 -0
  133. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/safe_request_test.py +0 -0
  134. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/utils.py +0 -0
  135. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/api/utils_test.py +0 -0
  136. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/postgres.py +0 -0
  137. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/query.py +0 -0
  138. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/uri.py +0 -0
  139. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/client/uri_test.py +0 -0
  140. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/collection.py +0 -0
  141. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/collection_test.py +0 -0
  142. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/constants.py +0 -0
  143. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/deprecate.py +0 -0
  144. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/env.py +0 -0
  145. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/files.py +0 -0
  146. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/files_test.py +0 -0
  147. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/formatter.py +0 -0
  148. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/formatter_test.csv +0 -0
  149. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/formatter_test.json +0 -0
  150. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/formatter_test.py +0 -0
  151. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/json_stream_write.py +0 -0
  152. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/load.py +0 -0
  153. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/object.py +0 -0
  154. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/object_test.py +0 -0
  155. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/pager/__init__.py +0 -0
  156. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/pager/pager.py +0 -0
  157. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/pager/pager_on_id.py +0 -0
  158. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/pager/pager_on_id_test.py +0 -0
  159. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/pager/pager_test.py +0 -0
  160. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/retry.py +0 -0
  161. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/retry_test.py +0 -0
  162. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/safe.py +0 -0
  163. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/safe_test.py +0 -0
  164. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/__init__.py +0 -0
  165. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/client.py +0 -0
  166. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/client_test.py +0 -0
  167. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/constants.py +0 -0
  168. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/credentials.py +0 -0
  169. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/credentials_test.py +0 -0
  170. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/salesforce/pagination.py +0 -0
  171. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/store.py +0 -0
  172. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/string.py +0 -0
  173. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/string_test.py +0 -0
  174. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/time.py +0 -0
  175. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/time_test.py +0 -0
  176. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/type.py +0 -0
  177. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/url.py +0 -0
  178. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/url_test.py +0 -0
  179. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/validation.py +0 -0
  180. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/validation_test.py +0 -0
  181. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/utils/write.py +0 -0
  182. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/__init__.py +0 -0
  183. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/__init__.py +0 -0
  184. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/assets.py +0 -0
  185. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/client/__init__.py +0 -0
  186. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/client/client.py +0 -0
  187. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/client/credentials.py +0 -0
  188. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/client/endpoints.py +0 -0
  189. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/client/pagination.py +0 -0
  190. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/client/pagination_test.py +0 -0
  191. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/domo/extract.py +0 -0
  192. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/__init__.py +0 -0
  193. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/__init__.py +0 -0
  194. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/client.py +0 -0
  195. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/client_test.py +0 -0
  196. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/constants.py +0 -0
  197. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/credentials.py +0 -0
  198. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/extraction_parameters.py +0 -0
  199. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/sdk.py +0 -0
  200. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/sdk_test.py +0 -0
  201. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/api/utils.py +0 -0
  202. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/assets.py +0 -0
  203. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/constant.py +0 -0
  204. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/constants.py +0 -0
  205. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/extract.py +0 -0
  206. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/fields.py +0 -0
  207. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/fields_test.py +0 -0
  208. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker/multithreading.py +0 -0
  209. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/__init__.py +0 -0
  210. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/assets.py +0 -0
  211. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/__init__.py +0 -0
  212. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/admin_sdk_client.py +0 -0
  213. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/client.py +0 -0
  214. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/credentials.py +0 -0
  215. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/endpoints.py +0 -0
  216. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/enums.py +0 -0
  217. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py +0 -0
  218. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/pagination.py +0 -0
  219. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/client/queries/query.sql +0 -0
  220. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/extract.py +0 -0
  221. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/looker_studio/extract_test.py +0 -0
  222. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/__init__.py +0 -0
  223. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/assets.py +0 -0
  224. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/__init__.py +0 -0
  225. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/api/__init__.py +0 -0
  226. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/api/client.py +0 -0
  227. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/api/client_test.py +0 -0
  228. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/api/credentials.py +0 -0
  229. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/__init__.py +0 -0
  230. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/client.py +0 -0
  231. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/credentials.py +0 -0
  232. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/.sqlfluff +0 -0
  233. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/base_url.sql +0 -0
  234. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/card.sql +0 -0
  235. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/collection.sql +0 -0
  236. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/dashboard.sql +0 -0
  237. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/dashboard_cards.sql +0 -0
  238. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/database.sql +0 -0
  239. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/table.sql +0 -0
  240. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/db/queries/user.sql +0 -0
  241. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/decryption.py +0 -0
  242. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/decryption_test.py +0 -0
  243. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/client/shared.py +0 -0
  244. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/errors.py +0 -0
  245. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/extract.py +0 -0
  246. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/metabase/types.py +0 -0
  247. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/__init__.py +0 -0
  248. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/assets.py +0 -0
  249. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/client/__init__.py +0 -0
  250. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/client/client.py +0 -0
  251. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/client/client_test.json +0 -0
  252. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/client/client_test.py +0 -0
  253. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/client/constants.py +0 -0
  254. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/client/credentials.py +0 -0
  255. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/errors.py +0 -0
  256. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/mode/extract.py +0 -0
  257. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/__init__.py +0 -0
  258. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/assets.py +0 -0
  259. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/__init__.py +0 -0
  260. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/authentication.py +0 -0
  261. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/client_test.py +0 -0
  262. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/constants.py +0 -0
  263. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/credentials.py +0 -0
  264. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/credentials_test.py +0 -0
  265. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/endpoints.py +0 -0
  266. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/client/pagination.py +0 -0
  267. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/powerbi/extract.py +0 -0
  268. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/__init__.py +0 -0
  269. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/assets.py +0 -0
  270. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/__init__.py +0 -0
  271. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/constants.py +0 -0
  272. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/__init__.py +0 -0
  273. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/client.py +0 -0
  274. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/constants.py +0 -0
  275. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/credentials.py +0 -0
  276. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/error.py +0 -0
  277. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/error_test.py +0 -0
  278. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/json_rpc.py +0 -0
  279. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/json_rpc_test.py +0 -0
  280. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/engine/websocket.py +0 -0
  281. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/master.py +0 -0
  282. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/rest.py +0 -0
  283. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/client/rest_test.py +0 -0
  284. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/qlik/extract.py +0 -0
  285. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/salesforce_reporting/__init__.py +0 -0
  286. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/salesforce_reporting/assets.py +0 -0
  287. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/salesforce_reporting/client/__init__.py +0 -0
  288. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/salesforce_reporting/client/rest.py +0 -0
  289. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/salesforce_reporting/client/soql.py +0 -0
  290. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/salesforce_reporting/extract.py +0 -0
  291. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/__init__.py +0 -0
  292. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/client/__init__.py +0 -0
  293. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/client/client_test.py +0 -0
  294. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/client/credentials.py +0 -0
  295. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/sigma/client/pagination.py +0 -0
  296. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/__init__.py +0 -0
  297. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/assets.py +0 -0
  298. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/client/__init__.py +0 -0
  299. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/client/client.py +0 -0
  300. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/client/credentials.py +0 -0
  301. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/client/properties.py +0 -0
  302. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/strategy/extract.py +0 -0
  303. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/__init__.py +0 -0
  304. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/assets.py +0 -0
  305. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/__init__.py +0 -0
  306. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/client.py +0 -0
  307. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/client_metadata_api.py +0 -0
  308. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/client_metadata_api_test.py +0 -0
  309. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/client_rest_api.py +0 -0
  310. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/client_tsc.py +0 -0
  311. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/credentials.py +0 -0
  312. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/errors.py +0 -0
  313. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/gql_queries.py +0 -0
  314. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/client/rest_fields.py +0 -0
  315. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/constants.py +0 -0
  316. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/tableau/extract.py +0 -0
  317. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/__init__.py +0 -0
  318. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/assets.py +0 -0
  319. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/client/__init__.py +0 -0
  320. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/client/client.py +0 -0
  321. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/client/credentials.py +0 -0
  322. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/client/endpoints.py +0 -0
  323. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/client/pagination.py +0 -0
  324. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/visualization/thoughtspot/extract.py +0 -0
  325. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/__init__.py +0 -0
  326. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/__init__.py +0 -0
  327. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/asset.py +0 -0
  328. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/asset_test.py +0 -0
  329. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/extract.py +0 -0
  330. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/query.py +0 -0
  331. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/time_filter.py +0 -0
  332. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/abstract/time_filter_test.py +0 -0
  333. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/__init__.py +0 -0
  334. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/client.py +0 -0
  335. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/client_test.py +0 -0
  336. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/credentials.py +0 -0
  337. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/extract.py +0 -0
  338. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/.sqlfluff +0 -0
  339. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/column.sql +0 -0
  340. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/cte/sharded.sql +0 -0
  341. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/database.sql +0 -0
  342. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/query.sql +0 -0
  343. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/schema.sql +0 -0
  344. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/table.sql +0 -0
  345. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/table_with_tags.sql +0 -0
  346. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/user.sql +0 -0
  347. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/queries/view_ddl.sql +0 -0
  348. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/query.py +0 -0
  349. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/bigquery/types.py +0 -0
  350. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/__init__.py +0 -0
  351. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/api_client.py +0 -0
  352. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/api_client_test.py +0 -0
  353. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/credentials.py +0 -0
  354. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/endpoints.py +0 -0
  355. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/enums.py +0 -0
  356. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/extract.py +0 -0
  357. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/format.py +0 -0
  358. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/format_test.py +0 -0
  359. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/pagination.py +0 -0
  360. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/types.py +0 -0
  361. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/utils.py +0 -0
  362. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/databricks/utils_test.py +0 -0
  363. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/__init__.py +0 -0
  364. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/client.py +0 -0
  365. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/client_test.py +0 -0
  366. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/extract.py +0 -0
  367. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/.sqlfluff +0 -0
  368. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/column.sql +0 -0
  369. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/database.sql +0 -0
  370. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/query.sql +0 -0
  371. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/schema.sql +0 -0
  372. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/table.sql +0 -0
  373. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/user.sql +0 -0
  374. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/queries/view_ddl.sql +0 -0
  375. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/mysql/query.py +0 -0
  376. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/__init__.py +0 -0
  377. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/extract.py +0 -0
  378. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/.sqlfluff +0 -0
  379. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/column.sql +0 -0
  380. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/database.sql +0 -0
  381. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/group.sql +0 -0
  382. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/schema.sql +0 -0
  383. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/table.sql +0 -0
  384. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/queries/user.sql +0 -0
  385. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/postgres/query.py +0 -0
  386. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/__init__.py +0 -0
  387. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/client.py +0 -0
  388. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/client_test.py +0 -0
  389. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/extract.py +0 -0
  390. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/extract_test.py +0 -0
  391. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/.sqlfluff +0 -0
  392. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/column.sql +0 -0
  393. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/database.sql +0 -0
  394. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/group.sql +0 -0
  395. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/query.sql +0 -0
  396. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/query_serverless.sql +0 -0
  397. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/schema.sql +0 -0
  398. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/table.sql +0 -0
  399. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/table_freshness.sql +0 -0
  400. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/user.sql +0 -0
  401. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/queries/view_ddl.sql +0 -0
  402. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/redshift/query.py +0 -0
  403. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/__init__.py +0 -0
  404. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/client.py +0 -0
  405. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/constants.py +0 -0
  406. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/extract.py +0 -0
  407. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/format.py +0 -0
  408. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/format_test.py +0 -0
  409. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/pagination.py +0 -0
  410. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/salesforce/soql.py +0 -0
  411. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/__init__.py +0 -0
  412. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/client.py +0 -0
  413. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/client_test.py +0 -0
  414. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/credentials.py +0 -0
  415. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/credentials_test.py +0 -0
  416. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/extract.py +0 -0
  417. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/.sqlfluff +0 -0
  418. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/column.sql +0 -0
  419. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/column_lineage.sql +0 -0
  420. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/database.sql +0 -0
  421. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/function.sql +0 -0
  422. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/grant_to_role.sql +0 -0
  423. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/grant_to_user.sql +0 -0
  424. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/query.sql +0 -0
  425. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/role.sql +0 -0
  426. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/schema.sql +0 -0
  427. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/table.sql +0 -0
  428. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/user.sql +0 -0
  429. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/queries/view_ddl.sql +0 -0
  430. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/snowflake/query.py +0 -0
  431. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/__init__.py +0 -0
  432. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/client.py +0 -0
  433. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/queries/.sqlfluff +0 -0
  434. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/queries/database.sql +0 -0
  435. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/queries/user.sql +0 -0
  436. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/sqlserver/query.py +0 -0
  437. {castor_extractor-0.24.36 → castor_extractor-0.24.40}/castor_extractor/warehouse/synapse/queries/column.sql +0 -0
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.24.40 - 2025-08-18
4
+
5
+ * SQLServer: fix database allowlist/blocklist filtering
6
+
7
+ ## 0.24.39 - 2025-08-18
8
+
9
+ * Databricks:
10
+ * Fix vanishing owner ID column for tables
11
+ * Deduplicate lineage with SQL to reduce memory use
12
+
13
+ ## 0.24.38 - 2025-08-07
14
+
15
+ * Uploader: Support US and EU zones
16
+
17
+ ## 0.24.37 - 2025-08-06
18
+
19
+ * Sigma: extract data models, dataset sources and workbook sources
20
+
3
21
  ## 0.24.36 - 2025-08-04
4
22
 
5
23
  * Sigma:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: castor-extractor
3
- Version: 0.24.36
3
+ Version: 0.24.40
4
4
  Summary: Extract your metadata assets.
5
5
  Home-page: https://www.castordoc.com/
6
6
  License: EULA
@@ -215,6 +215,24 @@ For any questions or bug report, contact us at [support@coalesce.io](mailto:supp
215
215
 
216
216
  # Changelog
217
217
 
218
+ ## 0.24.40 - 2025-08-18
219
+
220
+ * SQLServer: fix database allowlist/blocklist filtering
221
+
222
+ ## 0.24.39 - 2025-08-18
223
+
224
+ * Databricks:
225
+ * Fix vanishing owner ID column for tables
226
+ * Deduplicate lineage with SQL to reduce memory use
227
+
228
+ ## 0.24.38 - 2025-08-07
229
+
230
+ * Uploader: Support US and EU zones
231
+
232
+ ## 0.24.37 - 2025-08-06
233
+
234
+ * Sigma: extract data models, dataset sources and workbook sources
235
+
218
236
  ## 0.24.36 - 2025-08-04
219
237
 
220
238
  * Sigma:
@@ -3,6 +3,7 @@ from argparse import ArgumentParser
3
3
 
4
4
  from castor_extractor.uploader import ( # type: ignore
5
5
  FileType,
6
+ Zone,
6
7
  upload_any,
7
8
  )
8
9
  from castor_extractor.utils import parse_filled_arguments # type: ignore
@@ -40,6 +41,15 @@ def _args() -> ArgumentParser:
40
41
  ),
41
42
  choices=supported_file_type,
42
43
  )
44
+ supported_zones = [zone.value for zone in Zone]
45
+ parser.add_argument(
46
+ "-z",
47
+ "--zone",
48
+ help="geographic zone to upload, currently supported are {}, defaults to EU".format(
49
+ supported_zones,
50
+ ),
51
+ choices=supported_zones,
52
+ )
43
53
  return parser
44
54
 
45
55
 
@@ -1,2 +1,3 @@
1
1
  from .constant import FileType
2
+ from .enums import Zone
2
3
  from .upload import upload, upload_any, upload_manifest
@@ -1,9 +1,13 @@
1
1
  from enum import Enum
2
2
 
3
3
  from ..utils import RetryStrategy
4
+ from .enums import Zone
4
5
 
5
6
  # url of the gcs proxy
6
- INGEST_URL = "https://ingest.castordoc.com"
7
+ INGEST_URLS = {
8
+ Zone.EU: "https://ingest.castordoc.com",
9
+ Zone.US: "https://ingest.us.castordoc.com",
10
+ }
7
11
 
8
12
  RETRY_BASE_MS = 10_000
9
13
  RETRY_JITTER_MS = 1_000
@@ -0,0 +1,8 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Zone(Enum):
5
+ """Geographic cluster location"""
6
+
7
+ EU = "EU"
8
+ US = "US"
@@ -4,6 +4,7 @@ from pydantic import UUID4, Field
4
4
  from pydantic_settings import BaseSettings, SettingsConfigDict
5
5
 
6
6
  from .constant import FileType
7
+ from .enums import Zone
7
8
 
8
9
  UPLOADER_ENV_PREFIX = "CASTOR_UPLOADER_"
9
10
 
@@ -22,3 +23,4 @@ class UploaderSettings(BaseSettings):
22
23
  file_type: FileType
23
24
  source_id: UUID4
24
25
  token: str = Field(repr=False)
26
+ zone: Optional[Zone] = Zone.EU
@@ -10,13 +10,14 @@ import requests
10
10
 
11
11
  from ..utils.retry import retry
12
12
  from .constant import (
13
- INGEST_URL,
13
+ INGEST_URLS,
14
14
  PATH_TEMPLATES,
15
15
  RETRY_BASE_MS,
16
16
  RETRY_JITTER_MS,
17
17
  RETRY_STRATEGY,
18
18
  FileType,
19
19
  )
20
+ from .enums import Zone
20
21
  from .env import get_blob_env
21
22
  from .settings import UploaderSettings
22
23
  from .utils import iter_files
@@ -33,6 +34,7 @@ def _path_and_url(
33
34
  source_id: UUID,
34
35
  file_type: FileType,
35
36
  file_path: str,
37
+ zone: Zone,
36
38
  ) -> tuple[str, str]:
37
39
  now = datetime.utcnow()
38
40
  timestamp = int(now.timestamp())
@@ -44,7 +46,7 @@ def _path_and_url(
44
46
  filename=filename,
45
47
  )
46
48
 
47
- url = f"{INGEST_URL}/{path}"
49
+ url = f"{INGEST_URLS[zone]}/{path}"
48
50
 
49
51
  return path, url
50
52
 
@@ -61,13 +63,16 @@ def _upload(
61
63
  source_id: UUID,
62
64
  file_path: str,
63
65
  file_type: FileType,
66
+ zone: Optional[Zone] = Zone.EU,
64
67
  ) -> None:
65
68
  """
66
69
  Upload the given file to Google Cloud Storage (GCS)
67
70
  - Don't call GCS API directly
68
71
  - Call the ingestion proxy which handles authorisation and uploading
69
72
  """
70
- path, url = _path_and_url(source_id, file_type, file_path)
73
+ if not zone:
74
+ zone = Zone.EU
75
+ path, url = _path_and_url(source_id, file_type, file_path, zone)
71
76
  headers = _headers(token)
72
77
  timeout, max_retries = get_blob_env()
73
78
 
@@ -97,6 +102,7 @@ def _upload(
97
102
  def upload_manifest(
98
103
  token: str,
99
104
  source_id: UUID,
105
+ zone: Optional[Zone],
100
106
  file_path: Optional[str] = None,
101
107
  ) -> None:
102
108
  """
@@ -106,13 +112,20 @@ def upload_manifest(
106
112
  """
107
113
  if not file_path:
108
114
  raise ValueError("file path is needed to upload a manifest")
109
- _upload(token, source_id, file_path, FileType.DBT)
115
+ _upload(
116
+ token=token,
117
+ source_id=source_id,
118
+ file_path=file_path,
119
+ file_type=FileType.DBT,
120
+ zone=zone,
121
+ )
110
122
 
111
123
 
112
124
  def upload(
113
125
  token: str,
114
126
  source_id: UUID,
115
127
  file_type: FileType,
128
+ zone: Optional[Zone],
116
129
  file_path: Optional[str] = None,
117
130
  directory_path: Optional[str] = None,
118
131
  ) -> None:
@@ -133,7 +146,13 @@ def upload(
133
146
  raise ValueError(message)
134
147
 
135
148
  for file_ in files:
136
- _upload(token, source_id, file_, file_type)
149
+ _upload(
150
+ token=token,
151
+ source_id=source_id,
152
+ file_path=file_,
153
+ file_type=file_type,
154
+ zone=zone,
155
+ )
137
156
 
138
157
 
139
158
  def upload_any(**kwargs) -> None:
@@ -156,6 +175,7 @@ def upload_any(**kwargs) -> None:
156
175
  token=settings.token,
157
176
  source_id=settings.source_id,
158
177
  file_path=settings.file_path,
178
+ zone=settings.zone,
159
179
  )
160
180
  return None
161
181
 
@@ -165,4 +185,5 @@ def upload_any(**kwargs) -> None:
165
185
  file_type=file_type,
166
186
  file_path=settings.file_path,
167
187
  directory_path=settings.directory_path,
188
+ zone=settings.zone,
168
189
  )
@@ -1,6 +1,7 @@
1
1
  from uuid import UUID
2
2
 
3
- from .constant import INGEST_URL, FileType
3
+ from .constant import INGEST_URLS, FileType
4
+ from .enums import Zone
4
5
  from .upload import _path_and_url
5
6
 
6
7
 
@@ -8,7 +9,8 @@ def test__path():
8
9
  source_id = UUID("399a8b22-3187-11ec-8d3d-0242ac130003")
9
10
  file_type = FileType.VIZ
10
11
  file_path = "filename"
12
+ zone = Zone.EU
11
13
 
12
- path, url = _path_and_url(source_id, file_type, file_path)
14
+ path, url = _path_and_url(source_id, file_type, file_path, zone)
13
15
  assert path == f"visualization-{source_id}/{file_path}"
14
- assert url == f"{INGEST_URL}/{path}"
16
+ assert url == f"{INGEST_URLS[Zone.EU]}/{path}"
@@ -28,6 +28,7 @@ POWERBI_DEFAULT_TIMEOUT_S = 30
28
28
  METADATA_BATCH_SIZE = 100
29
29
  POWERBI_SCAN_STATUS_DONE = "Succeeded"
30
30
  POWERBI_SCAN_SLEEP_S = 1
31
+ POWERBI_SCAN_TIMEOUT_S = 60
31
32
 
32
33
  MAX_RETRY_PAGES = 1
33
34
  RETRY_PAGES_TIMEOUT_MS = 35 * 1000 # 35 seconds
@@ -142,7 +143,7 @@ class PowerbiClient(APIClient):
142
143
  endpoint = self.endpoint_factory.metadata_scan_status(scan_id)
143
144
  total_waiting_time_s = 0
144
145
 
145
- while total_waiting_time_s < POWERBI_DEFAULT_TIMEOUT_S:
146
+ while total_waiting_time_s < POWERBI_SCAN_TIMEOUT_S:
146
147
  try:
147
148
  result = self._get(endpoint)
148
149
  except HTTPError as e:
@@ -4,10 +4,13 @@ from ...types import ExternalAsset
4
4
  class SigmaAsset(ExternalAsset):
5
5
  """Sigma assets"""
6
6
 
7
+ DATAMODELS = "datamodels"
7
8
  DATASETS = "datasets"
9
+ DATASET_SOURCES = "dataset_sources"
8
10
  ELEMENTS = "elements"
9
11
  FILES = "files"
10
12
  LINEAGES = "lineages"
11
13
  MEMBERS = "members"
12
14
  QUERIES = "queries"
13
15
  WORKBOOKS = "workbooks"
16
+ WORKBOOK_SOURCES = "workbook_sources"
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from collections.abc import Iterator
2
3
  from concurrent.futures import ThreadPoolExecutor
3
4
  from functools import partial
@@ -24,6 +25,9 @@ from .pagination import (
24
25
  SIGMA_QUERIES_PAGINATION_LIMIT,
25
26
  SigmaPagination,
26
27
  )
28
+ from .sources_transformer import SigmaSourcesTransformer
29
+
30
+ logger = logging.getLogger(__name__)
27
31
 
28
32
  _CONTENT_TYPE = "application/x-www-form-urlencoded"
29
33
 
@@ -135,6 +139,12 @@ class SigmaClient(APIClient):
135
139
  params={"limit": limit},
136
140
  )
137
141
 
142
+ def _get_all_datamodels(self) -> Iterator[dict]:
143
+ request = self._get_paginated(
144
+ endpoint=SigmaEndpointFactory.datamodels()
145
+ )
146
+ yield from fetch_all_pages(request, SigmaPagination)
147
+
138
148
  def _get_all_datasets(self) -> Iterator[dict]:
139
149
  request = self._get_paginated(endpoint=SigmaEndpointFactory.datasets())
140
150
  yield from fetch_all_pages(request, SigmaPagination)
@@ -275,18 +285,36 @@ class SigmaClient(APIClient):
275
285
 
276
286
  yield from self._yield_deduplicated_queries(queries, workbook_id)
277
287
 
288
+ def _get_all_dataset_sources(self, datasets: list[dict]) -> Iterator[dict]:
289
+ yield from SigmaSourcesTransformer(self).get_dataset_sources(datasets)
290
+
291
+ def _get_all_workbook_sources(
292
+ self, workbooks: list[dict]
293
+ ) -> Iterator[dict]:
294
+ yield from SigmaSourcesTransformer(self).get_workbook_sources(workbooks)
295
+
278
296
  def fetch(
279
297
  self,
280
298
  asset: SigmaAsset,
281
- workbooks: Optional[list[dict]] = None,
299
+ datasets: Optional[list[dict]] = None,
282
300
  elements: Optional[list[dict]] = None,
301
+ workbooks: Optional[list[dict]] = None,
283
302
  ) -> Iterator[dict]:
284
303
  """Returns the needed metadata for the queried asset"""
285
- if asset == SigmaAsset.DATASETS:
304
+ if asset == SigmaAsset.DATAMODELS:
305
+ yield from self._get_all_datamodels()
306
+
307
+ elif asset == SigmaAsset.DATASETS:
286
308
  yield from self._get_all_datasets()
287
309
 
310
+ elif asset == SigmaAsset.DATASET_SOURCES:
311
+ if datasets is None:
312
+ raise ValueError("Missing datasets to extract dataset sources")
313
+
314
+ yield from self._get_all_dataset_sources(datasets)
315
+
288
316
  elif asset == SigmaAsset.ELEMENTS:
289
- if not workbooks:
317
+ if workbooks is None:
290
318
  raise ValueError("Missing workbooks to extract elements")
291
319
 
292
320
  yield from self._get_all_elements(workbooks)
@@ -295,15 +323,16 @@ class SigmaClient(APIClient):
295
323
  yield from self._get_all_files()
296
324
 
297
325
  elif asset == SigmaAsset.LINEAGES:
298
- if not elements:
326
+ if elements is None:
299
327
  raise ValueError("Missing elements to extract lineage")
328
+
300
329
  yield from self._get_all_lineages(elements)
301
330
 
302
331
  elif asset == SigmaAsset.MEMBERS:
303
332
  yield from self._get_all_members()
304
333
 
305
334
  elif asset == SigmaAsset.QUERIES:
306
- if not workbooks:
335
+ if workbooks is None:
307
336
  raise ValueError("Missing workbooks to extract queries")
308
337
 
309
338
  yield from self._get_all_queries(workbooks)
@@ -311,5 +340,13 @@ class SigmaClient(APIClient):
311
340
  elif asset == SigmaAsset.WORKBOOKS:
312
341
  yield from self._get_all_workbooks()
313
342
 
343
+ elif asset == SigmaAsset.WORKBOOK_SOURCES:
344
+ if workbooks is None:
345
+ raise ValueError(
346
+ "Missing workbooks to extract workbook sources"
347
+ )
348
+
349
+ yield from self._get_all_workbook_sources(workbooks)
350
+
314
351
  else:
315
352
  raise ValueError(f"This asset {asset} is unknown")
@@ -1,6 +1,7 @@
1
1
  class SigmaEndpointFactory:
2
2
  """Wrapper class around all endpoints we're using"""
3
3
 
4
+ DATAMODELS = "dataModels"
4
5
  DATASETS = "datasets"
5
6
  FILES = "files"
6
7
  MEMBERS = "members"
@@ -10,10 +11,22 @@ class SigmaEndpointFactory:
10
11
  def authentication(cls) -> str:
11
12
  return "v2/auth/token"
12
13
 
14
+ @classmethod
15
+ def connection_path(cls, inode_id: str) -> str:
16
+ return f"v2/connections/paths/{inode_id}"
17
+
18
+ @classmethod
19
+ def datamodels(cls) -> str:
20
+ return f"v2/{cls.DATAMODELS}"
21
+
13
22
  @classmethod
14
23
  def datasets(cls) -> str:
15
24
  return f"v2/{cls.DATASETS}"
16
25
 
26
+ @classmethod
27
+ def dataset_sources(cls, dataset_id: str) -> str:
28
+ return f"v2/{cls.DATASETS}/{dataset_id}/sources"
29
+
17
30
  @classmethod
18
31
  def elements(cls, workbook_id: str, page_id: str) -> str:
19
32
  return f"v2/{cls.WORKBOOKS}/{workbook_id}/pages/{page_id}/elements"
@@ -41,3 +54,7 @@ class SigmaEndpointFactory:
41
54
  @classmethod
42
55
  def workbooks(cls) -> str:
43
56
  return f"v2/{cls.WORKBOOKS}"
57
+
58
+ @classmethod
59
+ def workbook_sources(cls, workbook_id: str) -> str:
60
+ return f"v2/{cls.WORKBOOKS}/{workbook_id}/sources"
@@ -0,0 +1,94 @@
1
+ import logging
2
+ from typing import TYPE_CHECKING, Callable, Iterator
3
+
4
+ from .endpoints import SigmaEndpointFactory
5
+
6
+ if TYPE_CHECKING:
7
+ from .client import SigmaClient
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class SigmaSourcesTransformer:
13
+ """Retrieves asset sources and enhances them with additional information."""
14
+
15
+ def __init__(self, api_client: "SigmaClient"):
16
+ self.api_client = api_client
17
+
18
+ def _map_table_id_to_connection_path(
19
+ self, all_sources: list
20
+ ) -> dict[str, dict]:
21
+ """Maps a table id to its connection and path information."""
22
+ logger.info("Mapping table ids to connection and path information")
23
+
24
+ unique_table_ids = {
25
+ source["inodeId"]
26
+ for asset_sources in all_sources
27
+ for source in asset_sources["sources"]
28
+ if source["type"] == "table"
29
+ }
30
+
31
+ return {
32
+ table_id: self.api_client._get(
33
+ endpoint=SigmaEndpointFactory.connection_path(table_id)
34
+ )
35
+ for table_id in unique_table_ids
36
+ }
37
+
38
+ @staticmethod
39
+ def _enhance_table_source(source: dict, table_to_path: dict) -> dict:
40
+ """
41
+ Combines a single table source with its connection and path information.
42
+ """
43
+ if source["type"] != "table":
44
+ return source
45
+
46
+ path_info = table_to_path.get(source["inodeId"], {})
47
+ source["connectionId"] = path_info.get("connectionId")
48
+ source["path"] = path_info.get("path")
49
+ return source
50
+
51
+ def _transform_sources(
52
+ self, all_sources: list, table_to_path: dict
53
+ ) -> Iterator[dict]:
54
+ """
55
+ Yields all sources, with table sources being enhanced with additional information.
56
+ """
57
+ logger.info("Merging sources with table information")
58
+
59
+ for asset_sources in all_sources:
60
+ enhanced_sources = [
61
+ self._enhance_table_source(source, table_to_path)
62
+ for source in asset_sources["sources"]
63
+ ]
64
+
65
+ yield {
66
+ "asset_id": asset_sources["asset_id"],
67
+ "sources": enhanced_sources,
68
+ }
69
+
70
+ def _get_all_sources(
71
+ self, endpoint: Callable[[str], str], asset_ids: set[str]
72
+ ) -> Iterator[dict]:
73
+ """Returns transformed sources for the given assets"""
74
+ all_sources = []
75
+
76
+ for asset_id in asset_ids:
77
+ sources = self.api_client._get(endpoint=endpoint(asset_id))
78
+ all_sources.append({"asset_id": asset_id, "sources": sources})
79
+
80
+ table_to_path = self._map_table_id_to_connection_path(all_sources)
81
+
82
+ yield from self._transform_sources(all_sources, table_to_path)
83
+
84
+ def get_dataset_sources(self, datasets: list[dict]) -> Iterator[dict]:
85
+ asset_ids = {dataset["datasetId"] for dataset in datasets}
86
+ yield from self._get_all_sources(
87
+ endpoint=SigmaEndpointFactory.dataset_sources, asset_ids=asset_ids
88
+ )
89
+
90
+ def get_workbook_sources(self, workbooks: list[dict]) -> Iterator[dict]:
91
+ asset_ids = {workbook["workbookId"] for workbook in workbooks}
92
+ yield from self._get_all_sources(
93
+ endpoint=SigmaEndpointFactory.workbook_sources, asset_ids=asset_ids
94
+ )
@@ -0,0 +1,101 @@
1
+ from unittest.mock import Mock
2
+
3
+ from .sources_transformer import SigmaSourcesTransformer
4
+
5
+ _ALL_SOURCES = [
6
+ {
7
+ "asset_id": "asset1",
8
+ "sources": [
9
+ {"type": "dataset", "inodeId": "1234"}, # non-table source
10
+ {"type": "table", "inodeId": "table1"},
11
+ {"type": "table", "inodeId": "table2"},
12
+ ],
13
+ },
14
+ {
15
+ "asset_id": "asset2",
16
+ "sources": [
17
+ {"type": "table", "inodeId": "table1"}, # repeated source
18
+ ],
19
+ },
20
+ ]
21
+
22
+
23
+ _TABLE_TO_PATH = {
24
+ "table1": {
25
+ "connectionId": "conn1",
26
+ "path": ["db", "schema", "table1"],
27
+ },
28
+ "table2": {
29
+ "connectionId": "conn2",
30
+ "path": ["db", "schema", "table2"],
31
+ },
32
+ }
33
+
34
+
35
+ def test__map_table_id_to_connection_path():
36
+ transformer = SigmaSourcesTransformer(api_client=Mock())
37
+
38
+ def mock_get(endpoint):
39
+ if "table1" in endpoint:
40
+ return _TABLE_TO_PATH["table1"]
41
+ elif "table2" in endpoint:
42
+ return _TABLE_TO_PATH["table2"]
43
+ else:
44
+ raise ValueError(f"Unexpected endpoint: {endpoint}")
45
+
46
+ transformer.api_client._get.side_effect = mock_get
47
+
48
+ result = transformer._map_table_id_to_connection_path(_ALL_SOURCES)
49
+
50
+ assert len(result) == 2
51
+ assert result["table1"] == {
52
+ "connectionId": "conn1",
53
+ "path": ["db", "schema", "table1"],
54
+ }
55
+ assert result["table2"] == {
56
+ "connectionId": "conn2",
57
+ "path": ["db", "schema", "table2"],
58
+ }
59
+ assert transformer.api_client._get.call_count == 2
60
+
61
+
62
+ def test__transform_sources():
63
+ transformer = SigmaSourcesTransformer(api_client=Mock())
64
+
65
+ result = list(transformer._transform_sources(_ALL_SOURCES, _TABLE_TO_PATH))
66
+
67
+ assert len(result) == 2
68
+
69
+ asset_1_results = result[0]
70
+ assert len(asset_1_results["sources"]) == 3
71
+ actual_sources = sorted(
72
+ asset_1_results["sources"], key=lambda x: x["inodeId"]
73
+ )
74
+ expected_sources = [
75
+ {"type": "dataset", "inodeId": "1234"},
76
+ {
77
+ "type": "table",
78
+ "inodeId": "table1",
79
+ "connectionId": "conn1",
80
+ "path": ["db", "schema", "table1"],
81
+ },
82
+ {
83
+ "type": "table",
84
+ "inodeId": "table2",
85
+ "connectionId": "conn2",
86
+ "path": ["db", "schema", "table2"],
87
+ },
88
+ ]
89
+ expected_sources = sorted(expected_sources, key=lambda x: x["inodeId"])
90
+ assert actual_sources == expected_sources
91
+
92
+ asset_2_results = result[1]
93
+ assert asset_2_results["asset_id"] == "asset2"
94
+ assert asset_2_results["sources"] == [
95
+ {
96
+ "type": "table",
97
+ "inodeId": "table1",
98
+ "connectionId": "conn1",
99
+ "path": ["db", "schema", "table1"],
100
+ }
101
+ ]
@@ -22,14 +22,30 @@ def iterate_all_data(
22
22
  ) -> Iterable[tuple[SigmaAsset, Union[list, Iterator, dict]]]:
23
23
  """Iterate over the extracted data from Sigma"""
24
24
 
25
+ logger.info("Extracting DATA MODELS from API")
26
+ datamodels = client.fetch(SigmaAsset.DATAMODELS)
27
+ yield SigmaAsset.DATASETS, list(deep_serialize(datamodels))
28
+
25
29
  logger.info("Extracting DATASETS from API")
26
- datasets = client.fetch(SigmaAsset.DATASETS)
30
+ datasets = list(client.fetch(SigmaAsset.DATASETS))
27
31
  yield SigmaAsset.DATASETS, list(deep_serialize(datasets))
28
32
 
33
+ logger.info("Extracting DATASET SOURCES from API")
34
+ dataset_sources = client.fetch(
35
+ SigmaAsset.DATASET_SOURCES, datasets=datasets
36
+ )
37
+ yield SigmaAsset.DATASET_SOURCES, list(deep_serialize(dataset_sources))
38
+
29
39
  logger.info("Extracting WORKBOOKS from API")
30
40
  workbooks = list(client.fetch(SigmaAsset.WORKBOOKS))
31
41
  yield SigmaAsset.WORKBOOKS, list(deep_serialize(workbooks))
32
42
 
43
+ logger.info("Extracting WORKBOOK SOURCES from API")
44
+ workbook_sources = client.fetch(
45
+ SigmaAsset.WORKBOOK_SOURCES, workbooks=workbooks
46
+ )
47
+ yield SigmaAsset.WORKBOOKS, list(deep_serialize(workbook_sources))
48
+
33
49
  logger.info("Extracting FILES from API")
34
50
  files = client.fetch(SigmaAsset.FILES)
35
51
  yield SigmaAsset.FILES, list(deep_serialize(files))
@@ -46,12 +46,11 @@ class DatabricksClient:
46
46
 
47
47
  @staticmethod
48
48
  def _match_table_with_user(table: dict, user_mapping: dict) -> dict:
49
+ """Matches the table's owner email to an ID, or None if not found."""
49
50
  table_owner_email = table.get("owner_email")
50
- if not table_owner_email:
51
- return table
52
- owner_external_id = user_mapping.get(table_owner_email)
53
- if not owner_external_id:
54
- return table
51
+ owner_external_id = (
52
+ user_mapping.get(table_owner_email) if table_owner_email else None
53
+ )
55
54
  return {**table, "owner_external_id": owner_external_id}
56
55
 
57
56
  @staticmethod
@@ -36,5 +36,6 @@ def test_DatabricksClient__match_table_with_user():
36
36
  assert table_with_owner == {**table, "owner_external_id": 3}
37
37
 
38
38
  table_without_owner = {"id": 1, "owner_email": None}
39
+ expected = {"id": 1, "owner_email": None, "owner_external_id": None}
39
40
  actual = client._match_table_with_user(table_without_owner, user_mapping)
40
- assert actual == table_without_owner
41
+ assert actual == expected