gooddata-pipelines 1.51.0__tar.gz → 1.52.0__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 gooddata-pipelines might be problematic. Click here for more details.

Files changed (145) hide show
  1. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/PKG-INFO +2 -2
  2. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/TODO.md +0 -5
  3. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/backup_input_processor.py +2 -3
  4. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/backup_manager.py +2 -2
  5. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/constants.py +4 -4
  6. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/user_data_filters/models/udf_models.py +8 -10
  7. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/user_data_filters/user_data_filters.py +2 -2
  8. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/models/permissions.py +3 -1
  9. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/models/user_groups.py +9 -1
  10. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/models/users.py +3 -1
  11. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/workspaces/models.py +1 -1
  12. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/utils/utils.py +24 -15
  13. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/pyproject.toml +3 -2
  14. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/users/test_permissions.py +4 -4
  15. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/users/test_users.py +6 -6
  16. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/workspaces/test_workspace_data_filters.py +3 -3
  17. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/test_provisioning.py +105 -0
  18. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/test_models/test_analytical_object.py +2 -3
  19. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/.gitignore +0 -0
  20. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/LICENSE.txt +0 -0
  21. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/Makefile +0 -0
  22. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/README.md +0 -0
  23. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/__init__.py +0 -0
  24. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/_version.py +0 -0
  25. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/api/__init__.py +0 -0
  26. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/api/exceptions.py +0 -0
  27. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/api/gooddata_api.py +0 -0
  28. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/api/gooddata_api_wrapper.py +0 -0
  29. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/api/gooddata_sdk.py +0 -0
  30. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/api/utils.py +0 -0
  31. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/__init__.py +0 -0
  32. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/csv_reader.py +0 -0
  33. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/models/__init__.py +0 -0
  34. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/models/input_type.py +0 -0
  35. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/models/storage.py +0 -0
  36. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/models/workspace_response.py +0 -0
  37. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/storage/__init__.py +0 -0
  38. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/storage/base_storage.py +0 -0
  39. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/storage/local_storage.py +0 -0
  40. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/backup_and_restore/storage/s3_storage.py +0 -0
  41. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/__init__.py +0 -0
  42. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/input_processor.py +0 -0
  43. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/input_validator.py +0 -0
  44. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/ldm_extension_manager.py +0 -0
  45. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/models/__init__.py +0 -0
  46. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/models/aliases.py +0 -0
  47. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/models/analytical_object.py +0 -0
  48. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/ldm_extension/models/custom_data_object.py +0 -0
  49. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/logger/__init__.py +0 -0
  50. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/logger/logger.py +0 -0
  51. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/__init__.py +0 -0
  52. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/assets/wdf_setting.json +0 -0
  53. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/__init__.py +0 -0
  54. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/user_data_filters/__init__.py +0 -0
  55. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/user_data_filters/models/__init__.py +0 -0
  56. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/__init__.py +0 -0
  57. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/models/__init__.py +0 -0
  58. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/permissions.py +0 -0
  59. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/user_groups.py +0 -0
  60. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/users/users.py +0 -0
  61. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/workspaces/__init__.py +0 -0
  62. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/workspaces/workspace.py +0 -0
  63. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/workspaces/workspace_data_filters.py +0 -0
  64. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/workspaces/workspace_data_parser.py +0 -0
  65. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/entities/workspaces/workspace_data_validator.py +0 -0
  66. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/provisioning.py +0 -0
  67. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/utils/__init__.py +0 -0
  68. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/utils/context_objects.py +0 -0
  69. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/provisioning/utils/exceptions.py +0 -0
  70. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/py.typed +0 -0
  71. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/utils/__init__.py +0 -0
  72. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/gooddata_pipelines/utils/rate_limiter.py +0 -0
  73. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/__init__.py +0 -0
  74. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/backup_and_restore/__init__.py +0 -0
  75. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/backup_and_restore/test_backup.py +0 -0
  76. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/backup_and_restore/test_backup_input_processor.py +0 -0
  77. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/conftest.py +0 -0
  78. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/__init__.py +0 -0
  79. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/__init__.py +0 -0
  80. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_conf.yaml +0 -0
  81. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  82. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  83. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  84. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  85. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/analytics_model/metrics/.gitkeep +0 -0
  86. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  87. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid1/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid1/ldm/datasets/test.yaml +0 -0
  88. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  89. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  90. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  91. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  92. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  93. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/analytics_model/metrics/.gitkeep +0 -0
  94. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  95. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/ldm/datasets/.gitkeep +0 -0
  96. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid2/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid2/ldm/date_instances/.gitkeep +0 -0
  97. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  98. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  99. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  100. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  101. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/analytics_model/metrics/.gitkeep +0 -0
  102. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/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
  103. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/ldm/datasets/.gitkeep +0 -0
  104. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/ldm/date_instances/.gitkeep +0 -0
  105. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_exports/services/wsid3/20230713-132759-1_3_1_dev5/gooddata_layouts/services/workspaces/wsid3/user_data_filters/.gitkeep +0 -0
  106. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/backup/test_local_conf.yaml +0 -0
  107. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/custom_fields/response_get_all_dashboards.json +0 -0
  108. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/custom_fields/response_get_all_metrics.json +0 -0
  109. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/custom_fields/response_get_all_visualizations.json +0 -0
  110. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/mock_responses.py +0 -0
  111. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/profiles.yaml +0 -0
  112. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/permissions/existing_upstream_permissions.json +0 -0
  113. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/permissions/permissions_expected_full_load.json +0 -0
  114. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/permissions/permissions_expected_incremental_load.json +0 -0
  115. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/permissions/permissions_input_full_load.json +0 -0
  116. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/permissions/permissions_input_incremental_load.json +0 -0
  117. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/existing_upstream_users.json +0 -0
  118. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/profile_response_content.json +0 -0
  119. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_expected_full_load.json +0 -0
  120. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_expected_incremental_load.json +0 -0
  121. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_input_full_load.json +0 -0
  122. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_input_full_load_modifies_protected_user.json +0 -0
  123. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_input_incremental_load.json +0 -0
  124. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_input_incremental_load_deletes_protected_user.json +0 -0
  125. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/data/provisioning/entities/users/users_input_incremental_load_modifies_protected_user.json +0 -0
  126. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/panther/__init__.py +0 -0
  127. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/panther/test_api_wrapper.py +0 -0
  128. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/panther/test_sdk_wrapper.py +0 -0
  129. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/__init__.py +0 -0
  130. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/__init__.py +0 -0
  131. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/users/__init__.py +0 -0
  132. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/users/test_user_groups.py +0 -0
  133. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/workspaces/__init__.py +0 -0
  134. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/workspaces/test_provisioning.py +0 -0
  135. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/workspaces/test_workspace.py +0 -0
  136. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/workspaces/test_workspace_data_parser.py +0 -0
  137. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/provisioning/entities/workspaces/test_workspace_data_validator.py +0 -0
  138. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/__init__.py +0 -0
  139. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/test_input_processor.py +0 -0
  140. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/test_input_validator.py +0 -0
  141. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/test_ldm_extension_manager.py +0 -0
  142. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/test_models/__init__.py +0 -0
  143. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/test_ldm_extension/test_models/test_custom_data_object.py +0 -0
  144. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tests/utils/test_rate_limiter.py +0 -0
  145. {gooddata_pipelines-1.51.0 → gooddata_pipelines-1.52.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gooddata-pipelines
3
- Version: 1.51.0
3
+ Version: 1.52.0
4
4
  Summary: GoodData Cloud lifecycle automation pipelines
5
5
  Author-email: GoodData <support@gooddata.com>
6
6
  License: MIT
@@ -8,7 +8,7 @@ License-File: LICENSE.txt
8
8
  Requires-Python: >=3.10
9
9
  Requires-Dist: boto3-stubs<2.0.0,>=1.39.3
10
10
  Requires-Dist: boto3<2.0.0,>=1.39.3
11
- Requires-Dist: gooddata-sdk~=1.51.0
11
+ Requires-Dist: gooddata-sdk~=1.52.0
12
12
  Requires-Dist: pydantic<3.0.0,>=2.11.3
13
13
  Requires-Dist: requests<3.0.0,>=2.32.3
14
14
  Requires-Dist: types-pyyaml<7.0.0,>=6.0.12.20250326
@@ -10,15 +10,10 @@ A list of outstanding tasks, features, or technical debt to be addressed in this
10
10
 
11
11
  - [ ] Integrate with GoodDataApiClient
12
12
  - [ ] Consider replacing the SdkMethods wrapper with direct calls to the SDK methods
13
- - [ ] Consider using orjson library instead of json to load test data
14
13
  - [ ] Cleanup custom exceptions
15
14
  - [ ] Improve test coverage. Write missing unit tests for legacy code (e.g., user data filters)
16
15
 
17
16
  ## Documentation
18
17
 
19
18
  - [ ] Improve package README
20
- - [ ] Workspace provisioning
21
- - [ ] User provisioning
22
- - [ ] User group provisioning
23
- - [ ] Permission provisioning
24
19
  - [ ] User data filter provisioning
@@ -1,7 +1,6 @@
1
1
  # (C) 2025 GoodData Corporation
2
2
 
3
- from dataclasses import dataclass
4
-
3
+ import attrs
5
4
  import requests
6
5
 
7
6
  from gooddata_pipelines.api import GoodDataApi
@@ -46,7 +45,7 @@ class BackupInputProcessor:
46
45
  )
