castor-extractor 0.9.2__tar.gz → 0.10.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.9.2 → castor_extractor-0.10.1}/CHANGELOG.md +8 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/PKG-INFO +1 -1
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/client/client.py +4 -1
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/client/pagination.py +8 -3
- castor_extractor-0.10.1/castor_extractor/visualization/domo/client/pagination_test.py +22 -0
- castor_extractor-0.10.1/castor_extractor/visualization/looker/__init__.py +3 -0
- castor_extractor-0.10.1/castor_extractor/visualization/looker/api/__init__.py +3 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/api/client.py +5 -6
- castor_extractor-0.10.1/castor_extractor/visualization/looker/api/utils.py +24 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/extract.py +13 -12
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/multithreading.py +5 -17
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/client.py +47 -15
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/client_test.py +4 -1
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/pyproject.toml +1 -1
- castor_extractor-0.9.2/castor_extractor/visualization/looker/__init__.py +0 -9
- castor_extractor-0.9.2/castor_extractor/visualization/looker/api/__init__.py +0 -7
- castor_extractor-0.9.2/castor_extractor/visualization/looker/api/utils.py +0 -49
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/Dockerfile +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/LICENCE +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/README.md +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_bigquery.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_domo.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_looker.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_metabase_api.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_metabase_db.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_mode.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_postgres.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_powerbi.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_qlik.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_redshift.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_sigma.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_snowflake.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_tableau.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/file_check.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/upload.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/column.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/column_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/enums.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/file.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/file_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/file_test_users.csv +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/file_test_users_valid.csv +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/templates/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/templates/generic_warehouse.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/logger.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/client/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/client/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/client/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/types.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/constant.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/env.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/env_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/upload.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/upload_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/uploader/utils.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/collection.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/deprecate.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/env.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/files.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/files_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/formatter.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/formatter_test.csv +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/formatter_test.json +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/formatter_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/json_stream_write.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/load.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/object.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/object_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/pager.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/pager_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/retry.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/retry_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/safe.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/safe_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/store.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/string.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/string_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/time.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/time_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/type.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/uri.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/uri_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/validation.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/validation_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/write.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/client/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/client/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/client/endpoints.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/domo/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/api/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/api/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/api/sdk.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/api/sdk_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/constant.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/env.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/fields.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/fields_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/parameters.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/api/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/api/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/api/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/.sqlfluff +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/base_url.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/card.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/collection.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/dashboard.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/dashboard_cards.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/database.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/table.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/db/queries/user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/decryption.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/decryption_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/client/shared.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/errors.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/metabase/types.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/client/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/client/client_test.json +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/client/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/client/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/client/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/errors.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/mode/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/credentials_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/rest.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/rest_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/utils.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/client/utils_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/powerbi/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/error.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/error_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/json_rpc.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/json_rpc_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/engine/websocket.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/master.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/rest.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/client/rest_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/qlik/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/client/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/client/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/client/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/client/endpoints.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/client/pagination.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/sigma/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/assets.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/client/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/client/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/client/client_utils.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/client/credentials.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/client/project.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/client/safe_mode.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/constants.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/errors.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/gql_fields.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_1_get.json +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_2_get.json +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/auth.xml +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/project_get.xml +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/user_get.xml +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/view_get_usage.xml +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/assets/rest_api/workbook_get.xml +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/graphql/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/graphql/paginated_object_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/auth_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/credentials_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/projects_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/usages_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/users_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/rest_api/workbooks_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/utils/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tests/unit/utils/env_key.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/tsc_fields.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/types.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/tableau/usage.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/asset.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/query.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/time_filter.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/abstract/time_filter_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/.sqlfluff +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/column.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/cte/sharded.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/database.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/query.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/schema.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/table.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/table_with_tags.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/queries/view_ddl.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/query.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/types.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/.sqlfluff +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/column.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/database.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/group.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/schema.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/table.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/queries/user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/postgres/query.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/.sqlfluff +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/column.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/database.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/group.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/query.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/schema.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/table.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/table_freshness.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/queries/view_ddl.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/redshift/query.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/client.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/client_test.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/.sqlfluff +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/column.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/column_lineage.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/database.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/grant_to_role.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/grant_to_user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/query.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/role.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/schema.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/table.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/queries/view_ddl.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/snowflake/query.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/__init__.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/extract.py +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/.sqlfluff +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/column.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/database.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/query.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/schema.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/table.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/user.sql +0 -0
- {castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/synapse/queries/view_ddl.sql +0 -0
|
@@ -128,7 +128,10 @@ class DomoClient:
|
|
|
128
128
|
while pagination.needs_increment:
|
|
129
129
|
results = self._get_many(
|
|
130
130
|
endpoint=endpoint,
|
|
131
|
-
params={
|
|
131
|
+
params={
|
|
132
|
+
"offset": pagination.offset,
|
|
133
|
+
"limit": pagination.per_page,
|
|
134
|
+
},
|
|
132
135
|
)
|
|
133
136
|
all_results.extend(results)
|
|
134
137
|
number_of_items = len(results)
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
2
3
|
|
|
3
|
-
PER_PAGE = 50
|
|
4
|
+
PER_PAGE = 50 # maximum value accepted by DOMO is 50
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
@dataclass
|
|
7
8
|
class Pagination:
|
|
8
9
|
"""Handles pagination within DOMO Api"""
|
|
9
10
|
|
|
10
|
-
number_results: int =
|
|
11
|
+
number_results: Optional[int] = None
|
|
11
12
|
offset: int = 0
|
|
12
13
|
per_page: int = PER_PAGE
|
|
13
14
|
should_stop: bool = False
|
|
14
15
|
|
|
15
16
|
@property
|
|
16
17
|
def needs_increment(self) -> bool:
|
|
18
|
+
if self.number_results is None:
|
|
19
|
+
return True # first iteration
|
|
20
|
+
|
|
17
21
|
if (self.number_results < self.per_page) or self.should_stop:
|
|
18
22
|
return False
|
|
23
|
+
|
|
19
24
|
return True
|
|
20
25
|
|
|
21
26
|
def increment_offset(self, number_results: int) -> None:
|
|
22
|
-
self.offset +=
|
|
27
|
+
self.offset += number_results
|
|
23
28
|
self.number_results = number_results
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from .pagination import Pagination
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_pagination():
|
|
5
|
+
per_page = 20
|
|
6
|
+
|
|
7
|
+
pagination = Pagination(per_page=per_page)
|
|
8
|
+
|
|
9
|
+
assert pagination.number_results is None
|
|
10
|
+
assert pagination.offset == 0
|
|
11
|
+
|
|
12
|
+
pagination.increment_offset(per_page)
|
|
13
|
+
assert pagination.offset == per_page
|
|
14
|
+
assert pagination.needs_increment
|
|
15
|
+
|
|
16
|
+
pagination.increment_offset(per_page)
|
|
17
|
+
assert pagination.offset == per_page * 2
|
|
18
|
+
assert pagination.needs_increment
|
|
19
|
+
|
|
20
|
+
pagination.increment_offset(5)
|
|
21
|
+
assert pagination.offset == per_page * 2 + 5
|
|
22
|
+
assert not pagination.needs_increment
|
|
@@ -191,7 +191,7 @@ class ApiClient:
|
|
|
191
191
|
def explores(
|
|
192
192
|
self,
|
|
193
193
|
explore_names=Iterator[Tuple[str, str]],
|
|
194
|
-
) ->
|
|
194
|
+
) -> Iterator[LookmlModelExplore]:
|
|
195
195
|
"""Iterates explores of the given Looker account for the provided model/explore names"""
|
|
196
196
|
|
|
197
197
|
@safe_mode(self._safe_mode)
|
|
@@ -202,11 +202,10 @@ class ApiClient:
|
|
|
202
202
|
self._on_api_call()
|
|
203
203
|
return explore
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
_call(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return list(filter(None, explores))
|
|
205
|
+
for lookml_model_name, lookml_explore_name_ in explore_names:
|
|
206
|
+
explore_ = _call(lookml_model_name, lookml_explore_name_)
|
|
207
|
+
if explore_ is not None:
|
|
208
|
+
yield explore_
|
|
210
209
|
|
|
211
210
|
def connections(self) -> List[DBConnection]:
|
|
212
211
|
"""Lists databases connections of the given Looker account"""
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Iterable, Set, Tuple
|
|
2
|
+
|
|
3
|
+
from .sdk import LookmlModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def lookml_explore_names(
|
|
7
|
+
lookmls: Iterable[LookmlModel],
|
|
8
|
+
) -> Set[Tuple[str, str]]:
|
|
9
|
+
"""
|
|
10
|
+
Explores from the lookml models
|
|
11
|
+
Only valid explores are yielded: with all infos
|
|
12
|
+
"""
|
|
13
|
+
model_explores = (
|
|
14
|
+
(model, explore)
|
|
15
|
+
for model in lookmls
|
|
16
|
+
for explore in model.explores or []
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
(model.name, explore.name)
|
|
21
|
+
for model, explore in model_explores
|
|
22
|
+
# accept hidden resources
|
|
23
|
+
if model.name and explore.name
|
|
24
|
+
}
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/visualization/looker/extract.py
RENAMED
|
@@ -11,12 +11,8 @@ from ...utils import (
|
|
|
11
11
|
write_json,
|
|
12
12
|
write_summary,
|
|
13
13
|
)
|
|
14
|
-
from .api import
|
|
15
|
-
|
|
16
|
-
Credentials,
|
|
17
|
-
dashboard_explore_names,
|
|
18
|
-
explore_names_associated_to_dashboards,
|
|
19
|
-
)
|
|
14
|
+
from .api import ApiClient, Credentials, lookml_explore_names
|
|
15
|
+
from .api.sdk import LookmlModel
|
|
20
16
|
from .assets import LookerAsset
|
|
21
17
|
from .multithreading import MultithreadingFetcher
|
|
22
18
|
from .parameters import get_parameters
|
|
@@ -24,6 +20,15 @@ from .parameters import get_parameters
|
|
|
24
20
|
logger = logging.getLogger(__name__)
|
|
25
21
|
|
|
26
22
|
|
|
23
|
+
def _extract_explores_by_name(
|
|
24
|
+
lookmls: Iterable[LookmlModel], client: ApiClient
|
|
25
|
+
) -> Iterable[dict]:
|
|
26
|
+
explore_names = lookml_explore_names(lookmls)
|
|
27
|
+
explores = client.explores(explore_names)
|
|
28
|
+
for explore in explores:
|
|
29
|
+
yield deep_serialize(explore) # type: ignore
|
|
30
|
+
|
|
31
|
+
|
|
27
32
|
def _safe_mode(directory: str) -> SafeMode:
|
|
28
33
|
add_logging_file_handler(directory)
|
|
29
34
|
return SafeMode((Exception,), float("inf"))
|
|
@@ -79,10 +84,8 @@ def iterate_all_data(
|
|
|
79
84
|
if search_per_folder:
|
|
80
85
|
dashboards_stream = fetcher.fetch_assets(LookerAsset.DASHBOARDS)
|
|
81
86
|
yield LookerAsset.DASHBOARDS, StreamableList(dashboards_stream)
|
|
82
|
-
dashboard_explore_names_ = fetcher.explores
|
|
83
87
|
else:
|
|
84
88
|
dashboards = client.dashboards()
|
|
85
|
-
dashboard_explore_names_ = dashboard_explore_names(dashboards)
|
|
86
89
|
yield LookerAsset.DASHBOARDS, deep_serialize(dashboards)
|
|
87
90
|
|
|
88
91
|
logger.info("Extracting lookml models from Looker API")
|
|
@@ -90,10 +93,8 @@ def iterate_all_data(
|
|
|
90
93
|
yield LookerAsset.LOOKML_MODELS, deep_serialize(lookmls)
|
|
91
94
|
|
|
92
95
|
logger.info("Extracting explores from Looker API")
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
)
|
|
96
|
-
yield LookerAsset.EXPLORES, deep_serialize(client.explores(explore_names))
|
|
96
|
+
explores = _extract_explores_by_name(lookmls, client)
|
|
97
|
+
yield LookerAsset.EXPLORES, StreamableList(explores)
|
|
97
98
|
del lookmls
|
|
98
99
|
|
|
99
100
|
logger.info("Extracting connections from Looker API")
|
|
@@ -2,13 +2,13 @@ import logging
|
|
|
2
2
|
import sys
|
|
3
3
|
from concurrent.futures import ThreadPoolExecutor
|
|
4
4
|
from functools import partial
|
|
5
|
-
from typing import Iterable, List, Set
|
|
5
|
+
from typing import Iterable, List, Set
|
|
6
6
|
|
|
7
7
|
from tqdm import tqdm # type: ignore
|
|
8
8
|
|
|
9
9
|
from ...utils import RetryStrategy, deep_serialize, retry
|
|
10
|
-
from . import ApiClient
|
|
11
|
-
from .api.sdk import
|
|
10
|
+
from . import ApiClient
|
|
11
|
+
from .api.sdk import SDKError
|
|
12
12
|
from .assets import LookerAsset
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
@@ -54,16 +54,6 @@ class MultithreadingFetcher:
|
|
|
54
54
|
self._thread_pool_size = thread_pool_size
|
|
55
55
|
self._log_to_stdout = log_to_stdout
|
|
56
56
|
|
|
57
|
-
self.explores: Set[Tuple[str, str]] = set()
|
|
58
|
-
|
|
59
|
-
def _save_explore_names(self, dashboards_per_folder: Iterable[Dashboard]):
|
|
60
|
-
"""
|
|
61
|
-
Since dashboards are streamed right to the file, we need to keep
|
|
62
|
-
the relevant information to extract Explores later.
|
|
63
|
-
"""
|
|
64
|
-
explores = dashboard_explore_names(dashboards_per_folder)
|
|
65
|
-
self.explores.update(explores)
|
|
66
|
-
|
|
67
57
|
def _progress_bar(self, fetch_results: Iterable, total: int) -> tqdm:
|
|
68
58
|
"""Create a tqdm progress bar with the appropriate logs destination"""
|
|
69
59
|
file = sys.stderr
|
|
@@ -73,7 +63,7 @@ class MultithreadingFetcher:
|
|
|
73
63
|
|
|
74
64
|
return tqdm(fetch_results, total=total, file=file)
|
|
75
65
|
|
|
76
|
-
def fetch_assets(self, asset: LookerAsset):
|
|
66
|
+
def fetch_assets(self, asset: LookerAsset) -> Iterable[dict]:
|
|
77
67
|
"""
|
|
78
68
|
Yields serialized Looks or Dashboards with a request per folder ID.
|
|
79
69
|
Requests are parallelised.
|
|
@@ -88,12 +78,10 @@ class MultithreadingFetcher:
|
|
|
88
78
|
fetch_results = executor.map(_fetch, self._folder_ids)
|
|
89
79
|
|
|
90
80
|
for results in self._progress_bar(fetch_results, total_folders):
|
|
91
|
-
if asset == LookerAsset.DASHBOARDS:
|
|
92
|
-
self._save_explore_names(results)
|
|
93
|
-
|
|
94
81
|
for result in results:
|
|
95
82
|
if not result:
|
|
96
83
|
continue
|
|
84
|
+
|
|
97
85
|
total_assets_count += len(result)
|
|
98
86
|
yield deep_serialize(result)
|
|
99
87
|
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/warehouse/bigquery/client.py
RENAMED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
from typing import List, Optional, Set, Tuple
|
|
2
2
|
|
|
3
|
+
from google.api_core.exceptions import Forbidden
|
|
4
|
+
from google.api_core.page_iterator import Iterator as PageIterator
|
|
3
5
|
from google.cloud.bigquery import Client as GoogleCloudClient # type: ignore
|
|
6
|
+
from google.cloud.bigquery.dataset import Dataset # type: ignore
|
|
4
7
|
from google.oauth2.service_account import Credentials # type: ignore
|
|
5
8
|
|
|
9
|
+
from ...utils import retry
|
|
6
10
|
from ..abstract import SqlalchemyClient
|
|
7
11
|
|
|
8
12
|
BIGQUERY_URI = "bigquery://"
|
|
@@ -10,6 +14,9 @@ BIGQUERY_URI = "bigquery://"
|
|
|
10
14
|
CREDENTIALS_INFO_KEY = "credentials_info"
|
|
11
15
|
PROJECT_ID_KEY = "project_id"
|
|
12
16
|
|
|
17
|
+
_RETRY_NUMBER = 1
|
|
18
|
+
_RETRY_BASE_MS = 60_000
|
|
19
|
+
|
|
13
20
|
|
|
14
21
|
class BigQueryClient(SqlalchemyClient):
|
|
15
22
|
"""Connect to BigQuery and run SQL queries"""
|
|
@@ -25,6 +32,9 @@ class BigQueryClient(SqlalchemyClient):
|
|
|
25
32
|
self._db_allowed = db_allowed
|
|
26
33
|
self._db_blocked = db_blocked
|
|
27
34
|
self._dataset_blocked = dataset_blocked
|
|
35
|
+
self.client = self._client()
|
|
36
|
+
self._projects: List[str] | None = None
|
|
37
|
+
self._datasets: List[Dataset] | None = None
|
|
28
38
|
|
|
29
39
|
@staticmethod
|
|
30
40
|
def name() -> str:
|
|
@@ -51,7 +61,7 @@ class BigQueryClient(SqlalchemyClient):
|
|
|
51
61
|
def _build_uri(self, credentials: dict) -> str:
|
|
52
62
|
return BIGQUERY_URI
|
|
53
63
|
|
|
54
|
-
def
|
|
64
|
+
def _client(self) -> GoogleCloudClient:
|
|
55
65
|
assert (
|
|
56
66
|
CREDENTIALS_INFO_KEY in self._options
|
|
57
67
|
), "Missing BigQuery credentials in engine's options"
|
|
@@ -61,25 +71,47 @@ class BigQueryClient(SqlalchemyClient):
|
|
|
61
71
|
credentials=Credentials.from_service_account_info(credentials),
|
|
62
72
|
)
|
|
63
73
|
|
|
64
|
-
def _list_datasets(self) -> List:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
def _list_datasets(self) -> List[Dataset]:
|
|
75
|
+
"""
|
|
76
|
+
Returns datasets available for the given GCP client
|
|
77
|
+
Cache the result in self._datasets to reduce number of API calls
|
|
78
|
+
"""
|
|
79
|
+
if self._datasets is None:
|
|
80
|
+
self._datasets = [
|
|
81
|
+
dataset
|
|
82
|
+
for project_id in self.get_projects()
|
|
83
|
+
for dataset in self.client.list_datasets(project_id)
|
|
84
|
+
if self._keep_dataset(dataset.dataset_id)
|
|
85
|
+
]
|
|
86
|
+
return self._datasets
|
|
87
|
+
|
|
88
|
+
@retry((Forbidden,), count=_RETRY_NUMBER, base_ms=_RETRY_BASE_MS)
|
|
89
|
+
def _list_projects(self) -> PageIterator:
|
|
90
|
+
"""
|
|
91
|
+
Note: Calling list_projects from GoogleCloudClient causes some
|
|
92
|
+
```
|
|
93
|
+
google.api_core.exceptions.Forbidden: 403 GET https://bigquery.googleapis.com/bigquery/v2/projects?prettyPrint=false
|
|
94
|
+
Quota exceeded: Your user exceeded quota for concurrent project.lists requests.
|
|
95
|
+
````
|
|
96
|
+
|
|
97
|
+
This function aims to isolate the call with a custom retry strategy.
|
|
98
|
+
Note that google allows a retry parameter on client.list_projects but
|
|
99
|
+
that looks way too complex to customize.
|
|
100
|
+
"""
|
|
101
|
+
return self.client.list_projects()
|
|
72
102
|
|
|
73
103
|
def get_projects(self) -> List[str]:
|
|
74
104
|
"""
|
|
75
105
|
Returns distinct project_id available for the given GCP client
|
|
106
|
+
Cache the result in self._projects to reduce number of API calls
|
|
76
107
|
"""
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
108
|
+
if self._projects is None:
|
|
109
|
+
self._projects = [
|
|
110
|
+
p.project_id
|
|
111
|
+
for p in self._list_projects()
|
|
112
|
+
if self._keep_project(p.project_id)
|
|
113
|
+
]
|
|
114
|
+
return self._projects
|
|
83
115
|
|
|
84
116
|
def get_regions(self) -> Set[Tuple[str, str]]:
|
|
85
117
|
"""
|
|
@@ -26,8 +26,11 @@ class MockBigQueryClient(BigQueryClient):
|
|
|
26
26
|
self._db_allowed = ["project_2", "project_1"]
|
|
27
27
|
self._dataset_blocked = ["hidden_dataset"]
|
|
28
28
|
self._db_blocked = ["hidden_project"]
|
|
29
|
+
self._projects = None
|
|
30
|
+
self._datasets = None
|
|
31
|
+
self.client = self._client()
|
|
29
32
|
|
|
30
|
-
def
|
|
33
|
+
def _client(self) -> Mock:
|
|
31
34
|
fake_client = Mock()
|
|
32
35
|
fake_client.list_projects = Mock(
|
|
33
36
|
return_value=[
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from typing import Iterable, Set, Tuple
|
|
2
|
-
|
|
3
|
-
from .sdk import Dashboard, LookmlModel
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def lookml_explore_names(
|
|
7
|
-
lookmls: Iterable[LookmlModel],
|
|
8
|
-
) -> Set[Tuple[str, str]]:
|
|
9
|
-
"""
|
|
10
|
-
Explores from the lookml models
|
|
11
|
-
Only valid explores are yielded: with all infos
|
|
12
|
-
"""
|
|
13
|
-
model_explores = (
|
|
14
|
-
(model, explore)
|
|
15
|
-
for model in lookmls
|
|
16
|
-
for explore in model.explores or []
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
(model.name, explore.name)
|
|
21
|
-
for model, explore in model_explores
|
|
22
|
-
# accept hidden resources
|
|
23
|
-
if model.name and explore.name
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def dashboard_explore_names(
|
|
28
|
-
dashboards: Iterable[Dashboard],
|
|
29
|
-
) -> Set[Tuple[str, str]]:
|
|
30
|
-
"""Explores that appear in dashboards"""
|
|
31
|
-
elements = (
|
|
32
|
-
element
|
|
33
|
-
for dashboard in dashboards
|
|
34
|
-
for element in dashboard.dashboard_elements or []
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
(element.query.model, element.query.view)
|
|
39
|
-
for element in elements
|
|
40
|
-
if element.query and element.query.model and element.query.view
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def explore_names_associated_to_dashboards(
|
|
45
|
-
lookmls: Iterable[LookmlModel],
|
|
46
|
-
dashboard_explore_names_: Set[Tuple[str, str]],
|
|
47
|
-
):
|
|
48
|
-
"""Retrieve only explores that are associated to a looker dashboard"""
|
|
49
|
-
return lookml_explore_names(lookmls).intersection(dashboard_explore_names_)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_bigquery.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_domo.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_looker.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_metabase_api.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_metabase_db.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_mode.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_postgres.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_powerbi.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_qlik.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_redshift.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_sigma.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_snowflake.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/commands/extract_tableau.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/column_test.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/file_test.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/file_checker/file_test_users.csv
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/__init__.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/__init__.py
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/transformation/dbt/assets.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/formatter_test.csv
RENAMED
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/formatter_test.json
RENAMED
|
File without changes
|
|
File without changes
|
{castor_extractor-0.9.2 → castor_extractor-0.10.1}/castor_extractor/utils/json_stream_write.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|