castor-extractor 0.24.1__tar.gz → 0.24.4__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.1 → castor_extractor-0.24.4}/CHANGELOG.md +16 -0
  2. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/PKG-INFO +17 -1
  3. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_tableau.py +2 -2
  4. castor_extractor-0.24.4/castor_extractor/visualization/tableau/__init__.py +3 -0
  5. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/assets.py +4 -4
  6. castor_extractor-0.24.4/castor_extractor/visualization/tableau/client/__init__.py +2 -0
  7. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/client.py +15 -15
  8. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/client_metadata_api.py +9 -9
  9. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/client_rest_api.py +6 -6
  10. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/client_tsc.py +9 -9
  11. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/credentials.py +2 -2
  12. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/gql_queries.py +8 -8
  13. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/rest_fields.py +10 -10
  14. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/extract.py +7 -7
  15. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/client/client.py +54 -17
  16. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/client/endpoints.py +2 -2
  17. castor_extractor-0.24.4/castor_extractor/visualization/thoughtspot/client/pagination.py +25 -0
  18. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/column.sql +3 -1
  19. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/query.sql +19 -11
  20. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/schema.sql +1 -0
  21. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/table.sql +2 -2
  22. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/pyproject.toml +1 -1
  23. castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp/__init__.py +0 -3
  24. castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp/client/__init__.py +0 -2
  25. castor_extractor-0.24.1/castor_extractor/visualization/thoughtspot/client/utils.py +0 -31
  26. castor_extractor-0.24.1/castor_extractor/visualization/thoughtspot/client/utils_test.py +0 -75
  27. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/Dockerfile +0 -0
  28. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/DockerfileUsage.md +0 -0
  29. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/LICENCE +0 -0
  30. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/README.md +0 -0
  31. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/__init__.py +0 -0
  32. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/__init__.py +0 -0
  33. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_bigquery.py +0 -0
  34. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_confluence.py +0 -0
  35. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_databricks.py +0 -0
  36. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_domo.py +0 -0
  37. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_looker.py +0 -0
  38. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_looker_studio.py +0 -0
  39. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_metabase_api.py +0 -0
  40. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_metabase_db.py +0 -0
  41. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_mode.py +0 -0
  42. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_mysql.py +0 -0
  43. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_notion.py +0 -0
  44. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_postgres.py +0 -0
  45. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_powerbi.py +0 -0
  46. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_qlik.py +0 -0
  47. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_redshift.py +0 -0
  48. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_salesforce.py +0 -0
  49. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_salesforce_reporting.py +0 -0
  50. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_sigma.py +0 -0
  51. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_snowflake.py +0 -0
  52. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_sqlserver.py +0 -0
  53. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/extract_thoughtspot.py +0 -0
  54. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/file_check.py +0 -0
  55. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/commands/upload.py +0 -0
  56. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/__init__.py +0 -0
  57. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/column.py +0 -0
  58. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/column_test.py +0 -0
  59. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/constants.py +0 -0
  60. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/enums.py +0 -0
  61. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/file.py +0 -0
  62. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/file_test.py +0 -0
  63. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/file_test_users.csv +0 -0
  64. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/file_test_users_valid.csv +0 -0
  65. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/templates/__init__.py +0 -0
  66. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/file_checker/templates/generic_warehouse.py +0 -0
  67. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/__init__.py +0 -0
  68. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/__init__.py +0 -0
  69. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/assets.py +0 -0
  70. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/client/__init__.py +0 -0
  71. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/client/client.py +0 -0
  72. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/client/credentials.py +0 -0
  73. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/client/endpoints.py +0 -0
  74. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/client/pagination.py +0 -0
  75. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/confluence/extract.py +0 -0
  76. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/__init__.py +0 -0
  77. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/assets.py +0 -0
  78. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/__init__.py +0 -0
  79. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/client.py +0 -0
  80. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/client_test.py +0 -0
  81. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/constants.py +0 -0
  82. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/credentials.py +0 -0
  83. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/endpoints.py +0 -0
  84. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/client/pagination.py +0 -0
  85. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/knowledge/notion/extract.py +0 -0
  86. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/logger.py +0 -0
  87. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/__init__.py +0 -0
  88. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/__init__.py +0 -0
  89. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/assets.py +0 -0
  90. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/client/__init__.py +0 -0
  91. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/client/client.py +0 -0
  92. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/client/credentials.py +0 -0
  93. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/client/endpoints.py +0 -0
  94. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/quality/soda/client/pagination.py +0 -0
  95. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/types.py +0 -0
  96. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/__init__.py +0 -0
  97. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/constant.py +0 -0
  98. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/env.py +0 -0
  99. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/env_test.py +0 -0
  100. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/settings.py +0 -0
  101. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/upload.py +0 -0
  102. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/upload_test.py +0 -0
  103. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/uploader/utils.py +0 -0
  104. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/__init__.py +0 -0
  105. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/argument_parser.py +0 -0
  106. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/argument_parser_test.py +0 -0
  107. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/__init__.py +0 -0
  108. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/abstract.py +0 -0
  109. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/__init__.py +0 -0
  110. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/auth.py +0 -0
  111. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/auth_test.py +0 -0
  112. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/client.py +0 -0
  113. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/client_test.py +0 -0
  114. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/pagination.py +0 -0
  115. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/pagination_test.py +0 -0
  116. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/safe_request.py +0 -0
  117. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/safe_request_test.py +0 -0
  118. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/utils.py +0 -0
  119. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/api/utils_test.py +0 -0
  120. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/postgres.py +0 -0
  121. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/query.py +0 -0
  122. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/uri.py +0 -0
  123. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/client/uri_test.py +0 -0
  124. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/collection.py +0 -0
  125. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/collection_test.py +0 -0
  126. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/constants.py +0 -0
  127. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/dbt/__init__.py +0 -0
  128. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/dbt/assets.py +0 -0
  129. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/dbt/client.py +0 -0
  130. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/dbt/client_test.py +0 -0
  131. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/dbt/credentials.py +0 -0
  132. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/deprecate.py +0 -0
  133. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/env.py +0 -0
  134. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/files.py +0 -0
  135. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/files_test.py +0 -0
  136. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/formatter.py +0 -0
  137. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/formatter_test.csv +0 -0
  138. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/formatter_test.json +0 -0
  139. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/formatter_test.py +0 -0
  140. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/json_stream_write.py +0 -0
  141. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/load.py +0 -0
  142. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/object.py +0 -0
  143. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/object_test.py +0 -0
  144. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/pager/__init__.py +0 -0
  145. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/pager/pager.py +0 -0
  146. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/pager/pager_on_id.py +0 -0
  147. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/pager/pager_on_id_test.py +0 -0
  148. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/pager/pager_test.py +0 -0
  149. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/retry.py +0 -0
  150. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/retry_test.py +0 -0
  151. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/safe.py +0 -0
  152. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/safe_test.py +0 -0
  153. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/__init__.py +0 -0
  154. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/client.py +0 -0
  155. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/client_test.py +0 -0
  156. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/constants.py +0 -0
  157. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/credentials.py +0 -0
  158. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/credentials_test.py +0 -0
  159. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/salesforce/pagination.py +0 -0
  160. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/store.py +0 -0
  161. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/string.py +0 -0
  162. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/string_test.py +0 -0
  163. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/time.py +0 -0
  164. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/time_test.py +0 -0
  165. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/type.py +0 -0
  166. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/validation.py +0 -0
  167. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/validation_test.py +0 -0
  168. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/utils/write.py +0 -0
  169. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/__init__.py +0 -0
  170. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/__init__.py +0 -0
  171. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/assets.py +0 -0
  172. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/client/__init__.py +0 -0
  173. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/client/client.py +0 -0
  174. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/client/credentials.py +0 -0
  175. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/client/endpoints.py +0 -0
  176. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/client/pagination.py +0 -0
  177. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/client/pagination_test.py +0 -0
  178. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/domo/extract.py +0 -0
  179. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/__init__.py +0 -0
  180. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/__init__.py +0 -0
  181. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/client.py +0 -0
  182. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/client_test.py +0 -0
  183. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/constants.py +0 -0
  184. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/credentials.py +0 -0
  185. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/extraction_parameters.py +0 -0
  186. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/sdk.py +0 -0
  187. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/sdk_test.py +0 -0
  188. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/api/utils.py +0 -0
  189. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/assets.py +0 -0
  190. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/constant.py +0 -0
  191. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/constants.py +0 -0
  192. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/extract.py +0 -0
  193. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/fields.py +0 -0
  194. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/fields_test.py +0 -0
  195. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker/multithreading.py +0 -0
  196. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/__init__.py +0 -0
  197. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/assets.py +0 -0
  198. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/__init__.py +0 -0
  199. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/admin_sdk_client.py +0 -0
  200. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/client.py +0 -0
  201. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/credentials.py +0 -0
  202. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/endpoints.py +0 -0
  203. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/enums.py +0 -0
  204. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py +0 -0
  205. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/pagination.py +0 -0
  206. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/queries/query.sql +0 -0
  207. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/client/scopes.py +0 -0
  208. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/looker_studio/extract.py +0 -0
  209. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/__init__.py +0 -0
  210. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/assets.py +0 -0
  211. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/__init__.py +0 -0
  212. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/api/__init__.py +0 -0
  213. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/api/client.py +0 -0
  214. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/api/client_test.py +0 -0
  215. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/api/credentials.py +0 -0
  216. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/__init__.py +0 -0
  217. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/client.py +0 -0
  218. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/credentials.py +0 -0
  219. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/.sqlfluff +0 -0
  220. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/base_url.sql +0 -0
  221. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/card.sql +0 -0
  222. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/collection.sql +0 -0
  223. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/dashboard.sql +0 -0
  224. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/dashboard_cards.sql +0 -0
  225. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/database.sql +0 -0
  226. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/table.sql +0 -0
  227. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/db/queries/user.sql +0 -0
  228. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/decryption.py +0 -0
  229. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/decryption_test.py +0 -0
  230. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/client/shared.py +0 -0
  231. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/errors.py +0 -0
  232. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/extract.py +0 -0
  233. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/metabase/types.py +0 -0
  234. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/__init__.py +0 -0
  235. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/assets.py +0 -0
  236. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/client/__init__.py +0 -0
  237. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/client/client.py +0 -0
  238. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/client/client_test.json +0 -0
  239. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/client/client_test.py +0 -0
  240. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/client/constants.py +0 -0
  241. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/client/credentials.py +0 -0
  242. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/errors.py +0 -0
  243. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/mode/extract.py +0 -0
  244. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/__init__.py +0 -0
  245. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/assets.py +0 -0
  246. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/__init__.py +0 -0
  247. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/authentication.py +0 -0
  248. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/client.py +0 -0
  249. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/client_test.py +0 -0
  250. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/constants.py +0 -0
  251. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/credentials.py +0 -0
  252. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/credentials_test.py +0 -0
  253. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/endpoints.py +0 -0
  254. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/client/pagination.py +0 -0
  255. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/powerbi/extract.py +0 -0
  256. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/__init__.py +0 -0
  257. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/assets.py +0 -0
  258. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/__init__.py +0 -0
  259. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/constants.py +0 -0
  260. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/__init__.py +0 -0
  261. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/client.py +0 -0
  262. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/constants.py +0 -0
  263. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/credentials.py +0 -0
  264. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/error.py +0 -0
  265. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/error_test.py +0 -0
  266. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/json_rpc.py +0 -0
  267. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/json_rpc_test.py +0 -0
  268. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/engine/websocket.py +0 -0
  269. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/master.py +0 -0
  270. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/rest.py +0 -0
  271. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/client/rest_test.py +0 -0
  272. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/qlik/extract.py +0 -0
  273. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/salesforce_reporting/__init__.py +0 -0
  274. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/salesforce_reporting/assets.py +0 -0
  275. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/salesforce_reporting/client/__init__.py +0 -0
  276. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/salesforce_reporting/client/rest.py +0 -0
  277. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/salesforce_reporting/client/soql.py +0 -0
  278. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/salesforce_reporting/extract.py +0 -0
  279. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/__init__.py +0 -0
  280. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/assets.py +0 -0
  281. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/client/__init__.py +0 -0
  282. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/client/client.py +0 -0
  283. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/client/credentials.py +0 -0
  284. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/client/endpoints.py +0 -0
  285. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/client/pagination.py +0 -0
  286. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/sigma/extract.py +0 -0
  287. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/client/errors.py +0 -0
  288. {castor_extractor-0.24.1/castor_extractor/visualization/tableau_revamp → castor_extractor-0.24.4/castor_extractor/visualization/tableau}/constants.py +0 -0
  289. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/__init__.py +0 -0
  290. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/assets.py +0 -0
  291. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/client/__init__.py +0 -0
  292. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/client/credentials.py +0 -0
  293. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/visualization/thoughtspot/extract.py +0 -0
  294. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/__init__.py +0 -0
  295. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/__init__.py +0 -0
  296. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/asset.py +0 -0
  297. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/asset_test.py +0 -0
  298. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/extract.py +0 -0
  299. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/query.py +0 -0
  300. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/time_filter.py +0 -0
  301. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/abstract/time_filter_test.py +0 -0
  302. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/__init__.py +0 -0
  303. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/client.py +0 -0
  304. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/client_test.py +0 -0
  305. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/credentials.py +0 -0
  306. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/extract.py +0 -0
  307. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/.sqlfluff +0 -0
  308. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/column.sql +0 -0
  309. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/cte/sharded.sql +0 -0
  310. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/database.sql +0 -0
  311. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/query.sql +0 -0
  312. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/schema.sql +0 -0
  313. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/table.sql +0 -0
  314. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/table_with_tags.sql +0 -0
  315. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/user.sql +0 -0
  316. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/queries/view_ddl.sql +0 -0
  317. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/query.py +0 -0
  318. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/bigquery/types.py +0 -0
  319. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/__init__.py +0 -0
  320. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/api_client.py +0 -0
  321. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/api_client_test.py +0 -0
  322. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/client.py +0 -0
  323. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/client_test.py +0 -0
  324. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/credentials.py +0 -0
  325. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/endpoints.py +0 -0
  326. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/enums.py +0 -0
  327. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/extract.py +0 -0
  328. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/format.py +0 -0
  329. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/format_test.py +0 -0
  330. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/lineage.py +0 -0
  331. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/lineage_test.py +0 -0
  332. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/pagination.py +0 -0
  333. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/sql_client.py +0 -0
  334. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/types.py +0 -0
  335. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/utils.py +0 -0
  336. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/databricks/utils_test.py +0 -0
  337. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/__init__.py +0 -0
  338. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/client.py +0 -0
  339. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/client_test.py +0 -0
  340. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/extract.py +0 -0
  341. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/.sqlfluff +0 -0
  342. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/column.sql +0 -0
  343. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/database.sql +0 -0
  344. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/query.sql +0 -0
  345. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/schema.sql +0 -0
  346. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/table.sql +0 -0
  347. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/user.sql +0 -0
  348. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/queries/view_ddl.sql +0 -0
  349. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/mysql/query.py +0 -0
  350. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/__init__.py +0 -0
  351. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/extract.py +0 -0
  352. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/.sqlfluff +0 -0
  353. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/column.sql +0 -0
  354. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/database.sql +0 -0
  355. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/group.sql +0 -0
  356. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/schema.sql +0 -0
  357. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/table.sql +0 -0
  358. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/queries/user.sql +0 -0
  359. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/postgres/query.py +0 -0
  360. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/__init__.py +0 -0
  361. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/client.py +0 -0
  362. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/client_test.py +0 -0
  363. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/extract.py +0 -0
  364. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/extract_test.py +0 -0
  365. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/.sqlfluff +0 -0
  366. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/column.sql +0 -0
  367. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/database.sql +0 -0
  368. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/group.sql +0 -0
  369. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/query.sql +0 -0
  370. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/query_serverless.sql +0 -0
  371. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/schema.sql +0 -0
  372. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/table.sql +0 -0
  373. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/table_freshness.sql +0 -0
  374. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/user.sql +0 -0
  375. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/queries/view_ddl.sql +0 -0
  376. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/redshift/query.py +0 -0
  377. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/__init__.py +0 -0
  378. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/client.py +0 -0
  379. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/constants.py +0 -0
  380. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/extract.py +0 -0
  381. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/format.py +0 -0
  382. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/format_test.py +0 -0
  383. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/pagination.py +0 -0
  384. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/salesforce/soql.py +0 -0
  385. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/__init__.py +0 -0
  386. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/client.py +0 -0
  387. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/client_test.py +0 -0
  388. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/credentials.py +0 -0
  389. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/credentials_test.py +0 -0
  390. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/extract.py +0 -0
  391. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/.sqlfluff +0 -0
  392. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/column_lineage.sql +0 -0
  393. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/database.sql +0 -0
  394. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/function.sql +0 -0
  395. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/grant_to_role.sql +0 -0
  396. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/grant_to_user.sql +0 -0
  397. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/role.sql +0 -0
  398. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/user.sql +0 -0
  399. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/queries/view_ddl.sql +0 -0
  400. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/snowflake/query.py +0 -0
  401. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/__init__.py +0 -0
  402. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/client.py +0 -0
  403. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/extract.py +0 -0
  404. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/queries/.sqlfluff +0 -0
  405. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/queries/column.sql +0 -0
  406. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/queries/database.sql +0 -0
  407. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/queries/schema.sql +0 -0
  408. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/queries/table.sql +0 -0
  409. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/queries/user.sql +0 -0
  410. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/sqlserver/query.py +0 -0
  411. {castor_extractor-0.24.1 → castor_extractor-0.24.4}/castor_extractor/warehouse/synapse/queries/column.sql +0 -0
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.24.4 - 2025-03-19
4
+
5
+ * Snowflake:
6
+ * improve the list of ignored queries in the query history extraction
7
+ * ignore the following query types : CALL, COMMENT, EXPLAIN, REFRESH_DYNAMIC_TABLE_AT_REFRESH_VERSION, REVOKE, TRUNCATE_TABLE, UNDROP
8
+ * ignore queries with empty text
9
+ * filter out schemas with empty names
10
+
11
+ ## 0.24.3 - 2025-03-18
12
+
13
+ * Replace ThoughtSpot endpoint `/api/rest/2.0/report/liveboard` with `/api/rest/2.0/metadata/liveboard/data` following the deprecation of the CSV option
14
+
15
+ ## 0.24.2 - 2025-03-17
16
+
17
+ * Rename Revamped Tableau Connector classes
18
+
3
19
  ## 0.24.1 - 2025-03-14