47
46
  self.all_workspaces_endpoint = f"{self.base_workspace_endpoint}?page=0&size={self.page_size}&sort=name,asc&metaInclude=page"
48
47
 
49
- @dataclass
48
+ @attrs.define
50
49
  class _ProcessDataOutput:
51
50
  workspace_ids: list[str]
52
51
  sub_parents: list[str] | None = None
@@ -6,10 +6,10 @@ import shutil
6
6
  import tempfile
7
7
  import time
8
8
  import traceback
9
- from dataclasses import dataclass
10
9
  from pathlib import Path
11
10
  from typing import Any, Type
12
11
 
12
+ import attrs
13
13
  import requests
14
14
  import yaml
15
15
  from gooddata_sdk.utils import PROFILES_FILE_PATH, profile_content
@@ -40,7 +40,7 @@ from gooddata_pipelines.logger import LogObserver
40
40
  from gooddata_pipelines.utils.rate_limiter import RateLimiter
41
41
 
42
42
 
43
- @dataclass
43
+ @attrs.define
44
44
  class BackupBatch:
45
45
  list_of_ids: list[str]
46
46
 
@@ -1,11 +1,11 @@
1
1
  # (C) 2025 GoodData Corporation
2
2
  import datetime
3
- from dataclasses import dataclass
4
3
 
