gooddata-pipelines 1.47.1.dev1__py3-none-any.whl
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.
- gooddata_pipelines/__init__.py +59 -0
- gooddata_pipelines/_version.py +7 -0
- gooddata_pipelines/api/__init__.py +5 -0
- gooddata_pipelines/api/exceptions.py +41 -0
- gooddata_pipelines/api/gooddata_api.py +309 -0
- gooddata_pipelines/api/gooddata_api_wrapper.py +36 -0
- gooddata_pipelines/api/gooddata_sdk.py +374 -0
- gooddata_pipelines/api/utils.py +43 -0
- gooddata_pipelines/backup_and_restore/__init__.py +1 -0
- gooddata_pipelines/backup_and_restore/backup_input_processor.py +195 -0
- gooddata_pipelines/backup_and_restore/backup_manager.py +430 -0
- gooddata_pipelines/backup_and_restore/constants.py +42 -0
- gooddata_pipelines/backup_and_restore/csv_reader.py +41 -0
- gooddata_pipelines/backup_and_restore/models/__init__.py +1 -0
- gooddata_pipelines/backup_and_restore/models/input_type.py +11 -0
- gooddata_pipelines/backup_and_restore/models/storage.py +58 -0
- gooddata_pipelines/backup_and_restore/models/workspace_response.py +51 -0
- gooddata_pipelines/backup_and_restore/storage/__init__.py +1 -0
- gooddata_pipelines/backup_and_restore/storage/base_storage.py +18 -0
- gooddata_pipelines/backup_and_restore/storage/local_storage.py +37 -0
- gooddata_pipelines/backup_and_restore/storage/s3_storage.py +71 -0
- gooddata_pipelines/logger/__init__.py +8 -0
- gooddata_pipelines/logger/logger.py +115 -0
- gooddata_pipelines/provisioning/__init__.py +31 -0
- gooddata_pipelines/provisioning/assets/wdf_setting.json +14 -0
- gooddata_pipelines/provisioning/entities/__init__.py +1 -0
- gooddata_pipelines/provisioning/entities/user_data_filters/__init__.py +1 -0
- gooddata_pipelines/provisioning/entities/user_data_filters/models/__init__.py +1 -0
- gooddata_pipelines/provisioning/entities/user_data_filters/models/udf_models.py +32 -0
- gooddata_pipelines/provisioning/entities/user_data_filters/user_data_filters.py +221 -0
- gooddata_pipelines/provisioning/entities/users/__init__.py +1 -0
- gooddata_pipelines/provisioning/entities/users/models/__init__.py +1 -0
- gooddata_pipelines/provisioning/entities/users/models/permissions.py +242 -0
- gooddata_pipelines/provisioning/entities/users/models/user_groups.py +64 -0
- gooddata_pipelines/provisioning/entities/users/models/users.py +114 -0
- gooddata_pipelines/provisioning/entities/users/permissions.py +153 -0
- gooddata_pipelines/provisioning/entities/users/user_groups.py +212 -0
- gooddata_pipelines/provisioning/entities/users/users.py +179 -0
- gooddata_pipelines/provisioning/entities/workspaces/__init__.py +1 -0
- gooddata_pipelines/provisioning/entities/workspaces/models.py +78 -0
- gooddata_pipelines/provisioning/entities/workspaces/workspace.py +263 -0
- gooddata_pipelines/provisioning/entities/workspaces/workspace_data_filters.py +286 -0
- gooddata_pipelines/provisioning/entities/workspaces/workspace_data_parser.py +123 -0
- gooddata_pipelines/provisioning/entities/workspaces/workspace_data_validator.py +188 -0
- gooddata_pipelines/provisioning/provisioning.py +132 -0
- gooddata_pipelines/provisioning/utils/__init__.py +1 -0
- gooddata_pipelines/provisioning/utils/context_objects.py +32 -0
- gooddata_pipelines/provisioning/utils/exceptions.py +95 -0
- gooddata_pipelines/provisioning/utils/utils.py +80 -0
- gooddata_pipelines/py.typed +0 -0
- gooddata_pipelines-1.47.1.dev1.dist-info/METADATA +85 -0
- gooddata_pipelines-1.47.1.dev1.dist-info/RECORD +54 -0
- gooddata_pipelines-1.47.1.dev1.dist-info/WHEEL +4 -0
- gooddata_pipelines-1.47.1.dev1.dist-info/licenses/LICENSE.txt +1 -277
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
from ._version import __version__
|
|
4
|
+
|
|
5
|
+
# -------- Backup and Restore --------
|
|
6
|
+
from .backup_and_restore.backup_manager import BackupManager
|
|
7
|
+
from .backup_and_restore.models.storage import (
|
|
8
|
+
BackupRestoreConfig,
|
|
9
|
+
StorageType,
|
|
10
|
+
)
|
|
11
|
+
from .backup_and_restore.storage.local_storage import LocalStorage
|
|
12
|
+
from .backup_and_restore.storage.s3_storage import S3Storage
|
|
13
|
+
|
|
14
|
+
# -------- Provisioning --------
|
|
15
|
+
from .provisioning.entities.user_data_filters.models.udf_models import (
|
|
16
|
+
UserDataFilterFullLoad,
|
|
17
|
+
)
|
|
18
|
+
from .provisioning.entities.user_data_filters.user_data_filters import (
|
|
19
|
+
UserDataFilterProvisioner,
|
|
20
|
+
)
|
|
21
|
+
from .provisioning.entities.users.models.permissions import (
|
|
22
|
+
PermissionFullLoad,
|
|
23
|
+
PermissionIncrementalLoad,
|
|
24
|
+
)
|
|
25
|
+
from .provisioning.entities.users.models.user_groups import (
|
|
26
|
+
UserGroupFullLoad,
|
|
27
|
+
UserGroupIncrementalLoad,
|
|
28
|
+
)
|
|
29
|
+
from .provisioning.entities.users.models.users import (
|
|
30
|
+
UserFullLoad,
|
|
31
|
+
UserIncrementalLoad,
|
|
32
|
+
)
|
|
33
|
+
from .provisioning.entities.users.permissions import PermissionProvisioner
|
|
34
|
+
from .provisioning.entities.users.user_groups import UserGroupProvisioner
|
|
35
|
+
from .provisioning.entities.users.users import UserProvisioner
|
|
36
|
+
from .provisioning.entities.workspaces.models import WorkspaceFullLoad
|
|
37
|
+
from .provisioning.entities.workspaces.workspace import WorkspaceProvisioner
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"BackupManager",
|
|
41
|
+
"BackupRestoreConfig",
|
|
42
|
+
"StorageType",
|
|
43
|
+
"LocalStorage",
|
|
44
|
+
"S3Storage",
|
|
45
|
+
"WorkspaceFullLoad",
|
|
46
|
+
"WorkspaceProvisioner",
|
|
47
|
+
"UserIncrementalLoad",
|
|
48
|
+
"UserGroupIncrementalLoad",
|
|
49
|
+
"PermissionFullLoad",
|
|
50
|
+
"PermissionIncrementalLoad",
|
|
51
|
+
"UserFullLoad",
|
|
52
|
+
"UserGroupFullLoad",
|
|
53
|
+
"UserProvisioner",
|
|
54
|
+
"UserGroupProvisioner",
|
|
55
|
+
"PermissionProvisioner",
|
|
56
|
+
"UserDataFilterProvisioner",
|
|
57
|
+
"UserDataFilterFullLoad",
|
|
58
|
+
"__version__",
|
|
59
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
"""Exception class for Panther operations.
|
|
4
|
+
|
|
5
|
+
This module defines the internally used `PantherException` class, which is used
|
|
6
|
+
to handle exceptions that occur during operations related to the Panther SDK or
|
|
7
|
+
GoodData Cloud API.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GoodDataApiException(Exception):
|
|
12
|
+
"""Exception raised during Panther operations.
|
|
13
|
+
|
|
14
|
+
This exception is used to indicate errors that occur during operations
|
|
15
|
+
related to interactions with the GoodData Python SDK or GoodData Cloud API.
|
|
16
|
+
It can include additional context provided through keyword arguments.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, message: str, **kwargs: str) -> None:
|
|
20
|
+
"""Raise a PantherException with a message and optional context.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
message (str): The error message describing the exception.
|
|
24
|
+
**kwargs: Additional context for the exception, such as HTTP status,
|
|
25
|
+
API endpoint, and HTTP method or any other relevant information.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
super().__init__(message)
|
|
29
|
+
self.error_message: str = message
|
|
30
|
+
|
|
31
|
+
# Set default values for attributes.
|
|
32
|
+
# TODO: Consider if the defaults for these are still needed
|
|
33
|
+
# - the values were necessary for log schema implementations, which
|
|
34
|
+
# are not used anymore.
|
|
35
|
+
self.http_status: str = "500 Internal Server Error"
|
|
36
|
+
self.api_endpoint: str = "NA"
|
|
37
|
+
self.http_method: str = "NA"
|
|
38
|
+
|
|
39
|
+
# Set attributes from kwargs.
|
|
40
|
+
for key, value in kwargs.items():
|
|
41
|
+
setattr(self, key, value)
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
"""Interaction with GoodData Cloud via the direct API calls."""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
# TODO: Limit the use of "typing.Any". Improve readability by using either models
|
|
11
|
+
# or typed dicts.
|
|
12
|
+
|
|
13
|
+
TIMEOUT = 60
|
|
14
|
+
REQUEST_PAGE_SIZE = 250
|
|
15
|
+
API_VERSION = "v1"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ApiMethods:
|
|
19
|
+
headers: dict[str, str]
|
|
20
|
+
base_url: str
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def _get_base_url(domain: str) -> str:
|
|
24
|
+
"""Returns the root endpoint for the GoodData Cloud API.
|
|
25
|
+
|
|
26
|
+
Method ensures that the URL starts with "https://" and does not
|
|
27
|
+
end with a trailing slash.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
domain (str): The domain of the GoodData Cloud instance.
|
|
31
|
+
Returns:
|
|
32
|
+
str: The base URL for the GoodData Cloud API.
|
|
33
|
+
"""
|
|
34
|
+
# Remove trailing slash if present.
|
|
35
|
+
if domain[-1] == "/":
|
|
36
|
+
domain = domain[:-1]
|
|
37
|
+
|
|
38
|
+
if not domain.startswith("https://") and not domain.startswith(
|
|
39
|
+
"http://"
|
|
40
|
+
):
|
|
41
|
+
domain = f"https://{domain}"
|
|
42
|
+
|
|
43
|
+
if domain.startswith("http://") and not domain.startswith("https://"):
|
|
44
|
+
domain = domain.replace("http://", "https://")
|
|
45
|
+
|
|
46
|
+
return f"{domain}/api/{API_VERSION}"
|
|
47
|
+
|
|
48
|
+
def _get_url(self, endpoint: str) -> str:
|
|
49
|
+
"""Returns the full URL for a given API endpoint.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
endpoint (str): The API endpoint to be appended to the base URL.
|
|
53
|
+
Returns:
|
|
54
|
+
str: The full URL for the API endpoint.
|
|
55
|
+
"""
|
|
56
|
+
return f"{self.base_url}{endpoint}"
|
|
57
|
+
|
|
58
|
+
def get_custom_application_setting(
|
|
59
|
+
self, workspace_id: str, setting_id: str
|
|
60
|
+
) -> requests.Response:
|
|
61
|
+
"""Gets a custom application setting.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
workspace_id (str): The ID of the workspace.
|
|
65
|
+
setting_id (str): The ID of the custom application setting.
|
|
66
|
+
Returns:
|
|
67
|
+
requests.Response: The response from the server containing the
|
|
68
|
+
custom application setting.
|
|
69
|
+
"""
|
|
70
|
+
url = f"/entities/workspaces/{workspace_id}/customApplicationSettings/{setting_id}"
|
|
71
|
+
return self._get(url)
|
|
72
|
+
|
|
73
|
+
def put_custom_application_setting(
|
|
74
|
+
self, workspace_id: str, setting_id: str, data: dict[str, Any]
|
|
75
|
+
) -> requests.Response:
|
|
76
|
+
url = f"/entities/workspaces/{workspace_id}/customApplicationSettings/{setting_id}"
|
|
77
|
+
return self._put(url, data, self.headers)
|
|
78
|
+
|
|
79
|
+
def post_custom_application_setting(
|
|
80
|
+
self, workspace_id: str, data: dict[str, Any]
|
|
81
|
+
) -> requests.Response:
|
|
82
|
+
"""Creates a custom application setting for a given workspace.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
workspace_id (str): The ID of the workspace.
|
|
86
|
+
data (dict[str, Any]): The data for the custom application setting.
|
|
87
|
+
Returns:
|
|
88
|
+
requests.Response: The response from the server containing the
|
|
89
|
+
created custom application setting.
|
|
90
|
+
"""
|
|
91
|
+
url = f"/entities/workspaces/{workspace_id}/customApplicationSettings/"
|
|
92
|
+
return self._post(url, data, self.headers)
|
|
93
|
+
|
|
94
|
+
def get_all_workspace_data_filters(
|
|
95
|
+
self, workspace_id: str
|
|
96
|
+
) -> requests.Response:
|
|
97
|
+
"""Gets all workspace data filters for a given workspace.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
workspace_id (str): The ID of the workspace.
|
|
101
|
+
Returns:
|
|
102
|
+
requests.Response: The response from the server containing all
|
|
103
|
+
workspace data filters.
|
|
104
|
+
"""
|
|
105
|
+
url = f"/entities/workspaces/{workspace_id}/workspaceDataFilters"
|
|
106
|
+
return self._get(url)
|
|
107
|
+
|
|
108
|
+
def get_workspace_data_filter_settings(
|
|
109
|
+
self, workspace_id: str
|
|
110
|
+
) -> requests.Response:
|
|
111
|
+
"""Gets all workspace data filter settings for a given workspace.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
workspace_id (str): The ID of the workspace.
|
|
115
|
+
Returns:
|
|
116
|
+
requests.Response: The response from the server containing all
|
|
117
|
+
workspace data filter settings.
|
|
118
|
+
"""
|
|
119
|
+
url = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings?include=workspaceDataFilters"
|
|
120
|
+
return self._get(url)
|
|
121
|
+
|
|
122
|
+
def get_workspace_data_filter_setting(
|
|
123
|
+
self, workspace_id: str, wdf_id: str
|
|
124
|
+
) -> requests.Response:
|
|
125
|
+
"""Gets a specific workspace data filter setting.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
workspace_id (str): The ID of the workspace.
|
|
129
|
+
wdf_id (str): The ID of the workspace data filter setting.
|
|
130
|
+
Returns:
|
|
131
|
+
requests.Response: The response from the server containing the
|
|
132
|
+
workspace data filter setting.
|
|
133
|
+
"""
|
|
134
|
+
url = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/{wdf_id}"
|
|
135
|
+
return self._get(url)
|
|
136
|
+
|
|
137
|
+
def put_workspace_data_filter_setting(
|
|
138
|
+
self,
|
|
139
|
+
workspace_id: str,
|
|
140
|
+
wdf_setting: dict[str, Any],
|
|
141
|
+
) -> requests.Response:
|
|
142
|
+
"""Updates a workspace data filter setting.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
workspace_id (str): The ID of the workspace.
|
|
146
|
+
wdf_setting (dict[str, Any]): The workspace data filter setting to
|
|
147
|
+
update.
|
|
148
|
+
Returns:
|
|
149
|
+
requests.Response: The response from the server containing the
|
|
150
|
+
updated workspace data filter setting.
|
|
151
|
+
"""
|
|
152
|
+
wdf_setting_id = wdf_setting["data"]["id"]
|
|
153
|
+
endpoint = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/{wdf_setting_id}"
|
|
154
|
+
return self._put(
|
|
155
|
+
endpoint,
|
|
156
|
+
wdf_setting,
|
|
157
|
+
self.headers,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def post_workspace_data_filter_setting(
|
|
161
|
+
self,
|
|
162
|
+
workspace_id: str,
|
|
163
|
+
wdf_setting: dict[str, Any],
|
|
164
|
+
) -> requests.Response:
|
|
165
|
+
"""Creates a workspace data filter setting for a given workspace.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
workspace_id (str): The ID of the workspace.
|
|
169
|
+
wdf_setting (dict[str, Any]): The workspace data filter setting to
|
|
170
|
+
create.
|
|
171
|
+
Returns:
|
|
172
|
+
requests.Response: The response from the server containing the
|
|
173
|
+
created workspace data filter setting.
|
|
174
|
+
"""
|
|
175
|
+
endpoint = (
|
|
176
|
+
f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/"
|
|
177
|
+
)
|
|
178
|
+
return self._post(
|
|
179
|
+
endpoint,
|
|
180
|
+
wdf_setting,
|
|
181
|
+
self.headers,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def delete_workspace_data_filter_setting(
|
|
185
|
+
self,
|
|
186
|
+
workspace_id: str,
|
|
187
|
+
wdf_setting_id: str,
|
|
188
|
+
) -> requests.Response:
|
|
189
|
+
"""Deletes a workspace data filter setting.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
workspace_id (str): The ID of the workspace.
|
|
193
|
+
wdf_setting_id (str): The ID of the workspace data filter setting
|
|
194
|
+
to delete.
|
|
195
|
+
Returns:
|
|
196
|
+
requests.Response: The response from the server confirming the
|
|
197
|
+
deletion of the workspace data filter setting.
|
|
198
|
+
"""
|
|
199
|
+
endpoint = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/{wdf_setting_id}"
|
|
200
|
+
return self._delete(
|
|
201
|
+
endpoint,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
def post_workspace_data_filter(
|
|
205
|
+
self, workspace_id: str, data: dict[str, Any]
|
|
206
|
+
) -> requests.Response:
|
|
207
|
+
"""Creates a workspace data filter for a given workspace.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
workspace_id (str): The ID of the workspace.
|
|
211
|
+
data (dict[str, Any]): The data for the workspace data filter.
|
|
212
|
+
Returns:
|
|
213
|
+
requests.Response: The response from the server containing the
|
|
214
|
+
created workspace data filter.
|
|
215
|
+
"""
|
|
216
|
+
endpoint = f"/entities/workspaces/{workspace_id}/workspaceDataFilters"
|
|
217
|
+
return self._post(endpoint, data, self.headers)
|
|
218
|
+
|
|
219
|
+
def get_user_data_filters(self, workspace_id: str) -> requests.Response:
|
|
220
|
+
"""Gets the user data filters for a given workspace."""
|
|
221
|
+
endpoint = f"/layout/workspaces/{workspace_id}/userDataFilters"
|
|
222
|
+
return self._get(endpoint)
|
|
223
|
+
|
|
224
|
+
def get_automations(self, workspace_id: str) -> requests.Response:
|
|
225
|
+
"""Gets the automations for a given workspace."""
|
|
226
|
+
endpoint = (
|
|
227
|
+
f"/entities/workspaces/{workspace_id}/automations?include=ALL"
|
|
228
|
+
)
|
|
229
|
+
return self._get(endpoint)
|
|
230
|
+
|
|
231
|
+
def _get(
|
|
232
|
+
self, endpoint: str, headers: dict[str, str] | None = None
|
|
233
|
+
) -> requests.Response:
|
|
234
|
+
"""Sends a GET request to the server.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
endpoint (str): The API endpoint to send the GET request to.
|
|
238
|
+
headers (dict[str, str] | None): Headers to include in the request.
|
|
239
|
+
If no headers are provided, the default headers will be used.
|
|
240
|
+
Returns:
|
|
241
|
+
requests.Response: The response from the server.
|
|
242
|
+
"""
|
|
243
|
+
url = self._get_url(endpoint)
|
|
244
|
+
request_headers = headers if headers else self.headers
|
|
245
|
+
|
|
246
|
+
return requests.get(url, headers=request_headers, timeout=TIMEOUT)
|
|
247
|
+
|
|
248
|
+
def _post(
|
|
249
|
+
self,
|
|
250
|
+
endpoint: str,
|
|
251
|
+
data: Any,
|
|
252
|
+
headers: dict | None = None,
|
|
253
|
+
) -> requests.Response:
|
|
254
|
+
"""Sends a POST request to the server with a given JSON object.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
endpoint (str): The API endpoint to send the POST request to.
|
|
258
|
+
data (Any): The JSON data to send in the request body.
|
|
259
|
+
headers (dict | None): Headers to include in the request.
|
|
260
|
+
If no headers are provided, the default headers will be used.
|
|
261
|
+
Returns:
|
|
262
|
+
requests.Response: The response from the server.
|
|
263
|
+
"""
|
|
264
|
+
url = self._get_url(endpoint)
|
|
265
|
+
request_headers = headers if headers else self.headers
|
|
266
|
+
data_json = json.dumps(data)
|
|
267
|
+
|
|
268
|
+
return requests.post(
|
|
269
|
+
url, data=data_json, headers=request_headers, timeout=TIMEOUT
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
def _put(
|
|
273
|
+
self,
|
|
274
|
+
endpoint: str,
|
|
275
|
+
data: Any,
|
|
276
|
+
headers: dict | None = None,
|
|
277
|
+
) -> requests.Response:
|
|
278
|
+
"""Sends a PUT request to the server with a given JSON object.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
endpoint (str): The API endpoint to send the PUT request to.
|
|
282
|
+
data (Any): The JSON data to send in the request body.
|
|
283
|
+
headers (dict | None): Headers to include in the request.
|
|
284
|
+
If no headers are provided, the default headers will be used.
|
|
285
|
+
Returns:
|
|
286
|
+
requests.Response: The response from the server.
|
|
287
|
+
"""
|
|
288
|
+
url = self._get_url(endpoint)
|
|
289
|
+
request_headers = headers if headers else self.headers
|
|
290
|
+
data_json = json.dumps(data)
|
|
291
|
+
|
|
292
|
+
return requests.put(
|
|
293
|
+
url, data=data_json, headers=request_headers, timeout=TIMEOUT
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
def _delete(
|
|
297
|
+
self,
|
|
298
|
+
endpoint: str,
|
|
299
|
+
) -> requests.Response:
|
|
300
|
+
"""Sends a DELETE request to the server.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
endpoint (str): The API endpoint to send the DELETE request to.
|
|
304
|
+
Returns:
|
|
305
|
+
requests.Response: The response from the server.
|
|
306
|
+
"""
|
|
307
|
+
url = self._get_url(endpoint)
|
|
308
|
+
|
|
309
|
+
return requests.delete(url, headers=self.headers, timeout=TIMEOUT)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
"""Wrapper for interaction with GoodData Cloud."""
|
|
4
|
+
|
|
5
|
+
from gooddata_sdk.sdk import GoodDataSdk
|
|
6
|
+
|
|
7
|
+
from gooddata_pipelines.api.gooddata_api import ApiMethods
|
|
8
|
+
from gooddata_pipelines.api.gooddata_sdk import SdkMethods
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GoodDataApi(SdkMethods, ApiMethods):
|
|
12
|
+
"""Wrapper class for the GoodData Cloud API.
|
|
13
|
+
|
|
14
|
+
This class combines interactions with the GoodData Python SDK and direct API
|
|
15
|
+
calls.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, host: str, token: str) -> None:
|
|
19
|
+
"""Initialize the GoodDataApi with host and token.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
host (str): The GoodData Cloud host URL.
|
|
23
|
+
token (str): The authentication token for the GoodData Cloud API.
|
|
24
|
+
"""
|
|
25
|
+
self._domain: str = host
|
|
26
|
+
self._token: str = token
|
|
27
|
+
|
|
28
|
+
# Initialize the GoodData SDK
|
|
29
|
+
self._sdk = GoodDataSdk.create(self._domain, self._token)
|
|
30
|
+
|
|
31
|
+
# Set up utils for direct API interaction
|
|
32
|
+
self.base_url = self._get_base_url(self._domain)
|
|
33
|
+
self.headers: dict = {
|
|
34
|
+
"Authorization": f"Bearer {self._token}",
|
|
35
|
+
"Content-Type": "application/vnd.gooddata.api+json",
|
|
36
|
+
}
|