ordercloud-python 2026.4.1__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.
- ordercloud/__init__.py +37 -0
- ordercloud/auth.py +136 -0
- ordercloud/client.py +211 -0
- ordercloud/config.py +42 -0
- ordercloud/errors.py +47 -0
- ordercloud/http.py +218 -0
- ordercloud/middleware.py +66 -0
- ordercloud/models/__init__.py +271 -0
- ordercloud/models/address.py +47 -0
- ordercloud/models/api_client.py +116 -0
- ordercloud/models/approval.py +73 -0
- ordercloud/models/assignments.py +402 -0
- ordercloud/models/auth_models.py +114 -0
- ordercloud/models/bundle.py +31 -0
- ordercloud/models/buyer.py +271 -0
- ordercloud/models/catalog.py +33 -0
- ordercloud/models/category.py +35 -0
- ordercloud/models/cost_center.py +27 -0
- ordercloud/models/credit_card.py +35 -0
- ordercloud/models/delivery.py +277 -0
- ordercloud/models/discount.py +63 -0
- ordercloud/models/integration.py +76 -0
- ordercloud/models/inventory_record.py +53 -0
- ordercloud/models/line_item.py +95 -0
- ordercloud/models/line_item_types.py +89 -0
- ordercloud/models/message_sender.py +80 -0
- ordercloud/models/misc.py +280 -0
- ordercloud/models/open_id_connect.py +47 -0
- ordercloud/models/order.py +477 -0
- ordercloud/models/order_return.py +92 -0
- ordercloud/models/payment.py +77 -0
- ordercloud/models/price_schedule.py +76 -0
- ordercloud/models/product.py +227 -0
- ordercloud/models/product_collection.py +186 -0
- ordercloud/models/promotion.py +297 -0
- ordercloud/models/security.py +89 -0
- ordercloud/models/shared.py +131 -0
- ordercloud/models/shipment.py +150 -0
- ordercloud/models/spec.py +67 -0
- ordercloud/models/spending_account.py +33 -0
- ordercloud/models/subscription.py +125 -0
- ordercloud/models/supplier.py +43 -0
- ordercloud/models/sync.py +172 -0
- ordercloud/models/user.py +207 -0
- ordercloud/models/user_group.py +27 -0
- ordercloud/models/webhook.py +58 -0
- ordercloud/py.typed +0 -0
- ordercloud/resources/__init__.py +65 -0
- ordercloud/resources/addresses.py +228 -0
- ordercloud/resources/admin_addresses.py +128 -0
- ordercloud/resources/admin_user_groups.py +185 -0
- ordercloud/resources/admin_users.py +150 -0
- ordercloud/resources/api_clients.py +308 -0
- ordercloud/resources/approval_rules.py +144 -0
- ordercloud/resources/base.py +145 -0
- ordercloud/resources/bundle_line_items.py +59 -0
- ordercloud/resources/bundle_subscription_items.py +54 -0
- ordercloud/resources/bundles.py +278 -0
- ordercloud/resources/buyer_groups.py +128 -0
- ordercloud/resources/buyers.py +164 -0
- ordercloud/resources/cart.py +613 -0
- ordercloud/resources/catalogs.py +311 -0
- ordercloud/resources/categories.py +392 -0
- ordercloud/resources/cost_centers.py +222 -0
- ordercloud/resources/credit_cards.py +227 -0
- ordercloud/resources/delivery_configurations.py +132 -0
- ordercloud/resources/discounts.py +201 -0
- ordercloud/resources/entity_syncs.py +534 -0
- ordercloud/resources/error_configs.py +71 -0
- ordercloud/resources/forgotten_credentials.py +74 -0
- ordercloud/resources/group_orders.py +28 -0
- ordercloud/resources/impersonation_configs.py +132 -0
- ordercloud/resources/incrementors.py +128 -0
- ordercloud/resources/integration_events.py +203 -0
- ordercloud/resources/inventory_integrations.py +65 -0
- ordercloud/resources/inventory_records.py +484 -0
- ordercloud/resources/line_items.py +262 -0
- ordercloud/resources/locales.py +203 -0
- ordercloud/resources/me.py +1882 -0
- ordercloud/resources/message_senders.py +261 -0
- ordercloud/resources/open_id_connects.py +128 -0
- ordercloud/resources/order_returns.py +306 -0
- ordercloud/resources/order_syncs.py +65 -0
- ordercloud/resources/orders.py +689 -0
- ordercloud/resources/payments.py +176 -0
- ordercloud/resources/price_schedules.py +164 -0
- ordercloud/resources/product_collections.py +116 -0
- ordercloud/resources/product_facets.py +128 -0
- ordercloud/resources/product_syncs.py +76 -0
- ordercloud/resources/products.py +454 -0
- ordercloud/resources/promotion_integrations.py +65 -0
- ordercloud/resources/promotions.py +203 -0
- ordercloud/resources/security_profiles.py +222 -0
- ordercloud/resources/seller_approval_rules.py +128 -0
- ordercloud/resources/shipments.py +256 -0
- ordercloud/resources/specs.py +313 -0
- ordercloud/resources/spending_accounts.py +227 -0
- ordercloud/resources/subscription_integrations.py +65 -0
- ordercloud/resources/subscription_items.py +146 -0
- ordercloud/resources/subscriptions.py +128 -0
- ordercloud/resources/supplier_addresses.py +144 -0
- ordercloud/resources/supplier_user_groups.py +210 -0
- ordercloud/resources/supplier_users.py +170 -0
- ordercloud/resources/suppliers.py +190 -0
- ordercloud/resources/tracking_events.py +130 -0
- ordercloud/resources/user_groups.py +210 -0
- ordercloud/resources/users.py +254 -0
- ordercloud/resources/webhooks.py +128 -0
- ordercloud/resources/xp_indices.py +77 -0
- ordercloud/sync_client.py +170 -0
- ordercloud_python-2026.4.1.dist-info/METADATA +552 -0
- ordercloud_python-2026.4.1.dist-info/RECORD +114 -0
- ordercloud_python-2026.4.1.dist-info/WHEEL +4 -0
- ordercloud_python-2026.4.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# GENERATED by tools/codegen — DO NOT EDIT
|
|
2
|
+
# Source: ordercloud-openapi-v3.json
|
|
3
|
+
"""OrderCloud Users API resource."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from typing import Any, Optional, Union
|
|
7
|
+
|
|
8
|
+
from ..models.auth_models import AccessToken, ImpersonateTokenRequest
|
|
9
|
+
from ..models.user import User, UserOrderMoveOption
|
|
10
|
+
from ..models.shared import ListPage
|
|
11
|
+
from .base import BaseResource
|
|
12
|
+
|
|
13
|
+
__all__ = ["UsersResource"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class UsersResource(BaseResource):
|
|
17
|
+
"""Operations on OrderCloud Users."""
|
|
18
|
+
|
|
19
|
+
async def list(
|
|
20
|
+
self,
|
|
21
|
+
buyer_id: str,
|
|
22
|
+
*,
|
|
23
|
+
user_group_id: Optional[str] = None,
|
|
24
|
+
search: Optional[str] = None,
|
|
25
|
+
search_on: Optional[str] = None,
|
|
26
|
+
sort_by: Optional[str] = None,
|
|
27
|
+
page: Optional[int] = None,
|
|
28
|
+
page_size: Optional[int] = None,
|
|
29
|
+
filters: Optional[dict[str, Any]] = None,
|
|
30
|
+
) -> ListPage[User]:
|
|
31
|
+
"""List users
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
buyer_id: ID of the buyer.
|
|
35
|
+
user_group_id: ID of the user group.
|
|
36
|
+
search: Word or phrase to search for.
|
|
37
|
+
search_on: Comma-delimited list of fields to search on.
|
|
38
|
+
sort_by: Comma-delimited list of fields to sort by.
|
|
39
|
+
page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
|
|
40
|
+
page_size: Number of results to return per page.
|
|
41
|
+
filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
A paginated list of User objects.
|
|
45
|
+
"""
|
|
46
|
+
params = self._build_list_params(
|
|
47
|
+
search=search,
|
|
48
|
+
search_on=search_on,
|
|
49
|
+
sort_by=sort_by,
|
|
50
|
+
page=page,
|
|
51
|
+
page_size=page_size,
|
|
52
|
+
filters=filters,
|
|
53
|
+
)
|
|
54
|
+
if user_group_id is not None:
|
|
55
|
+
params["userGroupID"] = user_group_id
|
|
56
|
+
resp = await self._http.get(f"/buyers/{buyer_id}/users", **params)
|
|
57
|
+
return self._parse_list(resp.json(), User)
|
|
58
|
+
|
|
59
|
+
async def create(
|
|
60
|
+
self,
|
|
61
|
+
buyer_id: str,
|
|
62
|
+
user: Union[User, dict[str, Any]],
|
|
63
|
+
) -> User:
|
|
64
|
+
"""Create a user
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
buyer_id: ID of the buyer.
|
|
68
|
+
user: A ``User`` model or dict. Required fields: Username, FirstName, LastName, Email, Active.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
The User object.
|
|
72
|
+
"""
|
|
73
|
+
resp = await self._http.post(f"/buyers/{buyer_id}/users", json=self._serialize(user))
|
|
74
|
+
return User(**resp.json())
|
|
75
|
+
|
|
76
|
+
async def get(
|
|
77
|
+
self,
|
|
78
|
+
buyer_id: str,
|
|
79
|
+
user_id: str,
|
|
80
|
+
) -> User:
|
|
81
|
+
"""Retrieve a user
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
buyer_id: ID of the buyer.
|
|
85
|
+
user_id: ID of the user.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
The User object.
|
|
89
|
+
"""
|
|
90
|
+
resp = await self._http.get(f"/buyers/{buyer_id}/users/{user_id}")
|
|
91
|
+
return User(**resp.json())
|
|
92
|
+
|
|
93
|
+
async def save(
|
|
94
|
+
self,
|
|
95
|
+
buyer_id: str,
|
|
96
|
+
user_id: str,
|
|
97
|
+
user: Union[User, dict[str, Any]],
|
|
98
|
+
) -> User:
|
|
99
|
+
"""Create or update a user
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
buyer_id: ID of the buyer.
|
|
103
|
+
user_id: ID of the user.
|
|
104
|
+
user: A ``User`` model or dict. Required fields: Username, FirstName, LastName, Email, Active.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
The User object.
|
|
108
|
+
"""
|
|
109
|
+
resp = await self._http.put(
|
|
110
|
+
f"/buyers/{buyer_id}/users/{user_id}",
|
|
111
|
+
json=self._serialize(user),
|
|
112
|
+
)
|
|
113
|
+
return User(**resp.json())
|
|
114
|
+
|
|
115
|
+
async def delete(
|
|
116
|
+
self,
|
|
117
|
+
buyer_id: str,
|
|
118
|
+
user_id: str,
|
|
119
|
+
) -> None:
|
|
120
|
+
"""Delete a user
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
buyer_id: ID of the buyer.
|
|
124
|
+
user_id: ID of the user.
|
|
125
|
+
"""
|
|
126
|
+
await self._http.delete(f"/buyers/{buyer_id}/users/{user_id}")
|
|
127
|
+
|
|
128
|
+
async def patch(
|
|
129
|
+
self,
|
|
130
|
+
buyer_id: str,
|
|
131
|
+
user_id: str,
|
|
132
|
+
partial: dict[str, Any],
|
|
133
|
+
) -> User:
|
|
134
|
+
"""Partially update a user
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
buyer_id: ID of the buyer.
|
|
138
|
+
user_id: ID of the user.
|
|
139
|
+
partial: A dict of fields to update.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
The User object.
|
|
143
|
+
"""
|
|
144
|
+
resp = await self._http.patch(f"/buyers/{buyer_id}/users/{user_id}", json=partial)
|
|
145
|
+
return User(**resp.json())
|
|
146
|
+
|
|
147
|
+
async def get_access_token(
|
|
148
|
+
self,
|
|
149
|
+
buyer_id: str,
|
|
150
|
+
user_id: str,
|
|
151
|
+
impersonate_token_request: Union[ImpersonateTokenRequest, dict[str, Any]],
|
|
152
|
+
) -> AccessToken:
|
|
153
|
+
"""Retrieve a user access token
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
buyer_id: ID of the buyer.
|
|
157
|
+
user_id: ID of the user.
|
|
158
|
+
impersonate_token_request: A ``ImpersonateTokenRequest`` model or dict. Required fields: ClientID, Roles.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
The AccessToken object.
|
|
162
|
+
"""
|
|
163
|
+
resp = await self._http.post(
|
|
164
|
+
f"/buyers/{buyer_id}/users/{user_id}/accesstoken",
|
|
165
|
+
json=self._serialize(impersonate_token_request),
|
|
166
|
+
)
|
|
167
|
+
return AccessToken(**resp.json())
|
|
168
|
+
|
|
169
|
+
async def move(
|
|
170
|
+
self,
|
|
171
|
+
buyer_id: str,
|
|
172
|
+
user_id: str,
|
|
173
|
+
new_buyer_id: str,
|
|
174
|
+
*,
|
|
175
|
+
orders: UserOrderMoveOption,
|
|
176
|
+
) -> User:
|
|
177
|
+
"""Move a user to a different buyer
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
buyer_id: ID of the buyer.
|
|
181
|
+
user_id: ID of the user.
|
|
182
|
+
new_buyer_id: ID of the new buyer.
|
|
183
|
+
orders: Orders of the user. Possible values: None, Unsubmitted, All.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
The User object.
|
|
187
|
+
"""
|
|
188
|
+
_params: dict[str, Any] = {}
|
|
189
|
+
if orders is not None:
|
|
190
|
+
_params["orders"] = orders
|
|
191
|
+
resp = await self._http.post(
|
|
192
|
+
f"/buyers/{buyer_id}/users/{user_id}/moveto/{new_buyer_id}", params=_params or None
|
|
193
|
+
)
|
|
194
|
+
return User(**resp.json())
|
|
195
|
+
|
|
196
|
+
async def revoke_user_tokens(
|
|
197
|
+
self,
|
|
198
|
+
buyer_id: str,
|
|
199
|
+
user_id: str,
|
|
200
|
+
) -> None:
|
|
201
|
+
"""Revoke a user tokens
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
buyer_id: ID of the buyer.
|
|
205
|
+
user_id: ID of the user.
|
|
206
|
+
"""
|
|
207
|
+
await self._http.delete(f"/buyers/{buyer_id}/users/{user_id}/tokens")
|
|
208
|
+
|
|
209
|
+
async def unlock_user_account(
|
|
210
|
+
self,
|
|
211
|
+
buyer_id: str,
|
|
212
|
+
user_id: str,
|
|
213
|
+
) -> None:
|
|
214
|
+
"""Unlock a user account
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
buyer_id: ID of the buyer.
|
|
218
|
+
user_id: ID of the user.
|
|
219
|
+
"""
|
|
220
|
+
await self._http.post(f"/buyers/{buyer_id}/users/{user_id}/unlock")
|
|
221
|
+
|
|
222
|
+
async def list_across_buyers(
|
|
223
|
+
self,
|
|
224
|
+
*,
|
|
225
|
+
search: Optional[str] = None,
|
|
226
|
+
search_on: Optional[str] = None,
|
|
227
|
+
sort_by: Optional[str] = None,
|
|
228
|
+
page: Optional[int] = None,
|
|
229
|
+
page_size: Optional[int] = None,
|
|
230
|
+
filters: Optional[dict[str, Any]] = None,
|
|
231
|
+
) -> ListPage[User]:
|
|
232
|
+
"""List user across buyers
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
search: Word or phrase to search for.
|
|
236
|
+
search_on: Comma-delimited list of fields to search on.
|
|
237
|
+
sort_by: Comma-delimited list of fields to sort by.
|
|
238
|
+
page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
|
|
239
|
+
page_size: Number of results to return per page.
|
|
240
|
+
filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
A paginated list of User objects.
|
|
244
|
+
"""
|
|
245
|
+
params = self._build_list_params(
|
|
246
|
+
search=search,
|
|
247
|
+
search_on=search_on,
|
|
248
|
+
sort_by=sort_by,
|
|
249
|
+
page=page,
|
|
250
|
+
page_size=page_size,
|
|
251
|
+
filters=filters,
|
|
252
|
+
)
|
|
253
|
+
resp = await self._http.get("/buyerusers", **params)
|
|
254
|
+
return self._parse_list(resp.json(), User)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# GENERATED by tools/codegen — DO NOT EDIT
|
|
2
|
+
# Source: ordercloud-openapi-v3.json
|
|
3
|
+
"""OrderCloud Webhooks API resource."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from typing import Any, Optional, Union
|
|
7
|
+
|
|
8
|
+
from ..models.webhook import Webhook
|
|
9
|
+
from ..models.shared import ListPage
|
|
10
|
+
from .base import BaseResource
|
|
11
|
+
|
|
12
|
+
__all__ = ["WebhooksResource"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WebhooksResource(BaseResource):
|
|
16
|
+
"""Operations on OrderCloud Webhooks."""
|
|
17
|
+
|
|
18
|
+
async def list(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
search: Optional[str] = None,
|
|
22
|
+
search_on: Optional[str] = None,
|
|
23
|
+
sort_by: Optional[str] = None,
|
|
24
|
+
page: Optional[int] = None,
|
|
25
|
+
page_size: Optional[int] = None,
|
|
26
|
+
filters: Optional[dict[str, Any]] = None,
|
|
27
|
+
) -> ListPage[Webhook]:
|
|
28
|
+
"""List webhooks
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
search: Word or phrase to search for.
|
|
32
|
+
search_on: Comma-delimited list of fields to search on.
|
|
33
|
+
sort_by: Comma-delimited list of fields to sort by.
|
|
34
|
+
page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
|
|
35
|
+
page_size: Number of results to return per page.
|
|
36
|
+
filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
A paginated list of Webhook objects.
|
|
40
|
+
"""
|
|
41
|
+
params = self._build_list_params(
|
|
42
|
+
search=search,
|
|
43
|
+
search_on=search_on,
|
|
44
|
+
sort_by=sort_by,
|
|
45
|
+
page=page,
|
|
46
|
+
page_size=page_size,
|
|
47
|
+
filters=filters,
|
|
48
|
+
)
|
|
49
|
+
resp = await self._http.get("/webhooks", **params)
|
|
50
|
+
return self._parse_list(resp.json(), Webhook)
|
|
51
|
+
|
|
52
|
+
async def create(
|
|
53
|
+
self,
|
|
54
|
+
webhook: Union[Webhook, dict[str, Any]],
|
|
55
|
+
) -> Webhook:
|
|
56
|
+
"""Create a webhook
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
webhook: A ``Webhook`` model or dict. Required fields: Name.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
The Webhook object.
|
|
63
|
+
"""
|
|
64
|
+
resp = await self._http.post("/webhooks", json=self._serialize(webhook))
|
|
65
|
+
return Webhook(**resp.json())
|
|
66
|
+
|
|
67
|
+
async def get(
|
|
68
|
+
self,
|
|
69
|
+
webhook_id: str,
|
|
70
|
+
) -> Webhook:
|
|
71
|
+
"""Retrieve a webhook
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
webhook_id: ID of the webhook.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
The Webhook object.
|
|
78
|
+
"""
|
|
79
|
+
resp = await self._http.get(f"/webhooks/{webhook_id}")
|
|
80
|
+
return Webhook(**resp.json())
|
|
81
|
+
|
|
82
|
+
async def save(
|
|
83
|
+
self,
|
|
84
|
+
webhook_id: str,
|
|
85
|
+
webhook: Union[Webhook, dict[str, Any]],
|
|
86
|
+
) -> Webhook:
|
|
87
|
+
"""Create or update a webhook
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
webhook_id: ID of the webhook.
|
|
91
|
+
webhook: A ``Webhook`` model or dict. Required fields: Name.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
The Webhook object.
|
|
95
|
+
"""
|
|
96
|
+
resp = await self._http.put(
|
|
97
|
+
f"/webhooks/{webhook_id}",
|
|
98
|
+
json=self._serialize(webhook),
|
|
99
|
+
)
|
|
100
|
+
return Webhook(**resp.json())
|
|
101
|
+
|
|
102
|
+
async def delete(
|
|
103
|
+
self,
|
|
104
|
+
webhook_id: str,
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Delete a webhook
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
webhook_id: ID of the webhook.
|
|
110
|
+
"""
|
|
111
|
+
await self._http.delete(f"/webhooks/{webhook_id}")
|
|
112
|
+
|
|
113
|
+
async def patch(
|
|
114
|
+
self,
|
|
115
|
+
webhook_id: str,
|
|
116
|
+
partial: dict[str, Any],
|
|
117
|
+
) -> Webhook:
|
|
118
|
+
"""Partially update a webhook
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
webhook_id: ID of the webhook.
|
|
122
|
+
partial: A dict of fields to update.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
The Webhook object.
|
|
126
|
+
"""
|
|
127
|
+
resp = await self._http.patch(f"/webhooks/{webhook_id}", json=partial)
|
|
128
|
+
return Webhook(**resp.json())
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# GENERATED by tools/codegen — DO NOT EDIT
|
|
2
|
+
# Source: ordercloud-openapi-v3.json
|
|
3
|
+
"""OrderCloud XpIndices API resource."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from typing import Any, Optional, Union
|
|
7
|
+
|
|
8
|
+
from ..models.misc import XpIndex, XpThingType
|
|
9
|
+
from ..models.shared import ListPage
|
|
10
|
+
from .base import BaseResource
|
|
11
|
+
|
|
12
|
+
__all__ = ["XpIndicesResource"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class XpIndicesResource(BaseResource):
|
|
16
|
+
"""Operations on OrderCloud XpIndices."""
|
|
17
|
+
|
|
18
|
+
async def list(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
search: Optional[str] = None,
|
|
22
|
+
search_on: Optional[str] = None,
|
|
23
|
+
sort_by: Optional[str] = None,
|
|
24
|
+
page: Optional[int] = None,
|
|
25
|
+
page_size: Optional[int] = None,
|
|
26
|
+
filters: Optional[dict[str, Any]] = None,
|
|
27
|
+
) -> ListPage[XpIndex]:
|
|
28
|
+
"""List XP indices
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
search: Word or phrase to search for.
|
|
32
|
+
search_on: Comma-delimited list of fields to search on.
|
|
33
|
+
sort_by: Comma-delimited list of fields to sort by.
|
|
34
|
+
page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
|
|
35
|
+
page_size: Number of results to return per page.
|
|
36
|
+
filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
A paginated list of XpIndex objects.
|
|
40
|
+
"""
|
|
41
|
+
params = self._build_list_params(
|
|
42
|
+
search=search,
|
|
43
|
+
search_on=search_on,
|
|
44
|
+
sort_by=sort_by,
|
|
45
|
+
page=page,
|
|
46
|
+
page_size=page_size,
|
|
47
|
+
filters=filters,
|
|
48
|
+
)
|
|
49
|
+
resp = await self._http.get("/xpindices", **params)
|
|
50
|
+
return self._parse_list(resp.json(), XpIndex)
|
|
51
|
+
|
|
52
|
+
async def put(
|
|
53
|
+
self,
|
|
54
|
+
xp_index: Union[XpIndex, dict[str, Any]],
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Create or update an xp index
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
xp_index: A ``XpIndex`` model or dict.
|
|
60
|
+
"""
|
|
61
|
+
await self._http.put(
|
|
62
|
+
"/xpindices",
|
|
63
|
+
json=self._serialize(xp_index),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
async def delete(
|
|
67
|
+
self,
|
|
68
|
+
thing_type: XpThingType,
|
|
69
|
+
key: str,
|
|
70
|
+
) -> None:
|
|
71
|
+
"""Delete a XP index
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
thing_type: Thing type of the xp index. Possible values: Address, Variant, Order, OrderReturn, LineItem, CostCenter, CreditCard, Payment, Spec, SpecOption, UserGroup, Company, Category, PriceSchedule, Shipment, SpendingAccount, User, Promotion, ApprovalRule, SellerApprovalRule, Catalog, ProductFacet, MessageSender, InventoryRecord, ProductCollection, Subscription, GroupOrderInvitation, BuyerGroup, Discount.
|
|
75
|
+
key: Key of the xp index.
|
|
76
|
+
"""
|
|
77
|
+
await self._http.delete(f"/xpindices/{thing_type}/{key}")
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Synchronous wrapper around the async OrderCloud client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import functools
|
|
7
|
+
from collections.abc import Iterator
|
|
8
|
+
from typing import Any, TypeVar
|
|
9
|
+
|
|
10
|
+
from .config import OrderCloudConfig
|
|
11
|
+
from .middleware import AfterResponse, BeforeRequest
|
|
12
|
+
from .resources.base import BaseResource
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
|
|
16
|
+
__all__ = ["SyncOrderCloudClient", "paginate_sync"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _SyncProxy:
|
|
20
|
+
"""Wraps an async resource, making all async methods synchronous.
|
|
21
|
+
|
|
22
|
+
When an attribute is accessed that is a coroutine function, it is
|
|
23
|
+
wrapped so that calling it runs the coroutine to completion on the
|
|
24
|
+
client's event loop and returns the result directly.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, async_resource: BaseResource, runner: Any) -> None:
|
|
28
|
+
self._async = async_resource
|
|
29
|
+
self._run = runner
|
|
30
|
+
|
|
31
|
+
def __getattr__(self, name: str) -> Any:
|
|
32
|
+
attr = getattr(self._async, name)
|
|
33
|
+
if asyncio.iscoroutinefunction(attr):
|
|
34
|
+
|
|
35
|
+
@functools.wraps(attr)
|
|
36
|
+
def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
37
|
+
return self._run(attr(*args, **kwargs))
|
|
38
|
+
|
|
39
|
+
return sync_wrapper
|
|
40
|
+
return attr
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SyncOrderCloudClient:
|
|
44
|
+
"""Synchronous client for the OrderCloud API.
|
|
45
|
+
|
|
46
|
+
A thin wrapper around ``OrderCloudClient`` that manages its own
|
|
47
|
+
event loop internally. All resource methods are available as
|
|
48
|
+
regular (non-async) calls.
|
|
49
|
+
|
|
50
|
+
Usage::
|
|
51
|
+
|
|
52
|
+
with SyncOrderCloudClient.create(
|
|
53
|
+
client_id="YOUR_CLIENT_ID",
|
|
54
|
+
client_secret="YOUR_CLIENT_SECRET",
|
|
55
|
+
) as client:
|
|
56
|
+
products = client.products.list()
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, config: OrderCloudConfig) -> None:
|
|
60
|
+
# Import here to avoid circular import at module level.
|
|
61
|
+
from .client import OrderCloudClient
|
|
62
|
+
|
|
63
|
+
self._loop = asyncio.new_event_loop()
|
|
64
|
+
self._async_client = OrderCloudClient(config)
|
|
65
|
+
|
|
66
|
+
# Auto-wrap all resource attributes with sync proxies.
|
|
67
|
+
for name, value in vars(self._async_client).items():
|
|
68
|
+
if isinstance(value, BaseResource):
|
|
69
|
+
object.__setattr__(self, name, _SyncProxy(value, self._run))
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def create(
|
|
73
|
+
cls,
|
|
74
|
+
*,
|
|
75
|
+
client_id: str,
|
|
76
|
+
client_secret: str,
|
|
77
|
+
base_url: str = "https://api.ordercloud.io/v1",
|
|
78
|
+
auth_url: str = "https://auth.ordercloud.io/oauth/token",
|
|
79
|
+
scopes: list[str] | None = None,
|
|
80
|
+
timeout: float = 30.0,
|
|
81
|
+
max_retries: int = 0,
|
|
82
|
+
retry_backoff: float = 0.5,
|
|
83
|
+
) -> SyncOrderCloudClient:
|
|
84
|
+
"""Create a client from individual parameters.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
client_id: OAuth2 client ID.
|
|
88
|
+
client_secret: OAuth2 client secret.
|
|
89
|
+
base_url: API base URL (default: US production).
|
|
90
|
+
auth_url: OAuth2 token endpoint.
|
|
91
|
+
scopes: Requested scopes (default: ``["FullAccess"]``).
|
|
92
|
+
timeout: HTTP request timeout in seconds.
|
|
93
|
+
max_retries: Maximum retries on 429/5xx (0 = disabled).
|
|
94
|
+
retry_backoff: Base delay for exponential backoff.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
A configured ``SyncOrderCloudClient`` instance.
|
|
98
|
+
"""
|
|
99
|
+
config = OrderCloudConfig(
|
|
100
|
+
client_id=client_id,
|
|
101
|
+
client_secret=client_secret,
|
|
102
|
+
base_url=base_url,
|
|
103
|
+
auth_url=auth_url,
|
|
104
|
+
scopes=tuple(scopes) if scopes else ("FullAccess",),
|
|
105
|
+
timeout=timeout,
|
|
106
|
+
max_retries=max_retries,
|
|
107
|
+
retry_backoff=retry_backoff,
|
|
108
|
+
)
|
|
109
|
+
return cls(config)
|
|
110
|
+
|
|
111
|
+
def _run(self, coro: Any) -> Any:
|
|
112
|
+
"""Run a coroutine to completion on the internal event loop."""
|
|
113
|
+
return self._loop.run_until_complete(coro)
|
|
114
|
+
|
|
115
|
+
def add_before_request(self, hook: BeforeRequest) -> None:
|
|
116
|
+
"""Register a hook called before each HTTP request."""
|
|
117
|
+
self._async_client.add_before_request(hook)
|
|
118
|
+
|
|
119
|
+
def add_after_response(self, hook: AfterResponse) -> None:
|
|
120
|
+
"""Register a hook called after each HTTP response."""
|
|
121
|
+
self._async_client.add_after_response(hook)
|
|
122
|
+
|
|
123
|
+
def close(self) -> None:
|
|
124
|
+
"""Close the underlying HTTP client and event loop."""
|
|
125
|
+
self._run(self._async_client.close())
|
|
126
|
+
self._loop.close()
|
|
127
|
+
|
|
128
|
+
def __enter__(self) -> SyncOrderCloudClient:
|
|
129
|
+
return self
|
|
130
|
+
|
|
131
|
+
def __exit__(self, *args: object) -> None:
|
|
132
|
+
self.close()
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def paginate_sync(
|
|
136
|
+
list_method: Any,
|
|
137
|
+
*args: Any,
|
|
138
|
+
page_size: int = 100,
|
|
139
|
+
**kwargs: Any,
|
|
140
|
+
) -> Iterator[Any]:
|
|
141
|
+
"""Auto-paginate any sync list method, yielding individual items.
|
|
142
|
+
|
|
143
|
+
Works with the sync proxy methods on ``SyncOrderCloudClient``.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
list_method: A bound sync list method (e.g. ``client.products.list``).
|
|
147
|
+
*args: Positional arguments forwarded to the list method.
|
|
148
|
+
page_size: Items per page (default 100, the API maximum).
|
|
149
|
+
**kwargs: Keyword arguments forwarded to the list method.
|
|
150
|
+
|
|
151
|
+
Yields:
|
|
152
|
+
Individual items across all pages.
|
|
153
|
+
|
|
154
|
+
Example::
|
|
155
|
+
|
|
156
|
+
from ordercloud.sync_client import SyncOrderCloudClient, paginate_sync
|
|
157
|
+
|
|
158
|
+
with SyncOrderCloudClient.create(...) as client:
|
|
159
|
+
for product in paginate_sync(client.products.list, search="widget"):
|
|
160
|
+
print(product.name)
|
|
161
|
+
"""
|
|
162
|
+
page = 1
|
|
163
|
+
kwargs["page_size"] = page_size
|
|
164
|
+
while True:
|
|
165
|
+
kwargs["page"] = page
|
|
166
|
+
result = list_method(*args, **kwargs)
|
|
167
|
+
yield from result.items
|
|
168
|
+
if page >= result.meta.total_pages:
|
|
169
|
+
break
|
|
170
|
+
page += 1
|