castor-extractor 0.24.2__tar.gz → 0.24.7__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 (411) hide show
  1. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/CHANGELOG.md +24 -0
  2. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/PKG-INFO +27 -3
  3. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/__init__.py +1 -0
  4. castor_extractor-0.24.7/castor_extractor/utils/batch.py +16 -0
  5. castor_extractor-0.24.7/castor_extractor/utils/batch_test.py +27 -0
  6. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/client/client.py +10 -4
  7. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/client_metadata_api.py +23 -18
  8. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/gql_queries.py +1 -1
  9. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/client/client.py +54 -17
  10. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/client/endpoints.py +2 -2
  11. castor_extractor-0.24.7/castor_extractor/visualization/thoughtspot/client/pagination.py +25 -0
  12. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/column.sql +3 -1
  13. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/query.sql +19 -11
  14. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/schema.sql +1 -0
  15. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/table.sql +2 -2
  16. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/pyproject.toml +5 -5
  17. castor_extractor-0.24.2/castor_extractor/visualization/thoughtspot/client/utils.py +0 -31
  18. castor_extractor-0.24.2/castor_extractor/visualization/thoughtspot/client/utils_test.py +0 -75
  19. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/Dockerfile +0 -0
  20. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/DockerfileUsage.md +0 -0
  21. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/LICENCE +0 -0
  22. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/README.md +0 -0
  23. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/__init__.py +0 -0
  24. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/__init__.py +0 -0
  25. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_bigquery.py +0 -0
  26. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_confluence.py +0 -0
  27. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_databricks.py +0 -0
  28. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_domo.py +0 -0
  29. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_looker.py +0 -0
  30. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_looker_studio.py +0 -0
  31. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_metabase_api.py +0 -0
  32. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_metabase_db.py +0 -0
  33. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_mode.py +0 -0
  34. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_mysql.py +0 -0
  35. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_notion.py +0 -0
  36. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_postgres.py +0 -0
  37. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_powerbi.py +0 -0
  38. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_qlik.py +0 -0
  39. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_redshift.py +0 -0
  40. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_salesforce.py +0 -0
  41. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_salesforce_reporting.py +0 -0
  42. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_sigma.py +0 -0
  43. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_snowflake.py +0 -0
  44. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_sqlserver.py +0 -0
  45. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_tableau.py +0 -0
  46. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/extract_thoughtspot.py +0 -0
  47. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/file_check.py +0 -0
  48. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/commands/upload.py +0 -0
  49. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/__init__.py +0 -0
  50. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/column.py +0 -0
  51. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/column_test.py +0 -0
  52. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/constants.py +0 -0
  53. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/enums.py +0 -0
  54. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/file.py +0 -0
  55. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/file_test.py +0 -0
  56. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/file_test_users.csv +0 -0
  57. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/file_test_users_valid.csv +0 -0
  58. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/templates/__init__.py +0 -0
  59. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/file_checker/templates/generic_warehouse.py +0 -0
  60. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/__init__.py +0 -0
  61. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/__init__.py +0 -0
  62. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/assets.py +0 -0
  63. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/client/__init__.py +0 -0
  64. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/client/client.py +0 -0
  65. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/client/credentials.py +0 -0
  66. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/client/endpoints.py +0 -0
  67. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/client/pagination.py +0 -0
  68. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/confluence/extract.py +0 -0
  69. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/__init__.py +0 -0
  70. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/assets.py +0 -0
  71. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/__init__.py +0 -0
  72. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/client.py +0 -0
  73. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/client_test.py +0 -0
  74. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/constants.py +0 -0
  75. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/credentials.py +0 -0
  76. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/endpoints.py +0 -0
  77. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/client/pagination.py +0 -0
  78. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/knowledge/notion/extract.py +0 -0
  79. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/logger.py +0 -0
  80. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/__init__.py +0 -0
  81. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/__init__.py +0 -0
  82. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/assets.py +0 -0
  83. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/client/__init__.py +0 -0
  84. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/client/client.py +0 -0
  85. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/client/credentials.py +0 -0
  86. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/client/endpoints.py +0 -0
  87. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/quality/soda/client/pagination.py +0 -0
  88. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/types.py +0 -0
  89. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/__init__.py +0 -0
  90. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/constant.py +0 -0
  91. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/env.py +0 -0
  92. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/env_test.py +0 -0
  93. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/settings.py +0 -0
  94. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/upload.py +0 -0
  95. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/upload_test.py +0 -0
  96. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/uploader/utils.py +0 -0
  97. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/argument_parser.py +0 -0
  98. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/argument_parser_test.py +0 -0
  99. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/__init__.py +0 -0
  100. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/abstract.py +0 -0
  101. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/__init__.py +0 -0
  102. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/auth.py +0 -0
  103. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/auth_test.py +0 -0
  104. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/client.py +0 -0
  105. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/client_test.py +0 -0
  106. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/pagination.py +0 -0
  107. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/pagination_test.py +0 -0
  108. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/safe_request.py +0 -0
  109. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/safe_request_test.py +0 -0
  110. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/utils.py +0 -0
  111. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/api/utils_test.py +0 -0
  112. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/postgres.py +0 -0
  113. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/query.py +0 -0
  114. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/uri.py +0 -0
  115. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/client/uri_test.py +0 -0
  116. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/collection.py +0 -0
  117. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/collection_test.py +0 -0
  118. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/constants.py +0 -0
  119. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/dbt/__init__.py +0 -0
  120. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/dbt/assets.py +0 -0
  121. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/dbt/client.py +0 -0
  122. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/dbt/client_test.py +0 -0
  123. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/dbt/credentials.py +0 -0
  124. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/deprecate.py +0 -0
  125. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/env.py +0 -0
  126. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/files.py +0 -0
  127. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/files_test.py +0 -0
  128. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/formatter.py +0 -0
  129. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/formatter_test.csv +0 -0
  130. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/formatter_test.json +0 -0
  131. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/formatter_test.py +0 -0
  132. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/json_stream_write.py +0 -0
  133. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/load.py +0 -0
  134. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/object.py +0 -0
  135. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/object_test.py +0 -0
  136. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/pager/__init__.py +0 -0
  137. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/pager/pager.py +0 -0
  138. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/pager/pager_on_id.py +0 -0
  139. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/pager/pager_on_id_test.py +0 -0
  140. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/pager/pager_test.py +0 -0
  141. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/retry.py +0 -0
  142. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/retry_test.py +0 -0
  143. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/safe.py +0 -0
  144. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/safe_test.py +0 -0
  145. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/__init__.py +0 -0
  146. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/client.py +0 -0
  147. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/client_test.py +0 -0
  148. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/constants.py +0 -0
  149. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/credentials.py +0 -0
  150. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/credentials_test.py +0 -0
  151. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/salesforce/pagination.py +0 -0
  152. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/store.py +0 -0
  153. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/string.py +0 -0
  154. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/string_test.py +0 -0
  155. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/time.py +0 -0
  156. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/time_test.py +0 -0
  157. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/type.py +0 -0
  158. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/validation.py +0 -0
  159. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/validation_test.py +0 -0
  160. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/utils/write.py +0 -0
  161. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/__init__.py +0 -0
  162. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/__init__.py +0 -0
  163. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/assets.py +0 -0
  164. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/client/__init__.py +0 -0
  165. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/client/credentials.py +0 -0
  166. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/client/endpoints.py +0 -0
  167. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/client/pagination.py +0 -0
  168. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/client/pagination_test.py +0 -0
  169. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/domo/extract.py +0 -0
  170. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/__init__.py +0 -0
  171. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/__init__.py +0 -0
  172. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/client.py +0 -0
  173. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/client_test.py +0 -0
  174. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/constants.py +0 -0
  175. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/credentials.py +0 -0
  176. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/extraction_parameters.py +0 -0
  177. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/sdk.py +0 -0
  178. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/sdk_test.py +0 -0
  179. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/api/utils.py +0 -0
  180. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/assets.py +0 -0
  181. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/constant.py +0 -0
  182. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/constants.py +0 -0
  183. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/extract.py +0 -0
  184. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/fields.py +0 -0
  185. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/fields_test.py +0 -0
  186. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker/multithreading.py +0 -0
  187. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/__init__.py +0 -0
  188. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/assets.py +0 -0
  189. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/__init__.py +0 -0
  190. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/admin_sdk_client.py +0 -0
  191. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/client.py +0 -0
  192. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/credentials.py +0 -0
  193. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/endpoints.py +0 -0
  194. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/enums.py +0 -0
  195. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py +0 -0
  196. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/pagination.py +0 -0
  197. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/queries/query.sql +0 -0
  198. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/client/scopes.py +0 -0
  199. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/looker_studio/extract.py +0 -0
  200. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/__init__.py +0 -0
  201. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/assets.py +0 -0
  202. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/__init__.py +0 -0
  203. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/api/__init__.py +0 -0
  204. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/api/client.py +0 -0
  205. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/api/client_test.py +0 -0
  206. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/api/credentials.py +0 -0
  207. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/__init__.py +0 -0
  208. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/client.py +0 -0
  209. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/credentials.py +0 -0
  210. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/.sqlfluff +0 -0
  211. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/base_url.sql +0 -0
  212. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/card.sql +0 -0
  213. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/collection.sql +0 -0
  214. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/dashboard.sql +0 -0
  215. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/dashboard_cards.sql +0 -0
  216. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/database.sql +0 -0
  217. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/table.sql +0 -0
  218. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/db/queries/user.sql +0 -0
  219. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/decryption.py +0 -0
  220. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/decryption_test.py +0 -0
  221. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/client/shared.py +0 -0
  222. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/errors.py +0 -0
  223. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/extract.py +0 -0
  224. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/metabase/types.py +0 -0
  225. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/__init__.py +0 -0
  226. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/assets.py +0 -0
  227. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/client/__init__.py +0 -0
  228. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/client/client.py +0 -0
  229. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/client/client_test.json +0 -0
  230. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/client/client_test.py +0 -0
  231. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/client/constants.py +0 -0
  232. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/client/credentials.py +0 -0
  233. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/errors.py +0 -0
  234. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/mode/extract.py +0 -0
  235. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/__init__.py +0 -0
  236. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/assets.py +0 -0
  237. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/__init__.py +0 -0
  238. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/authentication.py +0 -0
  239. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/client.py +0 -0
  240. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/client_test.py +0 -0
  241. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/constants.py +0 -0
  242. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/credentials.py +0 -0
  243. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/credentials_test.py +0 -0
  244. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/endpoints.py +0 -0
  245. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/client/pagination.py +0 -0
  246. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/powerbi/extract.py +0 -0
  247. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/__init__.py +0 -0
  248. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/assets.py +0 -0
  249. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/__init__.py +0 -0
  250. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/constants.py +0 -0
  251. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/__init__.py +0 -0
  252. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/client.py +0 -0
  253. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/constants.py +0 -0
  254. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/credentials.py +0 -0
  255. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/error.py +0 -0
  256. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/error_test.py +0 -0
  257. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/json_rpc.py +0 -0
  258. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/json_rpc_test.py +0 -0
  259. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/engine/websocket.py +0 -0
  260. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/master.py +0 -0
  261. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/rest.py +0 -0
  262. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/client/rest_test.py +0 -0
  263. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/qlik/extract.py +0 -0
  264. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/salesforce_reporting/__init__.py +0 -0
  265. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/salesforce_reporting/assets.py +0 -0
  266. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/salesforce_reporting/client/__init__.py +0 -0
  267. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/salesforce_reporting/client/rest.py +0 -0
  268. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/salesforce_reporting/client/soql.py +0 -0
  269. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/salesforce_reporting/extract.py +0 -0
  270. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/__init__.py +0 -0
  271. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/assets.py +0 -0
  272. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/client/__init__.py +0 -0
  273. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/client/client.py +0 -0
  274. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/client/credentials.py +0 -0
  275. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/client/endpoints.py +0 -0
  276. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/client/pagination.py +0 -0
  277. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/sigma/extract.py +0 -0
  278. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/__init__.py +0 -0
  279. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/assets.py +0 -0
  280. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/__init__.py +0 -0
  281. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/client.py +0 -0
  282. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/client_rest_api.py +0 -0
  283. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/client_tsc.py +0 -0
  284. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/credentials.py +0 -0
  285. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/errors.py +0 -0
  286. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/client/rest_fields.py +0 -0
  287. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/constants.py +0 -0
  288. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/tableau/extract.py +0 -0
  289. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/__init__.py +0 -0
  290. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/assets.py +0 -0
  291. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/client/__init__.py +0 -0
  292. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/client/credentials.py +0 -0
  293. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/visualization/thoughtspot/extract.py +0 -0
  294. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/__init__.py +0 -0
  295. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/__init__.py +0 -0
  296. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/asset.py +0 -0
  297. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/asset_test.py +0 -0
  298. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/extract.py +0 -0
  299. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/query.py +0 -0
  300. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/time_filter.py +0 -0
  301. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/abstract/time_filter_test.py +0 -0
  302. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/__init__.py +0 -0
  303. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/client.py +0 -0
  304. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/client_test.py +0 -0
  305. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/credentials.py +0 -0
  306. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/extract.py +0 -0
  307. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/.sqlfluff +0 -0
  308. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/column.sql +0 -0
  309. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/cte/sharded.sql +0 -0
  310. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/database.sql +0 -0
  311. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/query.sql +0 -0
  312. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/schema.sql +0 -0
  313. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/table.sql +0 -0
  314. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/table_with_tags.sql +0 -0
  315. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/user.sql +0 -0
  316. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/queries/view_ddl.sql +0 -0
  317. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/query.py +0 -0
  318. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/bigquery/types.py +0 -0
  319. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/__init__.py +0 -0
  320. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/api_client.py +0 -0
  321. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/api_client_test.py +0 -0
  322. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/client.py +0 -0
  323. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/client_test.py +0 -0
  324. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/credentials.py +0 -0
  325. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/endpoints.py +0 -0
  326. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/enums.py +0 -0
  327. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/extract.py +0 -0
  328. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/format.py +0 -0
  329. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/format_test.py +0 -0
  330. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/lineage.py +0 -0
  331. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/lineage_test.py +0 -0
  332. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/pagination.py +0 -0
  333. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/sql_client.py +0 -0
  334. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/types.py +0 -0
  335. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/utils.py +0 -0
  336. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/databricks/utils_test.py +0 -0
  337. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/__init__.py +0 -0
  338. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/client.py +0 -0
  339. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/client_test.py +0 -0
  340. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/extract.py +0 -0
  341. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/.sqlfluff +0 -0
  342. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/column.sql +0 -0
  343. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/database.sql +0 -0
  344. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/query.sql +0 -0
  345. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/schema.sql +0 -0
  346. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/table.sql +0 -0
  347. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/user.sql +0 -0
  348. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/queries/view_ddl.sql +0 -0
  349. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/mysql/query.py +0 -0
  350. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/__init__.py +0 -0
  351. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/extract.py +0 -0
  352. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/.sqlfluff +0 -0
  353. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/column.sql +0 -0
  354. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/database.sql +0 -0
  355. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/group.sql +0 -0
  356. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/schema.sql +0 -0
  357. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/table.sql +0 -0
  358. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/queries/user.sql +0 -0
  359. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/postgres/query.py +0 -0
  360. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/__init__.py +0 -0
  361. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/client.py +0 -0
  362. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/client_test.py +0 -0
  363. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/extract.py +0 -0
  364. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/extract_test.py +0 -0
  365. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/.sqlfluff +0 -0
  366. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/column.sql +0 -0
  367. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/database.sql +0 -0
  368. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/group.sql +0 -0
  369. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/query.sql +0 -0
  370. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/query_serverless.sql +0 -0
  371. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/schema.sql +0 -0
  372. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/table.sql +0 -0
  373. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/table_freshness.sql +0 -0
  374. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/user.sql +0 -0
  375. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/queries/view_ddl.sql +0 -0
  376. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/redshift/query.py +0 -0
  377. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/__init__.py +0 -0
  378. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/client.py +0 -0
  379. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/constants.py +0 -0
  380. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/extract.py +0 -0
  381. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/format.py +0 -0
  382. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/format_test.py +0 -0
  383. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/pagination.py +0 -0
  384. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/salesforce/soql.py +0 -0
  385. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/__init__.py +0 -0
  386. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/client.py +0 -0
  387. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/client_test.py +0 -0
  388. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/credentials.py +0 -0
  389. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/credentials_test.py +0 -0
  390. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/extract.py +0 -0
  391. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/.sqlfluff +0 -0
  392. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/column_lineage.sql +0 -0
  393. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/database.sql +0 -0
  394. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/function.sql +0 -0
  395. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/grant_to_role.sql +0 -0
  396. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/grant_to_user.sql +0 -0
  397. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/role.sql +0 -0
  398. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/user.sql +0 -0
  399. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/queries/view_ddl.sql +0 -0
  400. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/snowflake/query.py +0 -0
  401. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/__init__.py +0 -0
  402. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/client.py +0 -0
  403. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/extract.py +0 -0
  404. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/queries/.sqlfluff +0 -0
  405. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/queries/column.sql +0 -0
  406. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/queries/database.sql +0 -0
  407. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/queries/schema.sql +0 -0
  408. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/queries/table.sql +0 -0
  409. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/queries/user.sql +0 -0
  410. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/sqlserver/query.py +0 -0
  411. {castor_extractor-0.24.2 → castor_extractor-0.24.7}/castor_extractor/warehouse/synapse/queries/column.sql +0 -0
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.24.7 - 2025-04-07
4
+
5
+ * Tableau - switch from `cursor` to `offset` pagination to mitigate timeout issues
6
+
7
+ ## 0.24.6 - 2025-04-03
8
+
9
+ * Domo - extract cards metadata by batch to prevent from hitting URL max length
10
+
11
+ ## 0.24.5 - 2025-04-02
12
+
13
+ * bump dependencies: google-cloud-storage
14
+
15
+ ## 0.24.4 - 2025-03-19
16
+
17
+ * Snowflake:
18
+ * improve the list of ignored queries in the query history extraction
19
+ * ignore the following query types : CALL, COMMENT, EXPLAIN, REFRESH_DYNAMIC_TABLE_AT_REFRESH_VERSION, REVOKE, TRUNCATE_TABLE, UNDROP
20
+ * ignore queries with empty text
21
+ * filter out schemas with empty names
22
+
23
+ ## 0.24.3 - 2025-03-18
24
+
25
+ * Replace ThoughtSpot endpoint `/api/rest/2.0/report/liveboard` with `/api/rest/2.0/metadata/liveboard/data` following the deprecation of the CSV option
26
+
3
27
  ## 0.24.2 - 2025-03-17
