getdx 0.1.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.
- getdx/__init__.py +51 -0
- getdx/client.py +71 -0
- getdx/config.py +95 -0
- getdx/data_cloud/__init__.py +4 -0
- getdx/data_cloud/client.py +301 -0
- getdx/data_cloud/operations.py +319 -0
- getdx/data_cloud/services/__init__.py +28 -0
- getdx/data_cloud/services/ai_tool_metrics.py +60 -0
- getdx/data_cloud/services/custom_data.py +137 -0
- getdx/data_cloud/services/deployments.py +68 -0
- getdx/data_cloud/services/incidents.py +46 -0
- getdx/data_cloud/services/pipeline_runs.py +58 -0
- getdx/data_cloud/services/repo_groups.py +132 -0
- getdx/errors.py +77 -0
- getdx/helpers.py +20 -0
- getdx/http/__init__.py +3 -0
- getdx/http/retry.py +49 -0
- getdx/http/transport.py +135 -0
- getdx/py.typed +0 -0
- getdx/types.py +12 -0
- getdx/web/__init__.py +12 -0
- getdx/web/aggregates.py +165 -0
- getdx/web/client.py +55 -0
- getdx/web/operations.py +822 -0
- getdx/web/services/__init__.py +52 -0
- getdx/web/services/entities.py +201 -0
- getdx/web/services/entity_relations.py +38 -0
- getdx/web/services/entity_types.py +133 -0
- getdx/web/services/events.py +36 -0
- getdx/web/services/initiatives.py +74 -0
- getdx/web/services/orgfiles.py +113 -0
- getdx/web/services/platformx.py +56 -0
- getdx/web/services/queries.py +31 -0
- getdx/web/services/scorecards.py +121 -0
- getdx/web/services/snapshots.py +93 -0
- getdx/web/services/teams.py +94 -0
- getdx/web/services/user_groups.py +123 -0
- getdx/web/services/users.py +77 -0
- getdx/web/services/workflow_runs.py +121 -0
- getdx-0.1.0.dist-info/METADATA +146 -0
- getdx-0.1.0.dist-info/RECORD +43 -0
- getdx-0.1.0.dist-info/WHEEL +4 -0
- getdx-0.1.0.dist-info/licenses/LICENSE +21 -0
getdx/__init__.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
__version__ = version("getdx")
|
|
5
|
+
except PackageNotFoundError:
|
|
6
|
+
__version__ = "unknown"
|
|
7
|
+
|
|
8
|
+
from getdx.client import DXClient
|
|
9
|
+
from getdx.config import DXClientConfig, DXDataCloudConfig, DXWebConfig, RetryConfig
|
|
10
|
+
from getdx.data_cloud.client import DXDataCloudClient
|
|
11
|
+
from getdx.errors import (
|
|
12
|
+
DXAPIError,
|
|
13
|
+
DXArgumentError,
|
|
14
|
+
DXAuthError,
|
|
15
|
+
DXClientConfigurationError,
|
|
16
|
+
DXClientNotConfiguredError,
|
|
17
|
+
DXFeatureUnavailableError,
|
|
18
|
+
DXPermissionError,
|
|
19
|
+
DXRateLimitError,
|
|
20
|
+
DXResponseError,
|
|
21
|
+
DXServerError,
|
|
22
|
+
DXTransportError,
|
|
23
|
+
DXValidationError,
|
|
24
|
+
)
|
|
25
|
+
from getdx.web.aggregates import EntityOverview, EntityRelationsGraph
|
|
26
|
+
from getdx.web.client import DXWebClient
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"DXAPIError",
|
|
30
|
+
"DXArgumentError",
|
|
31
|
+
"DXAuthError",
|
|
32
|
+
"DXClient",
|
|
33
|
+
"DXClientConfig",
|
|
34
|
+
"DXClientConfigurationError",
|
|
35
|
+
"DXClientNotConfiguredError",
|
|
36
|
+
"DXDataCloudClient",
|
|
37
|
+
"DXDataCloudConfig",
|
|
38
|
+
"DXFeatureUnavailableError",
|
|
39
|
+
"DXPermissionError",
|
|
40
|
+
"DXRateLimitError",
|
|
41
|
+
"DXResponseError",
|
|
42
|
+
"DXServerError",
|
|
43
|
+
"DXTransportError",
|
|
44
|
+
"DXValidationError",
|
|
45
|
+
"DXWebClient",
|
|
46
|
+
"DXWebConfig",
|
|
47
|
+
"EntityOverview",
|
|
48
|
+
"EntityRelationsGraph",
|
|
49
|
+
"RetryConfig",
|
|
50
|
+
"__version__",
|
|
51
|
+
]
|
getdx/client.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from getdx.config import DXClientConfig, DXDataCloudConfig, DXWebConfig
|
|
4
|
+
from getdx.data_cloud.client import DXDataCloudClient
|
|
5
|
+
from getdx.errors import DXClientConfigurationError, DXClientNotConfiguredError
|
|
6
|
+
from getdx.web.client import DXWebClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DXClient:
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
*,
|
|
13
|
+
web: DXWebConfig | None = None,
|
|
14
|
+
data_cloud: DXDataCloudConfig | None = None,
|
|
15
|
+
config: DXClientConfig | None = None,
|
|
16
|
+
) -> None:
|
|
17
|
+
resolved_web = web if web is not None else (config.web if config is not None else None)
|
|
18
|
+
resolved_data_cloud = (
|
|
19
|
+
data_cloud
|
|
20
|
+
if data_cloud is not None
|
|
21
|
+
else (config.data_cloud if config is not None else None)
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
if resolved_web is None and resolved_data_cloud is None:
|
|
25
|
+
raise DXClientConfigurationError(
|
|
26
|
+
"DXClient requires at least one API config. Provide web=DXWebConfig(...) "
|
|
27
|
+
"and/or data_cloud=DXDataCloudConfig(...)."
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
self._web = DXWebClient(resolved_web) if resolved_web is not None else None
|
|
31
|
+
self._data_cloud = (
|
|
32
|
+
DXDataCloudClient(resolved_data_cloud) if resolved_data_cloud is not None else None
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def has_web(self) -> bool:
|
|
37
|
+
return self._web is not None
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def has_data_cloud(self) -> bool:
|
|
41
|
+
return self._data_cloud is not None
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def web(self) -> DXWebClient:
|
|
45
|
+
if self._web is None:
|
|
46
|
+
raise DXClientNotConfiguredError(
|
|
47
|
+
"DXClient.web is not configured. "
|
|
48
|
+
"Pass web=DXWebConfig(...) when constructing DXClient."
|
|
49
|
+
)
|
|
50
|
+
return self._web
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def data_cloud(self) -> DXDataCloudClient:
|
|
54
|
+
if self._data_cloud is None:
|
|
55
|
+
raise DXClientNotConfiguredError(
|
|
56
|
+
"DXClient.data_cloud is not configured. Pass data_cloud=DXDataCloudConfig(...) "
|
|
57
|
+
"when constructing DXClient."
|
|
58
|
+
)
|
|
59
|
+
return self._data_cloud
|
|
60
|
+
|
|
61
|
+
def close(self) -> None:
|
|
62
|
+
if self._web is not None:
|
|
63
|
+
self._web.close()
|
|
64
|
+
if self._data_cloud is not None:
|
|
65
|
+
self._data_cloud.close()
|
|
66
|
+
|
|
67
|
+
def __enter__(self) -> DXClient:
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
def __exit__(self, exc_type, exc, tb) -> None: # type: ignore[no-untyped-def]
|
|
71
|
+
self.close()
|
getdx/config.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
DEFAULT_WEB_BASE_URL = "https://api.getdx.com"
|
|
7
|
+
DEFAULT_TIMEOUT_SECONDS = 30.0
|
|
8
|
+
DEFAULT_DATA_CLOUD_URL_TEMPLATE = "https://{instance}.getdx.net/api"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class RetryConfig:
|
|
13
|
+
max_attempts: int = 3
|
|
14
|
+
backoff_base_seconds: float = 0.25
|
|
15
|
+
backoff_max_seconds: float = 2.0
|
|
16
|
+
retry_statuses: tuple[int, ...] = (429, 500, 502, 503, 504)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class APITransportConfig:
|
|
21
|
+
base_url: str
|
|
22
|
+
timeout_seconds: float
|
|
23
|
+
user_agent: str
|
|
24
|
+
retry: RetryConfig
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class DXWebConfig:
|
|
29
|
+
token: str | None = None
|
|
30
|
+
base_url: str = DEFAULT_WEB_BASE_URL
|
|
31
|
+
timeout_seconds: float = DEFAULT_TIMEOUT_SECONDS
|
|
32
|
+
user_agent: str = "getdx/web"
|
|
33
|
+
retry: RetryConfig = field(default_factory=RetryConfig)
|
|
34
|
+
|
|
35
|
+
def resolved_token(self) -> str:
|
|
36
|
+
token = self.token or os.getenv("DX_WEB_API_TOKEN")
|
|
37
|
+
if not token:
|
|
38
|
+
raise ValueError(
|
|
39
|
+
"DX Web API token missing. Set DX_WEB_API_TOKEN or pass token in DXWebConfig."
|
|
40
|
+
)
|
|
41
|
+
return token
|
|
42
|
+
|
|
43
|
+
def resolved_transport_config(self) -> APITransportConfig:
|
|
44
|
+
return APITransportConfig(
|
|
45
|
+
base_url=self.base_url.rstrip("/"),
|
|
46
|
+
timeout_seconds=self.timeout_seconds,
|
|
47
|
+
user_agent=self.user_agent,
|
|
48
|
+
retry=self.retry,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class DXDataCloudConfig:
|
|
54
|
+
token: str | None = None
|
|
55
|
+
instance: str | None = None
|
|
56
|
+
base_url: str | None = None
|
|
57
|
+
timeout_seconds: float = DEFAULT_TIMEOUT_SECONDS
|
|
58
|
+
user_agent: str = "getdx/data-cloud"
|
|
59
|
+
retry: RetryConfig = field(default_factory=RetryConfig)
|
|
60
|
+
|
|
61
|
+
def resolved_token(self) -> str:
|
|
62
|
+
token = self.token or os.getenv("DX_DATA_CLOUD_TOKEN")
|
|
63
|
+
if not token:
|
|
64
|
+
raise ValueError(
|
|
65
|
+
"DX Data Cloud token missing. "
|
|
66
|
+
"Set DX_DATA_CLOUD_TOKEN or pass token in DXDataCloudConfig."
|
|
67
|
+
)
|
|
68
|
+
return token
|
|
69
|
+
|
|
70
|
+
def resolved_base_url(self) -> str:
|
|
71
|
+
if self.base_url:
|
|
72
|
+
return self.base_url.rstrip("/")
|
|
73
|
+
|
|
74
|
+
instance = self.instance or os.getenv("DX_DATA_CLOUD_INSTANCE")
|
|
75
|
+
if not instance:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
"DX Data Cloud base URL cannot be resolved. "
|
|
78
|
+
"Set DX_DATA_CLOUD_INSTANCE or pass instance/base_url in DXDataCloudConfig."
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return DEFAULT_DATA_CLOUD_URL_TEMPLATE.format(instance=instance).rstrip("/")
|
|
82
|
+
|
|
83
|
+
def resolved_transport_config(self) -> APITransportConfig:
|
|
84
|
+
return APITransportConfig(
|
|
85
|
+
base_url=self.resolved_base_url(),
|
|
86
|
+
timeout_seconds=self.timeout_seconds,
|
|
87
|
+
user_agent=self.user_agent,
|
|
88
|
+
retry=self.retry,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass(frozen=True)
|
|
93
|
+
class DXClientConfig:
|
|
94
|
+
web: DXWebConfig | None = None
|
|
95
|
+
data_cloud: DXDataCloudConfig | None = None
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from getdx.config import DXDataCloudConfig
|
|
7
|
+
from getdx.data_cloud.services import (
|
|
8
|
+
AiToolMetricsService,
|
|
9
|
+
CustomDataService,
|
|
10
|
+
DeploymentsService,
|
|
11
|
+
IncidentsService,
|
|
12
|
+
PipelineRunsService,
|
|
13
|
+
RepoGroupsService,
|
|
14
|
+
)
|
|
15
|
+
from getdx.errors import DXArgumentError
|
|
16
|
+
from getdx.helpers import JSONReturn
|
|
17
|
+
from getdx.http.transport import DXTransport
|
|
18
|
+
from getdx.types import BodyValue
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CustomDataAPI:
|
|
22
|
+
def __init__(self, service: CustomDataService) -> None:
|
|
23
|
+
self._service = service
|
|
24
|
+
|
|
25
|
+
def get(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
id: str | None = None,
|
|
29
|
+
reference: str | None = None,
|
|
30
|
+
key: str | None = None,
|
|
31
|
+
) -> JSONReturn:
|
|
32
|
+
if id is not None:
|
|
33
|
+
if reference is not None or key is not None:
|
|
34
|
+
raise DXArgumentError(
|
|
35
|
+
"Pass either id or reference+key for custom_data.get, not both."
|
|
36
|
+
)
|
|
37
|
+
return self._service.get(id=id)
|
|
38
|
+
|
|
39
|
+
if reference is not None and key is not None:
|
|
40
|
+
return self._service.get(reference=reference, key=key)
|
|
41
|
+
|
|
42
|
+
raise DXArgumentError("custom_data.get requires id or both reference and key.")
|
|
43
|
+
|
|
44
|
+
def get_all_by_reference(self, reference: str) -> JSONReturn:
|
|
45
|
+
return self._service.get_all_by_reference(reference=reference)
|
|
46
|
+
|
|
47
|
+
def set(
|
|
48
|
+
self,
|
|
49
|
+
*,
|
|
50
|
+
reference: BodyValue,
|
|
51
|
+
key: BodyValue,
|
|
52
|
+
value: BodyValue,
|
|
53
|
+
timestamp: BodyValue | None = None,
|
|
54
|
+
) -> JSONReturn:
|
|
55
|
+
return self._service.set(reference=reference, key=key, value=value, timestamp=timestamp)
|
|
56
|
+
|
|
57
|
+
def set_all(self, *, data: BodyValue) -> JSONReturn:
|
|
58
|
+
return self._service.set_all(data=data)
|
|
59
|
+
|
|
60
|
+
def delete(
|
|
61
|
+
self,
|
|
62
|
+
*,
|
|
63
|
+
id: str | None = None,
|
|
64
|
+
reference: str | None = None,
|
|
65
|
+
key: str | None = None,
|
|
66
|
+
) -> JSONReturn:
|
|
67
|
+
if id is not None:
|
|
68
|
+
if reference is not None or key is not None:
|
|
69
|
+
raise DXArgumentError(
|
|
70
|
+
"Pass either id or reference+key for custom_data.delete, not both."
|
|
71
|
+
)
|
|
72
|
+
return self._service.delete(payload={"id": id})
|
|
73
|
+
|
|
74
|
+
if reference is not None and key is not None:
|
|
75
|
+
return self._service.delete(payload={"reference": reference, "key": key})
|
|
76
|
+
|
|
77
|
+
raise DXArgumentError("custom_data.delete requires id or both reference and key.")
|
|
78
|
+
|
|
79
|
+
def delete_by_id(self, id: str) -> JSONReturn:
|
|
80
|
+
return self._service.delete(payload={"id": id})
|
|
81
|
+
|
|
82
|
+
def delete_by_reference_key(self, reference: str, key: str) -> JSONReturn:
|
|
83
|
+
return self._service.delete(payload={"reference": reference, "key": key})
|
|
84
|
+
|
|
85
|
+
def delete_all_by_reference(self, *, reference: BodyValue) -> JSONReturn:
|
|
86
|
+
return self._service.delete_all_by_reference(reference=reference)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class RepoGroupsAPI:
|
|
90
|
+
def __init__(self, service: RepoGroupsService) -> None:
|
|
91
|
+
self._service = service
|
|
92
|
+
|
|
93
|
+
def get(self, *, id: str | None = None, reference_id: str | None = None) -> JSONReturn:
|
|
94
|
+
selector = _exactly_one_selector(
|
|
95
|
+
id=id, reference_id=reference_id, method_name="repo_groups.get"
|
|
96
|
+
)
|
|
97
|
+
return self._service.get(**selector)
|
|
98
|
+
|
|
99
|
+
def delete(
|
|
100
|
+
self, *, id: BodyValue | None = None, reference_id: BodyValue | None = None
|
|
101
|
+
) -> JSONReturn:
|
|
102
|
+
selector = _exactly_one_selector(
|
|
103
|
+
id=id,
|
|
104
|
+
reference_id=reference_id,
|
|
105
|
+
method_name="repo_groups.delete",
|
|
106
|
+
)
|
|
107
|
+
return self._service.delete(**selector)
|
|
108
|
+
|
|
109
|
+
def upsert(
|
|
110
|
+
self,
|
|
111
|
+
*,
|
|
112
|
+
name: BodyValue,
|
|
113
|
+
id: BodyValue | None = None,
|
|
114
|
+
reference_id: BodyValue | None = None,
|
|
115
|
+
parent_id: BodyValue | None = None,
|
|
116
|
+
repos: BodyValue | None = None,
|
|
117
|
+
) -> JSONReturn:
|
|
118
|
+
return self._service.upsert(
|
|
119
|
+
name=name,
|
|
120
|
+
id=id,
|
|
121
|
+
reference_id=reference_id,
|
|
122
|
+
parent_id=parent_id,
|
|
123
|
+
repos=repos,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def add_repos(
|
|
127
|
+
self,
|
|
128
|
+
*,
|
|
129
|
+
repos: BodyValue,
|
|
130
|
+
id: BodyValue | None = None,
|
|
131
|
+
reference_id: BodyValue | None = None,
|
|
132
|
+
) -> JSONReturn:
|
|
133
|
+
selector = _exactly_one_selector(
|
|
134
|
+
id=id,
|
|
135
|
+
reference_id=reference_id,
|
|
136
|
+
method_name="repo_groups.add_repos",
|
|
137
|
+
)
|
|
138
|
+
return self._service.add_repos(repos=repos, **selector)
|
|
139
|
+
|
|
140
|
+
def remove_repos(
|
|
141
|
+
self,
|
|
142
|
+
*,
|
|
143
|
+
repos: BodyValue,
|
|
144
|
+
id: BodyValue | None = None,
|
|
145
|
+
reference_id: BodyValue | None = None,
|
|
146
|
+
) -> JSONReturn:
|
|
147
|
+
selector = _exactly_one_selector(
|
|
148
|
+
id=id,
|
|
149
|
+
reference_id=reference_id,
|
|
150
|
+
method_name="repo_groups.remove_repos",
|
|
151
|
+
)
|
|
152
|
+
return self._service.remove_repos(repos=repos, **selector)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class DeploymentsAPI:
|
|
156
|
+
def __init__(self, service: DeploymentsService) -> None:
|
|
157
|
+
self._service = service
|
|
158
|
+
|
|
159
|
+
def create(
|
|
160
|
+
self,
|
|
161
|
+
*,
|
|
162
|
+
deployed_at: BodyValue,
|
|
163
|
+
service: BodyValue,
|
|
164
|
+
commit_sha: BodyValue | None = None,
|
|
165
|
+
integration_branch: BodyValue | None = None,
|
|
166
|
+
merge_commit_shas: BodyValue | None = None,
|
|
167
|
+
metadata: BodyValue | None = None,
|
|
168
|
+
reference_id: BodyValue | None = None,
|
|
169
|
+
repository: BodyValue | None = None,
|
|
170
|
+
source_name: BodyValue | None = None,
|
|
171
|
+
source_url: BodyValue | None = None,
|
|
172
|
+
success: BodyValue | None = None,
|
|
173
|
+
) -> JSONReturn:
|
|
174
|
+
return self._service.create(
|
|
175
|
+
deployed_at=deployed_at,
|
|
176
|
+
service=service,
|
|
177
|
+
commit_sha=commit_sha,
|
|
178
|
+
integration_branch=integration_branch,
|
|
179
|
+
merge_commit_shas=merge_commit_shas,
|
|
180
|
+
metadata=metadata,
|
|
181
|
+
reference_id=reference_id,
|
|
182
|
+
repository=repository,
|
|
183
|
+
source_name=source_name,
|
|
184
|
+
source_url=source_url,
|
|
185
|
+
success=success,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
def set_pull_services(self, *, payload: dict[str, Any]) -> JSONReturn:
|
|
189
|
+
return self._service.set_pull_services(payload=payload)
|
|
190
|
+
|
|
191
|
+
def set_pull_services_by_github_pull_id(
|
|
192
|
+
self,
|
|
193
|
+
*,
|
|
194
|
+
github_pull_id: int,
|
|
195
|
+
services: Sequence[dict[str, Any]],
|
|
196
|
+
) -> JSONReturn:
|
|
197
|
+
return self._service.set_pull_services(
|
|
198
|
+
payload={
|
|
199
|
+
"github_pull_id": github_pull_id,
|
|
200
|
+
"services": list(services),
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
def set_pull_services_by_repo_and_number(
|
|
205
|
+
self,
|
|
206
|
+
*,
|
|
207
|
+
repository: str,
|
|
208
|
+
pull_number: int,
|
|
209
|
+
services: Sequence[dict[str, Any]],
|
|
210
|
+
) -> JSONReturn:
|
|
211
|
+
return self._service.set_pull_services(
|
|
212
|
+
payload={
|
|
213
|
+
"repository": repository,
|
|
214
|
+
"pull_number": pull_number,
|
|
215
|
+
"services": list(services),
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class PipelineRunsAPI:
|
|
221
|
+
def __init__(self, service: PipelineRunsService) -> None:
|
|
222
|
+
self._service = service
|
|
223
|
+
|
|
224
|
+
def upsert(
|
|
225
|
+
self,
|
|
226
|
+
*,
|
|
227
|
+
pipeline_name: BodyValue,
|
|
228
|
+
pipeline_source: BodyValue,
|
|
229
|
+
reference_id: BodyValue,
|
|
230
|
+
started_at: BodyValue,
|
|
231
|
+
commit_sha: BodyValue | None = None,
|
|
232
|
+
email: BodyValue | None = None,
|
|
233
|
+
finished_at: BodyValue | None = None,
|
|
234
|
+
github_username: BodyValue | None = None,
|
|
235
|
+
gitlab_username: BodyValue | None = None,
|
|
236
|
+
head_branch: BodyValue | None = None,
|
|
237
|
+
pr_number: BodyValue | None = None,
|
|
238
|
+
repository: BodyValue | None = None,
|
|
239
|
+
source_url: BodyValue | None = None,
|
|
240
|
+
status: BodyValue | None = None,
|
|
241
|
+
) -> JSONReturn:
|
|
242
|
+
if (commit_sha is not None or pr_number is not None) and repository is None:
|
|
243
|
+
raise DXArgumentError(
|
|
244
|
+
"pipeline_runs.upsert requires repository when commit_sha/pr_number is set."
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return self._service.upsert(
|
|
248
|
+
pipeline_name=pipeline_name,
|
|
249
|
+
pipeline_source=pipeline_source,
|
|
250
|
+
reference_id=reference_id,
|
|
251
|
+
started_at=started_at,
|
|
252
|
+
commit_sha=commit_sha,
|
|
253
|
+
email=email,
|
|
254
|
+
finished_at=finished_at,
|
|
255
|
+
github_username=github_username,
|
|
256
|
+
gitlab_username=gitlab_username,
|
|
257
|
+
head_branch=head_branch,
|
|
258
|
+
pr_number=pr_number,
|
|
259
|
+
repository=repository,
|
|
260
|
+
source_url=source_url,
|
|
261
|
+
status=status,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class DXDataCloudClient:
|
|
266
|
+
def __init__(self, config: DXDataCloudConfig) -> None:
|
|
267
|
+
self._config = config
|
|
268
|
+
self._transport = DXTransport(
|
|
269
|
+
config=config.resolved_transport_config(),
|
|
270
|
+
token=config.resolved_token(),
|
|
271
|
+
api_name="data_cloud",
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
self.ai_tool_metrics = AiToolMetricsService(self._transport)
|
|
275
|
+
self.custom_data = CustomDataAPI(CustomDataService(self._transport))
|
|
276
|
+
self.deployments = DeploymentsAPI(DeploymentsService(self._transport))
|
|
277
|
+
self.incidents = IncidentsService(self._transport)
|
|
278
|
+
self.pipeline_runs = PipelineRunsAPI(PipelineRunsService(self._transport))
|
|
279
|
+
self.repo_groups = RepoGroupsAPI(RepoGroupsService(self._transport))
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def config(self) -> DXDataCloudConfig:
|
|
283
|
+
return self._config
|
|
284
|
+
|
|
285
|
+
def close(self) -> None:
|
|
286
|
+
self._transport.close()
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def _exactly_one_selector(
|
|
290
|
+
*,
|
|
291
|
+
id: Any,
|
|
292
|
+
reference_id: Any,
|
|
293
|
+
method_name: str,
|
|
294
|
+
) -> dict[str, Any]:
|
|
295
|
+
if id is not None and reference_id is not None:
|
|
296
|
+
raise DXArgumentError(f"{method_name} accepts either id or reference_id, not both.")
|
|
297
|
+
if id is None and reference_id is None:
|
|
298
|
+
raise DXArgumentError(f"{method_name} requires id or reference_id.")
|
|
299
|
+
if id is not None:
|
|
300
|
+
return {"id": id}
|
|
301
|
+
return {"reference_id": reference_id}
|