4
20
 
5
21
  * Added support for Looker Studio
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: castor-extractor
3
- Version: 0.24.1
3
+ Version: 0.24.4
4
4
  Summary: Extract your metadata assets.
5
5
  Home-page: https://www.castordoc.com/
6
6
  License: EULA
@@ -210,6 +210,22 @@ For any questions or bug report, contact us at [support@castordoc.com](mailto:su
210
210
 
211
211
  # Changelog
212
212
 
213
+ ## 0.24.4 - 2025-03-19
214
+
215
+ * Snowflake:
216
+ * improve the list of ignored queries in the query history extraction
217
+ * ignore the following query types : CALL, COMMENT, EXPLAIN, REFRESH_DYNAMIC_TABLE_AT_REFRESH_VERSION, REVOKE, TRUNCATE_TABLE, UNDROP
218
+ * ignore queries with empty text
219
+ * filter out schemas with empty names
220
+
221
+ ## 0.24.3 - 2025-03-18
222
+
223
+ * Replace ThoughtSpot endpoint `/api/rest/2.0/report/liveboard` with `/api/rest/2.0/metadata/liveboard/data` following the deprecation of the CSV option
224
+
225
+ ## 0.24.2 - 2025-03-17
226
+
227
+ * Rename Revamped Tableau Connector classes
228
+
213
229
  ## 0.24.1 - 2025-03-14
214
230
 
215
231
  * Added support for Looker Studio
@@ -2,7 +2,7 @@ import logging
2
2
  from argparse import ArgumentParser
3
3
 
4
4
  from castor_extractor.utils import parse_filled_arguments # type: ignore
5
- from castor_extractor.visualization import tableau_revamp # type: ignore
5
+ from castor_extractor.visualization import tableau # type: ignore
6
6
 
7
7
  logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
8
8
 
@@ -36,4 +36,4 @@ def main():
36
36
 
37
37
  parser.add_argument("-o", "--output", help="Directory to write to")
38
38
 
39
- tableau_revamp.extract_all(**parse_filled_arguments(parser))
39
+ tableau.extract_all(**parse_filled_arguments(parser))
@@ -0,0 +1,3 @@
1
+ from .assets import TableauAsset
2
+ from .client import TableauClient, TableauCredentials
3
+ from .extract import extract_all, iterate_all_data
@@ -1,7 +1,7 @@
1
1
  from ...types import ExternalAsset
2
2
 
3
3
 
4
- class TableauRevampAsset(ExternalAsset):
4
+ class TableauAsset(ExternalAsset):
5
5
  """
6
6
  Tableau assets
7
7
  """
@@ -23,7 +23,7 @@ class TableauRevampAsset(ExternalAsset):
23
23
 
24
24
  # assets that are only available for clients using Tableau Pulse
25
25
  TABLEAU_PULSE_ASSETS = (
26
- TableauRevampAsset.METRIC,
27
- TableauRevampAsset.METRIC_DEFINITION,
28
- TableauRevampAsset.SUBSCRIPTION,
26
+ TableauAsset.METRIC,
27
+ TableauAsset.METRIC_DEFINITION,
28
+ TableauAsset.SUBSCRIPTION,
29
29
  )
@@ -0,0 +1,2 @@
1
+ from .client import TableauClient
2
+ from .credentials import TableauCredentials
@@ -4,31 +4,31 @@ from typing import Optional
4
4
  import tableauserverclient as TSC # type: ignore
5
5
 
6
6
  from ....utils import SerializedAsset
7
- from ..assets import TABLEAU_PULSE_ASSETS, TableauRevampAsset
7
+ from ..assets import TABLEAU_PULSE_ASSETS, TableauAsset
8
8
  from ..constants import CREDENTIALS_SITE_ID_KEY, DEFAULT_TIMEOUT_SECONDS
9
9
  from .client_metadata_api import TableauClientMetadataApi
10
10
  from .client_rest_api import TableauClientRestApi
11
11
  from .client_tsc import TableauClientTSC
12
- from .credentials import TableauRevampCredentials
12
+ from .credentials import TableauCredentials
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
16
16
  # these assets must be extracted via TableauServerClient (TSC)
17
17
  _TSC_ASSETS = (
18
18
  # projects are not available in Metadata API
19
- TableauRevampAsset.PROJECT,
19
+ TableauAsset.PROJECT,
20
20
  # view count are not available in Metadata API
21
- TableauRevampAsset.USAGE,
21
+ TableauAsset.USAGE,
22
22
  # only users who published content can be extracted from MetadataAPI
23
- TableauRevampAsset.USER,
23
+ TableauAsset.USER,
24
24
  )
25
25
 
26
26
  # these assets must be extracted via the REST API
27
27
  _REST_API_ASSETS = (
28
28
  # Tableau Pulse assets are only available in REST API
29
- TableauRevampAsset.METRIC,
30
- TableauRevampAsset.METRIC_DEFINITION,
31
- TableauRevampAsset.SUBSCRIPTION,
29
+ TableauAsset.METRIC,
30
+ TableauAsset.METRIC_DEFINITION,
31
+ TableauAsset.SUBSCRIPTION,
32
32
  )
33
33
 
34
34
  logging.getLogger("tableau.endpoint").setLevel(logging.WARNING)
@@ -109,7 +109,7 @@ def _server(
109
109
  return server
110
110
 
111
111
 
112
- class TableauRevampClient:
112
+ class TableauClient:
113
113
  """
114
114
  Connect to Tableau's API and extract assets.
115
115
 
@@ -119,7 +119,7 @@ class TableauRevampClient:
119
119
 
120
120
  def __init__(
121
121
  self,
122
- credentials: TableauRevampCredentials,
122
+ credentials: TableauCredentials,
123
123
  timeout_sec: int = DEFAULT_TIMEOUT_SECONDS,
124
124
  with_pulse: bool = False,
125
125
  override_page_size: Optional[int] = None,
@@ -186,7 +186,7 @@ class TableauRevampClient:
186
186
  )
187
187
 
188
188
  def _fetch_datasources(self) -> SerializedAsset:
189
- asset = TableauRevampAsset.DATASOURCE
189
+ asset = TableauAsset.DATASOURCE
190
190
 
191
191
  datasources = self._client_metadata.fetch(asset)
192
192
  tsc_datasources = self._client_tsc.fetch(asset)
@@ -194,7 +194,7 @@ class TableauRevampClient:
194
194
  return _merge_datasources(datasources, tsc_datasources)
195
195
 
196
196
  def _fetch_workbooks(self) -> SerializedAsset:
197
- asset = TableauRevampAsset.WORKBOOK
197
+ asset = TableauAsset.WORKBOOK
198
198
 
199
199
  site_id = self._credentials.site_id
200
200
  workbooks = self._client_metadata.fetch(asset)
@@ -206,7 +206,7 @@ class TableauRevampClient:
206
206
 
207
207
  def fetch(
208
208
  self,
209
- asset: TableauRevampAsset,
209
+ asset: TableauAsset,
210
210
  ) -> SerializedAsset:
211
211
  """
212
212
  Extract the given Tableau Asset
@@ -217,11 +217,11 @@ class TableauRevampClient:
217
217
 
218
218
  logger.info(f"Extracting {asset.name}...")
219
219
 
220
- if asset == TableauRevampAsset.DATASOURCE:
220
+ if asset == TableauAsset.DATASOURCE:
221
221
  # two APIs are required to extract datasources
222
222
  return self._fetch_datasources()
223
223
 
224
- if asset == TableauRevampAsset.WORKBOOK:
224
+ if asset == TableauAsset.WORKBOOK:
225
225
  # two APIs are required to extract workbooks
226
226
  return self._fetch_workbooks()
227
227
 
@@ -4,21 +4,21 @@ from typing import Optional
4
4
  import tableauserverclient as TSC # type: ignore
5
5
 
6
6
  from ....utils import SerializedAsset, retry
7
- from ..assets import TableauRevampAsset
7
+ from ..assets import TableauAsset
8
8
  from ..constants import DEFAULT_PAGE_SIZE
9
9
  from .errors import TableauApiError, TableauApiTimeout
10
10
  from .gql_queries import FIELDS_QUERIES, GQL_QUERIES, QUERY_TEMPLATE
11
11
 
12
12
  # increase the value when extraction is too slow
13
13
  # decrease the value when timeouts arise
14
- _CUSTOM_PAGE_SIZE: dict[TableauRevampAsset, int] = {
14
+ _CUSTOM_PAGE_SIZE: dict[TableauAsset, int] = {
15
15
  # for some clients, extraction of columns tend to hit the node limit
16
16
  # https://community.tableau.com/s/question/0D54T00000YuK60SAF/metadata-query-nodelimitexceeded-error
17
17
  # the workaround is to reduce pagination
18
- TableauRevampAsset.COLUMN: 50,
18
+ TableauAsset.COLUMN: 50,
19
19
  # fields are light but volumes are bigger
20
- TableauRevampAsset.FIELD: 1000,
21
- TableauRevampAsset.TABLE: 50,
20
+ TableauAsset.FIELD: 1000,
21
+ TableauAsset.TABLE: 50,
22
22
  }
23
23
 
24
24
  _TIMEOUT_MESSAGE = (
@@ -115,7 +115,7 @@ class TableauClientMetadataApi:
115
115
  result_pages = gql_query_scroll(self._server, query, resource)
116
116
  return [asset for page in result_pages for asset in page]
117
117
 
118
- def _page_size(self, asset: TableauRevampAsset) -> int:
118
+ def _page_size(self, asset: TableauAsset) -> int:
119
119
  return (
120
120
  self._override_page_size
121
121
  or _CUSTOM_PAGE_SIZE.get(asset)
@@ -124,7 +124,7 @@ class TableauClientMetadataApi:
124
124
 
125
125
  def _fetch_fields(self) -> SerializedAsset:
126
126
  result: SerializedAsset = []
127
- page_size = self._page_size(TableauRevampAsset.FIELD)
127
+ page_size = self._page_size(TableauAsset.FIELD)
128
128
  for resource, fields in FIELDS_QUERIES:
129
129
  current = self._call(resource, fields, page_size)
130
130
  result.extend(current)
@@ -132,9 +132,9 @@ class TableauClientMetadataApi:
132
132
 
133
133
  def fetch(
134
134
  self,
135
- asset: TableauRevampAsset,
135
+ asset: TableauAsset,
136
136
  ) -> SerializedAsset:
137
- if asset == TableauRevampAsset.FIELD:
137
+ if asset == TableauAsset.FIELD:
138
138
  return self._fetch_fields()
139
139
 
140
140
  page_size = self._page_size(asset)
@@ -5,7 +5,7 @@ import requests
5
5
  import tableauserverclient as TSC # type: ignore
6
6
 
7
7
  from ....utils import SerializedAsset, deduplicate
8
- from ..assets import TableauRevampAsset
8
+ from ..assets import TableauAsset
9
9
  from .rest_fields import REST_FIELDS
10
10
 
11
11
  logger = logging.getLogger(__name__)
@@ -17,7 +17,7 @@ _METRICS_DEFINITION_URL = "{base}/pulse/site/{site}/{definition_id}"
17
17
 
18
18
  def _pick(
19
19
  data: SerializedAsset,
20
- asset: TableauRevampAsset,
20
+ asset: TableauAsset,
21
21
  ) -> SerializedAsset:
22
22
  keys = REST_FIELDS[asset]
23
23
  return [{key: row[key] for key in keys} for row in data]
@@ -107,18 +107,18 @@ class TableauClientRestApi:
107
107
 
108
108
  def fetch(
109
109
  self,
110
- asset: TableauRevampAsset,
110
+ asset: TableauAsset,
111
111
  ) -> SerializedAsset:
112
- if asset == TableauRevampAsset.SUBSCRIPTION:
112
+ if asset == TableauAsset.SUBSCRIPTION:
113
113
  # https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_pulse.htm#PulseSubscriptionService_ListSubscriptions
114
114
  data = self._call(path=_PULSE_API, target="subscriptions")
115
115
 
116
- elif asset == TableauRevampAsset.METRIC_DEFINITION:
116
+ elif asset == TableauAsset.METRIC_DEFINITION:
117
117
  # https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_pulse.htm#MetricQueryService_ListDefinitions
118
118
  data = self._call(path=_PULSE_API, target="definitions")
119
119
  self._compute_metric_url(data)
120
120
 
121
- elif asset == TableauRevampAsset.METRIC:
121
+ elif asset == TableauAsset.METRIC:
122
122
  # https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_pulse.htm#MetricQueryService_ListMetrics
123
123
  definitions = self._call(path=_PULSE_API, target="definitions")
124
124
  data = self._fetch_metrics(definitions)
@@ -4,7 +4,7 @@ from typing import Any
4
4
  import tableauserverclient as TSC # type: ignore
5
5
 
6
6
  from ....utils import JsonType, SerializedAsset
7
- from ..assets import TableauRevampAsset
7
+ from ..assets import TableauAsset
8
8
  from .rest_fields import REST_FIELDS
9
9
 
10
10
 
@@ -30,13 +30,13 @@ class TableauClientTSC:
30
30
  def _pick_fields(
31
31
  self,
32
32
  data: Iterable,
33
- asset: TableauRevampAsset,
33
+ asset: TableauAsset,
34
34
  ) -> Iterator[dict]:
35
35
  keys = REST_FIELDS[asset]
36
36
 
37
37
  for row in data:
38
38
  fields = {key: _pick(row, key) for key in keys}
39
- if asset == TableauRevampAsset.USER:
39
+ if asset == TableauAsset.USER:
40
40
  self._server.users.populate_groups(row)
41
41
  fields["group_ids"] = [group.id for group in row.groups]
42
42
 
@@ -44,21 +44,21 @@ class TableauClientTSC:
44
44
 
45
45
  def fetch(
46
46
  self,
47
- asset: TableauRevampAsset,
47
+ asset: TableauAsset,
48
48
  ) -> SerializedAsset:
49
- if asset == TableauRevampAsset.DATASOURCE:
49
+ if asset == TableauAsset.DATASOURCE:
50
50
  data = TSC.Pager(self._server.datasources)
51
51
 
52
- elif asset == TableauRevampAsset.PROJECT:
52
+ elif asset == TableauAsset.PROJECT:
53
53
  data = TSC.Pager(self._server.projects)
54
54
 
55
- elif asset == TableauRevampAsset.USAGE:
55
+ elif asset == TableauAsset.USAGE:
56
56
  data = TSC.Pager(self._server.views, usage=True)
57
57
 
58
- elif asset == TableauRevampAsset.USER:
58
+ elif asset == TableauAsset.USER:
59
59
  data = TSC.Pager(self._server.users)
60
60
 
61
- elif asset == TableauRevampAsset.WORKBOOK:
61
+ elif asset == TableauAsset.WORKBOOK:
62
62
  data = TSC.Pager(self._server.workbooks)
63
63
 
64
64
  else:
@@ -15,7 +15,7 @@ _DEFAULT_SITE_ID_USER_INPUT = "default"
15
15
  TABLEAU_ENV_PREFIX = "CASTOR_TABLEAU_"
16
16
 
17
17
 
18
- class TableauRevampCredentials(BaseSettings):
18
+ class TableauCredentials(BaseSettings):
19
19
  """
20
20
  Tableau's credentials to connect to both APIs (REST and GRAPHQL)
21
21
  """
@@ -42,7 +42,7 @@ class TableauRevampCredentials(BaseSettings):
42
42
  return site_id
43
43
 
44
44
  @model_validator(mode="after")
45
- def _check_user_xor_pat_login(self) -> "TableauRevampCredentials":
45
+ def _check_user_xor_pat_login(self) -> "TableauCredentials":
46
46
  """
47
47
  Checks that credentials are correctly input, it means either:
48
48
  - User and password are filled
@@ -1,4 +1,4 @@
1
- from ..assets import TableauRevampAsset
1
+ from ..assets import TableauAsset
2
2
 
3
3
  QUERY_TEMPLATE = """
4
4
  {{
@@ -128,13 +128,13 @@ workbook { id }
128
128
  """
129
129
 
130
130
 
131
- GQL_QUERIES: dict[TableauRevampAsset, tuple[str, str]] = {
132
- TableauRevampAsset.COLUMN: ("columns", _COLUMNS_QUERY),
133
- TableauRevampAsset.DASHBOARD: ("dashboards", _DASHBOARDS_QUERY),
134
- TableauRevampAsset.DATASOURCE: ("datasources", _DATASOURCES_QUERY),
135
- TableauRevampAsset.SHEET: ("sheets", _SHEETS_QUERY),
136
- TableauRevampAsset.TABLE: ("tables", _TABLES_QUERY),
137
- TableauRevampAsset.WORKBOOK: ("workbooks", _WORKBOOKS_QUERY),
131
+ GQL_QUERIES: dict[TableauAsset, tuple[str, str]] = {
132
+ TableauAsset.COLUMN: ("columns", _COLUMNS_QUERY),
133
+ TableauAsset.DASHBOARD: ("dashboards", _DASHBOARDS_QUERY),
134
+ TableauAsset.DATASOURCE: ("datasources", _DATASOURCES_QUERY),
135
+ TableauAsset.SHEET: ("sheets", _SHEETS_QUERY),
136
+ TableauAsset.TABLE: ("tables", _TABLES_QUERY),
137
+ TableauAsset.WORKBOOK: ("workbooks", _WORKBOOKS_QUERY),
138
138
  }
139
139
 
140
140
  FIELDS_QUERIES = (
@@ -1,44 +1,44 @@
1
- from ..assets import TableauRevampAsset
1
+ from ..assets import TableauAsset
2
2
 
3
3
  # list of fields to pick in REST API or TSC responses
4
- REST_FIELDS: dict[TableauRevampAsset, set[str]] = {
5
- TableauRevampAsset.DATASOURCE: {
4
+ REST_FIELDS: dict[TableauAsset, set[str]] = {
5
+ TableauAsset.DATASOURCE: {
6
6
  "id",
7
7
  "project_id",
8
8
  "webpage_url",
9
9
  },
10
- TableauRevampAsset.METRIC: {
10
+ TableauAsset.METRIC: {
11
11
  "id",
12
12
  "definition_id",
13
13
  },
14
- TableauRevampAsset.METRIC_DEFINITION: {
14
+ TableauAsset.METRIC_DEFINITION: {
15
15
  "metadata",
16
16
  "specification",
17
17
  },
18
- TableauRevampAsset.PROJECT: {
18
+ TableauAsset.PROJECT: {
19
19
  "description",
20
20
  "id",
21
21
  "name",
22
22
  "parent_id",
23
23
  },
24
- TableauRevampAsset.SUBSCRIPTION: {
24
+ TableauAsset.SUBSCRIPTION: {
25
25
  "follower",
26
26
  "id",
27
27
  "metric_id",
28
28
  },
29
- TableauRevampAsset.USAGE: {
29
+ TableauAsset.USAGE: {
30
30
  "name",
31
31
  "total_views",
32
32
  "workbook_id",
33
33
  },
34
- TableauRevampAsset.USER: {
34
+ TableauAsset.USER: {
35
35
  "email",
36
36
  "fullname",
37
37
  "id",
38
38
  "name",
39
39
  "site_role",
40
40
  },
41
- TableauRevampAsset.WORKBOOK: {
41
+ TableauAsset.WORKBOOK: {
42
42
  "id",
43
43
  "project_id",
44
44
  },
@@ -10,18 +10,18 @@ from ...utils import (
10
10
  write_json,
11
11
  write_summary,
12
12
  )
13
- from .assets import TableauRevampAsset
14
- from .client import TableauRevampClient, TableauRevampCredentials
13
+ from .assets import TableauAsset
14
+ from .client import TableauClient, TableauCredentials
15
15
 
16
16
  logger = logging.getLogger(__name__)
17
17
 
18
18
 
19
19
  def iterate_all_data(
20
- client: TableauRevampClient,
21
- ) -> Iterable[tuple[TableauRevampAsset, list]]:
20
+ client: TableauClient,
21
+ ) -> Iterable[tuple[TableauAsset, list]]:
22
22
  """Iterate over the extracted Data from Tableau"""
23
23
 
24
- for asset in TableauRevampAsset:
24
+ for asset in TableauAsset:
25
25
  data = client.fetch(asset)
26
26
  yield asset, deep_serialize(data)
27
27
 
@@ -36,8 +36,8 @@ def extract_all(**kwargs) -> None:
36
36
  page_size = kwargs.get("page_size")
37
37
  timestamp = current_timestamp()
38
38
 
39
- credentials = TableauRevampCredentials(**kwargs)
40
- client = TableauRevampClient(
39
+ credentials = TableauCredentials(**kwargs)
40
+ client = TableauClient(
41
41
  credentials,
42
42
  with_pulse=with_pulse,
43
43
  override_page_size=page_size,
@@ -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