4
28
 
5
29
  * Rename Revamped Tableau Connector classes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: castor-extractor
3
- Version: 0.24.2
3
+ Version: 0.24.7
4
4
  Summary: Extract your metadata assets.
5
5
  Home-page: https://www.castordoc.com/
6
6
  License: EULA
@@ -35,7 +35,7 @@ Requires-Dist: google-api-core (>=2.1.1,<3.0.0)
35
35
  Requires-Dist: google-api-python-client (>=2.121.0,<3.0.0) ; extra == "lookerstudio" or extra == "all"
36
36
  Requires-Dist: google-auth (>=2,<3)
37
37
  Requires-Dist: google-cloud-core (>=2.1.0,<3.0.0)
38
- Requires-Dist: google-cloud-storage (>=2,<3)
38
+ Requires-Dist: google-cloud-storage (>=3.1.0,<4.0.0)
39
39
  Requires-Dist: google-resumable-media (>=2.0.3,<3.0.0)
40
40
  Requires-Dist: googleapis-common-protos (>=1.53.0,<2.0.0)
41
41
  Requires-Dist: looker-sdk (>=25.0.0,<26.0.0) ; extra == "looker" or extra == "all"
@@ -51,7 +51,7 @@ Requires-Dist: pymssql (>=2.2.11,<3.0.0) ; extra == "sqlserver" or extra == "all
51
51
  Requires-Dist: pymysql[rsa] (>=1.1.0,<2.0.0) ; extra == "mysql" or extra == "all"
