gooddata-pipelines 1.64.1.dev1__tar.gz → 1.64.1.dev2__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.
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/PKG-INFO +2 -2
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/pyproject.toml +2 -2
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/input_processor.py +82 -5
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py +70 -4
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/models/custom_data_object.py +17 -1
- gooddata_pipelines-1.64.1.dev2/tests/test_ldm_extension/conftest.py +84 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/test_ldm_extension/test_input_processor.py +33 -76
- gooddata_pipelines-1.64.1.dev2/tests/test_ldm_extension/test_ldm_extension_manager.py +395 -0
- gooddata_pipelines-1.64.1.dev2/tests/test_ldm_extension/test_merge_ldm.py +84 -0
- gooddata_pipelines-1.64.1.dev1/tests/test_ldm_extension/test_ldm_extension_manager.py +0 -194
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/.gitignore +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/LICENSE.txt +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/Makefile +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/README.md +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/_version.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/api/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/api/gooddata_api.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/api/gooddata_api_wrapper.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/backup_input_processor.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/backup_manager.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/base_manager.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/constants.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/csv_reader.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/models/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/models/input_type.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/models/storage.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/models/workspace_response.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/restore_manager.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/storage/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/storage/azure_storage.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/storage/base_storage.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/storage/local_storage.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/backup_and_restore/storage/s3_storage.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/input_validator.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/models/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/models/aliases.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/ldm_extension/models/analytical_object.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/logger/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/logger/logger.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/assets/wdf_setting.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/user_data_filters/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/user_data_filters/models/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/user_data_filters/models/udf_models.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/user_data_filters/user_data_filters.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/models/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/models/permissions.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/models/user_groups.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/models/users.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/permissions.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/user_groups.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/users/users.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/workspaces/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/workspaces/models.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/workspaces/workspace.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/workspaces/workspace_data_filters.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/workspaces/workspace_data_parser.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/entities/workspaces/workspace_data_validator.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/generic/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/generic/config.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/generic/provision.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/provisioning.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/utils/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/utils/context_objects.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/utils/exceptions.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/provisioning/utils/utils.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/py.typed +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/utils/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/utils/decorators.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/utils/file_utils.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/src/gooddata_pipelines/utils/rate_limiter.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/backup_and_restore/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/backup_and_restore/test_backup.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/backup_and_restore/test_backup_input_processor.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/backup_and_restore/test_restore.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/conftest.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_conf.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/analytical_dashboard_extensions/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/analytical_dashboards/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/dashboard_plugins/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/filter_contexts/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/metrics/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/visualization_objects/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/ldm/datasets/test.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/ldm/date_instances/testinstance.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/analytical_dashboard_extensions/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/analytical_dashboards/id.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/dashboard_plugins/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/filter_contexts/id.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/metrics/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/visualization_objects/test.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/ldm/datasets/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/ldm/date_instances/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/analytical_dashboard_extensions/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/analytical_dashboards/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/dashboard_plugins/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/filter_contexts/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/metrics/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/visualization_objects/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/ldm/datasets/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/ldm/date_instances/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/user_data_filters/.gitkeep +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/backup/test_local_conf.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/custom_fields/response_get_all_dashboards.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/custom_fields/response_get_all_metrics.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/custom_fields/response_get_all_visualizations.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/mock_responses.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/profiles.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/permissions/existing_upstream_permissions.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/permissions/permissions_expected_full_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/permissions/permissions_expected_incremental_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/permissions/permissions_input_full_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/permissions/permissions_input_incremental_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/existing_upstream_users.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/profile_response_content.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_expected_full_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_expected_incremental_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_input_full_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_input_full_load_modifies_protected_user.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_input_incremental_load.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_input_incremental_load_deletes_protected_user.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/provisioning/entities/users/users_input_incremental_load_modifies_protected_user.json +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/restore/test_conf.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/restore/test_udf_root/filter1.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/restore/test_udf_root/filter2.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/restore/test_udf_root/user_data_filters/filter1.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/data/restore/test_udf_root/user_data_filters/filter2.yaml +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/panther/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/panther/test_api_wrapper.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/panther/test_sdk_wrapper.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/users/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/users/test_permissions.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/users/test_user_groups.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/users/test_users.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/workspaces/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/workspaces/test_provisioning.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/workspaces/test_workspace.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/workspaces/test_workspace_data_filters.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/workspaces/test_workspace_data_parser.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/entities/workspaces/test_workspace_data_validator.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/provisioning/test_provisioning.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/test_ldm_extension/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/test_ldm_extension/test_input_validator.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/test_ldm_extension/test_models/__init__.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/test_ldm_extension/test_models/test_analytical_object.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/test_ldm_extension/test_models/test_custom_data_object.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/utils/test_decorators.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tests/utils/test_rate_limiter.py +0 -0
- {gooddata_pipelines-1.64.1.dev1 → gooddata_pipelines-1.64.1.dev2}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gooddata-pipelines
|
|
3
|
-
Version: 1.64.1.
|
|
3
|
+
Version: 1.64.1.dev2
|
|
4
4
|
Summary: GoodData Cloud lifecycle automation pipelines
|
|
5
5
|
Author-email: GoodData <support@gooddata.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -10,7 +10,7 @@ Requires-Dist: azure-identity<2.0.0,>=1.15.0
|
|
|
10
10
|
Requires-Dist: azure-storage-blob<13.0.0,>=12.19.0
|
|
11
11
|
Requires-Dist: boto3-stubs<2.0.0,>=1.39.3
|
|
12
12
|
Requires-Dist: boto3<2.0.0,>=1.39.3
|
|
13
|
-
Requires-Dist: gooddata-sdk~=1.64.1.
|
|
13
|
+
Requires-Dist: gooddata-sdk~=1.64.1.dev2
|
|
14
14
|
Requires-Dist: pydantic<3.0.0,>=2.9.2
|
|
15
15
|
Requires-Dist: requests<3.0.0,>=2.32.3
|
|
16
16
|
Requires-Dist: types-pyyaml<7.0.0,>=6.0.12.20250326
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# (C) 2025 GoodData Corporation
|
|
2
2
|
[project]
|
|
3
3
|
name = "gooddata-pipelines"
|
|
4
|
-
version = "1.64.1.
|
|
4
|
+
version = "1.64.1.dev2"
|
|
5
5
|
description = "GoodData Cloud lifecycle automation pipelines"
|
|
6
6
|
authors = [{ name = "GoodData", email = "support@gooddata.com" }]
|
|
7
7
|
license = "MIT"
|
|
@@ -11,7 +11,7 @@ dependencies = [
|
|
|
11
11
|
"pydantic (>=2.9.2,<3.0.0)",
|
|
12
12
|
"requests (>=2.32.3,<3.0.0)",
|
|
13
13
|
"types-requests (>1.0.0,<3.0.0)",
|
|
14
|
-
"gooddata-sdk~=1.64.1.
|
|
14
|
+
"gooddata-sdk~=1.64.1.dev2",
|
|
15
15
|
"boto3 (>=1.39.3,<2.0.0)",
|
|
16
16
|
"boto3-stubs (>=1.39.3,<2.0.0)",
|
|
17
17
|
"azure-storage-blob (>=12.19.0,<13.0.0)",
|
|
@@ -5,6 +5,8 @@ This module is responsible for converting validated custom datasets and fields
|
|
|
5
5
|
into objects defined in the GoodData Python SDK.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import copy
|
|
9
|
+
|
|
8
10
|
from gooddata_sdk.catalog.identifier import (
|
|
9
11
|
CatalogDatasetWorkspaceDataFilterIdentifier,
|
|
10
12
|
CatalogGrainIdentifier,
|
|
@@ -36,11 +38,26 @@ from gooddata_pipelines.ldm_extension.models.aliases import DatasetId
|
|
|
36
38
|
from gooddata_pipelines.ldm_extension.models.custom_data_object import (
|
|
37
39
|
ColumnDataType,
|
|
38
40
|
CustomDataset,
|
|
41
|
+
CustomDatasetDefinition,
|
|
39
42
|
CustomFieldDefinition,
|
|
40
43
|
CustomFieldType,
|
|
41
44
|
)
|
|
42
45
|
|
|
43
46
|
|
|
47
|
+
def _effective_field_tags(
|
|
48
|
+
dataset_name: str, custom_field: CustomFieldDefinition
|
|
49
|
+
) -> list[str]:
|
|
50
|
+
if custom_field.tags is not None:
|
|
51
|
+
return list(custom_field.tags)
|
|
52
|
+
return [dataset_name]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _effective_dataset_tags(definition: CustomDatasetDefinition) -> list[str]:
|
|
56
|
+
if definition.dataset_tags is not None:
|
|
57
|
+
return list(definition.dataset_tags)
|
|
58
|
+
return [definition.dataset_name]
|
|
59
|
+
|
|
60
|
+
|
|
44
61
|
class LdmExtensionDataProcessor:
|
|
45
62
|
"""Create GoodData LDM from validated custom datasets and fields."""
|
|
46
63
|
|
|
@@ -77,7 +94,8 @@ class LdmExtensionDataProcessor:
|
|
|
77
94
|
source_column=custom_field.custom_field_source_column,
|
|
78
95
|
labels=[],
|
|
79
96
|
source_column_data_type=custom_field.custom_field_source_column_data_type.value,
|
|
80
|
-
|
|
97
|
+
description=custom_field.description,
|
|
98
|
+
tags=_effective_field_tags(dataset_name, custom_field),
|
|
81
99
|
)
|
|
82
100
|
|
|
83
101
|
@staticmethod
|
|
@@ -91,7 +109,8 @@ class LdmExtensionDataProcessor:
|
|
|
91
109
|
title=custom_field.custom_field_name,
|
|
92
110
|
source_column=custom_field.custom_field_source_column,
|
|
93
111
|
source_column_data_type=custom_field.custom_field_source_column_data_type.value,
|
|
94
|
-
|
|
112
|
+
description=custom_field.description,
|
|
113
|
+
tags=_effective_field_tags(dataset_name, custom_field),
|
|
95
114
|
)
|
|
96
115
|
|
|
97
116
|
def _date_from_field(
|
|
@@ -109,7 +128,8 @@ class LdmExtensionDataProcessor:
|
|
|
109
128
|
title_pattern="%titleBase - %granularityTitle",
|
|
110
129
|
),
|
|
111
130
|
granularities=self.DATE_GRANULARITIES,
|
|
112
|
-
|
|
131
|
+
description=custom_field.description,
|
|
132
|
+
tags=_effective_field_tags(dataset_name, custom_field),
|
|
113
133
|
)
|
|
114
134
|
|
|
115
135
|
@staticmethod
|
|
@@ -258,7 +278,7 @@ class LdmExtensionDataProcessor:
|
|
|
258
278
|
),
|
|
259
279
|
]
|
|
260
280
|
+ date_references,
|
|
261
|
-
description=
|
|
281
|
+
description=dataset.definition.dataset_description,
|
|
262
282
|
attributes=attributes,
|
|
263
283
|
facts=facts,
|
|
264
284
|
data_source_table_id=dataset_source_table_id,
|
|
@@ -278,7 +298,7 @@ class LdmExtensionDataProcessor:
|
|
|
278
298
|
filter_column_data_type=ColumnDataType.STRING.value,
|
|
279
299
|
)
|
|
280
300
|
],
|
|
281
|
-
tags=
|
|
301
|
+
tags=_effective_dataset_tags(dataset.definition),
|
|
282
302
|
)
|
|
283
303
|
)
|
|
284
304
|
|
|
@@ -287,3 +307,60 @@ class LdmExtensionDataProcessor:
|
|
|
287
307
|
datasets=declarative_datasets, date_instances=date_instances
|
|
288
308
|
)
|
|
289
309
|
return CatalogDeclarativeModel(ldm=ldm)
|
|
310
|
+
|
|
311
|
+
def merge_custom_ldm_into_existing(
|
|
312
|
+
self,
|
|
313
|
+
existing: CatalogDeclarativeModel,
|
|
314
|
+
custom_datasets: dict[DatasetId, CustomDataset],
|
|
315
|
+
*,
|
|
316
|
+
remove_managed_datasets_missing_from_input: bool = False,
|
|
317
|
+
management_tag: str | None = None,
|
|
318
|
+
) -> CatalogDeclarativeModel:
|
|
319
|
+
"""Merge datasets produced from ``custom_datasets`` into an existing declarative LDM.
|
|
320
|
+
|
|
321
|
+
Custom datasets and date instances that share an ``id`` with the fragment replace
|
|
322
|
+
their previous definitions. When ``remove_managed_datasets_missing_from_input`` is
|
|
323
|
+
set, datasets that carry ``management_tag`` but are absent from the incoming
|
|
324
|
+
fragment are removed first (typical for tooling-owned extension datasets).
|
|
325
|
+
|
|
326
|
+
Any other pre-existing LDM objects (previously uploaded extensions whose ids
|
|
327
|
+
are not in the incoming fragment) are preserved unchanged.
|
|
328
|
+
"""
|
|
329
|
+
fragment = self.datasets_to_ldm(custom_datasets)
|
|
330
|
+
fragment_ldm = fragment.ldm or CatalogDeclarativeLdm(
|
|
331
|
+
datasets=[], date_instances=[]
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
result = copy.deepcopy(existing)
|
|
335
|
+
result_ldm = result.ldm or CatalogDeclarativeLdm(
|
|
336
|
+
datasets=[], date_instances=[]
|
|
337
|
+
)
|
|
338
|
+
result.ldm = result_ldm
|
|
339
|
+
|
|
340
|
+
incoming_dataset_ids = {d.id for d in fragment_ldm.datasets}
|
|
341
|
+
incoming_date_ids = {d.id for d in fragment_ldm.date_instances}
|
|
342
|
+
|
|
343
|
+
datasets = list(result_ldm.datasets)
|
|
344
|
+
if remove_managed_datasets_missing_from_input and management_tag:
|
|
345
|
+
datasets = [
|
|
346
|
+
d
|
|
347
|
+
for d in datasets
|
|
348
|
+
if not (
|
|
349
|
+
d.tags
|
|
350
|
+
and management_tag in d.tags
|
|
351
|
+
and d.id not in incoming_dataset_ids
|
|
352
|
+
)
|
|
353
|
+
]
|
|
354
|
+
datasets = [d for d in datasets if d.id not in incoming_dataset_ids]
|
|
355
|
+
datasets.extend(fragment_ldm.datasets)
|
|
356
|
+
result_ldm.datasets = datasets
|
|
357
|
+
|
|
358
|
+
date_instances = [
|
|
359
|
+
d
|
|
360
|
+
for d in result_ldm.date_instances
|
|
361
|
+
if d.id not in incoming_date_ids
|
|
362
|
+
]
|
|
363
|
+
date_instances.extend(fragment_ldm.date_instances)
|
|
364
|
+
result_ldm.date_instances = date_instances
|
|
365
|
+
|
|
366
|
+
return result
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.ldm import (
|
|
7
|
+
CatalogDeclarativeModel,
|
|
8
|
+
)
|
|
6
9
|
from gooddata_sdk.sdk import GoodDataSdk
|
|
7
10
|
from gooddata_sdk.utils import PROFILES_FILE_PATH, profile_content
|
|
8
11
|
|
|
@@ -147,9 +150,35 @@ class LdmExtensionManager:
|
|
|
147
150
|
# If the set of new invalid relations is a subset of the current one,
|
|
148
151
|
return set_new_invalid_relations.issubset(set_current_invalid_relations)
|
|
149
152
|
|
|
153
|
+
def _ldm_payload_for_workspace(
|
|
154
|
+
self,
|
|
155
|
+
workspace_id: str,
|
|
156
|
+
datasets: dict[DatasetId, CustomDataset],
|
|
157
|
+
*,
|
|
158
|
+
merge_into_existing_ldm: bool,
|
|
159
|
+
remove_managed_datasets_missing_from_input: bool,
|
|
160
|
+
management_tag: str | None,
|
|
161
|
+
) -> CatalogDeclarativeModel:
|
|
162
|
+
"""Build the declarative LDM payload to upload for one workspace."""
|
|
163
|
+
if not merge_into_existing_ldm:
|
|
164
|
+
return self._processor.datasets_to_ldm(datasets)
|
|
165
|
+
current = self._sdk.catalog_workspace_content.get_declarative_ldm(
|
|
166
|
+
workspace_id
|
|
167
|
+
)
|
|
168
|
+
return self._processor.merge_custom_ldm_into_existing(
|
|
169
|
+
current,
|
|
170
|
+
datasets,
|
|
171
|
+
remove_managed_datasets_missing_from_input=remove_managed_datasets_missing_from_input,
|
|
172
|
+
management_tag=management_tag,
|
|
173
|
+
)
|
|
174
|
+
|
|
150
175
|
def _process_with_relations_check(
|
|
151
176
|
self,
|
|
152
177
|
validated_data: dict[WorkspaceId, dict[DatasetId, CustomDataset]],
|
|
178
|
+
*,
|
|
179
|
+
merge_into_existing_ldm: bool = False,
|
|
180
|
+
remove_managed_datasets_missing_from_input: bool = False,
|
|
181
|
+
management_tag: str | None = None,
|
|
153
182
|
) -> None:
|
|
154
183
|
"""Check whether relations of analytical objects are valid before and after
|
|
155
184
|
updating the LDM in the GoodData workspace.
|
|
@@ -173,7 +202,13 @@ class LdmExtensionManager:
|
|
|
173
202
|
# Put the LDM with custom datasets into the GoodData workspace.
|
|
174
203
|
self._sdk.catalog_workspace_content.put_declarative_ldm(
|
|
175
204
|
workspace_id=workspace_id,
|
|
176
|
-
ldm=self.
|
|
205
|
+
ldm=self._ldm_payload_for_workspace(
|
|
206
|
+
workspace_id,
|
|
207
|
+
datasets,
|
|
208
|
+
merge_into_existing_ldm=merge_into_existing_ldm,
|
|
209
|
+
remove_managed_datasets_missing_from_input=remove_managed_datasets_missing_from_input,
|
|
210
|
+
management_tag=management_tag,
|
|
211
|
+
),
|
|
177
212
|
)
|
|
178
213
|
|
|
179
214
|
# Get a set of objects with invalid relations from the new workspace state
|
|
@@ -232,13 +267,23 @@ class LdmExtensionManager:
|
|
|
232
267
|
def _process_without_relations_check(
|
|
233
268
|
self,
|
|
234
269
|
validated_data: dict[WorkspaceId, dict[DatasetId, CustomDataset]],
|
|
270
|
+
*,
|
|
271
|
+
merge_into_existing_ldm: bool = False,
|
|
272
|
+
remove_managed_datasets_missing_from_input: bool = False,
|
|
273
|
+
management_tag: str | None = None,
|
|
235
274
|
) -> None:
|
|
236
275
|
"""Update the LDM in the GoodData workspace without checking relations."""
|
|
237
276
|
for workspace_id, datasets in validated_data.items():
|
|
238
277
|
# Put the LDM with custom datasets into the GoodData workspace.
|
|
239
278
|
self._sdk.catalog_workspace_content.put_declarative_ldm(
|
|
240
279
|
workspace_id=workspace_id,
|
|
241
|
-
ldm=self.
|
|
280
|
+
ldm=self._ldm_payload_for_workspace(
|
|
281
|
+
workspace_id,
|
|
282
|
+
datasets,
|
|
283
|
+
merge_into_existing_ldm=merge_into_existing_ldm,
|
|
284
|
+
remove_managed_datasets_missing_from_input=remove_managed_datasets_missing_from_input,
|
|
285
|
+
management_tag=management_tag,
|
|
286
|
+
),
|
|
242
287
|
)
|
|
243
288
|
self._log_success_message(workspace_id)
|
|
244
289
|
|
|
@@ -251,6 +296,9 @@ class LdmExtensionManager:
|
|
|
251
296
|
custom_datasets: list[CustomDatasetDefinition],
|
|
252
297
|
custom_fields: list[CustomFieldDefinition],
|
|
253
298
|
check_relations: bool = True,
|
|
299
|
+
merge_into_existing_ldm: bool = False,
|
|
300
|
+
remove_managed_datasets_missing_from_input: bool = False,
|
|
301
|
+
management_tag: str | None = None,
|
|
254
302
|
) -> None:
|
|
255
303
|
"""Create custom datasets and fields in GoodData workspaces.
|
|
256
304
|
|
|
@@ -266,6 +314,14 @@ class LdmExtensionManager:
|
|
|
266
314
|
after updating the LDM. If the number of invalid relations increases,
|
|
267
315
|
the LDM will be reverted to its previous state. If False, the check
|
|
268
316
|
is skiped and the LDM is updated directly. Defaults to True.
|
|
317
|
+
merge_into_existing_ldm (bool): When True, load the workspace LDM first and merge
|
|
318
|
+
the generated custom datasets and date instances into it instead of uploading
|
|
319
|
+
only the extension fragment. Defaults to False for backward compatibility.
|
|
320
|
+
remove_managed_datasets_missing_from_input (bool): When ``merge_into_existing_ldm``
|
|
321
|
+
is True, remove existing datasets that contain ``management_tag`` but whose
|
|
322
|
+
dataset id is not present in this ``process`` call (tooling cleanup).
|
|
323
|
+
management_tag (str | None): Tag value used with
|
|
324
|
+
``remove_managed_datasets_missing_from_input``.
|
|
269
325
|
|
|
270
326
|
Raises:
|
|
271
327
|
ValueError: If there are validation errors in the dataset or field definitions.
|
|
@@ -278,6 +334,16 @@ class LdmExtensionManager:
|
|
|
278
334
|
|
|
279
335
|
if check_relations:
|
|
280
336
|
# Process the validated data with relations check.
|
|
281
|
-
self._process_with_relations_check(
|
|
337
|
+
self._process_with_relations_check(
|
|
338
|
+
validated_data,
|
|
339
|
+
merge_into_existing_ldm=merge_into_existing_ldm,
|
|
340
|
+
remove_managed_datasets_missing_from_input=remove_managed_datasets_missing_from_input,
|
|
341
|
+
management_tag=management_tag,
|
|
342
|
+
)
|
|
282
343
|
else:
|
|
283
|
-
self._process_without_relations_check(
|
|
344
|
+
self._process_without_relations_check(
|
|
345
|
+
validated_data,
|
|
346
|
+
merge_into_existing_ldm=merge_into_existing_ldm,
|
|
347
|
+
remove_managed_datasets_missing_from_input=remove_managed_datasets_missing_from_input,
|
|
348
|
+
management_tag=management_tag,
|
|
349
|
+
)
|
|
@@ -7,7 +7,7 @@ further processing.
|
|
|
7
7
|
|
|
8
8
|
from enum import Enum
|
|
9
9
|
|
|
10
|
-
from pydantic import BaseModel, model_validator
|
|
10
|
+
from pydantic import BaseModel, Field, model_validator
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class CustomFieldType(str, Enum):
|
|
@@ -42,6 +42,14 @@ class CustomFieldDefinition(BaseModel):
|
|
|
42
42
|
custom_field_type: CustomFieldType
|
|
43
43
|
custom_field_source_column: str
|
|
44
44
|
custom_field_source_column_data_type: ColumnDataType
|
|
45
|
+
description: str | None = Field(
|
|
46
|
+
default=None,
|
|
47
|
+
description="Declarative description on the attribute, fact, or date dataset.",
|
|
48
|
+
)
|
|
49
|
+
tags: list[str] | None = Field(
|
|
50
|
+
default=None,
|
|
51
|
+
description="If set, replaces the default tag list (dataset display name only).",
|
|
52
|
+
)
|
|
45
53
|
|
|
46
54
|
@model_validator(mode="after")
|
|
47
55
|
def check_ids_not_equal(self) -> "CustomFieldDefinition":
|
|
@@ -68,6 +76,14 @@ class CustomDatasetDefinition(BaseModel):
|
|
|
68
76
|
dataset_reference_source_column_data_type: ColumnDataType
|
|
69
77
|
workspace_data_filter_id: str
|
|
70
78
|
workspace_data_filter_column_name: str
|
|
79
|
+
dataset_description: str | None = Field(
|
|
80
|
+
default=None,
|
|
81
|
+
description="Declarative description on the custom dataset.",
|
|
82
|
+
)
|
|
83
|
+
dataset_tags: list[str] | None = Field(
|
|
84
|
+
default=None,
|
|
85
|
+
description="If set, replaces the default tag list (dataset display name only).",
|
|
86
|
+
)
|
|
71
87
|
|
|
72
88
|
@model_validator(mode="after")
|
|
73
89
|
def check_source(self) -> "CustomDatasetDefinition":
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from gooddata_pipelines.ldm_extension.models.custom_data_object import (
|
|
5
|
+
ColumnDataType,
|
|
6
|
+
CustomDataset,
|
|
7
|
+
CustomDatasetDefinition,
|
|
8
|
+
CustomFieldDefinition,
|
|
9
|
+
CustomFieldType,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def mock_custom_field_attribute():
|
|
15
|
+
return CustomFieldDefinition(
|
|
16
|
+
workspace_id="workspace1",
|
|
17
|
+
dataset_id="ds1",
|
|
18
|
+
custom_field_id="attr1",
|
|
19
|
+
custom_field_name="Attribute 1",
|
|
20
|
+
custom_field_type=CustomFieldType.ATTRIBUTE,
|
|
21
|
+
custom_field_source_column="col_attr1",
|
|
22
|
+
custom_field_source_column_data_type=ColumnDataType.STRING,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture
|
|
27
|
+
def mock_custom_field_fact():
|
|
28
|
+
return CustomFieldDefinition(
|
|
29
|
+
workspace_id="workspace1",
|
|
30
|
+
dataset_id="ds1",
|
|
31
|
+
custom_field_id="fact1",
|
|
32
|
+
custom_field_name="Fact 1",
|
|
33
|
+
custom_field_type=CustomFieldType.FACT,
|
|
34
|
+
custom_field_source_column="col_fact1",
|
|
35
|
+
custom_field_source_column_data_type=ColumnDataType.INT,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@pytest.fixture
|
|
40
|
+
def mock_custom_field_date():
|
|
41
|
+
return CustomFieldDefinition(
|
|
42
|
+
workspace_id="workspace1",
|
|
43
|
+
dataset_id="ds1",
|
|
44
|
+
custom_field_id="date1",
|
|
45
|
+
custom_field_name="Date 1",
|
|
46
|
+
custom_field_type=CustomFieldType.DATE,
|
|
47
|
+
custom_field_source_column="col_date1",
|
|
48
|
+
custom_field_source_column_data_type=ColumnDataType.DATE,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.fixture
|
|
53
|
+
def mock_dataset_definition():
|
|
54
|
+
return CustomDatasetDefinition(
|
|
55
|
+
workspace_id="workspace1",
|
|
56
|
+
dataset_id="ds1",
|
|
57
|
+
dataset_name="Dataset 1",
|
|
58
|
+
dataset_source_table="table1",
|
|
59
|
+
dataset_datasource_id="ds_source",
|
|
60
|
+
dataset_source_sql=None,
|
|
61
|
+
parent_dataset_reference="parent_ds",
|
|
62
|
+
parent_dataset_reference_attribute_id="parent_attr",
|
|
63
|
+
dataset_reference_source_column="ref_col",
|
|
64
|
+
dataset_reference_source_column_data_type=ColumnDataType.STRING,
|
|
65
|
+
workspace_data_filter_id="wdf1",
|
|
66
|
+
workspace_data_filter_column_name="col1",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@pytest.fixture
|
|
71
|
+
def mock_custom_dataset(
|
|
72
|
+
mock_dataset_definition,
|
|
73
|
+
mock_custom_field_attribute,
|
|
74
|
+
mock_custom_field_fact,
|
|
75
|
+
mock_custom_field_date,
|
|
76
|
+
):
|
|
77
|
+
return CustomDataset(
|
|
78
|
+
definition=mock_dataset_definition,
|
|
79
|
+
custom_fields=[
|
|
80
|
+
mock_custom_field_attribute,
|
|
81
|
+
mock_custom_field_fact,
|
|
82
|
+
mock_custom_field_date,
|
|
83
|
+
],
|
|
84
|
+
)
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
# (C) 2025 GoodData Corporation
|
|
2
|
-
import pytest
|
|
3
|
-
|
|
4
2
|
from gooddata_pipelines.ldm_extension.input_processor import (
|
|
5
3
|
LdmExtensionDataProcessor,
|
|
6
4
|
)
|
|
7
5
|
from gooddata_pipelines.ldm_extension.models.custom_data_object import (
|
|
8
6
|
ColumnDataType,
|
|
9
7
|
CustomDataset,
|
|
10
|
-
CustomDatasetDefinition,
|
|
11
8
|
CustomFieldDefinition,
|
|
12
9
|
CustomFieldType,
|
|
13
10
|
)
|
|
14
11
|
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
def test_attribute_from_field(mock_custom_field_attribute):
|
|
14
|
+
attr = LdmExtensionDataProcessor._attribute_from_field(
|
|
15
|
+
"dataset_name", mock_custom_field_attribute
|
|
16
|
+
)
|
|
17
|
+
assert attr.id == "attr1"
|
|
18
|
+
assert attr.title == "Attribute 1"
|
|
19
|
+
assert attr.source_column == "col_attr1"
|
|
20
|
+
assert attr.source_column_data_type == ColumnDataType.STRING.value
|
|
21
|
+
assert attr.tags == ["dataset_name"]
|
|
22
|
+
assert attr.description is None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_attribute_from_field_custom_tags_and_description():
|
|
26
|
+
field = CustomFieldDefinition(
|
|
19
27
|
workspace_id="workspace1",
|
|
20
28
|
dataset_id="ds1",
|
|
21
29
|
custom_field_id="attr1",
|
|
@@ -23,79 +31,14 @@ def mock_custom_field_attribute():
|
|
|
23
31
|
custom_field_type=CustomFieldType.ATTRIBUTE,
|
|
24
32
|
custom_field_source_column="col_attr1",
|
|
25
33
|
custom_field_source_column_data_type=ColumnDataType.STRING,
|
|
34
|
+
tags=["t1", "t2"],
|
|
35
|
+
description="Attr desc",
|
|
26
36
|
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@pytest.fixture
|
|
30
|
-
def mock_custom_field_fact():
|
|
31
|
-
return CustomFieldDefinition(
|
|
32
|
-
workspace_id="workspace1",
|
|
33
|
-
dataset_id="ds1",
|
|
34
|
-
custom_field_id="fact1",
|
|
35
|
-
custom_field_name="Fact 1",
|
|
36
|
-
custom_field_type=CustomFieldType.FACT,
|
|
37
|
-
custom_field_source_column="col_fact1",
|
|
38
|
-
custom_field_source_column_data_type=ColumnDataType.INT,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@pytest.fixture
|
|
43
|
-
def mock_custom_field_date():
|
|
44
|
-
return CustomFieldDefinition(
|
|
45
|
-
workspace_id="workspace1",
|
|
46
|
-
dataset_id="ds1",
|
|
47
|
-
custom_field_id="date1",
|
|
48
|
-
custom_field_name="Date 1",
|
|
49
|
-
custom_field_type=CustomFieldType.DATE,
|
|
50
|
-
custom_field_source_column="col_date1",
|
|
51
|
-
custom_field_source_column_data_type=ColumnDataType.DATE,
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
@pytest.fixture
|
|
56
|
-
def mock_dataset_definition():
|
|
57
|
-
return CustomDatasetDefinition(
|
|
58
|
-
workspace_id="workspace1",
|
|
59
|
-
dataset_id="ds1",
|
|
60
|
-
dataset_name="Dataset 1",
|
|
61
|
-
dataset_source_table="table1",
|
|
62
|
-
dataset_datasource_id="ds_source",
|
|
63
|
-
dataset_source_sql=None,
|
|
64
|
-
parent_dataset_reference="parent_ds",
|
|
65
|
-
parent_dataset_reference_attribute_id="parent_attr",
|
|
66
|
-
dataset_reference_source_column="ref_col",
|
|
67
|
-
dataset_reference_source_column_data_type=ColumnDataType.STRING,
|
|
68
|
-
workspace_data_filter_id="wdf1",
|
|
69
|
-
workspace_data_filter_column_name="col1",
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
@pytest.fixture
|
|
74
|
-
def mock_custom_dataset(
|
|
75
|
-
mock_dataset_definition,
|
|
76
|
-
mock_custom_field_attribute,
|
|
77
|
-
mock_custom_field_fact,
|
|
78
|
-
mock_custom_field_date,
|
|
79
|
-
):
|
|
80
|
-
return CustomDataset(
|
|
81
|
-
definition=mock_dataset_definition,
|
|
82
|
-
custom_fields=[
|
|
83
|
-
mock_custom_field_attribute,
|
|
84
|
-
mock_custom_field_fact,
|
|
85
|
-
mock_custom_field_date,
|
|
86
|
-
],
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def test_attribute_from_field(mock_custom_field_attribute):
|
|
91
37
|
attr = LdmExtensionDataProcessor._attribute_from_field(
|
|
92
|
-
"dataset_name",
|
|
38
|
+
"dataset_name", field
|
|
93
39
|
)
|
|
94
|
-
assert attr.
|
|
95
|
-
assert attr.
|
|
96
|
-
assert attr.source_column == "col_attr1"
|
|
97
|
-
assert attr.source_column_data_type == ColumnDataType.STRING.value
|
|
98
|
-
assert attr.tags == ["dataset_name"]
|
|
40
|
+
assert attr.tags == ["t1", "t2"]
|
|
41
|
+
assert attr.description == "Attr desc"
|
|
99
42
|
|
|
100
43
|
|
|
101
44
|
def test_fact_from_field(mock_custom_field_fact):
|
|
@@ -149,6 +92,20 @@ def test_get_sources_sql_only(mock_dataset_definition):
|
|
|
149
92
|
assert sql.statement == "SELECT * FROM foo"
|
|
150
93
|
|
|
151
94
|
|
|
95
|
+
def test_datasets_to_ldm_dataset_tags_and_description(mock_dataset_definition):
|
|
96
|
+
mock_dataset_definition.dataset_tags = ["managed", "extra"]
|
|
97
|
+
mock_dataset_definition.dataset_description = "DS desc"
|
|
98
|
+
mock_dataset_definition.dataset_source_sql = "SELECT 1"
|
|
99
|
+
mock_dataset_definition.dataset_source_table = None
|
|
100
|
+
ds = CustomDataset(definition=mock_dataset_definition, custom_fields=[])
|
|
101
|
+
processor = LdmExtensionDataProcessor()
|
|
102
|
+
model = processor.datasets_to_ldm({"ds1": ds})
|
|
103
|
+
d = model.ldm.datasets[0]
|
|
104
|
+
assert d.description == "DS desc"
|
|
105
|
+
assert d.tags == ["managed", "extra"]
|
|
106
|
+
assert d.sql is not None
|
|
107
|
+
|
|
108
|
+
|
|
152
109
|
def test_datasets_to_ldm(mock_custom_dataset):
|
|
153
110
|
print(mock_custom_dataset)
|
|
154
111
|
processor = LdmExtensionDataProcessor()
|