4
+ import attrs
5
5
  from gooddata_sdk._version import __version__ as sdk_version
6
6
 
7
7
 
8
- @dataclass(frozen=True)
8
+ @attrs.frozen
9
9
  class DirNames:
10
10
  """
11
11
  Folder names used in the SDK backup process:
@@ -21,14 +21,14 @@ class DirNames:
21
21
  UDF = "user_data_filters"
22
22
 
23
23
 
24
- @dataclass(frozen=True)
24
+ @attrs.frozen
25
25
  class ApiDefaults:
26
26
  DEFAULT_PAGE_SIZE = 100
27
27
  DEFAULT_BATCH_SIZE = 100
28
28
  DEFAULT_API_CALLS_PER_SECOND = 1.0
29
29
 
30
30
 
31
- @dataclass(frozen=True)
31
+ @attrs.frozen
32
32
  class BackupSettings(ApiDefaults):
33
33
  MAX_RETRIES = 3
34
34
  RETRY_DELAY = 5 # seconds
@@ -2,31 +2,29 @@
2
2
 
3
3
  """This module defines data models for user data filters in a GoodData workspace."""
4
4
 
5
- # TODO: consider using attrs instead of dataclasses for these models. Dataclasses
6
- # have different functionality per Python version (not package version).
5
+ import attrs
6
+ from pydantic import BaseModel, ConfigDict
7
7
 
8
- from dataclasses import dataclass, field
9
8
 
10
-
11
- @dataclass
9
+ @attrs.define
12
10
  class UserDataFilterGroup:
13
11
  udf_id: str
14
12
  udf_values: list[str]
15
13
 
16
14
 
17
- @dataclass
15
+ @attrs.define
18
16
  class WorkspaceUserDataFilters:
19
17
  workspace_id: str
20
- user_data_filters: list["UserDataFilterGroup"] = field(default_factory=list)
18
+ user_data_filters: list["UserDataFilterGroup"] = attrs.field(factory=list)
19
+
21
20
 
21
+ class UserDataFilterFullLoad(BaseModel):
22
+ model_config = ConfigDict(extra="forbid")
22
23
 
23
- @dataclass
24
- class UserDataFilterFullLoad:
25
24
  workspace_id: str
26
25
  udf_id: str
27
26
  udf_value: str
28
27
 
29
28
 
30
- @dataclass
31
29
  class UserDataFilterIncrementalLoad(UserDataFilterFullLoad):
32
30
  is_active: bool
@@ -50,6 +50,8 @@ class UserDataFilterProvisioner(
50
50
  ldm_column_name: str = ""
51
51
  maql_column_name: str = ""
52
52
 
53
+ FULL_LOAD_TYPE = UserDataFilterFullLoad
54
+
53
55
  def set_ldm_column_name(self, ldm_column_name: str) -> None:
54
56
  """Set the LDM column name for user data filters.