52
52
  Requires-Dist: python-dateutil (>=2.0.0,<=3.0.0)
53
53
  Requires-Dist: requests (>=2.0.0,<3.0.0)
54
- Requires-Dist: setuptools (>=75.6)
54
+ Requires-Dist: setuptools (>=78.1)
55
55
  Requires-Dist: snowflake-connector-python (>=3.4.0,<4.0.0) ; extra == "snowflake" or extra == "all"
56
56
  Requires-Dist: snowflake-sqlalchemy (!=1.2.5,<2.0.0) ; extra == "snowflake" or extra == "all"
57
57
  Requires-Dist: sqlalchemy (>=1.4,<1.5)
@@ -210,6 +210,30 @@ For any questions or bug report, contact us at [support@castordoc.com](mailto:su
210
210
 
211
211
  # Changelog
212
212
 
213
+ ## 0.24.7 - 2025-04-07
214
+
215
+ * Tableau - switch from `cursor` to `offset` pagination to mitigate timeout issues
216
+
217
+ ## 0.24.6 - 2025-04-03
218
+
219
+ * Domo - extract cards metadata by batch to prevent from hitting URL max length
220
+
221
+ ## 0.24.5 - 2025-04-02
222
+
223
+ * bump dependencies: google-cloud-storage
224
+
225
+ ## 0.24.4 - 2025-03-19
226
+
227
+ * Snowflake:
228
+ * improve the list of ignored queries in the query history extraction
229
+ * ignore the following query types : CALL, COMMENT, EXPLAIN, REFRESH_DYNAMIC_TABLE_AT_REFRESH_VERSION, REVOKE, TRUNCATE_TABLE, UNDROP
230
+ * ignore queries with empty text
231
+ * filter out schemas with empty names
232
+
233
+ ## 0.24.3 - 2025-03-18
234
+
235
+ * Replace ThoughtSpot endpoint `/api/rest/2.0/report/liveboard` with `/api/rest/2.0/metadata/liveboard/data` following the deprecation of the CSV option
236
+
213
237
  ## 0.24.2 - 2025-03-17
214
238
 
215
239
  * Rename Revamped Tableau Connector classes
@@ -1,4 +1,5 @@
1
1
  from .argument_parser import parse_filled_arguments
2
+ from .batch import batch_of_length
2
3
  from .client import (
3
4
  AbstractSourceClient,
4
5
  APIClient,
@@ -0,0 +1,16 @@
1
+ from typing import Iterator, List, TypeVar
2
+
3
+ T = TypeVar("T")
4
+
5
+
6
+ def batch_of_length(
7
+ elements: List[T],
8
+ batch_size: int,
9
+ ) -> Iterator[List[T]]:
10
+ """
11
+ Split the given elements into smaller chunks
12
+ """
13
+ assert batch_size > 1, "batch size must be greater or equal to 1"
14
+ element_count = len(elements)
15
+ for index in range(0, element_count, batch_size):
16
+ yield elements[index : min((index + batch_size), element_count)]
@@ -0,0 +1,27 @@
1
+ import pytest
2
+
3
+ from .batch import batch_of_length
4
+
5
+
6
+ def test_batch_of_length():
7
+ elements = ["a", "b", "c", "d", "e", "f", "g", "h"]
8
+ result = list(batch_of_length(elements, 3))
9
+ assert result == [
10
+ ["a", "b", "c"],
11
+ ["d", "e", "f"],
12
+ ["g", "h"],
13
+ ]
14
+
15
+ result = list(batch_of_length(elements, 1000))
16
+ assert result == [
17
+ elements,
18
+ ]
19
+
20
+ result = list(batch_of_length(elements, 7))
21
+ assert result == [
22
+ ["a", "b", "c", "d", "e", "f", "g"],
23
+ ["h"],
24
+ ]
25
+
26
+ with pytest.raises(AssertionError):
27
+ list(batch_of_length(elements, -12))
@@ -9,6 +9,7 @@ import requests
9
9
  from ....utils import (
10
10
  RequestSafeMode,
11
11
  at_midnight,
12
+ batch_of_length,
12
13
  current_date,
13
14
  empty_iterator,
14
15
  handle_response,
@@ -48,6 +49,8 @@ _RETRY_BASE_MS = 10 * 60 * 1000 # 10 minutes
48
49
 
49
50
  _PARENT_FOLDER = "/Dashboards"
50
51
 
52
+ _CARDS_BATCH_SIZE = 100
53
+
51
54
  logger = logging.getLogger(__name__)
52
55
 
53
56
 
@@ -156,16 +159,19 @@ class DomoClient:
156
159
 
157
160
  return all_results
158
161
 
162
+ def _cards_metadata(self, card_ids: list[int]) -> Iterator[dict]:
163
+ # batch to avoid hitting the URL max length
164
+ for batch_card_ids in batch_of_length(card_ids, _CARDS_BATCH_SIZE):
165
+ endpoint = self._endpoint_factory.cards_metadata(batch_card_ids)
166
+ yield from self._get_element(endpoint)
167
+
159
168
  def _datasources(self, card_ids: list[int]) -> RawData:
160
169
  """Yields all distinct datasources associated to the given cards"""
161
170
  if not card_ids:
162
171
  return empty_iterator()
163
172
 
164
- endpoint = self._endpoint_factory.cards_metadata(card_ids)
165
- cards_metadata = self._get_element(endpoint)
166
-
167
173
  processed: set[str] = set()
168
- for card in cards_metadata:
174
+ for card in self._cards_metadata(card_ids):
169
175
  for datasource in card["datasources"]:
170
176
  id_ = datasource["dataSourceId"]
171
177
  if id_ in processed:
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from collections.abc import Iterator
2
3
  from typing import Optional
3
4
 
@@ -9,15 +10,14 @@ from ..constants import DEFAULT_PAGE_SIZE
9
10
  from .errors import TableauApiError, TableauApiTimeout
10
11
  from .gql_queries import FIELDS_QUERIES, GQL_QUERIES, QUERY_TEMPLATE
11
12
 
13
+ logger = logging.getLogger(__name__)
14
+
12
15
  # increase the value when extraction is too slow
13
16
  # decrease the value when timeouts arise
14
17
  _CUSTOM_PAGE_SIZE: dict[TableauAsset, int] = {
15
- # for some clients, extraction of columns tend to hit the node limit
16
- # https://community.tableau.com/s/question/0D54T00000YuK60SAF/metadata-query-nodelimitexceeded-error
17
- # the workaround is to reduce pagination
18
- TableauAsset.COLUMN: 50,
19
18
  # fields are light but volumes are bigger
20
19
  TableauAsset.FIELD: 1000,
20
+ # tables are sometimes heavy
21
21
  TableauAsset.TABLE: 50,
22
22
  }
23
23
 
@@ -51,8 +51,9 @@ def _check_errors(answer: dict) -> None:
51
51
 
52
52
  def gql_query_scroll(
53
53
  server,
54
- query: str,
55
54
  resource: str,
55
+ fields: str,
56
+ page_size: int,
56
57
  ) -> Iterator[SerializedAsset]:
57
58
  """
58
59
  Iterate over GQL query results, handling pagination and cursor
@@ -67,23 +68,27 @@ def gql_query_scroll(
67
68
  max_retries=_RETRY_COUNT,
68
69
  base_ms=_RETRY_BASE_MS,
69
70
  )
70
- def _call(cursor: Optional[str]) -> dict:
71
- # If cursor is defined it must be quoted else use null token
72
- token = "null" if cursor is None else f'"{cursor}"'
73
- query_ = query.replace("AFTER_TOKEN_SIGNAL", token)
74
- answer = server.metadata.query(query_)
71
+ def _call(first: int, offset: int) -> dict:
72
+ query = QUERY_TEMPLATE.format(
73
+ resource=resource,
74
+ fields=fields,
75
+ first=first,
76
+ offset=offset,
77
+ )
78
+ answer = server.metadata.query(query)
75
79
  _check_errors(answer)
76
80
  return answer["data"][f"{resource}Connection"]
77
81
 
78
- cursor = None
82
+ current_offset = 0
79
83
  while True:
80
- payload = _call(cursor)
84
+ payload = _call(first=page_size, offset=current_offset)
81
85
  yield payload["nodes"]
82
86
 
83
- page_info = payload["pageInfo"]
84
- if page_info["hasNextPage"]:
85
- cursor = page_info["endCursor"]
86
- else:
87
+ current_offset += len(payload["nodes"])
88
+ total = payload["totalCount"]
89
+ logger.info(f"Extracted {current_offset}/{total} {resource}")
90
+
91
+ if not payload["pageInfo"]["hasNextPage"]:
87
92
  break
88
93
 
89
94
 
@@ -107,12 +112,12 @@ class TableauClientMetadataApi:
107
112
  fields: str,
108
113
  page_size: int = DEFAULT_PAGE_SIZE,
109
114
  ) -> SerializedAsset:
110
- query = QUERY_TEMPLATE.format(
115
+ result_pages = gql_query_scroll(
116
+ self._server,
111
117
  resource=resource,
112
118
  fields=fields,
113
119
  page_size=page_size,
114
120
  )
115
- result_pages = gql_query_scroll(self._server, query, resource)
116
121
  return [asset for page in result_pages for asset in page]
117
122
 
118
123
  def _page_size(self, asset: TableauAsset) -> int:
@@ -2,7 +2,7 @@ from ..assets import TableauAsset
2
2
 
3
3
  QUERY_TEMPLATE = """
4
4
  {{
5
- {resource}Connection(first: {page_size}, after: AFTER_TOKEN_SIGNAL) {{
5
+ {resource}Connection(first: {first}, offset: {offset}) {{
6
6
  nodes {{ {fields}
7
7
  }}
8
8
  pageInfo {{
@@ -1,13 +1,17 @@
1
+ import logging
1
2
  from collections.abc import Iterator
2
- from typing import Optional
3
+ from functools import partial
4
+ from typing import Iterable, Optional
3
5
 
4
6
  import requests
7
+ from requests import Response
5
8
 
6
9
  from ....utils import (
7
10
  APIClient,
8
11
  BearerAuth,
9
12
  RequestSafeMode,
10
13
  build_url,
14
+ fetch_all_pages,
11
15
  handle_response,
12
16
  )
13
17
  from ..assets import (
@@ -19,9 +23,7 @@ from .credentials import (
19
23
  from .endpoints import (
20
24
  ThoughtspotEndpointFactory,
21
25
  )
22
- from .utils import (
23
- usage_liveboard_reader,
24
- )
26
+ from .pagination import METADATA_BATCH_SIZE, ThoughtSpotPagination
25
27
 
26
28
  _AUTH_TIMEOUT_S = 60
27
29
  _THOUGHTSPOT_HEADERS = {
@@ -29,7 +31,6 @@ _THOUGHTSPOT_HEADERS = {
29
31
  "Accept": "application/json",
30
32
  "Content-Type": "application/json",
31
33
  }
32
- _METADATA_BATCH_SIZE = 100
33
34
  # https://docs.thoughtspot.com/cloud/latest/object-usage-liveboard
34
35
  _OBJECT_USAGE_LIVEBOARD = "Object Usage"
35
36
  _ANSWER_USAGE_VIZ = "Answer Usage, by User"
@@ -40,6 +41,9 @@ _LIVEBOARD_USAGE_VIZ = "Popular Liveboards Last 30 Days"
40
41
  THOUGHTSPOT_SAFE_MODE = RequestSafeMode()
41
42
 
42
43
 
44
+ logger = logging.getLogger(__name__)
45
+
46
+
43
47
  class ThoughtspotBearerAuth(BearerAuth):
44
48
  def __init__(self, host: str, token_payload: dict[str, str]):
45
49
  auth_endpoint = ThoughtspotEndpointFactory.authentication()
@@ -86,7 +90,7 @@ class ThoughtspotClient(APIClient):
86
90
  search_filters = {
87
91
  "metadata": [{"type": metadata_type}],
88
92
  "include_details": True,
89
- "record_size": _METADATA_BATCH_SIZE,
93
+ "record_size": METADATA_BATCH_SIZE,
90
94
  "record_offset": offset,
91
95
  }
92
96
  if identifier:
@@ -100,9 +104,9 @@ class ThoughtspotClient(APIClient):
100
104
  data=search_filters,
101
105
  )
102
106
  yield from metadata
103
- if len(metadata) < _METADATA_BATCH_SIZE:
107
+ if len(metadata) < METADATA_BATCH_SIZE:
104
108
  break
105
- offset = offset + _METADATA_BATCH_SIZE
109
+ offset = offset + METADATA_BATCH_SIZE
106
110
 
107
111
  def _get_all_answers(self) -> Iterator[dict]:
108
112
  yield from self._metadata_search(metadata_type="ANSWER")
@@ -120,7 +124,7 @@ class ThoughtspotClient(APIClient):
120
124
  self,
121
125
  liveboard_name: str,
122
126
  visualization_name: str,
123
- ) -> Iterator[dict]:
127
+ ) -> Iterator[list[list]]:
124
128
  """
125
129
  Yields the data of a given visualization in the given liveboard.
126
130
  ThoughtSpot maintains two system liveboards with stats about data usage,
@@ -133,29 +137,62 @@ class ThoughtspotClient(APIClient):
133
137
  )
134
138
  liveboard_id = usage_liveboard["metadata_id"]
135
139
 
136
- data = self._post(
137
- endpoint=ThoughtspotEndpointFactory.liveboard(),
138
- headers={"Accept": "application/octet-stream"},
140
+ def handler(response: Response) -> dict:
141
+ response_dict = response.json()
142
+ contents = response_dict.get("contents", [])
143
+ if not contents:
144
+ logger.warning("No data found in response")
145
+ return dict()
146
+ return contents[0]
147
+
148
+ request = partial(
149
+ self._post,
150
+ endpoint=ThoughtspotEndpointFactory.liveboard_data(),
139
151
  data={
140
152
  "metadata_identifier": liveboard_id,
141
- "file_format": "CSV",
142
153
  "visualization_identifiers": [visualization_name],
154
+ "record_offset": 0,
155
+ "record_size": METADATA_BATCH_SIZE,
143
156
  },
144
- handler=lambda x: x.text,
157
+ handler=handler,
145
158
  )
146
- yield from usage_liveboard_reader(data)
159
+ yield from fetch_all_pages(request, ThoughtSpotPagination)
147
160
 
148
161
  def _get_answer_usages(self) -> Iterator[dict]:
149
- return self._get_usages(
162
+ """
163
+ Returns the usage data of saved Answers, which is found in a visualization
164
+ of the "Object Usage" liveboard.
165
+ Each data row returned by the API is transformed from a list into a dictionary.
166
+ The columns are explicitly listed here because in the API response,
167
+ there is a mismatch between the number of column names and the number
168
+ of values per data row.
169
+ """
170
+ data: Iterable[list[list]] = self._get_usages(
150
171
  liveboard_name=_OBJECT_USAGE_LIVEBOARD,
151
172
  visualization_name=_ANSWER_USAGE_VIZ,
152
173
  )
174
+ columns = (
175
+ "Answer name",
176
+ "Number of unique users",
177
+ "Count of object interactions",
178
+ )
179
+ for row in data:
180
+ yield dict(zip(columns, row))
153
181
 
154
182
  def _get_liveboards_usages(self) -> Iterator[dict]:
155
- return self._get_usages(
183
+ """
184
+ Returns the usage data of Liveboards, which is found in a visualization
185
+ of the "User Adoption" liveboard.
186
+ Each data row returned by the API is transformed from a list into a dictionary.
187
+ See `_get_answer_usages` regarding the columns list.
188
+ """
189
+ data: Iterable[list[list]] = self._get_usages(
156
190
  liveboard_name=_USER_ADOPTION_LIVEBOARD,
157
191
  visualization_name=_LIVEBOARD_USAGE_VIZ,
158
192
  )
193
+ columns = ("Pinboard", "Unique Number of User", "Pinboard Views")
194
+ for row in data:
195
+ yield dict(zip(columns, row))
159
196
 
160
197
  def fetch(self, asset: ThoughtspotAsset) -> Iterator[dict]:
161
198
  if asset == ThoughtspotAsset.ANSWERS:
@@ -8,5 +8,5 @@ class ThoughtspotEndpointFactory:
8
8
  return "api/rest/2.0/metadata/search"
9
9
 
10
10
  @classmethod
11
- def liveboard(cls) -> str:
12
- return "api/rest/2.0/report/liveboard"
11
+ def liveboard_data(cls) -> str:
12
+ return "api/rest/2.0/metadata/liveboard/data"
@@ -0,0 +1,25 @@
1
+ from pydantic import ConfigDict, Field
2
+
3
+ from ....utils import PaginationModel
4
+
5
+ METADATA_BATCH_SIZE = 100
6
+
7
+
8
+ class ThoughtSpotPagination(PaginationModel):
9
+ data_rows: list = Field(default_factory=list)
10
+ record_offset: int
11
+ record_size: int
12
+
13
+ model_config = ConfigDict(
14
+ populate_by_name=True,
15
+ from_attributes=True,
16
+ )
17
+
18
+ def is_last(self) -> bool:
19
+ return len(self.data_rows) < METADATA_BATCH_SIZE
20
+
21
+ def next_page_payload(self) -> dict:
22
+ return {"record_offset": self.record_offset + METADATA_BATCH_SIZE}
23
+
24
+ def page_results(self) -> list:
25
+ return self.data_rows
@@ -47,7 +47,9 @@ FROM snowflake.account_usage.columns AS c
47
47
  JOIN snowflake.account_usage.tables AS t ON t.table_id = c.table_id
48
48
  JOIN tags_agg_columns ta ON c.column_id = ta.column_id
49
49
  WHERE TRUE
50
- AND COALESCE(c.column_name, '') != ''
50
+ AND TRIM(COALESCE(c.column_name, '')) != ''
51
+ AND TRIM(COALESCE(t.table_name, '')) != ''
52
+ AND TRIM(COALESCE(s.schema_name, '')) != ''
51
53
  AND UPPER(c.table_catalog) NOT IN ('SNOWFLAKE', 'UTIL_DB')
52
54
  AND (
53
55
  c.deleted IS NULL
@@ -51,20 +51,28 @@ WHERE TRUE
51
51
  AND HOUR(CONVERT_TIMEZONE('UTC', start_time)) BETWEEN :hour_min AND :hour_max
52
52
  AND execution_status = 'SUCCESS'
53
53
  AND query_text != 'SELECT 1'
54
+ AND TRIM(COALESCE(query_text, '')) != ''
54
55
  AND query_type NOT IN (
55
- 'SHOW',
56
- 'USE',
57
- 'ROLLBACK',
58
- 'DESCRIBE',
59
56
  'ALTER_SESSION',
60
- 'PUT_FILES',
57
+ 'BEGIN_TRANSACTION',
58
+ 'CALL',
59
+ 'COMMENT',
60
+ 'COMMIT',
61
61
  'CREATE', -- create objects: stage|function|schema|procedure|file|storage|pipe|notification integration
62
- 'SET',
62
+ 'DESCRIBE',
63
+ 'DROP',
64
+ 'EXPLAIN',
65
+ 'GET_FILES',
63
66
  'GRANT',
64
- 'COMMIT',
67
+ 'PUT_FILES',
68
+ 'REFRESH_DYNAMIC_TABLE_AT_REFRESH_VERSION',
69
+ 'REMOVE_FILES',
70
+ 'REVOKE',
71
+ 'ROLLBACK',
72
+ 'SET',
73
+ 'SHOW',
74
+ 'TRUNCATE_TABLE',
75
+ 'UNDROP',
65
76
  'UNLOAD',
66
- 'GET_FILES',
67
- 'DROP',
68
- 'BEGIN_TRANSACTION',
69
- 'REMOVE_FILES'
77
+ 'USE'
70
78
  )
@@ -16,6 +16,7 @@ WHERE TRUE
16
16
  deleted IS NULL
17
17
  OR deleted > CURRENT_TIMESTAMP - INTERVAL '1 day'
18
18
  )
19
+ AND TRIM(COALESCE(schema_name, '')) != ''
19
20
  {database_allowed}
20
21
  {database_blocked}
21
22
  AND CASE {has_fetch_transient} WHEN FALSE THEN NOT s.is_transient::BOOLEAN ELSE TRUE END
@@ -41,8 +41,8 @@ FROM snowflake.account_usage.tables AS t
41
41
  JOIN snowflake.account_usage.schemata AS s ON s.schema_id = t.table_schema_id
42
42
  JOIN tags_agg_tables ta ON t.table_id = ta.table_id
43
43
  WHERE TRUE
44
- AND t.table_name IS NOT NULL
45
- AND t.table_name != ''
44
+ AND TRIM(COALESCE(t.table_name, '')) != ''
45
+ AND TRIM(COALESCE(s.schema_name, '')) != ''
46
46
  AND UPPER(t.table_catalog) NOT IN ('SNOWFLAKE', 'UTIL_DB')
47
47
  AND (
48
48
  t.deleted IS NULL
@@ -1,9 +1,9 @@
1
- [build-system]
1
+ [build-system]
2
2
  requires = ["setuptools>=61.2"]
3
3
 
4
4
  [tool.poetry]
5
5
  name = "castor-extractor"
6
- version = "0.24.2"
6
+ version = "0.24.7"
7
7
  description = "Extract your metadata assets."
8
8
  authors = ["Castor <support@castordoc.com>"]
9
9
  license = "EULA"
@@ -32,7 +32,7 @@ google-api-core = ">=2.1.1, <3.0.0"
32
32
  google-api-python-client = {version = "^2.121.0", optional = true}
33
33
  google-auth = "^2"
34
34
  google-cloud-core = ">=2.1.0, <3.0.0"
35
- google-cloud-storage = "^2"
35
+ google-cloud-storage = "^3.1.0"
36
36
  google-resumable-media = "^2.0.3"
37
37
  googleapis-common-protos = "^1.53.0"
38
38
  looker-sdk = { version = "^25.0.0", optional = true }
@@ -50,7 +50,7 @@ python-dateutil = ">=2.0.0, <=3.0.0"
50
50
  requests = ">=2.0.0, <3.0.0"
51
51
  snowflake-connector-python = { version = "^3.4.0", optional = true }
52
52
  snowflake-sqlalchemy = { version = "!=1.2.5, <2.0.0", optional = true }
53
- setuptools = ">=75.6"
53
+ setuptools = ">=78.1"
54
54
  sqlalchemy = "~1.4"
55
55
  sqlalchemy-bigquery = { version = ">=1.0.0, <= 2.0.0", optional = true, extras = [
56
56
  "bqstorage",
@@ -66,7 +66,7 @@ pymssql = { version = "^2.2.11", optional = true }
66
66
  pymysql = { extras = ["rsa"], version = "^1.1.0", optional = true }
67
67
 
68
68
  # 3.7 has issue with urrllib dependency
69
- # https://castorglobal.slack.com/archives/C049PRU1GK1/p1738328811319309
69
+ # https://coalescesoftware.slack.com/archives/C08HEQHS487/p1738328811319309
70
70
  databricks-sql-connector = { version = "3.6.0", optional = true }
71
71
 
72
72
  [tool.poetry.extras]
@@ -1,31 +0,0 @@
1
- import csv
2
- import re
3
- from collections.abc import Iterator
4
- from io import StringIO
5
-
6
- _END_OF_GENERATED_TEXT = r'^""$'
7
-
8
-
9
- def usage_liveboard_reader(usage_liveboard_csv: str) -> Iterator[dict]:
10
- """
11
- Converts a CSV string into an iterator of dictionaries after
12
- ignoring the generated text that preceeds the actual CSV header row.
13
- The generated block ends with a row containing only two double quotes.
14
- Here is an example:
15
-
16
- "Data extract produced by Castor on 09/19/2024 06:54"
17
- "Filters applied on data :"
18
- "User Action IN [pinboard_embed_view,pinboard_tspublic_no_runtime_filter,pinboard_tspublic_runtime_filter,pinboard_view]"
19
- "Pinboard NOT IN [mlm - availability pinboard,null]"
20
- "Timestamp >= 20240820 00:00:00 < 20240919 00:00:00"
21
- "Timestamp >= 20240919 00:00:00 < 20240920 00:00:00"
22
- ""
23
-
24
- """
25
- csv_file = StringIO(usage_liveboard_csv)
26
-
27
- line = next(csv_file)
28
- while not re.match(_END_OF_GENERATED_TEXT, line.strip()):
29
- line = next(csv_file)
30
-
31
- yield from csv.DictReader(csv_file)