redblack-python-sdk 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.
- redblack/__init__.py +105 -0
- redblack/_generated/__init__.py +39 -0
- redblack/_generated/contract.py +212 -0
- redblack/_generated/operation_specs.py +5115 -0
- redblack/_version.py +4 -0
- redblack/auth.py +352 -0
- redblack/client.py +512 -0
- redblack/config.py +576 -0
- redblack/downloads.py +410 -0
- redblack/errors.py +483 -0
- redblack/models/__init__.py +105 -0
- redblack/models/base.py +150 -0
- redblack/models/generated.py +11736 -0
- redblack/odata.py +75 -0
- redblack/pagination.py +184 -0
- redblack/polling.py +163 -0
- redblack/py.typed +1 -0
- redblack/raw.py +102 -0
- redblack/resources/__init__.py +65 -0
- redblack/resources/_base.py +212 -0
- redblack/resources/_collections.py +80 -0
- redblack/resources/_exports.py +215 -0
- redblack/resources/accounts.py +132 -0
- redblack/resources/cash_actions.py +260 -0
- redblack/resources/equivalents.py +144 -0
- redblack/resources/households.py +138 -0
- redblack/resources/orders.py +118 -0
- redblack/resources/restrictions.py +146 -0
- redblack/resources/review_sets.py +889 -0
- redblack/resources/securities.py +175 -0
- redblack/resources/tasks.py +291 -0
- redblack/resources/users.py +88 -0
- redblack/response.py +118 -0
- redblack/transport.py +606 -0
- redblack_python_sdk-0.1.0.dist-info/METADATA +151 -0
- redblack_python_sdk-0.1.0.dist-info/RECORD +38 -0
- redblack_python_sdk-0.1.0.dist-info/WHEEL +5 -0
- redblack_python_sdk-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Securities and sweep-securities collection operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from typing import Any, Literal, overload
|
|
7
|
+
|
|
8
|
+
from ..models import Security, SweepSecurity
|
|
9
|
+
from ..odata import DEFAULT_PAGE_SIZE, ODataQuery
|
|
10
|
+
from ..pagination import Page, Paginator
|
|
11
|
+
from ._base import ApiResponseProtocol, HttpInfoMode, Resource
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SecuritiesResource(Resource[HttpInfoMode]):
|
|
15
|
+
OPERATION_IDS = frozenset({"Securities_Query", "Securities_QuerySweep"})
|
|
16
|
+
|
|
17
|
+
def _list_operation(
|
|
18
|
+
self,
|
|
19
|
+
operation_id: str,
|
|
20
|
+
*,
|
|
21
|
+
filter: str | None = None,
|
|
22
|
+
order_by: str | None = None,
|
|
23
|
+
top: int | None = None,
|
|
24
|
+
skip: int | None = None,
|
|
25
|
+
count: bool | None = None,
|
|
26
|
+
) -> Page[Any] | ApiResponseProtocol[Page[Any]]:
|
|
27
|
+
return self._page(
|
|
28
|
+
operation_id,
|
|
29
|
+
odata=ODataQuery(
|
|
30
|
+
filter=filter,
|
|
31
|
+
order_by=order_by,
|
|
32
|
+
top=top,
|
|
33
|
+
skip=skip,
|
|
34
|
+
count=count,
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
@overload
|
|
39
|
+
def list(
|
|
40
|
+
self: SecuritiesResource[Literal[False]],
|
|
41
|
+
*,
|
|
42
|
+
filter: str | None = None,
|
|
43
|
+
order_by: str | None = None,
|
|
44
|
+
top: int | None = None,
|
|
45
|
+
skip: int | None = None,
|
|
46
|
+
count: bool | None = None,
|
|
47
|
+
) -> Page[Security]: ...
|
|
48
|
+
|
|
49
|
+
@overload
|
|
50
|
+
def list(
|
|
51
|
+
self: SecuritiesResource[Literal[True]],
|
|
52
|
+
*,
|
|
53
|
+
filter: str | None = None,
|
|
54
|
+
order_by: str | None = None,
|
|
55
|
+
top: int | None = None,
|
|
56
|
+
skip: int | None = None,
|
|
57
|
+
count: bool | None = None,
|
|
58
|
+
) -> ApiResponseProtocol[Page[Security]]: ...
|
|
59
|
+
|
|
60
|
+
def list(
|
|
61
|
+
self,
|
|
62
|
+
*,
|
|
63
|
+
filter: str | None = None,
|
|
64
|
+
order_by: str | None = None,
|
|
65
|
+
top: int | None = None,
|
|
66
|
+
skip: int | None = None,
|
|
67
|
+
count: bool | None = None,
|
|
68
|
+
) -> Page[Security] | ApiResponseProtocol[Page[Security]]:
|
|
69
|
+
return self._list_operation(
|
|
70
|
+
"Securities_Query",
|
|
71
|
+
filter=filter,
|
|
72
|
+
order_by=order_by,
|
|
73
|
+
top=top,
|
|
74
|
+
skip=skip,
|
|
75
|
+
count=count,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@overload
|
|
79
|
+
def list_sweeps(
|
|
80
|
+
self: SecuritiesResource[Literal[False]],
|
|
81
|
+
*,
|
|
82
|
+
filter: str | None = None,
|
|
83
|
+
order_by: str | None = None,
|
|
84
|
+
top: int | None = None,
|
|
85
|
+
skip: int | None = None,
|
|
86
|
+
count: bool | None = None,
|
|
87
|
+
) -> Page[SweepSecurity]: ...
|
|
88
|
+
|
|
89
|
+
@overload
|
|
90
|
+
def list_sweeps(
|
|
91
|
+
self: SecuritiesResource[Literal[True]],
|
|
92
|
+
*,
|
|
93
|
+
filter: str | None = None,
|
|
94
|
+
order_by: str | None = None,
|
|
95
|
+
top: int | None = None,
|
|
96
|
+
skip: int | None = None,
|
|
97
|
+
count: bool | None = None,
|
|
98
|
+
) -> ApiResponseProtocol[Page[SweepSecurity]]: ...
|
|
99
|
+
|
|
100
|
+
def list_sweeps(
|
|
101
|
+
self,
|
|
102
|
+
*,
|
|
103
|
+
filter: str | None = None,
|
|
104
|
+
order_by: str | None = None,
|
|
105
|
+
top: int | None = None,
|
|
106
|
+
skip: int | None = None,
|
|
107
|
+
count: bool | None = None,
|
|
108
|
+
) -> Page[SweepSecurity] | ApiResponseProtocol[Page[SweepSecurity]]:
|
|
109
|
+
return self._list_operation(
|
|
110
|
+
"Securities_QuerySweep",
|
|
111
|
+
filter=filter,
|
|
112
|
+
order_by=order_by,
|
|
113
|
+
top=top,
|
|
114
|
+
skip=skip,
|
|
115
|
+
count=count,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def _iterator(
|
|
119
|
+
self,
|
|
120
|
+
operation_id: str,
|
|
121
|
+
*,
|
|
122
|
+
filter: str | None,
|
|
123
|
+
order_by: str | None,
|
|
124
|
+
count: bool | None,
|
|
125
|
+
start_skip: int,
|
|
126
|
+
page_size: int,
|
|
127
|
+
max_items: int | None,
|
|
128
|
+
) -> Paginator[Any]:
|
|
129
|
+
base = ODataQuery(filter=filter, order_by=order_by, count=count, skip=start_skip)
|
|
130
|
+
return Paginator(
|
|
131
|
+
fetch_page=lambda query: self._page_value(operation_id, odata=query),
|
|
132
|
+
query=base,
|
|
133
|
+
page_size=page_size,
|
|
134
|
+
max_items=max_items,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def iter_all(
|
|
138
|
+
self,
|
|
139
|
+
*,
|
|
140
|
+
filter: str | None = None,
|
|
141
|
+
order_by: str | None = None,
|
|
142
|
+
count: bool | None = None,
|
|
143
|
+
start_skip: int = 0,
|
|
144
|
+
page_size: int = DEFAULT_PAGE_SIZE,
|
|
145
|
+
max_items: int | None = None,
|
|
146
|
+
) -> Iterator[Security]:
|
|
147
|
+
return self._iterator(
|
|
148
|
+
"Securities_Query",
|
|
149
|
+
filter=filter,
|
|
150
|
+
order_by=order_by,
|
|
151
|
+
count=count,
|
|
152
|
+
start_skip=start_skip,
|
|
153
|
+
page_size=page_size,
|
|
154
|
+
max_items=max_items,
|
|
155
|
+
).iter_items()
|
|
156
|
+
|
|
157
|
+
def iter_all_sweeps(
|
|
158
|
+
self,
|
|
159
|
+
*,
|
|
160
|
+
filter: str | None = None,
|
|
161
|
+
order_by: str | None = None,
|
|
162
|
+
count: bool | None = None,
|
|
163
|
+
start_skip: int = 0,
|
|
164
|
+
page_size: int = DEFAULT_PAGE_SIZE,
|
|
165
|
+
max_items: int | None = None,
|
|
166
|
+
) -> Iterator[SweepSecurity]:
|
|
167
|
+
return self._iterator(
|
|
168
|
+
"Securities_QuerySweep",
|
|
169
|
+
filter=filter,
|
|
170
|
+
order_by=order_by,
|
|
171
|
+
count=count,
|
|
172
|
+
start_skip=start_skip,
|
|
173
|
+
page_size=page_size,
|
|
174
|
+
max_items=max_items,
|
|
175
|
+
).iter_items()
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""Task resources, settings lookups, and ETag-protected mutations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator, Mapping
|
|
6
|
+
from typing import Any, Literal, overload
|
|
7
|
+
|
|
8
|
+
from ..models import (
|
|
9
|
+
Task,
|
|
10
|
+
TaskCreate,
|
|
11
|
+
TaskCreateResult,
|
|
12
|
+
TaskListItem,
|
|
13
|
+
TaskStatus,
|
|
14
|
+
TaskType,
|
|
15
|
+
TaskUpdate,
|
|
16
|
+
TaskUpdateResult,
|
|
17
|
+
)
|
|
18
|
+
from ..odata import DEFAULT_PAGE_SIZE, ODataQuery
|
|
19
|
+
from ..pagination import Page, Paginator
|
|
20
|
+
from ._base import (
|
|
21
|
+
ApiResponseProtocol,
|
|
22
|
+
HttpInfoMode,
|
|
23
|
+
Resource,
|
|
24
|
+
VersionedResource,
|
|
25
|
+
body_value,
|
|
26
|
+
require_etag,
|
|
27
|
+
require_positive_identifier,
|
|
28
|
+
response_header,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TasksResource(Resource[HttpInfoMode]):
|
|
33
|
+
OPERATION_IDS = frozenset(
|
|
34
|
+
{
|
|
35
|
+
"TaskSettings_ListTypes",
|
|
36
|
+
"TaskSettings_ListStatuses",
|
|
37
|
+
"Tasks_ListTasks",
|
|
38
|
+
"Tasks_Add",
|
|
39
|
+
"Tasks_Get",
|
|
40
|
+
"Tasks_Delete",
|
|
41
|
+
"Tasks_Update",
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def _collection(
|
|
46
|
+
self,
|
|
47
|
+
operation_id: str,
|
|
48
|
+
*,
|
|
49
|
+
filter: str | None = None,
|
|
50
|
+
order_by: str | None = None,
|
|
51
|
+
top: int | None = None,
|
|
52
|
+
skip: int | None = None,
|
|
53
|
+
count: bool | None = None,
|
|
54
|
+
) -> Page[Any] | ApiResponseProtocol[Page[Any]]:
|
|
55
|
+
return self._page(
|
|
56
|
+
operation_id,
|
|
57
|
+
odata=ODataQuery(
|
|
58
|
+
filter=filter,
|
|
59
|
+
order_by=order_by,
|
|
60
|
+
top=top,
|
|
61
|
+
skip=skip,
|
|
62
|
+
count=count,
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@overload
|
|
67
|
+
def list(
|
|
68
|
+
self: TasksResource[Literal[False]],
|
|
69
|
+
*,
|
|
70
|
+
filter: str | None = None,
|
|
71
|
+
order_by: str | None = None,
|
|
72
|
+
top: int | None = None,
|
|
73
|
+
skip: int | None = None,
|
|
74
|
+
count: bool | None = None,
|
|
75
|
+
) -> Page[TaskListItem]: ...
|
|
76
|
+
|
|
77
|
+
@overload
|
|
78
|
+
def list(
|
|
79
|
+
self: TasksResource[Literal[True]],
|
|
80
|
+
*,
|
|
81
|
+
filter: str | None = None,
|
|
82
|
+
order_by: str | None = None,
|
|
83
|
+
top: int | None = None,
|
|
84
|
+
skip: int | None = None,
|
|
85
|
+
count: bool | None = None,
|
|
86
|
+
) -> ApiResponseProtocol[Page[TaskListItem]]: ...
|
|
87
|
+
|
|
88
|
+
def list(
|
|
89
|
+
self,
|
|
90
|
+
*,
|
|
91
|
+
filter: str | None = None,
|
|
92
|
+
order_by: str | None = None,
|
|
93
|
+
top: int | None = None,
|
|
94
|
+
skip: int | None = None,
|
|
95
|
+
count: bool | None = None,
|
|
96
|
+
) -> Page[TaskListItem] | ApiResponseProtocol[Page[TaskListItem]]:
|
|
97
|
+
return self._collection(
|
|
98
|
+
"Tasks_ListTasks",
|
|
99
|
+
filter=filter,
|
|
100
|
+
order_by=order_by,
|
|
101
|
+
top=top,
|
|
102
|
+
skip=skip,
|
|
103
|
+
count=count,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
@overload
|
|
107
|
+
def list_types(
|
|
108
|
+
self: TasksResource[Literal[False]],
|
|
109
|
+
*,
|
|
110
|
+
filter: str | None = None,
|
|
111
|
+
order_by: str | None = None,
|
|
112
|
+
top: int | None = None,
|
|
113
|
+
skip: int | None = None,
|
|
114
|
+
count: bool | None = None,
|
|
115
|
+
) -> Page[TaskType]: ...
|
|
116
|
+
|
|
117
|
+
@overload
|
|
118
|
+
def list_types(
|
|
119
|
+
self: TasksResource[Literal[True]],
|
|
120
|
+
*,
|
|
121
|
+
filter: str | None = None,
|
|
122
|
+
order_by: str | None = None,
|
|
123
|
+
top: int | None = None,
|
|
124
|
+
skip: int | None = None,
|
|
125
|
+
count: bool | None = None,
|
|
126
|
+
) -> ApiResponseProtocol[Page[TaskType]]: ...
|
|
127
|
+
|
|
128
|
+
def list_types(
|
|
129
|
+
self,
|
|
130
|
+
*,
|
|
131
|
+
filter: str | None = None,
|
|
132
|
+
order_by: str | None = None,
|
|
133
|
+
top: int | None = None,
|
|
134
|
+
skip: int | None = None,
|
|
135
|
+
count: bool | None = None,
|
|
136
|
+
) -> Page[TaskType] | ApiResponseProtocol[Page[TaskType]]:
|
|
137
|
+
return self._collection(
|
|
138
|
+
"TaskSettings_ListTypes",
|
|
139
|
+
filter=filter,
|
|
140
|
+
order_by=order_by,
|
|
141
|
+
top=top,
|
|
142
|
+
skip=skip,
|
|
143
|
+
count=count,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
@overload
|
|
147
|
+
def list_statuses(
|
|
148
|
+
self: TasksResource[Literal[False]],
|
|
149
|
+
*,
|
|
150
|
+
filter: str | None = None,
|
|
151
|
+
order_by: str | None = None,
|
|
152
|
+
top: int | None = None,
|
|
153
|
+
skip: int | None = None,
|
|
154
|
+
count: bool | None = None,
|
|
155
|
+
) -> Page[TaskStatus]: ...
|
|
156
|
+
|
|
157
|
+
@overload
|
|
158
|
+
def list_statuses(
|
|
159
|
+
self: TasksResource[Literal[True]],
|
|
160
|
+
*,
|
|
161
|
+
filter: str | None = None,
|
|
162
|
+
order_by: str | None = None,
|
|
163
|
+
top: int | None = None,
|
|
164
|
+
skip: int | None = None,
|
|
165
|
+
count: bool | None = None,
|
|
166
|
+
) -> ApiResponseProtocol[Page[TaskStatus]]: ...
|
|
167
|
+
|
|
168
|
+
def list_statuses(
|
|
169
|
+
self,
|
|
170
|
+
*,
|
|
171
|
+
filter: str | None = None,
|
|
172
|
+
order_by: str | None = None,
|
|
173
|
+
top: int | None = None,
|
|
174
|
+
skip: int | None = None,
|
|
175
|
+
count: bool | None = None,
|
|
176
|
+
) -> Page[TaskStatus] | ApiResponseProtocol[Page[TaskStatus]]:
|
|
177
|
+
return self._collection(
|
|
178
|
+
"TaskSettings_ListStatuses",
|
|
179
|
+
filter=filter,
|
|
180
|
+
order_by=order_by,
|
|
181
|
+
top=top,
|
|
182
|
+
skip=skip,
|
|
183
|
+
count=count,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
def iter_all(
|
|
187
|
+
self,
|
|
188
|
+
*,
|
|
189
|
+
filter: str | None = None,
|
|
190
|
+
order_by: str | None = None,
|
|
191
|
+
count: bool | None = None,
|
|
192
|
+
start_skip: int = 0,
|
|
193
|
+
page_size: int = DEFAULT_PAGE_SIZE,
|
|
194
|
+
max_items: int | None = None,
|
|
195
|
+
) -> Iterator[TaskListItem]:
|
|
196
|
+
base = ODataQuery(filter=filter, order_by=order_by, count=count, skip=start_skip)
|
|
197
|
+
return Paginator(
|
|
198
|
+
fetch_page=lambda query: self._page_value("Tasks_ListTasks", odata=query),
|
|
199
|
+
query=base,
|
|
200
|
+
page_size=page_size,
|
|
201
|
+
max_items=max_items,
|
|
202
|
+
).iter_items()
|
|
203
|
+
|
|
204
|
+
@overload
|
|
205
|
+
def create(
|
|
206
|
+
self: TasksResource[Literal[False]], task: TaskCreate | Mapping[str, object]
|
|
207
|
+
) -> TaskCreateResult: ...
|
|
208
|
+
|
|
209
|
+
@overload
|
|
210
|
+
def create(
|
|
211
|
+
self: TasksResource[Literal[True]], task: TaskCreate | Mapping[str, object]
|
|
212
|
+
) -> ApiResponseProtocol[TaskCreateResult]: ...
|
|
213
|
+
|
|
214
|
+
def create(
|
|
215
|
+
self, task: TaskCreate | Mapping[str, object]
|
|
216
|
+
) -> TaskCreateResult | ApiResponseProtocol[TaskCreateResult]:
|
|
217
|
+
response = self._request("Tasks_Add", json=body_value(task))
|
|
218
|
+
return self._finish(response, response.data)
|
|
219
|
+
|
|
220
|
+
@overload
|
|
221
|
+
def get(self: TasksResource[Literal[False]], task_id: int) -> VersionedResource[Task]: ...
|
|
222
|
+
|
|
223
|
+
@overload
|
|
224
|
+
def get(
|
|
225
|
+
self: TasksResource[Literal[True]], task_id: int
|
|
226
|
+
) -> ApiResponseProtocol[VersionedResource[Task]]: ...
|
|
227
|
+
|
|
228
|
+
def get(
|
|
229
|
+
self, task_id: int
|
|
230
|
+
) -> VersionedResource[Task] | ApiResponseProtocol[VersionedResource[Task]]:
|
|
231
|
+
require_positive_identifier("task_id", task_id)
|
|
232
|
+
response = self._request("Tasks_Get", path_params={"id": task_id})
|
|
233
|
+
versioned = VersionedResource(
|
|
234
|
+
data=response.data,
|
|
235
|
+
etag=response_header(response, "ETag"),
|
|
236
|
+
http=response.http,
|
|
237
|
+
)
|
|
238
|
+
return self._finish(response, versioned)
|
|
239
|
+
|
|
240
|
+
@overload
|
|
241
|
+
def update(
|
|
242
|
+
self: TasksResource[Literal[False]],
|
|
243
|
+
task_id: int,
|
|
244
|
+
patch: TaskUpdate | Mapping[str, object],
|
|
245
|
+
*,
|
|
246
|
+
if_match: str,
|
|
247
|
+
) -> TaskUpdateResult: ...
|
|
248
|
+
|
|
249
|
+
@overload
|
|
250
|
+
def update(
|
|
251
|
+
self: TasksResource[Literal[True]],
|
|
252
|
+
task_id: int,
|
|
253
|
+
patch: TaskUpdate | Mapping[str, object],
|
|
254
|
+
*,
|
|
255
|
+
if_match: str,
|
|
256
|
+
) -> ApiResponseProtocol[TaskUpdateResult]: ...
|
|
257
|
+
|
|
258
|
+
def update(
|
|
259
|
+
self,
|
|
260
|
+
task_id: int,
|
|
261
|
+
patch: TaskUpdate | Mapping[str, object],
|
|
262
|
+
*,
|
|
263
|
+
if_match: str,
|
|
264
|
+
) -> TaskUpdateResult | ApiResponseProtocol[TaskUpdateResult]:
|
|
265
|
+
require_positive_identifier("task_id", task_id)
|
|
266
|
+
require_etag(if_match)
|
|
267
|
+
response = self._request(
|
|
268
|
+
"Tasks_Update",
|
|
269
|
+
path_params={"id": task_id},
|
|
270
|
+
headers={"If-Match": if_match},
|
|
271
|
+
json=body_value(patch),
|
|
272
|
+
)
|
|
273
|
+
return self._finish(response, response.data)
|
|
274
|
+
|
|
275
|
+
@overload
|
|
276
|
+
def delete(self: TasksResource[Literal[False]], task_id: int, *, if_match: str) -> None: ...
|
|
277
|
+
|
|
278
|
+
@overload
|
|
279
|
+
def delete(
|
|
280
|
+
self: TasksResource[Literal[True]], task_id: int, *, if_match: str
|
|
281
|
+
) -> ApiResponseProtocol[None]: ...
|
|
282
|
+
|
|
283
|
+
def delete(self, task_id: int, *, if_match: str) -> None | ApiResponseProtocol[None]:
|
|
284
|
+
require_positive_identifier("task_id", task_id)
|
|
285
|
+
require_etag(if_match)
|
|
286
|
+
response = self._request(
|
|
287
|
+
"Tasks_Delete",
|
|
288
|
+
path_params={"id": task_id},
|
|
289
|
+
headers={"If-Match": if_match},
|
|
290
|
+
)
|
|
291
|
+
return self._finish(response, response.data)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""API users collection operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from typing import Literal, overload
|
|
7
|
+
|
|
8
|
+
from ..models import User
|
|
9
|
+
from ..odata import DEFAULT_PAGE_SIZE
|
|
10
|
+
from ..pagination import Page
|
|
11
|
+
from ._base import ApiResponseProtocol, HttpInfoMode
|
|
12
|
+
from ._collections import CollectionResource
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class UsersResource(CollectionResource[HttpInfoMode]):
|
|
16
|
+
LIST_OPERATION_ID = "Users_ListUsers"
|
|
17
|
+
OPERATION_IDS = frozenset({LIST_OPERATION_ID})
|
|
18
|
+
|
|
19
|
+
@overload
|
|
20
|
+
def list(
|
|
21
|
+
self: UsersResource[Literal[False]],
|
|
22
|
+
*,
|
|
23
|
+
filter: str | None = None,
|
|
24
|
+
order_by: str | None = None,
|
|
25
|
+
top: int | None = None,
|
|
26
|
+
skip: int | None = None,
|
|
27
|
+
count: bool | None = None,
|
|
28
|
+
) -> Page[User]: ...
|
|
29
|
+
|
|
30
|
+
@overload
|
|
31
|
+
def list(
|
|
32
|
+
self: UsersResource[Literal[True]],
|
|
33
|
+
*,
|
|
34
|
+
filter: str | None = None,
|
|
35
|
+
order_by: str | None = None,
|
|
36
|
+
top: int | None = None,
|
|
37
|
+
skip: int | None = None,
|
|
38
|
+
count: bool | None = None,
|
|
39
|
+
) -> ApiResponseProtocol[Page[User]]: ...
|
|
40
|
+
|
|
41
|
+
def list(
|
|
42
|
+
self,
|
|
43
|
+
*,
|
|
44
|
+
filter: str | None = None,
|
|
45
|
+
order_by: str | None = None,
|
|
46
|
+
top: int | None = None,
|
|
47
|
+
skip: int | None = None,
|
|
48
|
+
count: bool | None = None,
|
|
49
|
+
) -> Page[User] | ApiResponseProtocol[Page[User]]:
|
|
50
|
+
return self._list(filter=filter, order_by=order_by, top=top, skip=skip, count=count)
|
|
51
|
+
|
|
52
|
+
def iter_pages(
|
|
53
|
+
self,
|
|
54
|
+
*,
|
|
55
|
+
filter: str | None = None,
|
|
56
|
+
order_by: str | None = None,
|
|
57
|
+
count: bool | None = None,
|
|
58
|
+
start_skip: int = 0,
|
|
59
|
+
page_size: int = DEFAULT_PAGE_SIZE,
|
|
60
|
+
max_items: int | None = None,
|
|
61
|
+
) -> Iterator[Page[User]]:
|
|
62
|
+
return self._iter_pages(
|
|
63
|
+
filter=filter,
|
|
64
|
+
order_by=order_by,
|
|
65
|
+
count=count,
|
|
66
|
+
start_skip=start_skip,
|
|
67
|
+
page_size=page_size,
|
|
68
|
+
max_items=max_items,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def iter_all(
|
|
72
|
+
self,
|
|
73
|
+
*,
|
|
74
|
+
filter: str | None = None,
|
|
75
|
+
order_by: str | None = None,
|
|
76
|
+
count: bool | None = None,
|
|
77
|
+
start_skip: int = 0,
|
|
78
|
+
page_size: int = DEFAULT_PAGE_SIZE,
|
|
79
|
+
max_items: int | None = None,
|
|
80
|
+
) -> Iterator[User]:
|
|
81
|
+
return self._iter_all(
|
|
82
|
+
filter=filter,
|
|
83
|
+
order_by=order_by,
|
|
84
|
+
count=count,
|
|
85
|
+
start_skip=start_skip,
|
|
86
|
+
page_size=page_size,
|
|
87
|
+
max_items=max_items,
|
|
88
|
+
)
|
redblack/response.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""HTTP metadata containers shared by typed and raw SDK responses."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator, Mapping
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Generic, TypeVar
|
|
8
|
+
|
|
9
|
+
from .errors import sanitize_url
|
|
10
|
+
|
|
11
|
+
T = TypeVar("T")
|
|
12
|
+
U = TypeVar("U")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ResponseHeaders(Mapping[str, str]):
|
|
16
|
+
"""An immutable, case-insensitive mapping of safe response headers."""
|
|
17
|
+
|
|
18
|
+
__slots__ = ("_values",)
|
|
19
|
+
|
|
20
|
+
def __init__(self, values: Mapping[str, str] | None = None) -> None:
|
|
21
|
+
self._values = {str(name).lower(): str(value) for name, value in (values or {}).items()}
|
|
22
|
+
|
|
23
|
+
def __getitem__(self, name: str) -> str:
|
|
24
|
+
return self._values[name.lower()]
|
|
25
|
+
|
|
26
|
+
def __iter__(self) -> Iterator[str]:
|
|
27
|
+
return iter(self._values)
|
|
28
|
+
|
|
29
|
+
def __len__(self) -> int:
|
|
30
|
+
return len(self._values)
|
|
31
|
+
|
|
32
|
+
def __repr__(self) -> str:
|
|
33
|
+
return f"ResponseHeaders({self._values!r})"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(frozen=True, slots=True, repr=False)
|
|
37
|
+
class HttpMetadata:
|
|
38
|
+
"""Non-wire metadata associated with a decoded response.
|
|
39
|
+
|
|
40
|
+
``location`` may contain a short-lived signed URL and is intentionally
|
|
41
|
+
omitted from representations. ``headers`` contains a sanitized Location
|
|
42
|
+
value, while this dedicated property retains the value for an explicitly
|
|
43
|
+
requested export workflow.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
status_code: int
|
|
47
|
+
method: str
|
|
48
|
+
url: str
|
|
49
|
+
headers: Mapping[str, str] = field(default_factory=ResponseHeaders)
|
|
50
|
+
request_id: str | None = None
|
|
51
|
+
etag: str | None = None
|
|
52
|
+
location: str | None = field(default=None, repr=False)
|
|
53
|
+
attempts: int = 1
|
|
54
|
+
elapsed: float | None = None
|
|
55
|
+
|
|
56
|
+
def __post_init__(self) -> None:
|
|
57
|
+
object.__setattr__(self, "method", self.method.upper())
|
|
58
|
+
object.__setattr__(self, "url", sanitize_url(self.url))
|
|
59
|
+
if not isinstance(self.headers, ResponseHeaders):
|
|
60
|
+
object.__setattr__(self, "headers", ResponseHeaders(self.headers))
|
|
61
|
+
if self.attempts < 1:
|
|
62
|
+
raise ValueError("attempts must be at least 1")
|
|
63
|
+
|
|
64
|
+
def __repr__(self) -> str:
|
|
65
|
+
return (
|
|
66
|
+
"HttpMetadata("
|
|
67
|
+
f"status_code={self.status_code!r}, method={self.method!r}, "
|
|
68
|
+
"url=<redacted>, "
|
|
69
|
+
f"headers={self.headers!r}, "
|
|
70
|
+
f"request_id={self.request_id!r}, etag={self.etag!r}, "
|
|
71
|
+
f"has_location={self.location is not None}, attempts={self.attempts!r}, "
|
|
72
|
+
f"elapsed={self.elapsed!r})"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True, slots=True)
|
|
77
|
+
class ApiResponse(Generic[T]):
|
|
78
|
+
"""A decoded value plus safe transport details."""
|
|
79
|
+
|
|
80
|
+
data: T
|
|
81
|
+
http: HttpMetadata
|
|
82
|
+
raw: bytes = field(default=b"", repr=False)
|
|
83
|
+
|
|
84
|
+
def __post_init__(self) -> None:
|
|
85
|
+
if not self.raw and isinstance(self.data, bytes):
|
|
86
|
+
object.__setattr__(self, "raw", self.data)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def status_code(self) -> int:
|
|
90
|
+
return self.http.status_code
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def headers(self) -> Mapping[str, str]:
|
|
94
|
+
return self.http.headers
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def url(self) -> str:
|
|
98
|
+
return self.http.url
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def location(self) -> str | None:
|
|
102
|
+
return self.http.location
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def request_id(self) -> str | None:
|
|
106
|
+
return self.http.request_id
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def etag(self) -> str | None:
|
|
110
|
+
return self.http.etag
|
|
111
|
+
|
|
112
|
+
def with_data(self, value: U) -> ApiResponse[U]:
|
|
113
|
+
"""Return the same HTTP response information with a decoded value."""
|
|
114
|
+
|
|
115
|
+
return ApiResponse(data=value, http=self.http, raw=self.raw)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
__all__ = ["ApiResponse", "HttpMetadata", "ResponseHeaders"]
|