55
57
 
@@ -214,8 +216,6 @@ class UserDataFilterProvisioner(
214
216
  )
215
217
  self._create_user_data_filters(grouped_db_user_data_filters)
216
218
 
217
- self.logger.info("User data filters provisioning completed")
218
-
219
219
  def _provision_incremental_load(self) -> None:
220
220
  """Provision user data filters in GoodData workspaces."""
221
221
  raise NotImplementedError("Not implemented yet.")
@@ -9,7 +9,7 @@ from gooddata_sdk.catalog.permission.declarative_model.permission import (
9
9
  CatalogDeclarativeSingleWorkspacePermission,
10
10
  CatalogDeclarativeWorkspacePermissions,
11
11
  )
12
- from pydantic import BaseModel
12
+ from pydantic import BaseModel, ConfigDict
13
13
 
14
14
  from gooddata_pipelines.provisioning.utils.exceptions import BaseUserException
15
15
 
@@ -23,6 +23,8 @@ class EntityType(str, Enum):
23
23
 
24
24
 
25
25
  class BasePermission(BaseModel):
26
+ model_config = ConfigDict(extra="forbid")
27
+
26
28
  permission: str
27
29
  workspace_id: str
28
30
  entity_id: str
@@ -1,9 +1,17 @@
1
1
  # (C) 2025 GoodData Corporation
2
2
 
3
- from pydantic import BaseModel, Field, ValidationInfo, field_validator
3
+ from pydantic import (
4
+ BaseModel,
5
+ ConfigDict,
6
+ Field,
7
+ ValidationInfo,
8
+ field_validator,
9
+ )
4
10
 
5
11
 
6
12
  class UserGroupBase(BaseModel):
13
+ model_config = ConfigDict(extra="forbid")
14
+
7
15
  user_group_id: str
8
16
  user_group_name: str
9
17
  parent_user_groups: list[str] = Field(default_factory=list)
@@ -3,7 +3,7 @@
3
3
  from typing import Any
4
4
 
5
5
  from gooddata_sdk.catalog.user.entity_model.user import CatalogUser
6
- from pydantic import BaseModel, Field
6
+ from pydantic import BaseModel, ConfigDict, Field
7
7
 
8
8
 
9
9
  class UserProfile(BaseModel):
@@ -18,6 +18,8 @@ class UserProfile(BaseModel):
18
18
  class BaseUser(BaseModel):
19
19
  """Base class containing shared user fields and functionality."""
20
20
 
21
+ model_config = ConfigDict(extra="forbid")
22
+
21
23
  user_id: str
22
24
  firstname: str | None
23
25
  lastname: str | None
@@ -22,7 +22,7 @@ class WorkspaceDataMaps:
22
22
 
23
23
 
24
24
  class WorkspaceBase(BaseModel):
25
- model_config = ConfigDict(coerce_numbers_to_str=True)
25
+ model_config = ConfigDict(coerce_numbers_to_str=True, extra="forbid")
26
26
 
27
27
  parent_id: str
28
28
  workspace_id: str
@@ -2,6 +2,8 @@
2
2
 
3
3
  """Module for utilities used in GoodData Pipelines provisioning."""
4
4
 
5
+ from typing import Any, cast
6
+
5
7
  import attrs
6
8
  from requests import Response
7
9
 
@@ -11,9 +13,8 @@ class AttributesMixin:
11
13
  Mixin class to provide a method for getting attributes of an object which may or may not exist.
