castor-extractor 0.23.3__tar.gz → 0.24.1__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.
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/CHANGELOG.md +8 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/PKG-INFO +11 -1
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/README.md +2 -0
- castor_extractor-0.24.1/castor_extractor/commands/extract_looker_studio.py +30 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/client/client.py +0 -13
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/client/endpoints.py +1 -1
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/__init__.py +1 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/assets.py +1 -0
- castor_extractor-0.24.1/castor_extractor/visualization/looker_studio/client/client.py +87 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/credentials.py +5 -0
- castor_extractor-0.24.1/castor_extractor/visualization/looker_studio/client/queries/query.sql +52 -0
- castor_extractor-0.24.1/castor_extractor/visualization/looker_studio/extract.py +84 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/pyproject.toml +2 -2
- castor_extractor-0.23.3/castor_extractor/visualization/looker_studio/client/client.py +0 -37
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/__init__.py +0 -3
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/assets.py +0 -49
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/client/__init__.py +0 -2
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/client/client.py +0 -229
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/client/client_utils.py +0 -75
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/client/credentials.py +0 -104
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/client/project.py +0 -28
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/client/safe_mode.py +0 -70
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/constants.py +0 -9
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/errors.py +0 -5
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/extract.py +0 -121
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/gql_fields.py +0 -249
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/__init__.py +0 -0
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_1_get.json +0 -15
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_2_get.json +0 -15
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/auth.xml +0 -7
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/project_get.xml +0 -9
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/user_get.xml +0 -8
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/view_get_usage.xml +0 -24
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/workbook_get.xml +0 -19
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/graphql/__init__.py +0 -0
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/graphql/paginated_object_test.py +0 -63
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/__init__.py +0 -0
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/auth_test.py +0 -39
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/credentials_test.py +0 -13
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/projects_test.py +0 -59
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/usages_test.py +0 -49
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/users_test.py +0 -52
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/rest_api/workbooks_test.py +0 -60
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/utils/__init__.py +0 -1
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests/unit/utils/env_key.py +0 -6
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/tsc_fields.py +0 -46
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/types.py +0 -11
- castor_extractor-0.23.3/castor_extractor/visualization/tableau/usage.py +0 -14
- castor_extractor-0.23.3/castor_extractor/warehouse/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/Dockerfile +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/DockerfileUsage.md +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/LICENCE +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_bigquery.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_confluence.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_databricks.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_domo.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_looker.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_metabase_api.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_metabase_db.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_mode.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_mysql.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_notion.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_postgres.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_powerbi.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_qlik.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_redshift.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_salesforce.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_salesforce_reporting.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_sigma.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_snowflake.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_sqlserver.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_tableau.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/extract_thoughtspot.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/file_check.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/commands/upload.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/column.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/column_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/enums.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/file.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/file_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/file_test_users.csv +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/file_test_users_valid.csv +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/templates/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/file_checker/templates/generic_warehouse.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/confluence/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/knowledge/notion/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/logger.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/quality/soda/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/types.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/constant.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/env.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/env_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/settings.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/upload.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/upload_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/uploader/utils.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/argument_parser.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/argument_parser_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/abstract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/auth.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/auth_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/pagination_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/safe_request.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/safe_request_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/utils.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/api/utils_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/postgres.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/uri.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/client/uri_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/collection.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/collection_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/dbt/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/dbt/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/dbt/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/dbt/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/dbt/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/deprecate.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/env.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/files.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/files_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/formatter.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/formatter_test.csv +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/formatter_test.json +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/formatter_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/json_stream_write.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/load.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/object.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/object_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/pager/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/pager/pager.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/pager/pager_on_id.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/pager/pager_on_id_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/pager/pager_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/retry.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/retry_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/safe.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/safe_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/credentials_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/salesforce/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/store.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/string.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/string_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/time.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/time_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/type.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/validation.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/validation_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/utils/write.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/client/pagination_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/domo/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/extraction_parameters.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/sdk.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/sdk_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/api/utils.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/constant.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/fields.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/fields_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker/multithreading.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/admin_sdk_client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/enums.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/looker_studio/client/scopes.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/api/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/api/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/api/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/api/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/base_url.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/card.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/collection.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/dashboard.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/dashboard_cards.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/db/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/decryption.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/decryption_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/client/shared.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/errors.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/metabase/types.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/client/client_test.json +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/client/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/client/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/errors.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/mode/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/authentication.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/credentials_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/powerbi/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/error.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/error_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/json_rpc.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/json_rpc_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/engine/websocket.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/master.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/rest.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/client/rest_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/qlik/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/salesforce_reporting/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/salesforce_reporting/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/salesforce_reporting/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/salesforce_reporting/client/rest.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/salesforce_reporting/client/soql.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/salesforce_reporting/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/client/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/sigma/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/client_metadata_api.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/client_rest_api.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/client_tsc.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/errors.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/gql_queries.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/client/rest_fields.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/tableau_revamp/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/assets.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/client/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/client/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/client/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/client/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/client/utils.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/client/utils_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/visualization/thoughtspot/extract.py +0 -0
- {castor_extractor-0.23.3/castor_extractor/visualization/tableau/tests → castor_extractor-0.24.1/castor_extractor/warehouse}/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/asset.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/asset_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/time_filter.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/abstract/time_filter_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/column.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/cte/sharded.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/query.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/schema.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/table_with_tags.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/queries/view_ddl.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/bigquery/types.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/api_client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/api_client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/endpoints.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/enums.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/format.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/format_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/lineage.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/lineage_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/sql_client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/types.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/utils.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/databricks/utils_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/column.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/query.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/schema.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/queries/view_ddl.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/mysql/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/column.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/group.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/schema.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/postgres/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/extract_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/column.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/group.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/query.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/query_serverless.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/schema.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/table_freshness.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/queries/view_ddl.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/redshift/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/constants.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/format.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/format_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/pagination.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/salesforce/soql.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/client_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/credentials.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/credentials_test.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/column.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/column_lineage.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/function.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/grant_to_role.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/grant_to_user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/query.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/role.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/schema.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/queries/view_ddl.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/snowflake/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/__init__.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/client.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/extract.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/queries/.sqlfluff +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/queries/column.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/queries/database.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/queries/schema.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/queries/table.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/queries/user.sql +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/sqlserver/query.py +0 -0
- {castor_extractor-0.23.3 → castor_extractor-0.24.1}/castor_extractor/warehouse/synapse/queries/column.sql +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: castor-extractor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.24.1
|
|
4
4
|
Summary: Extract your metadata assets.
|
|
5
5
|
Home-page: https://www.castordoc.com/
|
|
6
6
|
License: EULA
|
|
@@ -170,7 +170,9 @@ Depending on your use case, you can also install one of the following `extras`:
|
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
172
|
pip install castor-extractor[bigquery]
|
|
173
|
+
pip install castor-extractor[databricks]
|
|
173
174
|
pip install castor-extractor[looker]
|
|
175
|
+
pip install castor-extractor[lookerstudio]
|
|
174
176
|
pip install castor-extractor[metabase]
|
|
175
177
|
pip install castor-extractor[mysql]
|
|
176
178
|
pip install castor-extractor[powerbi]
|
|
@@ -208,6 +210,14 @@ For any questions or bug report, contact us at [support@castordoc.com](mailto:su
|
|
|
208
210
|
|
|
209
211
|
# Changelog
|
|
210
212
|
|
|
213
|
+
## 0.24.1 - 2025-03-14
|
|
214
|
+
|
|
215
|
+
* Added support for Looker Studio
|
|
216
|
+
|
|
217
|
+
## 0.24.0 - 2025-03-10
|
|
218
|
+
|
|
219
|
+
* Remove legacy Tableau Connector
|
|
220
|
+
|
|
211
221
|
## 0.23.3 - 2025-02-19
|
|
212
222
|
|
|
213
223
|
* Snowflake : add --insecure-mode option to turn off OCSP checking
|
|
@@ -104,7 +104,9 @@ Depending on your use case, you can also install one of the following `extras`:
|
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
pip install castor-extractor[bigquery]
|
|
107
|
+
pip install castor-extractor[databricks]
|
|
107
108
|
pip install castor-extractor[looker]
|
|
109
|
+
pip install castor-extractor[lookerstudio]
|
|
108
110
|
pip install castor-extractor[metabase]
|
|
109
111
|
pip install castor-extractor[mysql]
|
|
110
112
|
pip install castor-extractor[powerbi]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
|
|
3
|
+
from castor_extractor.utils import parse_filled_arguments # type: ignore
|
|
4
|
+
from castor_extractor.visualization import looker_studio # type: ignore
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main():
|
|
8
|
+
parser = ArgumentParser()
|
|
9
|
+
parser.add_argument(
|
|
10
|
+
"-c",
|
|
11
|
+
"--credentials",
|
|
12
|
+
help="File path to Service Account credentials with Looker Studio access",
|
|
13
|
+
)
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"-a",
|
|
16
|
+
"--admin-email",
|
|
17
|
+
help="Email of a Google Workspace user with admin access",
|
|
18
|
+
)
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
"-b",
|
|
21
|
+
"--bigquery-credentials",
|
|
22
|
+
help=(
|
|
23
|
+
"Optional: file path to Service Account credentials with BigQuery access. "
|
|
24
|
+
"This can be the same file path as for Looker Studio."
|
|
25
|
+
),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
parser.add_argument("-o", "--output", help="Directory to write to")
|
|
29
|
+
|
|
30
|
+
looker_studio.extract_all(**parse_filled_arguments(parser))
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
from collections.abc import Iterator
|
|
2
2
|
from functools import partial
|
|
3
|
-
from http import HTTPStatus
|
|
4
|
-
from typing import Optional
|
|
5
3
|
|
|
6
4
|
from ....utils import (
|
|
7
5
|
APIClient,
|
|
8
6
|
BasicAuth,
|
|
9
|
-
RequestSafeMode,
|
|
10
7
|
fetch_all_pages,
|
|
11
8
|
)
|
|
12
9
|
from ..assets import (
|
|
@@ -21,19 +18,11 @@ _HEADERS = {
|
|
|
21
18
|
"Content-Type": "application/json",
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
_MAX_ERROR_IGNORED_COUNT = 10
|
|
25
|
-
_IGNORED_ERROR_CODES = (HTTPStatus.BAD_GATEWAY,)
|
|
26
|
-
_SAFE_MODE = RequestSafeMode(
|
|
27
|
-
max_errors=_MAX_ERROR_IGNORED_COUNT,
|
|
28
|
-
status_codes=_IGNORED_ERROR_CODES,
|
|
29
|
-
)
|
|
30
|
-
|
|
31
21
|
|
|
32
22
|
class ConfluenceClient(APIClient):
|
|
33
23
|
def __init__(
|
|
34
24
|
self,
|
|
35
25
|
credentials: ConfluenceCredentials,
|
|
36
|
-
safe_mode: Optional[RequestSafeMode] = None,
|
|
37
26
|
):
|
|
38
27
|
self.account_id = credentials.account_id
|
|
39
28
|
auth = BasicAuth(
|
|
@@ -43,14 +32,12 @@ class ConfluenceClient(APIClient):
|
|
|
43
32
|
auth=auth,
|
|
44
33
|
host=credentials.base_url,
|
|
45
34
|
headers=_HEADERS,
|
|
46
|
-
safe_mode=safe_mode or _SAFE_MODE,
|
|
47
35
|
)
|
|
48
36
|
|
|
49
37
|
def pages(self):
|
|
50
38
|
request = partial(
|
|
51
39
|
self._get,
|
|
52
40
|
endpoint=ConfluenceEndpointFactory.pages(),
|
|
53
|
-
params={"body-format": "atlas_doc_format"},
|
|
54
41
|
)
|
|
55
42
|
yield from fetch_all_pages(request, ConfluencePagination)
|
|
56
43
|
|
|
@@ -14,7 +14,7 @@ class ConfluenceEndpointFactory:
|
|
|
14
14
|
Endpoint to fetch all pages.
|
|
15
15
|
More: https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/#api-pages-get
|
|
16
16
|
"""
|
|
17
|
-
return f"{cls.API}{cls.PAGES}"
|
|
17
|
+
return f"{cls.API}{cls.PAGES}?body-format=atlas_doc_format"
|
|
18
18
|
|
|
19
19
|
@classmethod
|
|
20
20
|
def users(cls) -> str:
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from typing import Iterator, Optional
|
|
2
|
+
|
|
3
|
+
from ....utils import empty_iterator
|
|
4
|
+
from ....warehouse.abstract import WarehouseAsset
|
|
5
|
+
from ....warehouse.bigquery import BigQueryClient, BigQueryQueryBuilder
|
|
6
|
+
from .. import LookerStudioAsset
|
|
7
|
+
from .admin_sdk_client import USER_EMAIL_FIELD, AdminSDKClient
|
|
8
|
+
from .credentials import LookerStudioCredentials
|
|
9
|
+
from .looker_studio_api_client import LookerStudioAPIClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LookerStudioQueryBuilder(BigQueryQueryBuilder):
|
|
13
|
+
def job_history_queries(self) -> list:
|
|
14
|
+
"""
|
|
15
|
+
This class and method are a convenient workaround to build the
|
|
16
|
+
ExtractionQueries which retrieve BigQuery's job history, but filtered on
|
|
17
|
+
Looker Studio only.
|
|
18
|
+
|
|
19
|
+
Compared to the generic BigQuery query history, only the SQL "template"
|
|
20
|
+
changes. By defining this class here, this will pick the SQL file
|
|
21
|
+
`queries/query.sql` located in the same directory as this file.
|
|
22
|
+
"""
|
|
23
|
+
return super().build(WarehouseAsset.QUERY) # type: ignore
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LookerStudioClient:
|
|
27
|
+
"""
|
|
28
|
+
Acts as a wrapper class to fetch Looker Studio assets, which requires
|
|
29
|
+
coordinating calls between the Admin SDK API and the Looker Studio API.
|
|
30
|
+
|
|
31
|
+
If the BigQuery credentials are provided, it can also fetch the source queries
|
|
32
|
+
of BigQuery data sources.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
credentials: LookerStudioCredentials,
|
|
38
|
+
bigquery_credentials: Optional[dict] = None,
|
|
39
|
+
):
|
|
40
|
+
self.admin_sdk_client = AdminSDKClient(credentials)
|
|
41
|
+
self.looker_studio_client = LookerStudioAPIClient(credentials)
|
|
42
|
+
|
|
43
|
+
self.bigquery_client: Optional[BigQueryClient] = None
|
|
44
|
+
if bigquery_credentials:
|
|
45
|
+
self.bigquery_client = BigQueryClient(bigquery_credentials)
|
|
46
|
+
|
|
47
|
+
def _get_assets(self) -> Iterator[dict]:
|
|
48
|
+
"""
|
|
49
|
+
Extracts reports and data sources user by user.
|
|
50
|
+
"""
|
|
51
|
+
users = self.admin_sdk_client.list_users()
|
|
52
|
+
|
|
53
|
+
for user in users:
|
|
54
|
+
email = user[USER_EMAIL_FIELD]
|
|
55
|
+
yield from self.looker_studio_client.fetch_user_assets(email)
|
|
56
|
+
|
|
57
|
+
def _get_source_queries(self) -> Iterator[dict]:
|
|
58
|
+
"""
|
|
59
|
+
Extracts the BigQuery jobs triggered by Looker Studio. The last job
|
|
60
|
+
per data source is returned.
|
|
61
|
+
"""
|
|
62
|
+
if not self.bigquery_client:
|
|
63
|
+
return empty_iterator()
|
|
64
|
+
|
|
65
|
+
query_builder = LookerStudioQueryBuilder(
|
|
66
|
+
regions=self.bigquery_client.get_regions(),
|
|
67
|
+
datasets=self.bigquery_client.get_datasets(),
|
|
68
|
+
extended_regions=self.bigquery_client.get_extended_regions(),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
queries = query_builder.job_history_queries()
|
|
72
|
+
|
|
73
|
+
for query in queries:
|
|
74
|
+
yield from self.bigquery_client.execute(query)
|
|
75
|
+
|
|
76
|
+
def fetch(self, asset: LookerStudioAsset) -> Iterator[dict]:
|
|
77
|
+
if asset == LookerStudioAsset.ASSETS:
|
|
78
|
+
yield from self._get_assets()
|
|
79
|
+
|
|
80
|
+
elif asset == LookerStudioAsset.SOURCE_QUERIES:
|
|
81
|
+
yield from self._get_source_queries()
|
|
82
|
+
|
|
83
|
+
elif asset == LookerStudioAsset.VIEW_ACTIVITY:
|
|
84
|
+
yield from self.admin_sdk_client.list_view_events()
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
raise ValueError(f"The asset {asset}, is not supported")
|
|
@@ -2,6 +2,11 @@ from pydantic import BaseModel, SecretStr, field_serializer
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class LookerStudioCredentials(BaseModel):
|
|
5
|
+
"""
|
|
6
|
+
Looker Studio Credentials match the Service Account credentials JSON
|
|
7
|
+
but with an additional admin_email field.
|
|
8
|
+
"""
|
|
9
|
+
|
|
5
10
|
admin_email: str
|
|
6
11
|
auth_provider_x509_cert_url: str
|
|
7
12
|
auth_uri: str
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Gets the query jobs triggered by Looker Studio when refreshing a BigQuery data source. Only the latest query per
|
|
3
|
+
data source is selected.
|
|
4
|
+
|
|
5
|
+
The `labels` column should indicate the `looker_studio_datasource_id` that triggered the job. In some cases, it also
|
|
6
|
+
contains a `looker_studio_report_id` value, which gives us a link between the data source and a report.
|
|
7
|
+
*/
|
|
8
|
+
WITH ranked_by_datasource AS (
|
|
9
|
+
SELECT
|
|
10
|
+
creation_time,
|
|
11
|
+
project_id AS database_name,
|
|
12
|
+
user_email,
|
|
13
|
+
query AS query_text,
|
|
14
|
+
referenced_tables,
|
|
15
|
+
labels,
|
|
16
|
+
ROW_NUMBER() OVER (
|
|
17
|
+
PARTITION BY (
|
|
18
|
+
SELECT
|
|
19
|
+
label.value
|
|
20
|
+
FROM
|
|
21
|
+
UNNEST(labels) AS label
|
|
22
|
+
WHERE
|
|
23
|
+
label.key = 'looker_studio_datasource_id'
|
|
24
|
+
)
|
|
25
|
+
ORDER BY
|
|
26
|
+
creation_time DESC
|
|
27
|
+
) AS row_num
|
|
28
|
+
FROM
|
|
29
|
+
`{project}.region-{region}.INFORMATION_SCHEMA.JOBS_BY_PROJECT`
|
|
30
|
+
WHERE
|
|
31
|
+
job_type = 'QUERY'
|
|
32
|
+
AND EXISTS (
|
|
33
|
+
SELECT
|
|
34
|
+
1
|
|
35
|
+
FROM
|
|
36
|
+
UNNEST(labels) AS label
|
|
37
|
+
WHERE
|
|
38
|
+
label.key = 'requestor'
|
|
39
|
+
AND label.value = 'looker_studio'
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
SELECT
|
|
43
|
+
creation_time,
|
|
44
|
+
database_name,
|
|
45
|
+
user_email,
|
|
46
|
+
query_text,
|
|
47
|
+
referenced_tables,
|
|
48
|
+
labels
|
|
49
|
+
FROM
|
|
50
|
+
ranked_by_datasource
|
|
51
|
+
WHERE
|
|
52
|
+
row_num = 1;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import Optional, Union, cast
|
|
5
|
+
|
|
6
|
+
from ...utils import (
|
|
7
|
+
OUTPUT_DIR,
|
|
8
|
+
current_timestamp,
|
|
9
|
+
deep_serialize,
|
|
10
|
+
from_env,
|
|
11
|
+
get_output_filename,
|
|
12
|
+
write_json,
|
|
13
|
+
write_summary,
|
|
14
|
+
)
|
|
15
|
+
from .assets import LookerStudioAsset
|
|
16
|
+
from .client import LookerStudioClient, LookerStudioCredentials
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
APPLICATION_CREDENTIALS = "GOOGLE_APPLICATION_CREDENTIALS"
|
|
21
|
+
LOOKER_STUDIO_ADMIN_EMAIL = "CASTOR_LOOKER_STUDIO_ADMIN_EMAIL"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def iterate_all_data(
|
|
25
|
+
client: LookerStudioClient,
|
|
26
|
+
) -> Iterable[tuple[LookerStudioAsset, Union[list, dict]]]:
|
|
27
|
+
for asset in LookerStudioAsset:
|
|
28
|
+
logger.info(f"Extracting {asset.name} from API")
|
|
29
|
+
data = list(deep_serialize(client.fetch(asset)))
|
|
30
|
+
yield asset, data
|
|
31
|
+
logger.info(f"Extracted {len(data)} {asset.name} from API")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _credentials(params: dict) -> LookerStudioCredentials:
|
|
35
|
+
"""
|
|
36
|
+
Builds the Looker Studio credentials by combining the Service Account
|
|
37
|
+
credentials with the admin email.
|
|
38
|
+
"""
|
|
39
|
+
path = params.get("credentials") or from_env(APPLICATION_CREDENTIALS)
|
|
40
|
+
logger.info(f"Looker Studio credentials loaded from {path}")
|
|
41
|
+
with open(path) as file:
|
|
42
|
+
credentials = cast(dict, json.load(file))
|
|
43
|
+
|
|
44
|
+
admin_email = params.get("admin_email") or from_env(
|
|
45
|
+
LOOKER_STUDIO_ADMIN_EMAIL
|
|
46
|
+
)
|
|
47
|
+
credentials["admin_email"] = admin_email
|
|
48
|
+
return LookerStudioCredentials(**credentials)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _bigquery_credentials_or_none(params: dict) -> Optional[dict]:
|
|
52
|
+
"""Extracts optional GCP credentials to access BigQuery"""
|
|
53
|
+
path = params.get("bigquery_credentials") or from_env(
|
|
54
|
+
APPLICATION_CREDENTIALS,
|
|
55
|
+
allow_missing=True,
|
|
56
|
+
)
|
|
57
|
+
if not path:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
logger.info(f"BigQuery credentials loaded from {path}")
|
|
61
|
+
with open(path) as file:
|
|
62
|
+
return cast(dict, json.load(file))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def extract_all(**kwargs) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Extracts data from Looker Studio and stores the output files locally under
|
|
68
|
+
the given output_directory.
|
|
69
|
+
"""
|
|
70
|
+
output_directory = kwargs.get("output") or from_env(OUTPUT_DIR)
|
|
71
|
+
credentials = _credentials(kwargs)
|
|
72
|
+
bigquery_credentials = _bigquery_credentials_or_none(kwargs)
|
|
73
|
+
|
|
74
|
+
client = LookerStudioClient(
|
|
75
|
+
credentials=credentials,
|
|
76
|
+
bigquery_credentials=bigquery_credentials,
|
|
77
|
+
)
|
|
78
|
+
ts = current_timestamp()
|
|
79
|
+
|
|
80
|
+
for key, data in iterate_all_data(client):
|
|
81
|
+
filename = get_output_filename(key.name.lower(), output_directory, ts)
|
|
82
|
+
write_json(filename, data)
|
|
83
|
+
|
|
84
|
+
write_summary(output_directory, ts)
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools>=61.2"]
|
|
|
3
3
|
|
|
4
4
|
[tool.poetry]
|
|
5
5
|
name = "castor-extractor"
|
|
6
|
-
version = "0.
|
|
6
|
+
version = "0.24.1"
|
|
7
7
|
description = "Extract your metadata assets."
|
|
8
8
|
authors = ["Castor <support@castordoc.com>"]
|
|
9
9
|
license = "EULA"
|
|
@@ -122,6 +122,7 @@ castor-extract-confluence = "castor_extractor.commands.extract_confluence:main"
|
|
|
122
122
|
castor-extract-databricks = "castor_extractor.commands.extract_databricks:main"
|
|
123
123
|
castor-extract-domo = "castor_extractor.commands.extract_domo:main"
|
|
124
124
|
castor-extract-looker = "castor_extractor.commands.extract_looker:main"
|
|
125
|
+
castor-extract-looker-studio = "castor_extractor.commands.extract_looker_studio:main"
|
|
125
126
|
castor-extract-metabase-api = "castor_extractor.commands.extract_metabase_api:main"
|
|
126
127
|
castor-extract-metabase-db = "castor_extractor.commands.extract_metabase_db:main"
|
|
127
128
|
castor-extract-mode = "castor_extractor.commands.extract_mode:main"
|
|
@@ -206,7 +207,6 @@ DEP002 = [
|
|
|
206
207
|
|
|
207
208
|
[tool.ruff]
|
|
208
209
|
line-length = 80
|
|
209
|
-
target-version = "py38"
|
|
210
210
|
src = ["extractor"]
|
|
211
211
|
include = ["**/*.py", "**/*.pyi"]
|
|
212
212
|
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
from typing import Iterator
|
|
2
|
-
|
|
3
|
-
from .. import LookerStudioAsset
|
|
4
|
-
from .admin_sdk_client import USER_EMAIL_FIELD, AdminSDKClient
|
|
5
|
-
from .credentials import LookerStudioCredentials
|
|
6
|
-
from .looker_studio_api_client import LookerStudioAPIClient
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class LookerStudioClient:
|
|
10
|
-
"""
|
|
11
|
-
Acts as a wrapper class to fetch Looker Studio assets, which requires
|
|
12
|
-
coordinating calls between the Admin SDK API and the Looker Studio API.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
def __init__(self, credentials: LookerStudioCredentials):
|
|
16
|
-
self.admin_sdk_client = AdminSDKClient(credentials)
|
|
17
|
-
self.looker_studio_client = LookerStudioAPIClient(credentials)
|
|
18
|
-
|
|
19
|
-
def _get_assets(self) -> Iterator[dict]:
|
|
20
|
-
"""
|
|
21
|
-
Extracts reports and data sources user by user.
|
|
22
|
-
"""
|
|
23
|
-
users = self.admin_sdk_client.list_users()
|
|
24
|
-
|
|
25
|
-
for user in users:
|
|
26
|
-
email = user[USER_EMAIL_FIELD]
|
|
27
|
-
yield from self.looker_studio_client.fetch_user_assets(email)
|
|
28
|
-
|
|
29
|
-
def fetch(self, asset: LookerStudioAsset) -> Iterator[dict]:
|
|
30
|
-
if asset == LookerStudioAsset.VIEW_ACTIVITY:
|
|
31
|
-
yield from self.admin_sdk_client.list_view_events()
|
|
32
|
-
|
|
33
|
-
elif asset == LookerStudioAsset.ASSETS:
|
|
34
|
-
yield from self._get_assets()
|
|
35
|
-
|
|
36
|
-
else:
|
|
37
|
-
raise ValueError(f"The asset {asset}, is not supported")
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
|
-
from ...types import ExternalAsset, classproperty
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TableauAsset(ExternalAsset):
|
|
7
|
-
"""
|
|
8
|
-
Tableau assets
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
CUSTOM_SQL_TABLE = "custom_sql_tables"
|
|
12
|
-
CUSTOM_SQL_QUERY = "custom_sql_queries"
|
|
13
|
-
DASHBOARD = "dashboards"
|
|
14
|
-
DASHBOARD_SHEET = "dashboards_sheets"
|
|
15
|
-
DATASOURCE = "datasources"
|
|
16
|
-
FIELD = "fields"
|
|
17
|
-
PROJECT = "projects"
|
|
18
|
-
PUBLISHED_DATASOURCE = "published_datasources"
|
|
19
|
-
SHEET = "sheets"
|
|
20
|
-
USAGE = "views"
|
|
21
|
-
USER = "users"
|
|
22
|
-
WORKBOOK = "workbooks"
|
|
23
|
-
WORKBOOK_TO_DATASOURCE = "workbooks_to_datasource"
|
|
24
|
-
|
|
25
|
-
@classproperty
|
|
26
|
-
def optional(cls) -> set["TableauAsset"]:
|
|
27
|
-
return {
|
|
28
|
-
TableauAsset.DASHBOARD,
|
|
29
|
-
TableauAsset.DASHBOARD_SHEET,
|
|
30
|
-
TableauAsset.FIELD,
|
|
31
|
-
TableauAsset.SHEET,
|
|
32
|
-
TableauAsset.PUBLISHED_DATASOURCE,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class TableauGraphqlAsset(Enum):
|
|
37
|
-
"""
|
|
38
|
-
Assets which can be fetched from Tableau
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
BIN_FIELD = "binFields"
|
|
42
|
-
CALCULATED_FIELD = "calculatedFields"
|
|
43
|
-
COLUMN_FIELD = "columnFields"
|
|
44
|
-
CUSTOM_SQL = "customSQLTables"
|
|
45
|
-
DASHBOARD = "dashboards"
|
|
46
|
-
DATASOURCE = "datasources"
|
|
47
|
-
GROUP_FIELD = "groupFields"
|
|
48
|
-
SHEETS = "sheets"
|
|
49
|
-
WORKBOOK_TO_DATASOURCE = "workbooks"
|