datamaker-py 0.7.0__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.
- datamaker/__init__.py +2 -0
- datamaker/core.py +11 -0
- datamaker/error.py +2 -0
- datamaker/main.py +886 -0
- datamaker/routes/__init__.py +37 -0
- datamaker/routes/api_keys.py +50 -0
- datamaker/routes/base.py +40 -0
- datamaker/routes/connections.py +87 -0
- datamaker/routes/custom_types.py +100 -0
- datamaker/routes/export_and_validation.py +25 -0
- datamaker/routes/folders_and_utils.py +80 -0
- datamaker/routes/generation.py +14 -0
- datamaker/routes/projects.py +35 -0
- datamaker/routes/scenario_files.py +453 -0
- datamaker/routes/sets.py +177 -0
- datamaker/routes/teams.py +62 -0
- datamaker/routes/templates.py +69 -0
- datamaker/routes/users.py +43 -0
- datamaker/template.py +162 -0
- datamaker_py-0.7.0.dist-info/METADATA +79 -0
- datamaker_py-0.7.0.dist-info/RECORD +24 -0
- datamaker_py-0.7.0.dist-info/WHEEL +5 -0
- datamaker_py-0.7.0.dist-info/licenses/LICENSE +21 -0
- datamaker_py-0.7.0.dist-info/top_level.txt +1 -0
datamaker/main.py
ADDED
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dotenv import load_dotenv
|
|
3
|
+
from typing import Optional, Dict
|
|
4
|
+
from .routes.base import BaseClient
|
|
5
|
+
from .routes.generation import GenerationClient
|
|
6
|
+
from .routes.templates import TemplatesClient
|
|
7
|
+
from .routes.api_keys import ApiKeysClient
|
|
8
|
+
from .routes.connections import ConnectionsClient
|
|
9
|
+
from .routes.projects import ProjectsClient
|
|
10
|
+
from .routes.users import UsersClient
|
|
11
|
+
from .routes.teams import TeamsClient, TeamMembersClient
|
|
12
|
+
from .routes.custom_types import (
|
|
13
|
+
CustomDataTypesClient,
|
|
14
|
+
EndpointFoldersClient,
|
|
15
|
+
EndpointsClient,
|
|
16
|
+
)
|
|
17
|
+
from .routes.folders_and_utils import (
|
|
18
|
+
TemplateFoldersClient,
|
|
19
|
+
ShortcutsClient,
|
|
20
|
+
FeedbackClient,
|
|
21
|
+
)
|
|
22
|
+
from .routes.export_and_validation import ExportClient, ValidationClient
|
|
23
|
+
from .routes.scenario_files import ScenarioFilesClient
|
|
24
|
+
from .routes.sets import SetsClient
|
|
25
|
+
|
|
26
|
+
load_dotenv()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DataMaker:
|
|
30
|
+
"""Main DataMaker client that provides access to all API functionality."""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
api_key: str = None,
|
|
35
|
+
default_headers: Dict[str, Optional[str]] = None,
|
|
36
|
+
base_url: Optional[str] = None,
|
|
37
|
+
verify: bool = True,
|
|
38
|
+
):
|
|
39
|
+
if default_headers is None:
|
|
40
|
+
default_headers = {"Content-Type": "application/json"}
|
|
41
|
+
|
|
42
|
+
# Initialize all route clients
|
|
43
|
+
self._generation = GenerationClient(api_key, default_headers, base_url, verify)
|
|
44
|
+
self._templates = TemplatesClient(api_key, default_headers, base_url, verify)
|
|
45
|
+
self._api_keys = ApiKeysClient(api_key, default_headers, base_url, verify)
|
|
46
|
+
self._connections = ConnectionsClient(
|
|
47
|
+
api_key, default_headers, base_url, verify
|
|
48
|
+
)
|
|
49
|
+
self._projects = ProjectsClient(api_key, default_headers, base_url, verify)
|
|
50
|
+
self._users = UsersClient(api_key, default_headers, base_url, verify)
|
|
51
|
+
self._teams = TeamsClient(api_key, default_headers, base_url, verify)
|
|
52
|
+
self._team_members = TeamMembersClient(
|
|
53
|
+
api_key, default_headers, base_url, verify
|
|
54
|
+
)
|
|
55
|
+
self._custom_data_types = CustomDataTypesClient(
|
|
56
|
+
api_key, default_headers, base_url, verify
|
|
57
|
+
)
|
|
58
|
+
self._endpoint_folders = EndpointFoldersClient(
|
|
59
|
+
api_key, default_headers, base_url, verify
|
|
60
|
+
)
|
|
61
|
+
self._endpoints = EndpointsClient(api_key, default_headers, base_url, verify)
|
|
62
|
+
self._template_folders = TemplateFoldersClient(
|
|
63
|
+
api_key, default_headers, base_url, verify
|
|
64
|
+
)
|
|
65
|
+
self._shortcuts = ShortcutsClient(api_key, default_headers, base_url, verify)
|
|
66
|
+
self._feedback = FeedbackClient(api_key, default_headers, base_url, verify)
|
|
67
|
+
self._export = ExportClient(api_key, default_headers, base_url, verify)
|
|
68
|
+
self._validation = ValidationClient(api_key, default_headers, base_url, verify)
|
|
69
|
+
self._scenario_files = ScenarioFilesClient(
|
|
70
|
+
api_key, default_headers, base_url, verify
|
|
71
|
+
)
|
|
72
|
+
self._sets = SetsClient(api_key, default_headers, base_url, verify)
|
|
73
|
+
|
|
74
|
+
# Maintain backward compatibility
|
|
75
|
+
self.api_key = self._generation.api_key
|
|
76
|
+
self.headers = self._generation.headers
|
|
77
|
+
self.base_url = self._generation.base_url
|
|
78
|
+
self.verify = verify
|
|
79
|
+
|
|
80
|
+
# =================== GENERATION METHODS ===================
|
|
81
|
+
def generate(self, template):
|
|
82
|
+
"""Generate data using a template."""
|
|
83
|
+
return self._generation.generate(template)
|
|
84
|
+
|
|
85
|
+
def generate_from_template_id(self, template_id: str, quantity: int = 10):
|
|
86
|
+
"""Generate data from a template ID with specified quantity."""
|
|
87
|
+
# Get the template
|
|
88
|
+
template = self._templates.get_template_by_id(template_id)
|
|
89
|
+
|
|
90
|
+
# Set the quantity
|
|
91
|
+
template["quantity"] = quantity
|
|
92
|
+
|
|
93
|
+
# Generate data using the template
|
|
94
|
+
return self.generate(template)
|
|
95
|
+
|
|
96
|
+
# =================== TEMPLATE METHODS ===================
|
|
97
|
+
def get_templates(self):
|
|
98
|
+
"""Fetch all templates from the API."""
|
|
99
|
+
return self._templates.get_templates()
|
|
100
|
+
|
|
101
|
+
def create_template(self, template_data: Dict, project_id: str, team_id: str):
|
|
102
|
+
"""Create a new template."""
|
|
103
|
+
return self._templates.create_template(template_data, project_id, team_id)
|
|
104
|
+
|
|
105
|
+
def get_template(self, template_id: str):
|
|
106
|
+
"""Get a specific template by ID."""
|
|
107
|
+
return self._templates.get_template(template_id)
|
|
108
|
+
|
|
109
|
+
def update_template(self, template_id: str, template_data: Dict):
|
|
110
|
+
"""Update a template."""
|
|
111
|
+
return self._templates.update_template(template_id, template_data)
|
|
112
|
+
|
|
113
|
+
def delete_template(self, template_id: str):
|
|
114
|
+
"""Delete a template."""
|
|
115
|
+
return self._templates.delete_template(template_id)
|
|
116
|
+
|
|
117
|
+
# =================== API KEY METHODS ===================
|
|
118
|
+
def get_api_keys(self):
|
|
119
|
+
"""Get all API keys."""
|
|
120
|
+
return self._api_keys.get_api_keys()
|
|
121
|
+
|
|
122
|
+
def create_api_key(
|
|
123
|
+
self,
|
|
124
|
+
key: str,
|
|
125
|
+
scope: str,
|
|
126
|
+
name: Optional[str] = None,
|
|
127
|
+
team_id: Optional[str] = None,
|
|
128
|
+
):
|
|
129
|
+
"""Create a new API key."""
|
|
130
|
+
return self._api_keys.create_api_key(key, scope, name, team_id)
|
|
131
|
+
|
|
132
|
+
def update_api_key(
|
|
133
|
+
self,
|
|
134
|
+
key_id: str,
|
|
135
|
+
key: str,
|
|
136
|
+
name: Optional[str] = None,
|
|
137
|
+
team_id: Optional[str] = None,
|
|
138
|
+
):
|
|
139
|
+
"""Update an API key."""
|
|
140
|
+
return self._api_keys.update_api_key(key_id, key, name, team_id)
|
|
141
|
+
|
|
142
|
+
def delete_api_key(self, key_id: str):
|
|
143
|
+
"""Delete an API key."""
|
|
144
|
+
return self._api_keys.delete_api_key(key_id)
|
|
145
|
+
|
|
146
|
+
# =================== CONNECTION METHODS ===================
|
|
147
|
+
def get_connections(self):
|
|
148
|
+
"""Get all connections."""
|
|
149
|
+
return self._connections.get_connections()
|
|
150
|
+
|
|
151
|
+
def create_connection(
|
|
152
|
+
self,
|
|
153
|
+
name: str,
|
|
154
|
+
connection_type: str,
|
|
155
|
+
connection_string: str,
|
|
156
|
+
created_by: str,
|
|
157
|
+
project_id: str,
|
|
158
|
+
team_id: str,
|
|
159
|
+
**kwargs,
|
|
160
|
+
):
|
|
161
|
+
"""Create a new database connection."""
|
|
162
|
+
return self._connections.create_connection(
|
|
163
|
+
name,
|
|
164
|
+
connection_type,
|
|
165
|
+
connection_string,
|
|
166
|
+
created_by,
|
|
167
|
+
project_id,
|
|
168
|
+
team_id,
|
|
169
|
+
**kwargs,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
def update_connection(
|
|
173
|
+
self,
|
|
174
|
+
connection_id: str,
|
|
175
|
+
name: str,
|
|
176
|
+
connection_type: str,
|
|
177
|
+
connection_string: str,
|
|
178
|
+
created_by: str,
|
|
179
|
+
project_id: str,
|
|
180
|
+
team_id: str,
|
|
181
|
+
**kwargs,
|
|
182
|
+
):
|
|
183
|
+
"""Update a database connection."""
|
|
184
|
+
return self._connections.update_connection(
|
|
185
|
+
connection_id,
|
|
186
|
+
name,
|
|
187
|
+
connection_type,
|
|
188
|
+
connection_string,
|
|
189
|
+
created_by,
|
|
190
|
+
project_id,
|
|
191
|
+
team_id,
|
|
192
|
+
**kwargs,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
def delete_connection(self, connection_id: str):
|
|
196
|
+
"""Delete a database connection."""
|
|
197
|
+
return self._connections.delete_connection(connection_id)
|
|
198
|
+
|
|
199
|
+
def test_connection(self, connection_data: Dict):
|
|
200
|
+
"""Test a database connection."""
|
|
201
|
+
return self._connections.test_connection(connection_data)
|
|
202
|
+
|
|
203
|
+
def get_tables(self):
|
|
204
|
+
"""Get all tables from connections."""
|
|
205
|
+
return self._connections.get_tables()
|
|
206
|
+
|
|
207
|
+
# =================== PROJECT METHODS ===================
|
|
208
|
+
def get_projects(self):
|
|
209
|
+
"""Get all projects."""
|
|
210
|
+
return self._projects.get_projects()
|
|
211
|
+
|
|
212
|
+
def create_project(self, project_data: Dict, team_id: str):
|
|
213
|
+
"""Create a new project."""
|
|
214
|
+
return self._projects.create_project(project_data, team_id)
|
|
215
|
+
|
|
216
|
+
def get_project(self, project_id: str):
|
|
217
|
+
"""Get a specific project by ID."""
|
|
218
|
+
return self._projects.get_project(project_id)
|
|
219
|
+
|
|
220
|
+
def update_project(self, project_id: str, project_data: Dict):
|
|
221
|
+
"""Update a project."""
|
|
222
|
+
return self._projects.update_project(project_id, project_data)
|
|
223
|
+
|
|
224
|
+
def delete_project(self, project_id: str):
|
|
225
|
+
"""Delete a project."""
|
|
226
|
+
return self._projects.delete_project(project_id)
|
|
227
|
+
|
|
228
|
+
# =================== USER METHODS ===================
|
|
229
|
+
def get_users(self):
|
|
230
|
+
"""Get all users."""
|
|
231
|
+
return self._users.get_users()
|
|
232
|
+
|
|
233
|
+
def create_user(self, user_data: Dict, user_id: str):
|
|
234
|
+
"""Create a new user."""
|
|
235
|
+
return self._users.create_user(user_data, user_id)
|
|
236
|
+
|
|
237
|
+
def get_current_user(self):
|
|
238
|
+
"""Get current user information."""
|
|
239
|
+
return self._users.get_current_user()
|
|
240
|
+
|
|
241
|
+
def provision_user(self, user_data: Dict):
|
|
242
|
+
"""Provision a new user."""
|
|
243
|
+
return self._users.provision_user(user_data)
|
|
244
|
+
|
|
245
|
+
def update_user(self, user_id: str, user_data: Dict):
|
|
246
|
+
"""Update a user."""
|
|
247
|
+
return self._users.update_user(user_id, user_data)
|
|
248
|
+
|
|
249
|
+
def patch_user(self, user_id: str, user_data: Dict):
|
|
250
|
+
"""Partially update a user."""
|
|
251
|
+
return self._users.patch_user(user_id, user_data)
|
|
252
|
+
|
|
253
|
+
def delete_user(self, user_id: str):
|
|
254
|
+
"""Delete a user."""
|
|
255
|
+
return self._users.delete_user(user_id)
|
|
256
|
+
|
|
257
|
+
# =================== TEAM METHODS ===================
|
|
258
|
+
def get_teams(self):
|
|
259
|
+
"""Get all teams."""
|
|
260
|
+
return self._teams.get_teams()
|
|
261
|
+
|
|
262
|
+
def create_team(self, team_data: Dict):
|
|
263
|
+
"""Create a new team."""
|
|
264
|
+
return self._teams.create_team(team_data)
|
|
265
|
+
|
|
266
|
+
def update_team(self, team_id: str, team_data: Dict):
|
|
267
|
+
"""Update a team."""
|
|
268
|
+
return self._teams.update_team(team_id, team_data)
|
|
269
|
+
|
|
270
|
+
def delete_team(self, team_id: str):
|
|
271
|
+
"""Delete a team."""
|
|
272
|
+
return self._teams.delete_team(team_id)
|
|
273
|
+
|
|
274
|
+
def setup_team(self, team_data: Dict):
|
|
275
|
+
"""Setup a new team."""
|
|
276
|
+
return self._teams.setup_team(team_data)
|
|
277
|
+
|
|
278
|
+
# =================== TEAM MEMBER METHODS ===================
|
|
279
|
+
def get_team_members(self):
|
|
280
|
+
"""Get all team members."""
|
|
281
|
+
return self._team_members.get_team_members()
|
|
282
|
+
|
|
283
|
+
def add_team_member(self, member_data: Dict):
|
|
284
|
+
"""Add a new team member."""
|
|
285
|
+
return self._team_members.add_team_member(member_data)
|
|
286
|
+
|
|
287
|
+
def invite_team_member(self, invite_data: Dict):
|
|
288
|
+
"""Invite a new team member."""
|
|
289
|
+
return self._team_members.invite_team_member(invite_data)
|
|
290
|
+
|
|
291
|
+
def update_team_member(self, member_id: str, member_data: Dict):
|
|
292
|
+
"""Update a team member."""
|
|
293
|
+
return self._team_members.update_team_member(member_id, member_data)
|
|
294
|
+
|
|
295
|
+
def remove_team_member(self, member_id: str):
|
|
296
|
+
"""Remove a team member."""
|
|
297
|
+
return self._team_members.remove_team_member(member_id)
|
|
298
|
+
|
|
299
|
+
# =================== CUSTOM DATA TYPE METHODS ===================
|
|
300
|
+
def get_custom_data_types(self, project_id: str):
|
|
301
|
+
"""Get all custom data types for a specific project."""
|
|
302
|
+
return self._custom_data_types.get_custom_data_types(project_id)
|
|
303
|
+
|
|
304
|
+
def create_custom_data_type(self, data_type_data: Dict):
|
|
305
|
+
"""Create a new custom data type."""
|
|
306
|
+
return self._custom_data_types.create_custom_data_type(data_type_data)
|
|
307
|
+
|
|
308
|
+
def update_custom_data_type(self, data_type_id: str, data_type_data: Dict):
|
|
309
|
+
"""Update a custom data type."""
|
|
310
|
+
return self._custom_data_types.update_custom_data_type(
|
|
311
|
+
data_type_id, data_type_data
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
def delete_custom_data_type(self, data_type_id: str):
|
|
315
|
+
"""Delete a custom data type."""
|
|
316
|
+
return self._custom_data_types.delete_custom_data_type(data_type_id)
|
|
317
|
+
|
|
318
|
+
# =================== ENDPOINT FOLDER METHODS ===================
|
|
319
|
+
def get_endpoint_folders(self):
|
|
320
|
+
"""Get all endpoint folders."""
|
|
321
|
+
return self._endpoint_folders.get_endpoint_folders()
|
|
322
|
+
|
|
323
|
+
def create_endpoint_folder(self, folder_data: Dict):
|
|
324
|
+
"""Create a new endpoint folder."""
|
|
325
|
+
return self._endpoint_folders.create_endpoint_folder(folder_data)
|
|
326
|
+
|
|
327
|
+
def update_endpoint_folder(self, folder_id: str, folder_data: Dict):
|
|
328
|
+
"""Update an endpoint folder."""
|
|
329
|
+
return self._endpoint_folders.update_endpoint_folder(folder_id, folder_data)
|
|
330
|
+
|
|
331
|
+
def delete_endpoint_folder(self, folder_id: str):
|
|
332
|
+
"""Delete an endpoint folder."""
|
|
333
|
+
return self._endpoint_folders.delete_endpoint_folder(folder_id)
|
|
334
|
+
|
|
335
|
+
# =================== ENDPOINT METHODS ===================
|
|
336
|
+
def get_endpoints(self):
|
|
337
|
+
"""Get all endpoints."""
|
|
338
|
+
return self._endpoints.get_endpoints()
|
|
339
|
+
|
|
340
|
+
def create_endpoint(self, endpoint_data: Dict):
|
|
341
|
+
"""Create a new endpoint."""
|
|
342
|
+
return self._endpoints.create_endpoint(endpoint_data)
|
|
343
|
+
|
|
344
|
+
def get_endpoint(self, endpoint_id: str):
|
|
345
|
+
"""Get a specific endpoint by ID."""
|
|
346
|
+
return self._endpoints.get_endpoint(endpoint_id)
|
|
347
|
+
|
|
348
|
+
def update_endpoint(self, endpoint_id: str, endpoint_data: Dict):
|
|
349
|
+
"""Update an endpoint."""
|
|
350
|
+
return self._endpoints.update_endpoint(endpoint_id, endpoint_data)
|
|
351
|
+
|
|
352
|
+
def delete_endpoint(self, endpoint_id: str):
|
|
353
|
+
"""Delete an endpoint."""
|
|
354
|
+
return self._endpoints.delete_endpoint(endpoint_id)
|
|
355
|
+
|
|
356
|
+
def resolve_endpoint_auth(self, endpoint_id: str):
|
|
357
|
+
"""Resolve an endpoint's real, decrypted credentials (Authorization
|
|
358
|
+
header + Basic username/password). See EndpointsClient for details."""
|
|
359
|
+
return self._endpoints.resolve_endpoint_auth(endpoint_id)
|
|
360
|
+
|
|
361
|
+
# =================== TEMPLATE FOLDER METHODS ===================
|
|
362
|
+
def get_template_folders(self):
|
|
363
|
+
"""Get all template folders."""
|
|
364
|
+
return self._template_folders.get_template_folders()
|
|
365
|
+
|
|
366
|
+
def create_template_folder(self, folder_data: Dict):
|
|
367
|
+
"""Create a new template folder."""
|
|
368
|
+
return self._template_folders.create_template_folder(folder_data)
|
|
369
|
+
|
|
370
|
+
def update_template_folder(self, folder_id: str, folder_data: Dict):
|
|
371
|
+
"""Update a template folder."""
|
|
372
|
+
return self._template_folders.update_template_folder(folder_id, folder_data)
|
|
373
|
+
|
|
374
|
+
def delete_template_folder(self, folder_id: str):
|
|
375
|
+
"""Delete a template folder."""
|
|
376
|
+
return self._template_folders.delete_template_folder(folder_id)
|
|
377
|
+
|
|
378
|
+
# =================== SHORTCUT METHODS ===================
|
|
379
|
+
def get_shortcuts(self):
|
|
380
|
+
"""Get all shortcuts."""
|
|
381
|
+
return self._shortcuts.get_shortcuts()
|
|
382
|
+
|
|
383
|
+
def create_shortcut(self, shortcut_data: Dict):
|
|
384
|
+
"""Create a new shortcut."""
|
|
385
|
+
return self._shortcuts.create_shortcut(shortcut_data)
|
|
386
|
+
|
|
387
|
+
def update_shortcut(self, shortcut_id: str, shortcut_data: Dict):
|
|
388
|
+
"""Update a shortcut."""
|
|
389
|
+
return self._shortcuts.update_shortcut(shortcut_id, shortcut_data)
|
|
390
|
+
|
|
391
|
+
def delete_shortcut(self, shortcut_id: str):
|
|
392
|
+
"""Delete a shortcut."""
|
|
393
|
+
return self._shortcuts.delete_shortcut(shortcut_id)
|
|
394
|
+
|
|
395
|
+
# =================== FEEDBACK METHODS ===================
|
|
396
|
+
def get_feedback(self):
|
|
397
|
+
"""Get all feedback."""
|
|
398
|
+
return self._feedback.get_feedback()
|
|
399
|
+
|
|
400
|
+
def submit_feedback(self, feedback_data: Dict):
|
|
401
|
+
"""Submit new feedback."""
|
|
402
|
+
return self._feedback.submit_feedback(feedback_data)
|
|
403
|
+
|
|
404
|
+
def update_feedback(self, feedback_id: str, feedback_data: Dict):
|
|
405
|
+
"""Update feedback."""
|
|
406
|
+
return self._feedback.update_feedback(feedback_id, feedback_data)
|
|
407
|
+
|
|
408
|
+
def delete_feedback(self, feedback_id: str):
|
|
409
|
+
"""Delete feedback."""
|
|
410
|
+
return self._feedback.delete_feedback(feedback_id)
|
|
411
|
+
|
|
412
|
+
# =================== EXPORT METHODS ===================
|
|
413
|
+
def export_to_rest(self, export_data: Dict):
|
|
414
|
+
"""Export data to REST API."""
|
|
415
|
+
return self._export.export_to_rest(export_data)
|
|
416
|
+
|
|
417
|
+
def export_to_database(self, export_data: Dict):
|
|
418
|
+
"""Export data to database."""
|
|
419
|
+
return self._export.export_to_database(export_data)
|
|
420
|
+
|
|
421
|
+
# =================== VALIDATION METHODS ===================
|
|
422
|
+
def validate_api_key(self):
|
|
423
|
+
"""Test API key authentication."""
|
|
424
|
+
return self._validation.validate_api_key()
|
|
425
|
+
|
|
426
|
+
# =================== SCENARIO FILE METHODS ===================
|
|
427
|
+
def get_scenario_files(self, scenario_id: Optional[str] = None):
|
|
428
|
+
"""Get all files for a scenario or all accessible files."""
|
|
429
|
+
return self._scenario_files.get_scenario_files(scenario_id)
|
|
430
|
+
|
|
431
|
+
def get_scenario_file(self, file_id: str, scenario_id: Optional[str] = None):
|
|
432
|
+
"""Get metadata for a specific file by ID.
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
file_id: The unique identifier of the file.
|
|
436
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
File metadata dictionary with refreshed presigned URL.
|
|
440
|
+
"""
|
|
441
|
+
return self._scenario_files.get_scenario_file(file_id, scenario_id)
|
|
442
|
+
|
|
443
|
+
def download_scenario_file(self, file_id: str, scenario_id: Optional[str] = None):
|
|
444
|
+
"""Download a file's content by ID.
|
|
445
|
+
|
|
446
|
+
Args:
|
|
447
|
+
file_id: The unique identifier of the file.
|
|
448
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
The file content as bytes.
|
|
452
|
+
"""
|
|
453
|
+
return self._scenario_files.download_scenario_file(file_id, scenario_id)
|
|
454
|
+
|
|
455
|
+
def download_scenario_file_to_path(
|
|
456
|
+
self, file_id: str, destination_path: str, scenario_id: Optional[str] = None
|
|
457
|
+
):
|
|
458
|
+
"""Download a file and save it to a local path.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
file_id: The unique identifier of the file.
|
|
462
|
+
destination_path: Local file path to save the downloaded content.
|
|
463
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
464
|
+
|
|
465
|
+
Returns:
|
|
466
|
+
The destination path where the file was saved.
|
|
467
|
+
"""
|
|
468
|
+
return self._scenario_files.download_scenario_file_to_path(
|
|
469
|
+
file_id, destination_path, scenario_id
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
def create_scenario_file(
|
|
473
|
+
self,
|
|
474
|
+
name: str,
|
|
475
|
+
content,
|
|
476
|
+
scenario_id: Optional[str] = None,
|
|
477
|
+
team_id: Optional[str] = None,
|
|
478
|
+
project_id: Optional[str] = None,
|
|
479
|
+
description: Optional[str] = None,
|
|
480
|
+
mime_type: Optional[str] = None,
|
|
481
|
+
folder_id: Optional[str] = None,
|
|
482
|
+
):
|
|
483
|
+
"""Create/upload a new file in a scenario.
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
name: The filename (e.g., 'data.json', 'config.yaml').
|
|
487
|
+
content: The file content - can be a string, bytes, or file-like object.
|
|
488
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
489
|
+
team_id: Optional team ID. Falls back to DATAMAKER_TEAM_ID env var.
|
|
490
|
+
project_id: Optional project ID. Falls back to DATAMAKER_PROJECT_ID env var.
|
|
491
|
+
description: Optional description of the file.
|
|
492
|
+
mime_type: Optional MIME type. If not provided, will be guessed from filename.
|
|
493
|
+
folder_id: Optional folder ID to place the file in.
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
The created file metadata dictionary.
|
|
497
|
+
"""
|
|
498
|
+
return self._scenario_files.create_scenario_file(
|
|
499
|
+
name=name,
|
|
500
|
+
content=content,
|
|
501
|
+
scenario_id=scenario_id,
|
|
502
|
+
team_id=team_id,
|
|
503
|
+
project_id=project_id,
|
|
504
|
+
description=description,
|
|
505
|
+
mime_type=mime_type,
|
|
506
|
+
folder_id=folder_id,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
def upload_scenario_file_from_path(
|
|
510
|
+
self,
|
|
511
|
+
file_path: str,
|
|
512
|
+
scenario_id: Optional[str] = None,
|
|
513
|
+
team_id: Optional[str] = None,
|
|
514
|
+
project_id: Optional[str] = None,
|
|
515
|
+
name: Optional[str] = None,
|
|
516
|
+
description: Optional[str] = None,
|
|
517
|
+
folder_id: Optional[str] = None,
|
|
518
|
+
folder: str = "uploads",
|
|
519
|
+
):
|
|
520
|
+
"""Upload a file from a local path to a scenario.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
file_path: Path to the local file to upload.
|
|
524
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
525
|
+
team_id: Optional team ID (deprecated, not used for multipart upload).
|
|
526
|
+
project_id: Optional project ID (deprecated, not used for multipart upload).
|
|
527
|
+
name: Optional filename. If not provided, uses the original filename.
|
|
528
|
+
description: Optional description (deprecated, not used for multipart upload).
|
|
529
|
+
folder_id: Optional folder ID (deprecated, not used for multipart upload).
|
|
530
|
+
folder: Folder to upload to ("uploads" or "outputs", default: "uploads").
|
|
531
|
+
|
|
532
|
+
Returns:
|
|
533
|
+
The created file metadata dictionary.
|
|
534
|
+
"""
|
|
535
|
+
return self._scenario_files.upload_scenario_file_from_path(
|
|
536
|
+
file_path=file_path,
|
|
537
|
+
scenario_id=scenario_id,
|
|
538
|
+
team_id=team_id,
|
|
539
|
+
project_id=project_id,
|
|
540
|
+
name=name,
|
|
541
|
+
description=description,
|
|
542
|
+
folder_id=folder_id,
|
|
543
|
+
folder=folder,
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
def delete_scenario_file(self, file_id: str, scenario_id: Optional[str] = None):
|
|
547
|
+
"""Delete a file by ID.
|
|
548
|
+
|
|
549
|
+
Args:
|
|
550
|
+
file_id: The unique identifier of the file to delete.
|
|
551
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
552
|
+
|
|
553
|
+
Returns:
|
|
554
|
+
Confirmation response.
|
|
555
|
+
"""
|
|
556
|
+
return self._scenario_files.delete_scenario_file(file_id, scenario_id)
|
|
557
|
+
|
|
558
|
+
def read_file_by_path(
|
|
559
|
+
self,
|
|
560
|
+
file_path: str,
|
|
561
|
+
storage_base_url: Optional[str] = None,
|
|
562
|
+
):
|
|
563
|
+
"""Read a file directly from storage by its path.
|
|
564
|
+
|
|
565
|
+
This method allows you to read files from the storage bucket using the
|
|
566
|
+
file path copied from the workspace files modal. It's useful for accessing
|
|
567
|
+
files uploaded to scenarios from within Python scripts.
|
|
568
|
+
|
|
569
|
+
Args:
|
|
570
|
+
file_path: The file path (key) in storage. This is typically copied from
|
|
571
|
+
the workspace files modal using the "Copy path" button.
|
|
572
|
+
Example: "scenarios/scenario-id/uploads/filename.txt"
|
|
573
|
+
storage_base_url: Optional base URL for the storage bucket. If not provided,
|
|
574
|
+
uses the DATAMAKER_STORAGE_URL environment variable or a default.
|
|
575
|
+
|
|
576
|
+
Returns:
|
|
577
|
+
The file content as bytes.
|
|
578
|
+
|
|
579
|
+
Example:
|
|
580
|
+
>>> dm = DataMaker(api_key="your-key")
|
|
581
|
+
>>> # Copy path from UI: "scenarios/abc123/uploads/data.json"
|
|
582
|
+
>>> content = dm.read_file_by_path("scenarios/abc123/uploads/data.json")
|
|
583
|
+
>>> data = json.loads(content.decode('utf-8'))
|
|
584
|
+
"""
|
|
585
|
+
return self._scenario_files.read_file_by_path(file_path, storage_base_url)
|
|
586
|
+
|
|
587
|
+
def read_file_by_path_as_text(
|
|
588
|
+
self,
|
|
589
|
+
file_path: str,
|
|
590
|
+
storage_base_url: Optional[str] = None,
|
|
591
|
+
encoding: str = "utf-8",
|
|
592
|
+
):
|
|
593
|
+
"""Read a file directly from storage by its path and return as text.
|
|
594
|
+
|
|
595
|
+
Convenience method that reads a file and decodes it as text.
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
file_path: The file path (key) in storage.
|
|
599
|
+
storage_base_url: Optional base URL for the storage bucket.
|
|
600
|
+
encoding: Text encoding to use (default: 'utf-8').
|
|
601
|
+
|
|
602
|
+
Returns:
|
|
603
|
+
The file content as a string.
|
|
604
|
+
|
|
605
|
+
Example:
|
|
606
|
+
>>> dm = DataMaker(api_key="your-key")
|
|
607
|
+
>>> content = dm.read_file_by_path_as_text("scenarios/abc123/uploads/data.txt")
|
|
608
|
+
>>> print(content)
|
|
609
|
+
"""
|
|
610
|
+
return self._scenario_files.read_file_by_path_as_text(
|
|
611
|
+
file_path, storage_base_url, encoding
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
def save_file(
|
|
615
|
+
self,
|
|
616
|
+
file_path: str,
|
|
617
|
+
scenario_id: Optional[str] = None,
|
|
618
|
+
team_id: Optional[str] = None,
|
|
619
|
+
project_id: Optional[str] = None,
|
|
620
|
+
name: Optional[str] = None,
|
|
621
|
+
description: Optional[str] = None,
|
|
622
|
+
folder_id: Optional[str] = None,
|
|
623
|
+
folder: str = "uploads",
|
|
624
|
+
) -> Dict:
|
|
625
|
+
"""Convenience method to save a local file to workspace storage.
|
|
626
|
+
|
|
627
|
+
This method simplifies uploading files by automatically pulling required
|
|
628
|
+
context (scenario_id) from environment variables if not provided.
|
|
629
|
+
This is especially useful in DataMaker sandbox environments where these
|
|
630
|
+
variables are pre-configured.
|
|
631
|
+
|
|
632
|
+
Args:
|
|
633
|
+
file_path: Path to the local file to save to workspace.
|
|
634
|
+
scenario_id: Optional scenario ID. Falls back to DATAMAKER_SCENARIO_ID env var.
|
|
635
|
+
team_id: Optional team ID (deprecated, not used).
|
|
636
|
+
project_id: Optional project ID (deprecated, not used).
|
|
637
|
+
name: Optional filename. If not provided, uses the original filename.
|
|
638
|
+
description: Optional description (deprecated, not used).
|
|
639
|
+
folder_id: Optional folder ID (deprecated, not used).
|
|
640
|
+
folder: Folder to upload to ("uploads" or "outputs", default: "uploads").
|
|
641
|
+
|
|
642
|
+
Returns:
|
|
643
|
+
The created file metadata dictionary.
|
|
644
|
+
|
|
645
|
+
Raises:
|
|
646
|
+
DataMakerError: If scenario_id is not provided and not available in environment.
|
|
647
|
+
|
|
648
|
+
Example:
|
|
649
|
+
>>> # In a DataMaker sandbox environment:
|
|
650
|
+
>>> dm = DataMaker()
|
|
651
|
+
>>> result = dm.save_file("test_file.txt")
|
|
652
|
+
>>> print(f"File saved: {result['name']}")
|
|
653
|
+
|
|
654
|
+
>>> # Or specify IDs explicitly:
|
|
655
|
+
>>> result = dm.save_file(
|
|
656
|
+
... "test_file.txt",
|
|
657
|
+
... scenario_id="scenario-123"
|
|
658
|
+
... )
|
|
659
|
+
"""
|
|
660
|
+
return self._scenario_files.save_file(
|
|
661
|
+
file_path=file_path,
|
|
662
|
+
scenario_id=scenario_id,
|
|
663
|
+
team_id=team_id,
|
|
664
|
+
project_id=project_id,
|
|
665
|
+
name=name,
|
|
666
|
+
description=description,
|
|
667
|
+
folder_id=folder_id,
|
|
668
|
+
folder=folder,
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
# =================== SET METHODS ===================
|
|
672
|
+
def get_sets(self, project_id: Optional[str] = None):
|
|
673
|
+
"""Get all saved sets for the caller's project/team scope.
|
|
674
|
+
|
|
675
|
+
Args:
|
|
676
|
+
project_id: Optional project ID to scope the listing to. Falls back
|
|
677
|
+
to the DATAMAKER_PROJECT_ID env var.
|
|
678
|
+
|
|
679
|
+
Returns:
|
|
680
|
+
A list of set metadata dictionaries.
|
|
681
|
+
"""
|
|
682
|
+
return self._sets.get_sets(project_id)
|
|
683
|
+
|
|
684
|
+
def get_set(self, set_id: str):
|
|
685
|
+
"""Get a single saved set by ID, including its full rows payload.
|
|
686
|
+
|
|
687
|
+
Args:
|
|
688
|
+
set_id: The unique identifier of the set.
|
|
689
|
+
|
|
690
|
+
Returns:
|
|
691
|
+
The set dictionary (including its saved rows in ``data``).
|
|
692
|
+
"""
|
|
693
|
+
return self._sets.get_set(set_id)
|
|
694
|
+
|
|
695
|
+
def create_set(
|
|
696
|
+
self,
|
|
697
|
+
name: str,
|
|
698
|
+
data=None,
|
|
699
|
+
description: Optional[str] = None,
|
|
700
|
+
row_count: Optional[int] = None,
|
|
701
|
+
project_id: Optional[str] = None,
|
|
702
|
+
):
|
|
703
|
+
"""Create (save) a new set.
|
|
704
|
+
|
|
705
|
+
Args:
|
|
706
|
+
name: A name for the saved set.
|
|
707
|
+
data: The rows payload to save - typically a list of row dicts.
|
|
708
|
+
description: Optional short description of what the set captures.
|
|
709
|
+
row_count: Optional explicit row count (derived from data otherwise).
|
|
710
|
+
project_id: Optional project ID. Falls back to DATAMAKER_PROJECT_ID.
|
|
711
|
+
|
|
712
|
+
Returns:
|
|
713
|
+
The created set dictionary.
|
|
714
|
+
"""
|
|
715
|
+
return self._sets.create_set(
|
|
716
|
+
name=name,
|
|
717
|
+
data=data,
|
|
718
|
+
description=description,
|
|
719
|
+
row_count=row_count,
|
|
720
|
+
project_id=project_id,
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
def update_set(
|
|
724
|
+
self,
|
|
725
|
+
set_id: str,
|
|
726
|
+
name: Optional[str] = None,
|
|
727
|
+
description: Optional[str] = None,
|
|
728
|
+
data=None,
|
|
729
|
+
row_count: Optional[int] = None,
|
|
730
|
+
):
|
|
731
|
+
"""Update a saved set.
|
|
732
|
+
|
|
733
|
+
Args:
|
|
734
|
+
set_id: The unique identifier of the set to update.
|
|
735
|
+
name: New name for the set.
|
|
736
|
+
description: New description.
|
|
737
|
+
data: Replacement rows payload.
|
|
738
|
+
row_count: Explicit row count override.
|
|
739
|
+
|
|
740
|
+
Returns:
|
|
741
|
+
The updated set dictionary.
|
|
742
|
+
"""
|
|
743
|
+
return self._sets.update_set(
|
|
744
|
+
set_id,
|
|
745
|
+
name=name,
|
|
746
|
+
description=description,
|
|
747
|
+
data=data,
|
|
748
|
+
row_count=row_count,
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
def delete_set(self, set_id: str):
|
|
752
|
+
"""Delete a saved set by ID.
|
|
753
|
+
|
|
754
|
+
Args:
|
|
755
|
+
set_id: The unique identifier of the set to delete.
|
|
756
|
+
|
|
757
|
+
Returns:
|
|
758
|
+
Confirmation response.
|
|
759
|
+
"""
|
|
760
|
+
return self._sets.delete_set(set_id)
|
|
761
|
+
|
|
762
|
+
def save_set(
|
|
763
|
+
self,
|
|
764
|
+
name: str,
|
|
765
|
+
data,
|
|
766
|
+
description: Optional[str] = None,
|
|
767
|
+
project_id: Optional[str] = None,
|
|
768
|
+
):
|
|
769
|
+
"""Convenience method to save rows as a named set.
|
|
770
|
+
|
|
771
|
+
Project context is pulled from DATAMAKER_PROJECT_ID when not provided,
|
|
772
|
+
which is convenient inside DataMaker sandbox environments.
|
|
773
|
+
|
|
774
|
+
Args:
|
|
775
|
+
name: A name for the saved set.
|
|
776
|
+
data: The rows to save - typically a list of row dicts.
|
|
777
|
+
description: Optional short description of what the set captures.
|
|
778
|
+
project_id: Optional project ID. Falls back to DATAMAKER_PROJECT_ID.
|
|
779
|
+
|
|
780
|
+
Returns:
|
|
781
|
+
The created set dictionary.
|
|
782
|
+
|
|
783
|
+
Example:
|
|
784
|
+
>>> dm = DataMaker()
|
|
785
|
+
>>> rows = dm.generate(template)
|
|
786
|
+
>>> result = dm.save_set("nightly-regression", rows)
|
|
787
|
+
>>> print(f"Saved set: {result['name']} ({result['rowCount']} rows)")
|
|
788
|
+
"""
|
|
789
|
+
return self._sets.save_set(
|
|
790
|
+
name=name,
|
|
791
|
+
data=data,
|
|
792
|
+
description=description,
|
|
793
|
+
project_id=project_id,
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
# =================== PROPERTY ACCESS TO CLIENTS ===================
|
|
797
|
+
# For advanced users who want direct access to specific clients
|
|
798
|
+
@property
|
|
799
|
+
def generation(self):
|
|
800
|
+
"""Access to generation client."""
|
|
801
|
+
return self._generation
|
|
802
|
+
|
|
803
|
+
@property
|
|
804
|
+
def templates(self):
|
|
805
|
+
"""Access to templates client."""
|
|
806
|
+
return self._templates
|
|
807
|
+
|
|
808
|
+
@property
|
|
809
|
+
def api_keys(self):
|
|
810
|
+
"""Access to API keys client."""
|
|
811
|
+
return self._api_keys
|
|
812
|
+
|
|
813
|
+
@property
|
|
814
|
+
def connections(self):
|
|
815
|
+
"""Access to connections client."""
|
|
816
|
+
return self._connections
|
|
817
|
+
|
|
818
|
+
@property
|
|
819
|
+
def projects(self):
|
|
820
|
+
"""Access to projects client."""
|
|
821
|
+
return self._projects
|
|
822
|
+
|
|
823
|
+
@property
|
|
824
|
+
def users(self):
|
|
825
|
+
"""Access to users client."""
|
|
826
|
+
return self._users
|
|
827
|
+
|
|
828
|
+
@property
|
|
829
|
+
def teams(self):
|
|
830
|
+
"""Access to teams client."""
|
|
831
|
+
return self._teams
|
|
832
|
+
|
|
833
|
+
@property
|
|
834
|
+
def team_members(self):
|
|
835
|
+
"""Access to team members client."""
|
|
836
|
+
return self._team_members
|
|
837
|
+
|
|
838
|
+
@property
|
|
839
|
+
def custom_data_types(self):
|
|
840
|
+
"""Access to custom data types client."""
|
|
841
|
+
return self._custom_data_types
|
|
842
|
+
|
|
843
|
+
@property
|
|
844
|
+
def endpoint_folders(self):
|
|
845
|
+
"""Access to endpoint folders client."""
|
|
846
|
+
return self._endpoint_folders
|
|
847
|
+
|
|
848
|
+
@property
|
|
849
|
+
def endpoints(self):
|
|
850
|
+
"""Access to endpoints client."""
|
|
851
|
+
return self._endpoints
|
|
852
|
+
|
|
853
|
+
@property
|
|
854
|
+
def template_folders(self):
|
|
855
|
+
"""Access to template folders client."""
|
|
856
|
+
return self._template_folders
|
|
857
|
+
|
|
858
|
+
@property
|
|
859
|
+
def shortcuts(self):
|
|
860
|
+
"""Access to shortcuts client."""
|
|
861
|
+
return self._shortcuts
|
|
862
|
+
|
|
863
|
+
@property
|
|
864
|
+
def feedback(self):
|
|
865
|
+
"""Access to feedback client."""
|
|
866
|
+
return self._feedback
|
|
867
|
+
|
|
868
|
+
@property
|
|
869
|
+
def export(self):
|
|
870
|
+
"""Access to export client."""
|
|
871
|
+
return self._export
|
|
872
|
+
|
|
873
|
+
@property
|
|
874
|
+
def validation(self):
|
|
875
|
+
"""Access to validation client."""
|
|
876
|
+
return self._validation
|
|
877
|
+
|
|
878
|
+
@property
|
|
879
|
+
def scenario_files(self):
|
|
880
|
+
"""Access to scenario files client."""
|
|
881
|
+
return self._scenario_files
|
|
882
|
+
|
|
883
|
+
@property
|
|
884
|
+
def sets(self):
|
|
885
|
+
"""Access to sets client."""
|
|
886
|
+
return self._sets
|