12
14
  """
13
15
 
14
- @staticmethod
15
16
  def get_attrs(
16
- *objects: object, overrides: dict[str, str] | None = None
17
+ self, *objects: object, overrides: dict[str, str] | None = None
17
18
  ) -> dict[str, str]:
18
19
  """
19
20
  Returns a dictionary of attributes from the given objects.
@@ -27,11 +28,11 @@ class AttributesMixin:
27
28
  """
28
29
  # TODO: This might not work great with nested objects, values which are lists of objects etc.
29
30
  # If we care about parsing the logs back from the string, we should consider some other approach
30
- attrs: dict[str, str] = {}
31
+ attributes: dict[str, str] = {}
31
32
  for context_object in objects:
32
33
  if isinstance(context_object, Response):
33
34
  # for request.Response objects, keys need to be renamed to match the log schema
34
- attrs.update(
35
+ attributes.update(
35
36
  {
36
37
  "http_status": str(context_object.status_code),
37
38
  "http_method": getattr(
@@ -42,23 +43,31 @@ class AttributesMixin:
42
43
  ),
43
44
  }
44
45
  )
46
+ elif attrs.has(type(context_object)):
47
+ for key, value in attrs.asdict(
48
+ cast(attrs.AttrsInstance, context_object)
49
+ ).items():
50
+ self._add_to_dict(attributes, key, value)
45
51
  else:
46
52
  # Generic handling for other objects
47
53
  for key, value in context_object.__dict__.items():
48
- if value is None:
49
- continue
50
-
51
- if isinstance(value, list):
52
- attrs[key] = ", ".join(
53
- str(list_item) for list_item in value
54
- )
55
- else:
56
- attrs[key] = str(value)
54
+ self._add_to_dict(attributes, key, value)
57
55
 
58
56
  if overrides:
59
- attrs.update(overrides)
57
+ attributes.update(overrides)
58
+
59
+ return attributes
60
+
61
+ def _add_to_dict(
62
+ self, attributes: dict[str, str], key: str, value: Any
63
+ ) -> None:
64
+ if value is None:
65
+ return
60
66
 
61
- return attrs
67
+ if isinstance(value, list):
68
+ attributes[key] = ", ".join(str(list_item) for list_item in value)
69
+ else:
70
+ attributes[key] = str(value)
62
71
 
63
72
 
64
73
  @attrs.define
@@ -1,7 +1,7 @@
1
1
  # (C) 2025 GoodData Corporation
2
2
  [project]
3
3
  name = "gooddata-pipelines"
4
- version = "1.51.0"
4
+ version = "1.52.0"
5
5
  description = "GoodData Cloud lifecycle automation pipelines"
6
6
  authors = [{ name = "GoodData", email = "support@gooddata.com" }]
7
7
  license = { text = "MIT" }
@@ -11,7 +11,7 @@ dependencies = [
11
11
  "pydantic (>=2.11.3,<3.0.0)",
12
12
  "requests (>=2.32.3,<3.0.0)",
13
13
  "types-requests (>=2.32.0,<3.0.0)",
14
- "gooddata-sdk~=1.51.0",
14
+ "gooddata-sdk~=1.52.0",
15
15
  "boto3 (>=1.39.3,<2.0.0)",
16
16
  "boto3-stubs (>=1.39.3,<2.0.0)",
17
17
  "types-pyyaml (>=6.0.12.20250326,<7.0.0)"
@@ -33,6 +33,7 @@ moto = ">=5.1.6,<6.0.0"
33
33
  pytest = ">=8.3.5,<9.0.0"
34
34
  pytest-mock = ">=3.14.0,<4.0.0"
35
35
  ruff = ">=0.11.2,<0.12.0"
36
+ orjson = "^3.11.3"
36
37
 
37
38
  [build-system]
38
39
  requires = ["hatchling"]
@@ -1,7 +1,7 @@
1
1
  # (C) 2025 GoodData Corporation
2
- import json
3
2
  from typing import Literal
4
3
 
4
+ import orjson
5
5
  import pytest
6
6
  from gooddata_api_client.exceptions import ( # type: ignore[import]
7
7
  NotFoundException,
@@ -455,7 +455,7 @@ def test_permission_provisioner(
455
455
  f"{TEST_DATA_SUBDIR}/existing_upstream_permissions.json"
456
456
  )
457
457
  with open(EXISTING_UPSTREAM_PERMISSIONS_PATH, "r") as f:
458
- raw_existing_upstream_permissions = json.load(f)
458
+ raw_existing_upstream_permissions = orjson.loads(f.read())
459
459
 
460
460
  existing_upstream_permissions = parse_expected_permissions(
461
461
  raw_existing_upstream_permissions
@@ -477,11 +477,11 @@ def test_permission_provisioner(
477
477
 
478
478
  # Load source data
479
479
  with open(f"{TEST_DATA_SUBDIR}/{source_data_path}", "r") as f:
480
- source_data = json.load(f)
480
+ source_data = orjson.loads(f.read())
481
481
 
482
482
  # Load and parse expected data
483
483
  with open(f"{TEST_DATA_SUBDIR}/{expected_data_path}", "r") as f:
484
- raw_expected_result = json.load(f)
484
+ raw_expected_result = orjson.loads(f.read())
485
485
 
486
486
  expected_result = parse_expected_permissions(raw_expected_result)
487
487
 
@@ -1,8 +1,8 @@
1
1
  # (C) 2025 GoodData Corporation
2
- import json
3
- from dataclasses import dataclass
4
2
  from typing import Literal, Optional
5
3
 
4
+ import attrs
5
+ import orjson
6
6
  import pytest
7
7
  from gooddata_api_client.exceptions import NotFoundException # type: ignore
8
8
  from gooddata_sdk.catalog.user.entity_model.user import (
@@ -29,7 +29,7 @@ from tests.conftest import TEST_DATA_DIR
29
29
  TEST_DATA_SUBDIR = f"{TEST_DATA_DIR}/provisioning/entities/users"
30
30
 
31
31
 
32
- @dataclass
32
+ @attrs.define
33
33
  class MockUser:
34
34
  id: str
35
35
  firstname: Optional[str]
@@ -225,15 +225,15 @@ def test_user_provisioning(
225
225
 
226
226
  # Load input data
227
227
  with open(f"{TEST_DATA_SUBDIR}/{input_path}", "r") as f:
228
- input_data = json.load(f)
228
+ input_data = orjson.loads(f.read())
229
229
 
230
230
  # Load expected data
231
231
  with open(f"{TEST_DATA_SUBDIR}/{expected_path}", "r") as f:
232
- raw_expected_data = json.load(f)
232
+ raw_expected_data = orjson.loads(f.read())
233
233
 
234
234
  # Load and patch "existing users"
235
235
  with open(f"{TEST_DATA_SUBDIR}/existing_upstream_users.json", "r") as f:
236
- raw_upstream_users = json.load(f)
236
+ raw_upstream_users = orjson.loads(f.read())
237
237
 
238
238
  upstream_users = parse_user_data(raw_upstream_users)
239
239
 
@@ -1,8 +1,8 @@
1
1
  # (C) 2025 GoodData Corporation
2
2
 
3
- import json
4
3
  from typing import Any
5
4
 
5
+ import orjson
6
6
  import pytest
7
7
  from pydantic import ValidationError
8
8
  from requests import Response
@@ -67,7 +67,7 @@ def test_get_wdf_settings_for_workspace_valid_payload(
67
67
 
68
68
  payload = WDF_VALID_PAYLOAD
69
69
 
70
- mock_response._content = json.dumps(payload).encode("utf-8")
70
+ mock_response._content = orjson.dumps(payload)
71
71
 
72
72
  mocker.patch.object(
73
73
  mock_gooddata_api,
@@ -102,7 +102,7 @@ def test_get_wdf_settings_for_workspace_invalid_payload(
102
102
  ]
103
103
  }
104
104
 
105
- mock_response._content = json.dumps(payload).encode("utf-8")
105
+ mock_response._content = orjson.dumps(payload)
106
106
 
107
107
  mocker.patch.object(
108
108
  mock_gooddata_api,
@@ -3,11 +3,13 @@ import os
3
3
  from pathlib import Path
4
4
 
5
5
  import pytest
6
+ from pydantic import BaseModel, ValidationError
6
7
 
7
8
  from gooddata_pipelines import (
8
9
  EntityType,
9
10
  PermissionFullLoad,
10
11
  PermissionIncrementalLoad,
12
+ UserDataFilterFullLoad,
11
13
  UserFullLoad,
12
14
  UserGroupFullLoad,
13
15
  UserGroupIncrementalLoad,
@@ -119,3 +121,106 @@ def test_create_from_profile() -> None:
119
121
  )
120
122
  assert provisioner._api._domain == "http://localhost:3000"
121
123
  assert provisioner._api._token == os.environ.pop("MOCK_TOKEN")
124
+
125
+
126
+ MODELS_AND_VALID_DATA = [
127
+ (
128
+ WorkspaceFullLoad,
129
+ {
130
+ "parent_id": "parent_id",
131
+ "workspace_id": "workspace_id",
132
+ "workspace_name": "workspace_name",
133
+ },
134
+ ),
135
+ (
136
+ WorkspaceIncrementalLoad,
137
+ {
138
+ "parent_id": "parent_id",
139
+ "workspace_id": "workspace_id",
140
+ "workspace_name": "workspace_name",
141
+ "is_active": True,
142
+ },
143
+ ),
144
+ (
145
+ UserFullLoad,
146
+ {
147
+ "user_id": "user_id",
148
+ "firstname": "firstname",
149
+ "lastname": "lastname",
150
+ "email": "email",
151
+ "auth_id": "auth_id",
152
+ "user_groups": ["user_group_id"],
153
+ },
154
+ ),
155
+ (
156
+ UserIncrementalLoad,
157
+ {
158
+ "user_id": "user_id",
159
+ "firstname": "firstname",
160
+ "lastname": "lastname",
161
+ "email": "email",
162
+ "auth_id": "auth_id",
163
+ "user_groups": ["user_group_id"],
164
+ "is_active": True,
165
+ },
166
+ ),
167
+ (
168
+ UserGroupFullLoad,
169
+ {
170
+ "user_group_id": "user_group_id",
171
+ "user_group_name": "user_group_name",
172
+ },
173
+ ),
174
+ (
175
+ UserGroupIncrementalLoad,
176
+ {
177
+ "user_group_id": "user_group_id",
178
+ "user_group_name": "user_group_name",
179
+ "is_active": True,
180
+ },
181
+ ),
182
+ (
183
+ PermissionFullLoad,
184
+ {
185
+ "permission": "permission",
186
+ "workspace_id": "workspace_id",
187
+ "entity_id": "entity_id",
188
+ "entity_type": EntityType.user,
189
+ },
190
+ ),
191
+ (
192
+ PermissionIncrementalLoad,
193
+ {
194
+ "permission": "permission",
195
+ "workspace_id": "workspace_id",
196
+ "entity_id": "entity_id",
197
+ "entity_type": EntityType.user,
198
+ "is_active": True,
199
+ },
200
+ ),
201
+ (
202
+ UserDataFilterFullLoad,
203
+ {
204
+ "workspace_id": "workspace_id",
205
+ "udf_id": "udf_id",
206
+ "udf_value": "udf_value",
207
+ },
208
+ ),
209
+ ]
210
+
211
+
212
+ @pytest.mark.parametrize(["provisioning_model", "data"], MODELS_AND_VALID_DATA)
213
+ def test_validate_valid_data(provisioning_model: BaseModel, data: dict) -> None:
214
+ """Test validating valid data."""
215
+ provisioning_model.model_validate(data)
216
+
217
+
218
+ @pytest.mark.parametrize(
219
+ ["provisioning_model", "data"],
220
+ MODELS_AND_VALID_DATA,
221
+ )
222
+ def test_raise_extra_fields(provisioning_model: BaseModel, data: dict) -> None:
223
+ """Test raising an error when extra fields are provided."""
224
+ data["extra_field"] = "extra_field"
225
+ with pytest.raises(ValidationError):
226
+ provisioning_model.model_validate(data)
@@ -1,6 +1,5 @@
1
1
  # (C) 2025 GoodData Corporation
2
- import json
3
-
2
+ import orjson
4
3
  import pytest
5
4
 
6
5
  from gooddata_pipelines.ldm_extension.models.analytical_object import (
@@ -20,7 +19,7 @@ from tests.conftest import TEST_DATA_DIR
20
19
  )
21
20
  def test_analytical_object_model_with_metrics(file_path):
22
21
  with open(file_path, "r") as file:
23
- data = json.load(file)
22
+ data = orjson.loads(file.read())
24
23
  analytical_objects = AnalyticalObjects(**data)
25
24
  assert isinstance(analytical_objects, AnalyticalObjects)
26
25
  assert isinstance(analytical_objects.data, list)