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
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Routes package for datamaker API endpoints."""
|
|
2
|
+
|
|
3
|
+
from .base import BaseClient
|
|
4
|
+
from .generation import GenerationClient
|
|
5
|
+
from .templates import TemplatesClient
|
|
6
|
+
from .api_keys import ApiKeysClient
|
|
7
|
+
from .connections import ConnectionsClient
|
|
8
|
+
from .projects import ProjectsClient
|
|
9
|
+
from .users import UsersClient
|
|
10
|
+
from .teams import TeamsClient, TeamMembersClient
|
|
11
|
+
from .custom_types import CustomDataTypesClient, EndpointFoldersClient, EndpointsClient
|
|
12
|
+
from .folders_and_utils import TemplateFoldersClient, ShortcutsClient, FeedbackClient
|
|
13
|
+
from .export_and_validation import ExportClient, ValidationClient
|
|
14
|
+
from .scenario_files import ScenarioFilesClient
|
|
15
|
+
from .sets import SetsClient
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"BaseClient",
|
|
19
|
+
"GenerationClient",
|
|
20
|
+
"TemplatesClient",
|
|
21
|
+
"ApiKeysClient",
|
|
22
|
+
"ConnectionsClient",
|
|
23
|
+
"ProjectsClient",
|
|
24
|
+
"UsersClient",
|
|
25
|
+
"TeamsClient",
|
|
26
|
+
"TeamMembersClient",
|
|
27
|
+
"CustomDataTypesClient",
|
|
28
|
+
"EndpointFoldersClient",
|
|
29
|
+
"EndpointsClient",
|
|
30
|
+
"TemplateFoldersClient",
|
|
31
|
+
"ShortcutsClient",
|
|
32
|
+
"FeedbackClient",
|
|
33
|
+
"ExportClient",
|
|
34
|
+
"ValidationClient",
|
|
35
|
+
"ScenarioFilesClient",
|
|
36
|
+
"SetsClient",
|
|
37
|
+
]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
from typing import Optional, Dict, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ApiKeysClient(BaseClient):
|
|
6
|
+
"""Client for API key management operations."""
|
|
7
|
+
|
|
8
|
+
def get_api_keys(self) -> List[Dict]:
|
|
9
|
+
"""Get all API keys."""
|
|
10
|
+
response = self._make_request("GET", "/apiKeys")
|
|
11
|
+
return response.json()
|
|
12
|
+
|
|
13
|
+
def create_api_key(
|
|
14
|
+
self,
|
|
15
|
+
key: str,
|
|
16
|
+
scope: str,
|
|
17
|
+
name: Optional[str] = None,
|
|
18
|
+
team_id: Optional[str] = None,
|
|
19
|
+
) -> Dict:
|
|
20
|
+
"""Create a new API key."""
|
|
21
|
+
data = {"key": key, "scope": scope}
|
|
22
|
+
if name:
|
|
23
|
+
data["name"] = name
|
|
24
|
+
if team_id:
|
|
25
|
+
data["teamId"] = team_id
|
|
26
|
+
|
|
27
|
+
response = self._make_request("POST", "/apiKeys", json=data)
|
|
28
|
+
return response.json()
|
|
29
|
+
|
|
30
|
+
def update_api_key(
|
|
31
|
+
self,
|
|
32
|
+
key_id: str,
|
|
33
|
+
key: str,
|
|
34
|
+
name: Optional[str] = None,
|
|
35
|
+
team_id: Optional[str] = None,
|
|
36
|
+
) -> Dict:
|
|
37
|
+
"""Update an API key."""
|
|
38
|
+
data = {"key": key}
|
|
39
|
+
if name:
|
|
40
|
+
data["name"] = name
|
|
41
|
+
if team_id:
|
|
42
|
+
data["teamId"] = team_id
|
|
43
|
+
|
|
44
|
+
response = self._make_request("PUT", f"/apiKeys/{key_id}", json=data)
|
|
45
|
+
return response.json()
|
|
46
|
+
|
|
47
|
+
def delete_api_key(self, key_id: str) -> Dict:
|
|
48
|
+
"""Delete an API key."""
|
|
49
|
+
response = self._make_request("DELETE", f"/apiKeys/{key_id}")
|
|
50
|
+
return response.json()
|
datamaker/routes/base.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Optional, Dict
|
|
4
|
+
from ..error import DataMakerError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseClient:
|
|
8
|
+
"""Base client for DataMaker API operations."""
|
|
9
|
+
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
api_key: str = None,
|
|
13
|
+
default_headers: Dict[str, Optional[str]] = None,
|
|
14
|
+
base_url: Optional[str] = None,
|
|
15
|
+
verify: bool = True,
|
|
16
|
+
):
|
|
17
|
+
if default_headers is None:
|
|
18
|
+
default_headers = {"Content-Type": "application/json"}
|
|
19
|
+
|
|
20
|
+
self.api_key = api_key or os.getenv("DATAMAKER_API_KEY")
|
|
21
|
+
self.headers = {
|
|
22
|
+
"X-API-Key": self.api_key,
|
|
23
|
+
**(default_headers or {}),
|
|
24
|
+
}
|
|
25
|
+
# Use DATAMAKER_API_URL environment variable if base_url is not provided
|
|
26
|
+
self.base_url = base_url or os.getenv("DATAMAKER_API_URL") or "https://api.datamaker.automators.com"
|
|
27
|
+
self.verify = verify
|
|
28
|
+
|
|
29
|
+
def _make_request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
|
|
30
|
+
"""Make an HTTP request to the API."""
|
|
31
|
+
url = f"{self.base_url}{endpoint}"
|
|
32
|
+
# Ensure verify is passed to requests, but allow kwargs to override if needed
|
|
33
|
+
if "verify" not in kwargs:
|
|
34
|
+
kwargs["verify"] = self.verify
|
|
35
|
+
response = requests.request(method, url, headers=self.headers, **kwargs)
|
|
36
|
+
|
|
37
|
+
if response.status_code not in [200, 201]:
|
|
38
|
+
raise DataMakerError(f"API request failed: {response.text}")
|
|
39
|
+
|
|
40
|
+
return response
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
from typing import Optional, Dict, List, Literal
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ConnectionsClient(BaseClient):
|
|
6
|
+
"""Client for database connection management operations."""
|
|
7
|
+
|
|
8
|
+
def get_connections(self) -> List[Dict]:
|
|
9
|
+
"""Get all connections."""
|
|
10
|
+
response = self._make_request("GET", "/connections")
|
|
11
|
+
return response.json()
|
|
12
|
+
|
|
13
|
+
def create_connection(
|
|
14
|
+
self,
|
|
15
|
+
name: str,
|
|
16
|
+
connection_type: Literal[
|
|
17
|
+
"db2", "postgresql", "mysql", "mssql", "mongodb", "oracle"
|
|
18
|
+
],
|
|
19
|
+
connection_string: str,
|
|
20
|
+
created_by: str,
|
|
21
|
+
project_id: str,
|
|
22
|
+
team_id: str,
|
|
23
|
+
read_only: Optional[bool] = None,
|
|
24
|
+
endpoint_folder_id: Optional[str] = None,
|
|
25
|
+
) -> Dict:
|
|
26
|
+
"""Create a new database connection."""
|
|
27
|
+
data = {
|
|
28
|
+
"name": name,
|
|
29
|
+
"type": connection_type,
|
|
30
|
+
"connectionString": connection_string,
|
|
31
|
+
"createdBy": created_by,
|
|
32
|
+
"projectId": project_id,
|
|
33
|
+
"teamId": team_id,
|
|
34
|
+
}
|
|
35
|
+
if read_only is not None:
|
|
36
|
+
data["readOnly"] = read_only
|
|
37
|
+
if endpoint_folder_id:
|
|
38
|
+
data["endpointFolderId"] = endpoint_folder_id
|
|
39
|
+
|
|
40
|
+
response = self._make_request("POST", "/connections", json=data)
|
|
41
|
+
return response.json()
|
|
42
|
+
|
|
43
|
+
def update_connection(
|
|
44
|
+
self,
|
|
45
|
+
connection_id: str,
|
|
46
|
+
name: str,
|
|
47
|
+
connection_type: Literal[
|
|
48
|
+
"db2", "postgresql", "mysql", "mssql", "mongodb", "oracle"
|
|
49
|
+
],
|
|
50
|
+
connection_string: str,
|
|
51
|
+
created_by: str,
|
|
52
|
+
project_id: str,
|
|
53
|
+
team_id: str,
|
|
54
|
+
read_only: Optional[bool] = None,
|
|
55
|
+
endpoint_folder_id: Optional[str] = None,
|
|
56
|
+
) -> Dict:
|
|
57
|
+
"""Update a database connection."""
|
|
58
|
+
data = {
|
|
59
|
+
"name": name,
|
|
60
|
+
"type": connection_type,
|
|
61
|
+
"connectionString": connection_string,
|
|
62
|
+
"createdBy": created_by,
|
|
63
|
+
"projectId": project_id,
|
|
64
|
+
"teamId": team_id,
|
|
65
|
+
}
|
|
66
|
+
if read_only is not None:
|
|
67
|
+
data["readOnly"] = read_only
|
|
68
|
+
if endpoint_folder_id:
|
|
69
|
+
data["endpointFolderId"] = endpoint_folder_id
|
|
70
|
+
|
|
71
|
+
response = self._make_request("PUT", f"/connections/{connection_id}", json=data)
|
|
72
|
+
return response.json()
|
|
73
|
+
|
|
74
|
+
def delete_connection(self, connection_id: str) -> Dict:
|
|
75
|
+
"""Delete a database connection."""
|
|
76
|
+
response = self._make_request("DELETE", f"/connections/{connection_id}")
|
|
77
|
+
return response.json()
|
|
78
|
+
|
|
79
|
+
def test_connection(self, connection_data: Dict) -> Dict:
|
|
80
|
+
"""Test a database connection."""
|
|
81
|
+
response = self._make_request("POST", "/connections/test", json=connection_data)
|
|
82
|
+
return response.json()
|
|
83
|
+
|
|
84
|
+
def get_tables(self) -> List[Dict]:
|
|
85
|
+
"""Get all tables from connections."""
|
|
86
|
+
response = self._make_request("GET", "/connections/tables")
|
|
87
|
+
return response.json()
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
from typing import Optional, Dict, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CustomDataTypesClient(BaseClient):
|
|
6
|
+
"""Client for custom data type management operations."""
|
|
7
|
+
|
|
8
|
+
def get_custom_data_types(self, project_id: str) -> List[Dict]:
|
|
9
|
+
"""Get all custom data types for a specific project."""
|
|
10
|
+
params = {"projectId": project_id}
|
|
11
|
+
response = self._make_request("GET", "/customDataTypes", params=params)
|
|
12
|
+
return response.json()
|
|
13
|
+
|
|
14
|
+
def create_custom_data_type(self, data_type_data: Dict) -> Dict:
|
|
15
|
+
"""Create a new custom data type."""
|
|
16
|
+
response = self._make_request("POST", "/customDataTypes", json=data_type_data)
|
|
17
|
+
return response.json()
|
|
18
|
+
|
|
19
|
+
def update_custom_data_type(self, data_type_id: str, data_type_data: Dict) -> Dict:
|
|
20
|
+
"""Update a custom data type."""
|
|
21
|
+
response = self._make_request(
|
|
22
|
+
"PUT", f"/customDataTypes/{data_type_id}", json=data_type_data
|
|
23
|
+
)
|
|
24
|
+
return response.json()
|
|
25
|
+
|
|
26
|
+
def delete_custom_data_type(self, data_type_id: str) -> Dict:
|
|
27
|
+
"""Delete a custom data type."""
|
|
28
|
+
response = self._make_request("DELETE", f"/customDataTypes/{data_type_id}")
|
|
29
|
+
return response.json()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class EndpointFoldersClient(BaseClient):
|
|
33
|
+
"""Client for endpoint folder management operations."""
|
|
34
|
+
|
|
35
|
+
def get_endpoint_folders(self) -> List[Dict]:
|
|
36
|
+
"""Get all endpoint folders."""
|
|
37
|
+
response = self._make_request("GET", "/endpointFolders")
|
|
38
|
+
return response.json()
|
|
39
|
+
|
|
40
|
+
def create_endpoint_folder(self, folder_data: Dict) -> Dict:
|
|
41
|
+
"""Create a new endpoint folder."""
|
|
42
|
+
response = self._make_request("POST", "/endpointFolders", json=folder_data)
|
|
43
|
+
return response.json()
|
|
44
|
+
|
|
45
|
+
def update_endpoint_folder(self, folder_id: str, folder_data: Dict) -> Dict:
|
|
46
|
+
"""Update an endpoint folder."""
|
|
47
|
+
response = self._make_request(
|
|
48
|
+
"PUT", f"/endpointFolders/{folder_id}", json=folder_data
|
|
49
|
+
)
|
|
50
|
+
return response.json()
|
|
51
|
+
|
|
52
|
+
def delete_endpoint_folder(self, folder_id: str) -> Dict:
|
|
53
|
+
"""Delete an endpoint folder."""
|
|
54
|
+
response = self._make_request("DELETE", f"/endpointFolders/{folder_id}")
|
|
55
|
+
return response.json()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class EndpointsClient(BaseClient):
|
|
59
|
+
"""Client for endpoint management operations."""
|
|
60
|
+
|
|
61
|
+
def get_endpoints(self) -> List[Dict]:
|
|
62
|
+
"""Get all endpoints."""
|
|
63
|
+
response = self._make_request("GET", "/endpoints")
|
|
64
|
+
return response.json()
|
|
65
|
+
|
|
66
|
+
def create_endpoint(self, endpoint_data: Dict) -> Dict:
|
|
67
|
+
"""Create a new endpoint."""
|
|
68
|
+
response = self._make_request("POST", "/endpoints", json=endpoint_data)
|
|
69
|
+
return response.json()
|
|
70
|
+
|
|
71
|
+
def get_endpoint(self, endpoint_id: str) -> Dict:
|
|
72
|
+
"""Get a specific endpoint by ID."""
|
|
73
|
+
response = self._make_request("GET", f"/endpoints/{endpoint_id}")
|
|
74
|
+
return response.json()
|
|
75
|
+
|
|
76
|
+
def update_endpoint(self, endpoint_id: str, endpoint_data: Dict) -> Dict:
|
|
77
|
+
"""Update an endpoint."""
|
|
78
|
+
response = self._make_request(
|
|
79
|
+
"PUT", f"/endpoints/{endpoint_id}", json=endpoint_data
|
|
80
|
+
)
|
|
81
|
+
return response.json()
|
|
82
|
+
|
|
83
|
+
def delete_endpoint(self, endpoint_id: str) -> Dict:
|
|
84
|
+
"""Delete an endpoint."""
|
|
85
|
+
response = self._make_request("DELETE", f"/endpoints/{endpoint_id}")
|
|
86
|
+
return response.json()
|
|
87
|
+
|
|
88
|
+
def resolve_endpoint_auth(self, endpoint_id: str) -> Dict:
|
|
89
|
+
"""Resolve an endpoint's real, usable credentials.
|
|
90
|
+
|
|
91
|
+
Unlike get_endpoint(), whose auth fields are masked (`*******`), this
|
|
92
|
+
returns the decrypted Authorization header (Basic decrypted / OAuth2
|
|
93
|
+
token exchanged) plus, for Basic auth, the real username/password.
|
|
94
|
+
|
|
95
|
+
Returns a dict: {authType, authHeader, fetchCsrf, basic}.
|
|
96
|
+
"""
|
|
97
|
+
response = self._make_request(
|
|
98
|
+
"POST", "/endpoints/auth-resolve", json={"endpointId": endpoint_id}
|
|
99
|
+
)
|
|
100
|
+
return response.json()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ExportClient(BaseClient):
|
|
6
|
+
"""Client for export operations."""
|
|
7
|
+
|
|
8
|
+
def export_to_rest(self, export_data: Dict) -> Dict:
|
|
9
|
+
"""Export data to REST API."""
|
|
10
|
+
response = self._make_request("POST", "/export/rest", json=export_data)
|
|
11
|
+
return response.json()
|
|
12
|
+
|
|
13
|
+
def export_to_database(self, export_data: Dict) -> Dict:
|
|
14
|
+
"""Export data to database."""
|
|
15
|
+
response = self._make_request("POST", "/export/db", json=export_data)
|
|
16
|
+
return response.json()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ValidationClient(BaseClient):
|
|
20
|
+
"""Client for validation operations."""
|
|
21
|
+
|
|
22
|
+
def validate_api_key(self) -> Dict:
|
|
23
|
+
"""Test API key authentication."""
|
|
24
|
+
response = self._make_request("GET", "/validate/apiKey")
|
|
25
|
+
return response.json()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
from typing import Optional, Dict, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TemplateFoldersClient(BaseClient):
|
|
6
|
+
"""Client for template folder management operations."""
|
|
7
|
+
|
|
8
|
+
def get_template_folders(self) -> List[Dict]:
|
|
9
|
+
"""Get all template folders."""
|
|
10
|
+
response = self._make_request("GET", "/templateFolders")
|
|
11
|
+
return response.json()
|
|
12
|
+
|
|
13
|
+
def create_template_folder(self, folder_data: Dict) -> Dict:
|
|
14
|
+
"""Create a new template folder."""
|
|
15
|
+
response = self._make_request("POST", "/templateFolders", json=folder_data)
|
|
16
|
+
return response.json()
|
|
17
|
+
|
|
18
|
+
def update_template_folder(self, folder_id: str, folder_data: Dict) -> Dict:
|
|
19
|
+
"""Update a template folder."""
|
|
20
|
+
response = self._make_request(
|
|
21
|
+
"PUT", f"/templateFolders/{folder_id}", json=folder_data
|
|
22
|
+
)
|
|
23
|
+
return response.json()
|
|
24
|
+
|
|
25
|
+
def delete_template_folder(self, folder_id: str) -> Dict:
|
|
26
|
+
"""Delete a template folder."""
|
|
27
|
+
response = self._make_request("DELETE", f"/templateFolders/{folder_id}")
|
|
28
|
+
return response.json()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ShortcutsClient(BaseClient):
|
|
32
|
+
"""Client for shortcuts management operations."""
|
|
33
|
+
|
|
34
|
+
def get_shortcuts(self) -> List[Dict]:
|
|
35
|
+
"""Get all shortcuts."""
|
|
36
|
+
response = self._make_request("GET", "/shortcuts")
|
|
37
|
+
return response.json()
|
|
38
|
+
|
|
39
|
+
def create_shortcut(self, shortcut_data: Dict) -> Dict:
|
|
40
|
+
"""Create a new shortcut."""
|
|
41
|
+
response = self._make_request("POST", "/shortcuts", json=shortcut_data)
|
|
42
|
+
return response.json()
|
|
43
|
+
|
|
44
|
+
def update_shortcut(self, shortcut_id: str, shortcut_data: Dict) -> Dict:
|
|
45
|
+
"""Update a shortcut."""
|
|
46
|
+
response = self._make_request(
|
|
47
|
+
"PUT", f"/shortcuts/{shortcut_id}", json=shortcut_data
|
|
48
|
+
)
|
|
49
|
+
return response.json()
|
|
50
|
+
|
|
51
|
+
def delete_shortcut(self, shortcut_id: str) -> Dict:
|
|
52
|
+
"""Delete a shortcut."""
|
|
53
|
+
response = self._make_request("DELETE", f"/shortcuts/{shortcut_id}")
|
|
54
|
+
return response.json()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class FeedbackClient(BaseClient):
|
|
58
|
+
"""Client for feedback management operations."""
|
|
59
|
+
|
|
60
|
+
def get_feedback(self) -> List[Dict]:
|
|
61
|
+
"""Get all feedback."""
|
|
62
|
+
response = self._make_request("GET", "/feedback")
|
|
63
|
+
return response.json()
|
|
64
|
+
|
|
65
|
+
def submit_feedback(self, feedback_data: Dict) -> Dict:
|
|
66
|
+
"""Submit new feedback."""
|
|
67
|
+
response = self._make_request("POST", "/feedback", json=feedback_data)
|
|
68
|
+
return response.json()
|
|
69
|
+
|
|
70
|
+
def update_feedback(self, feedback_id: str, feedback_data: Dict) -> Dict:
|
|
71
|
+
"""Update feedback."""
|
|
72
|
+
response = self._make_request(
|
|
73
|
+
"PUT", f"/feedback/{feedback_id}", json=feedback_data
|
|
74
|
+
)
|
|
75
|
+
return response.json()
|
|
76
|
+
|
|
77
|
+
def delete_feedback(self, feedback_id: str) -> Dict:
|
|
78
|
+
"""Delete feedback."""
|
|
79
|
+
response = self._make_request("DELETE", f"/feedback/{feedback_id}")
|
|
80
|
+
return response.json()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GenerationClient(BaseClient):
|
|
5
|
+
"""Client for data generation operations."""
|
|
6
|
+
|
|
7
|
+
def generate(self, template):
|
|
8
|
+
"""Generate data using a template."""
|
|
9
|
+
response = self._make_request(
|
|
10
|
+
"POST",
|
|
11
|
+
"/datamaker",
|
|
12
|
+
json=template.to_dict() if hasattr(template, "to_dict") else template,
|
|
13
|
+
)
|
|
14
|
+
return response.json()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .base import BaseClient
|
|
2
|
+
from typing import Optional, Dict, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ProjectsClient(BaseClient):
|
|
6
|
+
"""Client for project management operations."""
|
|
7
|
+
|
|
8
|
+
def get_projects(self) -> List[Dict]:
|
|
9
|
+
"""Get all projects."""
|
|
10
|
+
response = self._make_request("GET", "/projects")
|
|
11
|
+
return response.json()
|
|
12
|
+
|
|
13
|
+
def create_project(self, project_data: Dict, team_id: str) -> Dict:
|
|
14
|
+
"""Create a new project."""
|
|
15
|
+
# Ensure required teamId is present
|
|
16
|
+
project_data["teamId"] = team_id
|
|
17
|
+
response = self._make_request("POST", "/projects", json=project_data)
|
|
18
|
+
return response.json()
|
|
19
|
+
|
|
20
|
+
def get_project(self, project_id: str) -> Dict:
|
|
21
|
+
"""Get a specific project by ID."""
|
|
22
|
+
response = self._make_request("GET", f"/projects/{project_id}")
|
|
23
|
+
return response.json()
|
|
24
|
+
|
|
25
|
+
def update_project(self, project_id: str, project_data: Dict) -> Dict:
|
|
26
|
+
"""Update a project."""
|
|
27
|
+
response = self._make_request(
|
|
28
|
+
"PUT", f"/projects/{project_id}", json=project_data
|
|
29
|
+
)
|
|
30
|
+
return response.json()
|
|
31
|
+
|
|
32
|
+
def delete_project(self, project_id: str) -> Dict:
|
|
33
|
+
"""Delete a project."""
|
|
34
|
+
response = self._make_request("DELETE", f"/projects/{project_id}")
|
|
35
|
+
return response.json()
|