checkout-intents 0.1.0__py3-none-any.whl → 0.3.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.
- checkout_intents/__init__.py +2 -0
- checkout_intents/_client.py +65 -14
- checkout_intents/_exceptions.py +34 -0
- checkout_intents/_models.py +31 -14
- checkout_intents/_utils/_compat.py +1 -1
- checkout_intents/_utils/_utils.py +3 -3
- checkout_intents/_version.py +1 -1
- checkout_intents/pagination.py +89 -0
- checkout_intents/resources/brands.py +4 -4
- checkout_intents/resources/checkout_intents.py +902 -4
- checkout_intents/types/__init__.py +1 -0
- checkout_intents/types/checkout_intent.py +5 -0
- checkout_intents/types/checkout_intent_list_params.py +22 -0
- checkout_intents/types/payment_method.py +22 -3
- checkout_intents/types/payment_method_param.py +22 -3
- checkout_intents/types/variant_selection.py +0 -8
- checkout_intents/types/variant_selection_param.py +0 -8
- {checkout_intents-0.1.0.dist-info → checkout_intents-0.3.0.dist-info}/METADATA +199 -11
- {checkout_intents-0.1.0.dist-info → checkout_intents-0.3.0.dist-info}/RECORD +21 -19
- {checkout_intents-0.1.0.dist-info → checkout_intents-0.3.0.dist-info}/WHEEL +0 -0
- {checkout_intents-0.1.0.dist-info → checkout_intents-0.3.0.dist-info}/licenses/LICENSE +0 -0
checkout_intents/__init__.py
CHANGED
|
@@ -29,6 +29,7 @@ from ._exceptions import (
|
|
|
29
29
|
RateLimitError,
|
|
30
30
|
APITimeoutError,
|
|
31
31
|
BadRequestError,
|
|
32
|
+
PollTimeoutError,
|
|
32
33
|
APIConnectionError,
|
|
33
34
|
AuthenticationError,
|
|
34
35
|
InternalServerError,
|
|
@@ -66,6 +67,7 @@ __all__ = [
|
|
|
66
67
|
"UnprocessableEntityError",
|
|
67
68
|
"RateLimitError",
|
|
68
69
|
"InternalServerError",
|
|
70
|
+
"PollTimeoutError",
|
|
69
71
|
"Timeout",
|
|
70
72
|
"RequestOptions",
|
|
71
73
|
"Client",
|
checkout_intents/_client.py
CHANGED
|
@@ -48,6 +48,23 @@ ENVIRONMENTS: Dict[str, str] = {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
def _extract_environment_from_api_key(api_key: str) -> Literal["staging", "production"] | None:
|
|
52
|
+
"""
|
|
53
|
+
Extracts the environment from a Rye API key.
|
|
54
|
+
API keys follow the format: RYE/{environment}-{key}
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
api_key: The API key to parse
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
The extracted environment ('staging' or 'production'), or None if the format doesn't match
|
|
61
|
+
"""
|
|
62
|
+
import re
|
|
63
|
+
|
|
64
|
+
match = re.match(r"^RYE/(staging|production)-", api_key)
|
|
65
|
+
return match.group(1) if match else None # type: ignore[return-value]
|
|
66
|
+
|
|
67
|
+
|
|
51
68
|
class CheckoutIntents(SyncAPIClient):
|
|
52
69
|
checkout_intents: checkout_intents.CheckoutIntentsResource
|
|
53
70
|
brands: brands.BrandsResource
|
|
@@ -95,7 +112,26 @@ class CheckoutIntents(SyncAPIClient):
|
|
|
95
112
|
)
|
|
96
113
|
self.api_key = api_key
|
|
97
114
|
|
|
98
|
-
|
|
115
|
+
# Auto-infer environment from API key
|
|
116
|
+
inferred_environment = _extract_environment_from_api_key(api_key)
|
|
117
|
+
|
|
118
|
+
# Validate environment option matches API key (if both provided)
|
|
119
|
+
if is_given(environment) and inferred_environment and environment != inferred_environment:
|
|
120
|
+
raise CheckoutIntentsError(
|
|
121
|
+
f"Environment mismatch: API key is for '{inferred_environment}' environment but 'environment' option is set to '{environment}'. Please use an API key that matches your desired environment or omit the 'environment' option to auto-detect from the API key (only auto-detectable with the RYE/{{environment}}-abcdef api key format)."
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Use provided environment, or infer from API key, or default to staging
|
|
125
|
+
resolved_environment: Literal["staging", "production"]
|
|
126
|
+
if is_given(environment):
|
|
127
|
+
resolved_environment = cast(Literal["staging", "production"], environment)
|
|
128
|
+
self._environment = cast(Literal["staging", "production"], environment)
|
|
129
|
+
elif inferred_environment:
|
|
130
|
+
resolved_environment = inferred_environment
|
|
131
|
+
self._environment = inferred_environment
|
|
132
|
+
else:
|
|
133
|
+
resolved_environment = "staging"
|
|
134
|
+
self._environment = "staging"
|
|
99
135
|
|
|
100
136
|
base_url_env = os.environ.get("CHECKOUT_INTENTS_BASE_URL")
|
|
101
137
|
if is_given(base_url) and base_url is not None:
|
|
@@ -108,18 +144,16 @@ class CheckoutIntents(SyncAPIClient):
|
|
|
108
144
|
)
|
|
109
145
|
|
|
110
146
|
try:
|
|
111
|
-
base_url = ENVIRONMENTS[
|
|
147
|
+
base_url = ENVIRONMENTS[resolved_environment]
|
|
112
148
|
except KeyError as exc:
|
|
113
|
-
raise ValueError(f"Unknown environment: {
|
|
149
|
+
raise ValueError(f"Unknown environment: {resolved_environment}") from exc
|
|
114
150
|
elif base_url_env is not None:
|
|
115
151
|
base_url = base_url_env
|
|
116
152
|
else:
|
|
117
|
-
self._environment = environment = "staging"
|
|
118
|
-
|
|
119
153
|
try:
|
|
120
|
-
base_url = ENVIRONMENTS[
|
|
154
|
+
base_url = ENVIRONMENTS[resolved_environment]
|
|
121
155
|
except KeyError as exc:
|
|
122
|
-
raise ValueError(f"Unknown environment: {
|
|
156
|
+
raise ValueError(f"Unknown environment: {resolved_environment}") from exc
|
|
123
157
|
|
|
124
158
|
super().__init__(
|
|
125
159
|
version=__version__,
|
|
@@ -291,7 +325,26 @@ class AsyncCheckoutIntents(AsyncAPIClient):
|
|
|
291
325
|
)
|
|
292
326
|
self.api_key = api_key
|
|
293
327
|
|
|
294
|
-
|
|
328
|
+
# Auto-infer environment from API key
|
|
329
|
+
inferred_environment = _extract_environment_from_api_key(api_key)
|
|
330
|
+
|
|
331
|
+
# Validate environment option matches API key (if both provided)
|
|
332
|
+
if is_given(environment) and inferred_environment and environment != inferred_environment:
|
|
333
|
+
raise CheckoutIntentsError(
|
|
334
|
+
f"Environment mismatch: API key is for '{inferred_environment}' environment but 'environment' option is set to '{environment}'. Please use an API key that matches your desired environment or omit the 'environment' option to auto-detect from the API key (only auto-detectable with the RYE/{{environment}}-abcdef api key format)."
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Use provided environment, or infer from API key, or default to staging
|
|
338
|
+
resolved_environment: Literal["staging", "production"]
|
|
339
|
+
if is_given(environment):
|
|
340
|
+
resolved_environment = cast(Literal["staging", "production"], environment)
|
|
341
|
+
self._environment = cast(Literal["staging", "production"], environment)
|
|
342
|
+
elif inferred_environment:
|
|
343
|
+
resolved_environment = inferred_environment
|
|
344
|
+
self._environment = inferred_environment
|
|
345
|
+
else:
|
|
346
|
+
resolved_environment = "staging"
|
|
347
|
+
self._environment = "staging"
|
|
295
348
|
|
|
296
349
|
base_url_env = os.environ.get("CHECKOUT_INTENTS_BASE_URL")
|
|
297
350
|
if is_given(base_url) and base_url is not None:
|
|
@@ -304,18 +357,16 @@ class AsyncCheckoutIntents(AsyncAPIClient):
|
|
|
304
357
|
)
|
|
305
358
|
|
|
306
359
|
try:
|
|
307
|
-
base_url = ENVIRONMENTS[
|
|
360
|
+
base_url = ENVIRONMENTS[resolved_environment]
|
|
308
361
|
except KeyError as exc:
|
|
309
|
-
raise ValueError(f"Unknown environment: {
|
|
362
|
+
raise ValueError(f"Unknown environment: {resolved_environment}") from exc
|
|
310
363
|
elif base_url_env is not None:
|
|
311
364
|
base_url = base_url_env
|
|
312
365
|
else:
|
|
313
|
-
self._environment = environment = "staging"
|
|
314
|
-
|
|
315
366
|
try:
|
|
316
|
-
base_url = ENVIRONMENTS[
|
|
367
|
+
base_url = ENVIRONMENTS[resolved_environment]
|
|
317
368
|
except KeyError as exc:
|
|
318
|
-
raise ValueError(f"Unknown environment: {
|
|
369
|
+
raise ValueError(f"Unknown environment: {resolved_environment}") from exc
|
|
319
370
|
|
|
320
371
|
super().__init__(
|
|
321
372
|
version=__version__,
|
checkout_intents/_exceptions.py
CHANGED
|
@@ -15,6 +15,7 @@ __all__ = [
|
|
|
15
15
|
"UnprocessableEntityError",
|
|
16
16
|
"RateLimitError",
|
|
17
17
|
"InternalServerError",
|
|
18
|
+
"PollTimeoutError",
|
|
18
19
|
]
|
|
19
20
|
|
|
20
21
|
|
|
@@ -106,3 +107,36 @@ class RateLimitError(APIStatusError):
|
|
|
106
107
|
|
|
107
108
|
class InternalServerError(APIStatusError):
|
|
108
109
|
pass
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class PollTimeoutError(CheckoutIntentsError):
|
|
113
|
+
"""Raised when a polling operation times out before the condition is met."""
|
|
114
|
+
|
|
115
|
+
intent_id: str
|
|
116
|
+
attempts: int
|
|
117
|
+
poll_interval: float
|
|
118
|
+
max_attempts: int
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
*,
|
|
123
|
+
intent_id: str,
|
|
124
|
+
attempts: int,
|
|
125
|
+
poll_interval: float,
|
|
126
|
+
max_attempts: int,
|
|
127
|
+
message: str | None = None,
|
|
128
|
+
) -> None:
|
|
129
|
+
self.intent_id = intent_id
|
|
130
|
+
self.attempts = attempts
|
|
131
|
+
self.poll_interval = poll_interval
|
|
132
|
+
self.max_attempts = max_attempts
|
|
133
|
+
|
|
134
|
+
if message is None:
|
|
135
|
+
total_time_s = max_attempts * poll_interval
|
|
136
|
+
message = (
|
|
137
|
+
f"Polling timeout for checkout intent '{intent_id}': "
|
|
138
|
+
f"condition not met after {attempts} attempts ({total_time_s}s). "
|
|
139
|
+
f"Consider increasing max_attempts, polling_interval_ms, or checking the intent state manually."
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
super().__init__(message)
|
checkout_intents/_models.py
CHANGED
|
@@ -251,21 +251,22 @@ class BaseModel(pydantic.BaseModel):
|
|
|
251
251
|
# pydantic version they are currently using
|
|
252
252
|
|
|
253
253
|
@override
|
|
254
|
-
def model_dump(
|
|
254
|
+
def model_dump( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
|
|
255
255
|
self,
|
|
256
256
|
*,
|
|
257
257
|
mode: Literal["json", "python"] | str = "python",
|
|
258
258
|
include: IncEx | None = None,
|
|
259
259
|
exclude: IncEx | None = None,
|
|
260
|
+
context: Any | None = None,
|
|
260
261
|
by_alias: bool | None = None,
|
|
261
262
|
exclude_unset: bool = False,
|
|
262
263
|
exclude_defaults: bool = False,
|
|
263
264
|
exclude_none: bool = False,
|
|
265
|
+
exclude_computed_fields: bool = False,
|
|
264
266
|
round_trip: bool = False,
|
|
265
267
|
warnings: bool | Literal["none", "warn", "error"] = True,
|
|
266
|
-
context: dict[str, Any] | None = None,
|
|
267
|
-
serialize_as_any: bool = False,
|
|
268
268
|
fallback: Callable[[Any], Any] | None = None,
|
|
269
|
+
serialize_as_any: bool = False,
|
|
269
270
|
) -> dict[str, Any]:
|
|
270
271
|
"""Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump
|
|
271
272
|
|
|
@@ -273,16 +274,24 @@ class BaseModel(pydantic.BaseModel):
|
|
|
273
274
|
|
|
274
275
|
Args:
|
|
275
276
|
mode: The mode in which `to_python` should run.
|
|
276
|
-
If mode is 'json', the
|
|
277
|
-
If mode is 'python', the
|
|
278
|
-
include: A
|
|
279
|
-
exclude: A
|
|
277
|
+
If mode is 'json', the output will only contain JSON serializable types.
|
|
278
|
+
If mode is 'python', the output may contain non-JSON-serializable Python objects.
|
|
279
|
+
include: A set of fields to include in the output.
|
|
280
|
+
exclude: A set of fields to exclude from the output.
|
|
281
|
+
context: Additional context to pass to the serializer.
|
|
280
282
|
by_alias: Whether to use the field's alias in the dictionary key if defined.
|
|
281
|
-
exclude_unset: Whether to exclude fields that
|
|
282
|
-
exclude_defaults: Whether to exclude fields that are set to their default value
|
|
283
|
-
exclude_none: Whether to exclude fields that have a value of `None
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
exclude_unset: Whether to exclude fields that have not been explicitly set.
|
|
284
|
+
exclude_defaults: Whether to exclude fields that are set to their default value.
|
|
285
|
+
exclude_none: Whether to exclude fields that have a value of `None`.
|
|
286
|
+
exclude_computed_fields: Whether to exclude computed fields.
|
|
287
|
+
While this can be useful for round-tripping, it is usually recommended to use the dedicated
|
|
288
|
+
`round_trip` parameter instead.
|
|
289
|
+
round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
|
|
290
|
+
warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
|
|
291
|
+
"error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
|
|
292
|
+
fallback: A function to call when an unknown value is encountered. If not provided,
|
|
293
|
+
a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
|
|
294
|
+
serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
|
|
286
295
|
|
|
287
296
|
Returns:
|
|
288
297
|
A dictionary representation of the model.
|
|
@@ -299,6 +308,8 @@ class BaseModel(pydantic.BaseModel):
|
|
|
299
308
|
raise ValueError("serialize_as_any is only supported in Pydantic v2")
|
|
300
309
|
if fallback is not None:
|
|
301
310
|
raise ValueError("fallback is only supported in Pydantic v2")
|
|
311
|
+
if exclude_computed_fields != False:
|
|
312
|
+
raise ValueError("exclude_computed_fields is only supported in Pydantic v2")
|
|
302
313
|
dumped = super().dict( # pyright: ignore[reportDeprecated]
|
|
303
314
|
include=include,
|
|
304
315
|
exclude=exclude,
|
|
@@ -311,19 +322,21 @@ class BaseModel(pydantic.BaseModel):
|
|
|
311
322
|
return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped
|
|
312
323
|
|
|
313
324
|
@override
|
|
314
|
-
def model_dump_json(
|
|
325
|
+
def model_dump_json( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
|
|
315
326
|
self,
|
|
316
327
|
*,
|
|
317
328
|
indent: int | None = None,
|
|
329
|
+
ensure_ascii: bool = False,
|
|
318
330
|
include: IncEx | None = None,
|
|
319
331
|
exclude: IncEx | None = None,
|
|
332
|
+
context: Any | None = None,
|
|
320
333
|
by_alias: bool | None = None,
|
|
321
334
|
exclude_unset: bool = False,
|
|
322
335
|
exclude_defaults: bool = False,
|
|
323
336
|
exclude_none: bool = False,
|
|
337
|
+
exclude_computed_fields: bool = False,
|
|
324
338
|
round_trip: bool = False,
|
|
325
339
|
warnings: bool | Literal["none", "warn", "error"] = True,
|
|
326
|
-
context: dict[str, Any] | None = None,
|
|
327
340
|
fallback: Callable[[Any], Any] | None = None,
|
|
328
341
|
serialize_as_any: bool = False,
|
|
329
342
|
) -> str:
|
|
@@ -355,6 +368,10 @@ class BaseModel(pydantic.BaseModel):
|
|
|
355
368
|
raise ValueError("serialize_as_any is only supported in Pydantic v2")
|
|
356
369
|
if fallback is not None:
|
|
357
370
|
raise ValueError("fallback is only supported in Pydantic v2")
|
|
371
|
+
if ensure_ascii != False:
|
|
372
|
+
raise ValueError("ensure_ascii is only supported in Pydantic v2")
|
|
373
|
+
if exclude_computed_fields != False:
|
|
374
|
+
raise ValueError("exclude_computed_fields is only supported in Pydantic v2")
|
|
358
375
|
return super().json( # type: ignore[reportDeprecated]
|
|
359
376
|
indent=indent,
|
|
360
377
|
include=include,
|
|
@@ -34,7 +34,7 @@ def is_typeddict(tp: Type[Any]) -> bool:
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def is_literal_type(tp: Type[Any]) -> bool:
|
|
37
|
-
return get_origin(tp) in _LITERAL_TYPES
|
|
37
|
+
return get_origin(tp) in _LITERAL_TYPES # type: ignore[comparison-overlap]
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def parse_date(value: Union[date, StrBytesIntFloat]) -> date:
|
|
@@ -373,9 +373,9 @@ def get_required_header(headers: HeadersLike, header: str) -> str:
|
|
|
373
373
|
lower_header = header.lower()
|
|
374
374
|
if is_mapping_t(headers):
|
|
375
375
|
# mypy doesn't understand the type narrowing here
|
|
376
|
-
for k, v in headers.items(): # type: ignore
|
|
377
|
-
if k.lower() == lower_header and isinstance(v, str):
|
|
378
|
-
return v
|
|
376
|
+
for k, v in headers.items(): # type: ignore[misc, has-type, attr-defined]
|
|
377
|
+
if k.lower() == lower_header and isinstance(v, str): # type: ignore[has-type]
|
|
378
|
+
return v # type: ignore[has-type]
|
|
379
379
|
|
|
380
380
|
# to deal with the case where the header looks like Stainless-Event-Id
|
|
381
381
|
intercaps_header = re.sub(r"([^\w])(\w)", lambda pat: pat.group(1) + pat.group(2).upper(), header.capitalize())
|
checkout_intents/_version.py
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
|
+
|
|
3
|
+
from typing import List, Generic, TypeVar, Optional
|
|
4
|
+
from typing_extensions import override
|
|
5
|
+
|
|
6
|
+
from pydantic import Field as FieldInfo
|
|
7
|
+
|
|
8
|
+
from ._models import BaseModel
|
|
9
|
+
from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
|
|
10
|
+
|
|
11
|
+
__all__ = ["CursorPaginationPageInfo", "SyncCursorPagination", "AsyncCursorPagination"]
|
|
12
|
+
|
|
13
|
+
_T = TypeVar("_T")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CursorPaginationPageInfo(BaseModel):
|
|
17
|
+
end_cursor: Optional[str] = FieldInfo(alias="endCursor", default=None)
|
|
18
|
+
|
|
19
|
+
has_next_page: Optional[bool] = FieldInfo(alias="hasNextPage", default=None)
|
|
20
|
+
|
|
21
|
+
has_previous_page: Optional[bool] = FieldInfo(alias="hasPreviousPage", default=None)
|
|
22
|
+
|
|
23
|
+
start_cursor: Optional[str] = FieldInfo(alias="startCursor", default=None)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SyncCursorPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
|
|
27
|
+
data: List[_T]
|
|
28
|
+
page_info: Optional[CursorPaginationPageInfo] = FieldInfo(alias="pageInfo", default=None)
|
|
29
|
+
|
|
30
|
+
@override
|
|
31
|
+
def _get_page_items(self) -> List[_T]:
|
|
32
|
+
data = self.data
|
|
33
|
+
if not data:
|
|
34
|
+
return []
|
|
35
|
+
return data
|
|
36
|
+
|
|
37
|
+
@override
|
|
38
|
+
def next_page_info(self) -> Optional[PageInfo]:
|
|
39
|
+
if self._options.params.get("before"):
|
|
40
|
+
start_cursor = None
|
|
41
|
+
if self.page_info is not None:
|
|
42
|
+
if self.page_info.start_cursor is not None:
|
|
43
|
+
start_cursor = self.page_info.start_cursor
|
|
44
|
+
if not start_cursor:
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
return PageInfo(params={"before": start_cursor})
|
|
48
|
+
|
|
49
|
+
end_cursor = None
|
|
50
|
+
if self.page_info is not None:
|
|
51
|
+
if self.page_info.end_cursor is not None:
|
|
52
|
+
end_cursor = self.page_info.end_cursor
|
|
53
|
+
if not end_cursor:
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
return PageInfo(params={"after": end_cursor})
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class AsyncCursorPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
|
|
60
|
+
data: List[_T]
|
|
61
|
+
page_info: Optional[CursorPaginationPageInfo] = FieldInfo(alias="pageInfo", default=None)
|
|
62
|
+
|
|
63
|
+
@override
|
|
64
|
+
def _get_page_items(self) -> List[_T]:
|
|
65
|
+
data = self.data
|
|
66
|
+
if not data:
|
|
67
|
+
return []
|
|
68
|
+
return data
|
|
69
|
+
|
|
70
|
+
@override
|
|
71
|
+
def next_page_info(self) -> Optional[PageInfo]:
|
|
72
|
+
if self._options.params.get("before"):
|
|
73
|
+
start_cursor = None
|
|
74
|
+
if self.page_info is not None:
|
|
75
|
+
if self.page_info.start_cursor is not None:
|
|
76
|
+
start_cursor = self.page_info.start_cursor
|
|
77
|
+
if not start_cursor:
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
return PageInfo(params={"before": start_cursor})
|
|
81
|
+
|
|
82
|
+
end_cursor = None
|
|
83
|
+
if self.page_info is not None:
|
|
84
|
+
if self.page_info.end_cursor is not None:
|
|
85
|
+
end_cursor = self.page_info.end_cursor
|
|
86
|
+
if not end_cursor:
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
return PageInfo(params={"after": end_cursor})
|
|
@@ -53,8 +53,8 @@ class BrandsResource(SyncAPIResource):
|
|
|
53
53
|
"""
|
|
54
54
|
Retrieve brand information by domain name
|
|
55
55
|
|
|
56
|
-
Look up a brand by its domain name (e.g. "aloyoga.com").
|
|
57
|
-
information including the marketplace type if the lookup succeeds.
|
|
56
|
+
Look up a brand by its domain name (e.g. "aloyoga.com" or "www.amazon.com").
|
|
57
|
+
Returns brand information including the marketplace type if the lookup succeeds.
|
|
58
58
|
|
|
59
59
|
Args:
|
|
60
60
|
domain: Represents a valid domain name string.
|
|
@@ -112,8 +112,8 @@ class AsyncBrandsResource(AsyncAPIResource):
|
|
|
112
112
|
"""
|
|
113
113
|
Retrieve brand information by domain name
|
|
114
114
|
|
|
115
|
-
Look up a brand by its domain name (e.g. "aloyoga.com").
|
|
116
|
-
information including the marketplace type if the lookup succeeds.
|
|
115
|
+
Look up a brand by its domain name (e.g. "aloyoga.com" or "www.amazon.com").
|
|
116
|
+
Returns brand information including the marketplace type if the lookup succeeds.
|
|
117
117
|
|
|
118
118
|
Args:
|
|
119
119
|
domain: Represents a valid domain name string.
|