devrev-Python-SDK 1.0.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.
- devrev/__init__.py +47 -0
- devrev/client.py +343 -0
- devrev/config.py +180 -0
- devrev/exceptions.py +205 -0
- devrev/models/__init__.py +499 -0
- devrev/models/accounts.py +187 -0
- devrev/models/articles.py +109 -0
- devrev/models/base.py +147 -0
- devrev/models/code_changes.py +103 -0
- devrev/models/conversations.py +115 -0
- devrev/models/dev_users.py +258 -0
- devrev/models/groups.py +140 -0
- devrev/models/links.py +107 -0
- devrev/models/parts.py +110 -0
- devrev/models/rev_users.py +177 -0
- devrev/models/slas.py +112 -0
- devrev/models/tags.py +90 -0
- devrev/models/timeline_entries.py +100 -0
- devrev/models/webhooks.py +109 -0
- devrev/models/works.py +280 -0
- devrev/py.typed +1 -0
- devrev/services/__init__.py +74 -0
- devrev/services/accounts.py +325 -0
- devrev/services/articles.py +80 -0
- devrev/services/base.py +234 -0
- devrev/services/code_changes.py +80 -0
- devrev/services/conversations.py +98 -0
- devrev/services/dev_users.py +401 -0
- devrev/services/groups.py +103 -0
- devrev/services/links.py +68 -0
- devrev/services/parts.py +100 -0
- devrev/services/rev_users.py +235 -0
- devrev/services/slas.py +82 -0
- devrev/services/tags.py +80 -0
- devrev/services/timeline_entries.py +80 -0
- devrev/services/webhooks.py +80 -0
- devrev/services/works.py +363 -0
- devrev/utils/__init__.py +14 -0
- devrev/utils/deprecation.py +49 -0
- devrev/utils/http.py +521 -0
- devrev/utils/logging.py +139 -0
- devrev/utils/pagination.py +155 -0
- devrev_python_sdk-1.0.0.dist-info/METADATA +774 -0
- devrev_python_sdk-1.0.0.dist-info/RECORD +45 -0
- devrev_python_sdk-1.0.0.dist-info/WHEEL +4 -0
devrev/models/works.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""Work models for DevRev SDK.
|
|
2
|
+
|
|
3
|
+
This module contains Pydantic models for Work-related API operations.
|
|
4
|
+
Works include issues, tickets, tasks, and opportunities.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pydantic import Field
|
|
14
|
+
|
|
15
|
+
from devrev.models.base import (
|
|
16
|
+
CustomSchemaSpec,
|
|
17
|
+
DateFilter,
|
|
18
|
+
DevRevBaseModel,
|
|
19
|
+
DevRevResponseModel,
|
|
20
|
+
PaginatedResponse,
|
|
21
|
+
SetTagWithValue,
|
|
22
|
+
StageInfo,
|
|
23
|
+
StageUpdate,
|
|
24
|
+
TagWithValue,
|
|
25
|
+
UserSummary,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class WorkType(str, Enum):
|
|
30
|
+
"""Work item type enumeration."""
|
|
31
|
+
|
|
32
|
+
ISSUE = "issue"
|
|
33
|
+
TICKET = "ticket"
|
|
34
|
+
TASK = "task"
|
|
35
|
+
OPPORTUNITY = "opportunity"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class IssuePriority(str, Enum):
|
|
39
|
+
"""Issue priority enumeration."""
|
|
40
|
+
|
|
41
|
+
P0 = "p0"
|
|
42
|
+
P1 = "p1"
|
|
43
|
+
P2 = "p2"
|
|
44
|
+
P3 = "p3"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class TicketSeverity(str, Enum):
|
|
48
|
+
"""Ticket severity enumeration."""
|
|
49
|
+
|
|
50
|
+
BLOCKER = "blocker"
|
|
51
|
+
HIGH = "high"
|
|
52
|
+
LOW = "low"
|
|
53
|
+
MEDIUM = "medium"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class TicketChannels(str, Enum):
|
|
57
|
+
"""Ticket channel enumeration."""
|
|
58
|
+
|
|
59
|
+
EMAIL = "email"
|
|
60
|
+
PLUG = "plug"
|
|
61
|
+
SLACK = "slack"
|
|
62
|
+
OTHER = "other"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Work(DevRevResponseModel):
|
|
66
|
+
"""DevRev Work item model.
|
|
67
|
+
|
|
68
|
+
Represents a work item (issue, ticket, task, or opportunity).
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
id: str = Field(..., description="Work item ID")
|
|
72
|
+
type: WorkType = Field(..., description="Work item type")
|
|
73
|
+
display_id: str | None = Field(default=None, description="Human-readable display ID")
|
|
74
|
+
title: str | None = Field(default=None, description="Work item title")
|
|
75
|
+
body: str | None = Field(default=None, description="Work item body/description")
|
|
76
|
+
created_date: datetime | None = Field(default=None, description="Creation timestamp")
|
|
77
|
+
modified_date: datetime | None = Field(default=None, description="Last modification timestamp")
|
|
78
|
+
created_by: UserSummary | None = Field(default=None, description="User who created the work")
|
|
79
|
+
modified_by: UserSummary | None = Field(
|
|
80
|
+
default=None, description="User who last modified the work"
|
|
81
|
+
)
|
|
82
|
+
owned_by: list[UserSummary] | None = Field(default=None, description="Work owners")
|
|
83
|
+
reported_by: list[UserSummary] | None = Field(
|
|
84
|
+
default=None, description="Users who reported this work"
|
|
85
|
+
)
|
|
86
|
+
applies_to_part: str | None = Field(default=None, description="Part this work applies to")
|
|
87
|
+
stage: StageInfo | None = Field(default=None, description="Work stage")
|
|
88
|
+
tags: list[TagWithValue] | None = Field(default=None, description="Work tags")
|
|
89
|
+
priority: str | None = Field(default=None, description="Issue priority")
|
|
90
|
+
severity: str | None = Field(default=None, description="Ticket severity")
|
|
91
|
+
target_close_date: datetime | None = Field(default=None, description="Target close date")
|
|
92
|
+
actual_close_date: datetime | None = Field(default=None, description="Actual close date")
|
|
93
|
+
custom_fields: dict[str, Any] | None = Field(default=None, description="Custom fields")
|
|
94
|
+
external_ref: str | None = Field(default=None, description="External reference")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class WorkSummary(DevRevResponseModel):
|
|
98
|
+
"""Summary of a Work item for list/reference operations."""
|
|
99
|
+
|
|
100
|
+
id: str = Field(..., description="Work item ID")
|
|
101
|
+
type: WorkType = Field(..., description="Work item type")
|
|
102
|
+
display_id: str | None = Field(default=None, description="Human-readable display ID")
|
|
103
|
+
title: str | None = Field(default=None, description="Work item title")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Request Models
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class WorksCreateRequestIssue(DevRevBaseModel):
|
|
110
|
+
"""Issue-specific fields for work creation."""
|
|
111
|
+
|
|
112
|
+
priority: IssuePriority | None = Field(default=None, description="Issue priority")
|
|
113
|
+
priority_v2: int | None = Field(default=None, description="Priority enum ID")
|
|
114
|
+
target_start_date: datetime | None = Field(default=None, description="Target start date")
|
|
115
|
+
developed_with: list[str] | None = Field(
|
|
116
|
+
default=None, description="Part IDs associated with issue"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class WorksCreateRequestTicket(DevRevBaseModel):
|
|
121
|
+
"""Ticket-specific fields for work creation."""
|
|
122
|
+
|
|
123
|
+
account: str | None = Field(default=None, description="Associated account ID")
|
|
124
|
+
channels: list[TicketChannels] | None = Field(default=None, description="Ticket channels")
|
|
125
|
+
rev_org: str | None = Field(default=None, description="Rev organization ID")
|
|
126
|
+
severity: TicketSeverity | None = Field(default=None, description="Ticket severity")
|
|
127
|
+
is_spam: bool | None = Field(default=None, description="Whether the ticket is spam")
|
|
128
|
+
needs_response: bool | None = Field(default=None, description="Whether response is needed")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class WorksCreateRequest(DevRevBaseModel):
|
|
132
|
+
"""Request to create a work item."""
|
|
133
|
+
|
|
134
|
+
type: WorkType = Field(..., description="Work item type")
|
|
135
|
+
title: str = Field(..., description="Work title", min_length=1, max_length=256)
|
|
136
|
+
applies_to_part: str = Field(..., description="Part ID this work applies to")
|
|
137
|
+
owned_by: list[str] | None = Field(default=None, description="Owner user IDs")
|
|
138
|
+
body: str | None = Field(default=None, description="Work body", max_length=65536)
|
|
139
|
+
artifacts: list[str] | None = Field(default=None, description="Artifact IDs")
|
|
140
|
+
external_ref: str | None = Field(default=None, description="External reference")
|
|
141
|
+
target_close_date: datetime | None = Field(default=None, description="Target close date")
|
|
142
|
+
custom_fields: dict[str, Any] | None = Field(default=None, description="Custom fields")
|
|
143
|
+
custom_schema_spec: CustomSchemaSpec | None = Field(
|
|
144
|
+
default=None, description="Custom schema spec"
|
|
145
|
+
)
|
|
146
|
+
# Issue-specific
|
|
147
|
+
priority: IssuePriority | None = Field(default=None, description="Issue priority (for issues)")
|
|
148
|
+
# Ticket-specific
|
|
149
|
+
severity: TicketSeverity | None = Field(
|
|
150
|
+
default=None, description="Ticket severity (for tickets)"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class WorksGetRequest(DevRevBaseModel):
|
|
155
|
+
"""Request to get a work item by ID."""
|
|
156
|
+
|
|
157
|
+
id: str = Field(..., description="Work item ID")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class WorksListRequest(DevRevBaseModel):
|
|
161
|
+
"""Request to list work items."""
|
|
162
|
+
|
|
163
|
+
type: list[WorkType] | None = Field(default=None, description="Filter by work types")
|
|
164
|
+
applies_to_part: list[str] | None = Field(default=None, description="Filter by part IDs")
|
|
165
|
+
created_by: list[str] | None = Field(default=None, description="Filter by creator user IDs")
|
|
166
|
+
created_date: DateFilter | None = Field(default=None, description="Filter by creation date")
|
|
167
|
+
cursor: str | None = Field(default=None, description="Pagination cursor")
|
|
168
|
+
external_ref: list[str] | None = Field(default=None, description="Filter by external refs")
|
|
169
|
+
limit: int | None = Field(default=None, ge=1, le=100, description="Max results to return")
|
|
170
|
+
modified_date: DateFilter | None = Field(
|
|
171
|
+
default=None, description="Filter by modification date"
|
|
172
|
+
)
|
|
173
|
+
owned_by: list[str] | None = Field(default=None, description="Filter by owner user IDs")
|
|
174
|
+
sort_by: list[str] | None = Field(default=None, description="Sort order")
|
|
175
|
+
stage_name: list[str] | None = Field(default=None, description="Filter by stage names")
|
|
176
|
+
target_close_date: DateFilter | None = Field(
|
|
177
|
+
default=None, description="Filter by target close date"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class WorksUpdateRequestOwnedBy(DevRevBaseModel):
|
|
182
|
+
"""Owned by update for work items."""
|
|
183
|
+
|
|
184
|
+
set: list[str] | None = Field(default=None, description="Set owner IDs")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class WorksUpdateRequestTags(DevRevBaseModel):
|
|
188
|
+
"""Tags update for work items."""
|
|
189
|
+
|
|
190
|
+
set: list[SetTagWithValue] | None = Field(default=None, description="Set tags")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class WorksUpdateRequest(DevRevBaseModel):
|
|
194
|
+
"""Request to update a work item."""
|
|
195
|
+
|
|
196
|
+
id: str = Field(..., description="Work item ID")
|
|
197
|
+
title: str | None = Field(default=None, description="New title")
|
|
198
|
+
body: str | None = Field(default=None, description="New body")
|
|
199
|
+
applies_to_part: str | None = Field(default=None, description="New part ID")
|
|
200
|
+
owned_by: WorksUpdateRequestOwnedBy | None = Field(default=None, description="New owners")
|
|
201
|
+
stage: StageUpdate | None = Field(default=None, description="New stage")
|
|
202
|
+
tags: WorksUpdateRequestTags | None = Field(default=None, description="New tags")
|
|
203
|
+
target_close_date: datetime | None = Field(default=None, description="New target close date")
|
|
204
|
+
custom_fields: dict[str, Any] | None = Field(
|
|
205
|
+
default=None, description="Custom fields to update"
|
|
206
|
+
)
|
|
207
|
+
# Issue-specific
|
|
208
|
+
priority: IssuePriority | None = Field(default=None, description="New priority")
|
|
209
|
+
# Ticket-specific
|
|
210
|
+
severity: TicketSeverity | None = Field(default=None, description="New severity")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class WorksDeleteRequest(DevRevBaseModel):
|
|
214
|
+
"""Request to delete a work item."""
|
|
215
|
+
|
|
216
|
+
id: str = Field(..., description="Work item ID to delete")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class WorksExportRequest(DevRevBaseModel):
|
|
220
|
+
"""Request to export work items."""
|
|
221
|
+
|
|
222
|
+
type: list[WorkType] | None = Field(default=None, description="Filter by work types")
|
|
223
|
+
applies_to_part: list[str] | None = Field(default=None, description="Filter by part IDs")
|
|
224
|
+
created_by: list[str] | None = Field(default=None, description="Filter by creator user IDs")
|
|
225
|
+
created_date: DateFilter | None = Field(default=None, description="Filter by creation date")
|
|
226
|
+
first: int | None = Field(default=None, ge=1, le=10000, description="Max results")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class WorksCountRequest(DevRevBaseModel):
|
|
230
|
+
"""Request to count work items."""
|
|
231
|
+
|
|
232
|
+
type: list[WorkType] | None = Field(default=None, description="Filter by work types")
|
|
233
|
+
applies_to_part: list[str] | None = Field(default=None, description="Filter by part IDs")
|
|
234
|
+
created_by: list[str] | None = Field(default=None, description="Filter by creator user IDs")
|
|
235
|
+
owned_by: list[str] | None = Field(default=None, description="Filter by owner user IDs")
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# Response Models
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class WorksCreateResponse(DevRevResponseModel):
|
|
242
|
+
"""Response from creating a work item."""
|
|
243
|
+
|
|
244
|
+
work: Work = Field(..., description="Created work item")
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class WorksGetResponse(DevRevResponseModel):
|
|
248
|
+
"""Response from getting a work item."""
|
|
249
|
+
|
|
250
|
+
work: Work = Field(..., description="Retrieved work item")
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class WorksListResponse(PaginatedResponse):
|
|
254
|
+
"""Response from listing work items."""
|
|
255
|
+
|
|
256
|
+
works: list[Work] = Field(..., description="List of work items")
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class WorksUpdateResponse(DevRevResponseModel):
|
|
260
|
+
"""Response from updating a work item."""
|
|
261
|
+
|
|
262
|
+
work: Work = Field(..., description="Updated work item")
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class WorksDeleteResponse(DevRevResponseModel):
|
|
266
|
+
"""Response from deleting a work item."""
|
|
267
|
+
|
|
268
|
+
pass # Empty response body
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class WorksExportResponse(DevRevResponseModel):
|
|
272
|
+
"""Response from exporting work items."""
|
|
273
|
+
|
|
274
|
+
works: list[Work] = Field(..., description="Exported work items")
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class WorksCountResponse(DevRevResponseModel):
|
|
278
|
+
"""Response from counting work items."""
|
|
279
|
+
|
|
280
|
+
count: int = Field(..., description="Number of matching work items")
|
devrev/py.typed
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""DevRev SDK Service Classes.
|
|
2
|
+
|
|
3
|
+
This module contains service classes for interacting with DevRev API endpoints.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from devrev.services.accounts import AccountsService, AsyncAccountsService
|
|
7
|
+
from devrev.services.articles import ArticlesService, AsyncArticlesService
|
|
8
|
+
from devrev.services.base import AsyncBaseService, BaseService
|
|
9
|
+
from devrev.services.code_changes import AsyncCodeChangesService, CodeChangesService
|
|
10
|
+
from devrev.services.conversations import (
|
|
11
|
+
AsyncConversationsService,
|
|
12
|
+
ConversationsService,
|
|
13
|
+
)
|
|
14
|
+
from devrev.services.dev_users import AsyncDevUsersService, DevUsersService
|
|
15
|
+
from devrev.services.groups import AsyncGroupsService, GroupsService
|
|
16
|
+
from devrev.services.links import AsyncLinksService, LinksService
|
|
17
|
+
from devrev.services.parts import AsyncPartsService, PartsService
|
|
18
|
+
from devrev.services.rev_users import AsyncRevUsersService, RevUsersService
|
|
19
|
+
from devrev.services.slas import AsyncSlasService, SlasService
|
|
20
|
+
from devrev.services.tags import AsyncTagsService, TagsService
|
|
21
|
+
from devrev.services.timeline_entries import (
|
|
22
|
+
AsyncTimelineEntriesService,
|
|
23
|
+
TimelineEntriesService,
|
|
24
|
+
)
|
|
25
|
+
from devrev.services.webhooks import AsyncWebhooksService, WebhooksService
|
|
26
|
+
from devrev.services.works import AsyncWorksService, WorksService
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
# Base
|
|
30
|
+
"BaseService",
|
|
31
|
+
"AsyncBaseService",
|
|
32
|
+
# Accounts
|
|
33
|
+
"AccountsService",
|
|
34
|
+
"AsyncAccountsService",
|
|
35
|
+
# Articles
|
|
36
|
+
"ArticlesService",
|
|
37
|
+
"AsyncArticlesService",
|
|
38
|
+
# Code Changes
|
|
39
|
+
"CodeChangesService",
|
|
40
|
+
"AsyncCodeChangesService",
|
|
41
|
+
# Conversations
|
|
42
|
+
"ConversationsService",
|
|
43
|
+
"AsyncConversationsService",
|
|
44
|
+
# Dev Users
|
|
45
|
+
"DevUsersService",
|
|
46
|
+
"AsyncDevUsersService",
|
|
47
|
+
# Groups
|
|
48
|
+
"GroupsService",
|
|
49
|
+
"AsyncGroupsService",
|
|
50
|
+
# Links
|
|
51
|
+
"LinksService",
|
|
52
|
+
"AsyncLinksService",
|
|
53
|
+
# Parts
|
|
54
|
+
"PartsService",
|
|
55
|
+
"AsyncPartsService",
|
|
56
|
+
# Rev Users
|
|
57
|
+
"RevUsersService",
|
|
58
|
+
"AsyncRevUsersService",
|
|
59
|
+
# SLAs
|
|
60
|
+
"SlasService",
|
|
61
|
+
"AsyncSlasService",
|
|
62
|
+
# Tags
|
|
63
|
+
"TagsService",
|
|
64
|
+
"AsyncTagsService",
|
|
65
|
+
# Timeline Entries
|
|
66
|
+
"TimelineEntriesService",
|
|
67
|
+
"AsyncTimelineEntriesService",
|
|
68
|
+
# Webhooks
|
|
69
|
+
"WebhooksService",
|
|
70
|
+
"AsyncWebhooksService",
|
|
71
|
+
# Works
|
|
72
|
+
"WorksService",
|
|
73
|
+
"AsyncWorksService",
|
|
74
|
+
]
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"""Accounts service for DevRev SDK.
|
|
2
|
+
|
|
3
|
+
This module provides the AccountsService for managing DevRev accounts.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import Sequence
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
from devrev.models.accounts import (
|
|
12
|
+
Account,
|
|
13
|
+
AccountsCreateRequest,
|
|
14
|
+
AccountsCreateResponse,
|
|
15
|
+
AccountsDeleteRequest,
|
|
16
|
+
AccountsDeleteResponse,
|
|
17
|
+
AccountsExportRequest,
|
|
18
|
+
AccountsExportResponse,
|
|
19
|
+
AccountsGetRequest,
|
|
20
|
+
AccountsGetResponse,
|
|
21
|
+
AccountsListRequest,
|
|
22
|
+
AccountsListResponse,
|
|
23
|
+
AccountsMergeRequest,
|
|
24
|
+
AccountsMergeResponse,
|
|
25
|
+
AccountsUpdateRequest,
|
|
26
|
+
AccountsUpdateResponse,
|
|
27
|
+
)
|
|
28
|
+
from devrev.services.base import AsyncBaseService, BaseService
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from devrev.utils.http import AsyncHTTPClient, HTTPClient
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AccountsService(BaseService):
|
|
35
|
+
"""Synchronous service for managing DevRev accounts.
|
|
36
|
+
|
|
37
|
+
Provides methods for creating, reading, updating, and deleting accounts.
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
```python
|
|
41
|
+
from devrev import DevRevClient
|
|
42
|
+
|
|
43
|
+
client = DevRevClient()
|
|
44
|
+
accounts = client.accounts.list()
|
|
45
|
+
```
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, http_client: HTTPClient) -> None:
|
|
49
|
+
"""Initialize the AccountsService."""
|
|
50
|
+
super().__init__(http_client)
|
|
51
|
+
|
|
52
|
+
def create(
|
|
53
|
+
self,
|
|
54
|
+
display_name: str,
|
|
55
|
+
*,
|
|
56
|
+
description: str | None = None,
|
|
57
|
+
domains: list[str] | None = None,
|
|
58
|
+
external_refs: list[str] | None = None,
|
|
59
|
+
owned_by: list[str] | None = None,
|
|
60
|
+
tier: str | None = None,
|
|
61
|
+
custom_fields: dict[str, Any] | None = None,
|
|
62
|
+
) -> Account:
|
|
63
|
+
"""Create a new account.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
display_name: Account display name
|
|
67
|
+
description: Account description
|
|
68
|
+
domains: Associated domains
|
|
69
|
+
external_refs: External references
|
|
70
|
+
owned_by: Owner user IDs
|
|
71
|
+
tier: Account tier
|
|
72
|
+
custom_fields: Custom fields
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
The created Account
|
|
76
|
+
"""
|
|
77
|
+
request = AccountsCreateRequest(
|
|
78
|
+
display_name=display_name,
|
|
79
|
+
description=description,
|
|
80
|
+
domains=domains,
|
|
81
|
+
external_refs=external_refs,
|
|
82
|
+
owned_by=owned_by,
|
|
83
|
+
tier=tier,
|
|
84
|
+
custom_fields=custom_fields,
|
|
85
|
+
)
|
|
86
|
+
response = self._post("/accounts.create", request, AccountsCreateResponse)
|
|
87
|
+
return response.account
|
|
88
|
+
|
|
89
|
+
def get(self, id: str) -> Account:
|
|
90
|
+
"""Get an account by ID.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
id: Account ID
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
The Account
|
|
97
|
+
"""
|
|
98
|
+
request = AccountsGetRequest(id=id)
|
|
99
|
+
response = self._post("/accounts.get", request, AccountsGetResponse)
|
|
100
|
+
return response.account
|
|
101
|
+
|
|
102
|
+
def list(
|
|
103
|
+
self,
|
|
104
|
+
*,
|
|
105
|
+
cursor: str | None = None,
|
|
106
|
+
limit: int | None = None,
|
|
107
|
+
display_name: list[str] | None = None,
|
|
108
|
+
domains: list[str] | None = None,
|
|
109
|
+
owned_by: list[str] | None = None,
|
|
110
|
+
) -> AccountsListResponse:
|
|
111
|
+
"""List accounts.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
cursor: Pagination cursor
|
|
115
|
+
limit: Maximum number of results
|
|
116
|
+
display_name: Filter by display names
|
|
117
|
+
domains: Filter by domains
|
|
118
|
+
owned_by: Filter by owner user IDs
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Paginated list of accounts
|
|
122
|
+
"""
|
|
123
|
+
request = AccountsListRequest(
|
|
124
|
+
cursor=cursor,
|
|
125
|
+
limit=limit,
|
|
126
|
+
display_name=display_name,
|
|
127
|
+
domains=domains,
|
|
128
|
+
owned_by=owned_by,
|
|
129
|
+
)
|
|
130
|
+
return self._post("/accounts.list", request, AccountsListResponse)
|
|
131
|
+
|
|
132
|
+
def update(
|
|
133
|
+
self,
|
|
134
|
+
id: str,
|
|
135
|
+
*,
|
|
136
|
+
display_name: str | None = None,
|
|
137
|
+
description: str | None = None,
|
|
138
|
+
tier: str | None = None,
|
|
139
|
+
custom_fields: dict[str, Any] | None = None,
|
|
140
|
+
) -> Account:
|
|
141
|
+
"""Update an account.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
id: Account ID
|
|
145
|
+
display_name: New display name
|
|
146
|
+
description: New description
|
|
147
|
+
tier: New tier
|
|
148
|
+
custom_fields: Custom fields to update
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
The updated Account
|
|
152
|
+
"""
|
|
153
|
+
request = AccountsUpdateRequest(
|
|
154
|
+
id=id,
|
|
155
|
+
display_name=display_name,
|
|
156
|
+
description=description,
|
|
157
|
+
tier=tier,
|
|
158
|
+
custom_fields=custom_fields,
|
|
159
|
+
)
|
|
160
|
+
response = self._post("/accounts.update", request, AccountsUpdateResponse)
|
|
161
|
+
return response.account
|
|
162
|
+
|
|
163
|
+
def delete(self, id: str) -> None:
|
|
164
|
+
"""Delete an account.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
id: Account ID to delete
|
|
168
|
+
"""
|
|
169
|
+
request = AccountsDeleteRequest(id=id)
|
|
170
|
+
self._post("/accounts.delete", request, AccountsDeleteResponse)
|
|
171
|
+
|
|
172
|
+
def merge(self, primary_account: str, secondary_account: str) -> Account:
|
|
173
|
+
"""Merge two accounts.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
primary_account: Primary account ID (will be retained)
|
|
177
|
+
secondary_account: Secondary account ID (will be merged)
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
The merged Account
|
|
181
|
+
"""
|
|
182
|
+
request = AccountsMergeRequest(
|
|
183
|
+
primary_account=primary_account,
|
|
184
|
+
secondary_account=secondary_account,
|
|
185
|
+
)
|
|
186
|
+
response = self._post("/accounts.merge", request, AccountsMergeResponse)
|
|
187
|
+
return response.account
|
|
188
|
+
|
|
189
|
+
def export(
|
|
190
|
+
self,
|
|
191
|
+
*,
|
|
192
|
+
created_by: Sequence[str] | None = None,
|
|
193
|
+
first: int | None = None,
|
|
194
|
+
) -> Sequence[Account]:
|
|
195
|
+
"""Export accounts.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
created_by: Filter by creator user IDs
|
|
199
|
+
first: Maximum number of results
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
List of exported accounts
|
|
203
|
+
"""
|
|
204
|
+
request = AccountsExportRequest(
|
|
205
|
+
created_by=created_by,
|
|
206
|
+
first=first,
|
|
207
|
+
)
|
|
208
|
+
response = self._post("/accounts.export", request, AccountsExportResponse)
|
|
209
|
+
return response.accounts
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class AsyncAccountsService(AsyncBaseService):
|
|
213
|
+
"""Asynchronous service for managing DevRev accounts.
|
|
214
|
+
|
|
215
|
+
Provides async methods for creating, reading, updating, and deleting accounts.
|
|
216
|
+
|
|
217
|
+
Example:
|
|
218
|
+
```python
|
|
219
|
+
from devrev import AsyncDevRevClient
|
|
220
|
+
|
|
221
|
+
async with AsyncDevRevClient() as client:
|
|
222
|
+
accounts = await client.accounts.list()
|
|
223
|
+
```
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
def __init__(self, http_client: AsyncHTTPClient) -> None:
|
|
227
|
+
"""Initialize the AsyncAccountsService."""
|
|
228
|
+
super().__init__(http_client)
|
|
229
|
+
|
|
230
|
+
async def create(
|
|
231
|
+
self,
|
|
232
|
+
display_name: str,
|
|
233
|
+
*,
|
|
234
|
+
description: str | None = None,
|
|
235
|
+
domains: list[str] | None = None,
|
|
236
|
+
external_refs: list[str] | None = None,
|
|
237
|
+
owned_by: list[str] | None = None,
|
|
238
|
+
tier: str | None = None,
|
|
239
|
+
custom_fields: dict[str, Any] | None = None,
|
|
240
|
+
) -> Account:
|
|
241
|
+
"""Create a new account."""
|
|
242
|
+
request = AccountsCreateRequest(
|
|
243
|
+
display_name=display_name,
|
|
244
|
+
description=description,
|
|
245
|
+
domains=domains,
|
|
246
|
+
external_refs=external_refs,
|
|
247
|
+
owned_by=owned_by,
|
|
248
|
+
tier=tier,
|
|
249
|
+
custom_fields=custom_fields,
|
|
250
|
+
)
|
|
251
|
+
response = await self._post("/accounts.create", request, AccountsCreateResponse)
|
|
252
|
+
return response.account
|
|
253
|
+
|
|
254
|
+
async def get(self, id: str) -> Account:
|
|
255
|
+
"""Get an account by ID."""
|
|
256
|
+
request = AccountsGetRequest(id=id)
|
|
257
|
+
response = await self._post("/accounts.get", request, AccountsGetResponse)
|
|
258
|
+
return response.account
|
|
259
|
+
|
|
260
|
+
async def list(
|
|
261
|
+
self,
|
|
262
|
+
*,
|
|
263
|
+
cursor: str | None = None,
|
|
264
|
+
limit: int | None = None,
|
|
265
|
+
display_name: list[str] | None = None,
|
|
266
|
+
domains: list[str] | None = None,
|
|
267
|
+
owned_by: list[str] | None = None,
|
|
268
|
+
) -> AccountsListResponse:
|
|
269
|
+
"""List accounts."""
|
|
270
|
+
request = AccountsListRequest(
|
|
271
|
+
cursor=cursor,
|
|
272
|
+
limit=limit,
|
|
273
|
+
display_name=display_name,
|
|
274
|
+
domains=domains,
|
|
275
|
+
owned_by=owned_by,
|
|
276
|
+
)
|
|
277
|
+
return await self._post("/accounts.list", request, AccountsListResponse)
|
|
278
|
+
|
|
279
|
+
async def update(
|
|
280
|
+
self,
|
|
281
|
+
id: str,
|
|
282
|
+
*,
|
|
283
|
+
display_name: str | None = None,
|
|
284
|
+
description: str | None = None,
|
|
285
|
+
tier: str | None = None,
|
|
286
|
+
custom_fields: dict[str, Any] | None = None,
|
|
287
|
+
) -> Account:
|
|
288
|
+
"""Update an account."""
|
|
289
|
+
request = AccountsUpdateRequest(
|
|
290
|
+
id=id,
|
|
291
|
+
display_name=display_name,
|
|
292
|
+
description=description,
|
|
293
|
+
tier=tier,
|
|
294
|
+
custom_fields=custom_fields,
|
|
295
|
+
)
|
|
296
|
+
response = await self._post("/accounts.update", request, AccountsUpdateResponse)
|
|
297
|
+
return response.account
|
|
298
|
+
|
|
299
|
+
async def delete(self, id: str) -> None:
|
|
300
|
+
"""Delete an account."""
|
|
301
|
+
request = AccountsDeleteRequest(id=id)
|
|
302
|
+
await self._post("/accounts.delete", request, AccountsDeleteResponse)
|
|
303
|
+
|
|
304
|
+
async def merge(self, primary_account: str, secondary_account: str) -> Account:
|
|
305
|
+
"""Merge two accounts."""
|
|
306
|
+
request = AccountsMergeRequest(
|
|
307
|
+
primary_account=primary_account,
|
|
308
|
+
secondary_account=secondary_account,
|
|
309
|
+
)
|
|
310
|
+
response = await self._post("/accounts.merge", request, AccountsMergeResponse)
|
|
311
|
+
return response.account
|
|
312
|
+
|
|
313
|
+
async def export(
|
|
314
|
+
self,
|
|
315
|
+
*,
|
|
316
|
+
created_by: Sequence[str] | None = None,
|
|
317
|
+
first: int | None = None,
|
|
318
|
+
) -> Sequence[Account]:
|
|
319
|
+
"""Export accounts."""
|
|
320
|
+
request = AccountsExportRequest(
|
|
321
|
+
created_by=created_by,
|
|
322
|
+
first=first,
|
|
323
|
+
)
|
|
324
|
+
response = await self._post("/accounts.export", request, AccountsExportResponse)
|
|
325
|
+
return response.accounts
|