vtexpy 0.0.0b8__tar.gz → 0.0.0b10__tar.gz

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.

Potentially problematic release.


This version of vtexpy might be problematic. Click here for more details.

Files changed (26) hide show
  1. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/PKG-INFO +6 -4
  2. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/README.md +4 -3
  3. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/pyproject.toml +2 -1
  4. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/base.py +25 -45
  5. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/catalog.py +6 -6
  6. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/checkout.py +1 -1
  7. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/custom.py +29 -2
  8. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/license_manager.py +1 -1
  9. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/logistics.py +7 -7
  10. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/master_data.py +1 -1
  11. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/orders.py +4 -4
  12. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/payments_gateway.py +8 -8
  13. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/promotions_and_taxes.py +13 -3
  14. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_logging.py +9 -7
  15. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_utils.py +32 -9
  16. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_vtex.py +44 -33
  17. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/LICENSE +0 -0
  18. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/__init__.py +0 -0
  19. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_api/__init__.py +0 -0
  20. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_config.py +0 -0
  21. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_constants.py +0 -0
  22. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_dto.py +0 -0
  23. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_exceptions.py +0 -0
  24. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_sentinels.py +0 -0
  25. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/_types.py +0 -0
  26. {vtexpy-0.0.0b8 → vtexpy-0.0.0b10}/vtex/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vtexpy
3
- Version: 0.0.0b8
3
+ Version: 0.0.0b10
4
4
  Summary: Unofficial Python SDK for VTEX API
5
5
  Home-page: https://github.com/lvieirajr/vtex-python
6
6
  License: MIT
@@ -26,6 +26,7 @@ Classifier: Topic :: Software Development :: Libraries
26
26
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
27
  Classifier: Typing :: Typed
28
28
  Requires-Dist: httpx (>=0.26,<1.0)
29
+ Requires-Dist: python-dateutil (>=2.9,<3.0)
29
30
  Requires-Dist: tenacity (>=8.3,<10.0)
30
31
  Project-URL: Documentation, https://github.com/lvieirajr/vtex-python
31
32
  Project-URL: Repository, https://github.com/lvieirajr/vtex-python
@@ -53,9 +54,10 @@ API.
53
54
 
54
55
  #### Requirements
55
56
 
56
- - Python >= 3.9, <3.14
57
- - httpx >= 0.26, <1.0
58
- - tenacity >= 8.3, <10.0
57
+ - Python >= 3.9, < 3.14
58
+ - httpx >= 0.26, < 1.0
59
+ - python-dateutil >= 2.9, < 3.0
60
+ - tenacity >= 8.3, < 10.0
59
61
 
60
62
  #### Installation
61
63
 
@@ -20,9 +20,10 @@ API.
20
20
 
21
21
  #### Requirements
22
22
 
23
- - Python >= 3.9, <3.14
24
- - httpx >= 0.26, <1.0
25
- - tenacity >= 8.3, <10.0
23
+ - Python >= 3.9, < 3.14
24
+ - httpx >= 0.26, < 1.0
25
+ - python-dateutil >= 2.9, < 3.0
26
+ - tenacity >= 8.3, < 10.0
26
27
 
27
28
  #### Installation
28
29
 
@@ -32,7 +32,7 @@ classifiers = [
32
32
  packages = [
33
33
  {include = "vtex"},
34
34
  ]
35
- version = "0.0.0b8"
35
+ version = "0.0.0b10"
36
36
 
37
37
  [build-system]
38
38
  requires = ["poetry-core"]
@@ -41,6 +41,7 @@ build-backend = "poetry.core.masonry.api"
41
41
  [tool.poetry.dependencies]
42
42
  python = ">=3.9,<3.14"
43
43
  httpx = {version = ">=0.26,<1.0"}
44
+ python-dateutil = {version = ">=2.9,<3.0"}
44
45
  tenacity = {version = ">=8.3,<10.0"}
45
46
 
46
47
  [tool.poetry.group.dev.dependencies]
@@ -1,6 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from json import JSONDecodeError
3
- from logging import WARNING, Logger
3
+ from logging import WARNING
4
4
  from typing import Any, Type, Union, cast
5
5
  from urllib.parse import urljoin
6
6
 
@@ -32,7 +32,8 @@ from .._dto import VTEXResponse, VTEXResponseType
32
32
  from .._exceptions import VTEXRequestError, VTEXResponseError
33
33
  from .._logging import get_logger, log_before_retry
34
34
  from .._types import HTTPMethodType
35
- from .._utils import redact_headers, to_snake_case_deep
35
+ from .._utils import redact_headers, to_snake_case, to_snake_case_deep
36
+ from .._vtex import VTEX
36
37
 
37
38
 
38
39
  class BaseAPI:
@@ -40,13 +41,12 @@ class BaseAPI:
40
41
  Base client for VTEX API.
41
42
  """
42
43
 
43
- def __init__(
44
- self,
45
- config: Union[Config, None] = None,
46
- logger: Union[Logger, None] = None,
47
- ) -> None:
48
- self._config = config or Config()
49
- self._logger = get_logger(type(self).__name__, logger=logger)
44
+ def __init__(self, client: VTEX) -> None:
45
+ self.client = client
46
+ self.logger = get_logger(
47
+ name=to_snake_case(type(self).__name__),
48
+ parent=self.client.logger,
49
+ )
50
50
 
51
51
  def _request(
52
52
  self,
@@ -63,14 +63,18 @@ class BaseAPI:
63
63
  config: Union[Config, None] = None,
64
64
  response_class: Union[Type[VTEXResponseType], None] = None,
65
65
  ) -> VTEXResponseType:
66
- request_config = self._get_config(config=config)
67
- url = self._get_url(
68
- config=request_config,
69
- environment=environment,
70
- endpoint=endpoint,
66
+ request_config = config or self.client.config
67
+
68
+ url = urljoin(
69
+ f"https://{request_config.get_account_name()}.{environment}.com.br",
70
+ endpoint,
71
71
  )
72
- headers = self._get_headers(config=request_config, headers=headers)
73
- retry_statuses = set(request_config.get_retry_statuses())
72
+
73
+ headers = Headers(headers=headers)
74
+ headers[APP_KEY_HEADER] = request_config.get_app_key()
75
+ headers[APP_TOKEN_HEADER] = request_config.get_app_token()
76
+ headers["Content-Type"] = "application/json; charset=utf-8"
77
+ headers["Accept"] = "application/json"
74
78
 
75
79
  @retry(
76
80
  stop=stop_after_attempt(
@@ -83,7 +87,7 @@ class BaseAPI:
83
87
  ),
84
88
  retry=retry_if_exception_type(exception_types=HTTPError),
85
89
  before_sleep=(
86
- log_before_retry(logger=self._logger, log_level=WARNING)
90
+ log_before_retry(logger=self.logger, log_level=WARNING)
87
91
  if request_config.get_retry_logs()
88
92
  else None
89
93
  ),
@@ -107,7 +111,7 @@ class BaseAPI:
107
111
  redact_headers(dict(response.request.headers)),
108
112
  )
109
113
  response.headers = Headers(redact_headers(dict(response.headers)))
110
- if response.status_code in retry_statuses:
114
+ if response.status_code in request_config.get_retry_statuses():
111
115
  response.raise_for_status()
112
116
 
113
117
  return response
@@ -126,7 +130,7 @@ class BaseAPI:
126
130
  "headers": headers,
127
131
  }
128
132
 
129
- self._logger.error(str(exception), extra=details, exc_info=True)
133
+ self.logger.error(str(exception), extra=details, exc_info=True)
130
134
 
131
135
  raise VTEXRequestError(**details) from None # type: ignore[arg-type]
132
136
 
@@ -137,30 +141,6 @@ class BaseAPI:
137
141
  (response_class or VTEXResponse).factory(response),
138
142
  )
139
143
 
140
- def _get_config(self, config: Union[Config, None]) -> Config:
141
- return config or self._config
142
-
143
- def _get_url(self, config: Config, environment: str, endpoint: str) -> str:
144
- return urljoin(
145
- f"https://{config.get_account_name()}.{environment}.com.br",
146
- endpoint,
147
- )
148
-
149
- def _get_headers(
150
- self,
151
- config: Config,
152
- headers: Union[HeaderTypes, None] = None,
153
- ) -> Headers:
154
- request_headers = Headers(headers=headers)
155
-
156
- request_headers[APP_KEY_HEADER] = config.get_app_key()
157
- request_headers[APP_TOKEN_HEADER] = config.get_app_token()
158
-
159
- request_headers["Content-Type"] = "application/json; charset=utf-8"
160
- request_headers["Accept"] = "application/json"
161
-
162
- return request_headers
163
-
164
144
  def _raise_from_response(self, response: Response, config: Config) -> None:
165
145
  if response.is_error and config.get_raise_for_status():
166
146
  try:
@@ -179,8 +159,8 @@ class BaseAPI:
179
159
  )
180
160
 
181
161
  if response.is_server_error:
182
- self._logger.error(data, extra=error.to_dict())
162
+ self.logger.error(data, extra=error.to_dict())
183
163
  else:
184
- self._logger.warning(data, extra=error.to_dict())
164
+ self.logger.warning(data, extra=error.to_dict())
185
165
 
186
166
  raise error from None
@@ -39,7 +39,7 @@ class CatalogAPI(BaseAPI):
39
39
  "sellerType": seller_type,
40
40
  "isBetterScope": is_better_scope,
41
41
  }),
42
- config=self._config.with_overrides(**kwargs),
42
+ config=self.client.config.with_overrides(**kwargs),
43
43
  response_class=VTEXListResponse,
44
44
  )
45
45
 
@@ -60,7 +60,7 @@ class CatalogAPI(BaseAPI):
60
60
  MIN_PAGE_SIZE,
61
61
  ),
62
62
  },
63
- config=self._config.with_overrides(**kwargs),
63
+ config=self.client.config.with_overrides(**kwargs),
64
64
  response_class=VTEXListResponse,
65
65
  )
66
66
 
@@ -69,7 +69,7 @@ class CatalogAPI(BaseAPI):
69
69
  method="GET",
70
70
  environment=self.ENVIRONMENT,
71
71
  endpoint=f"/api/catalog_system/pvt/sku/stockkeepingunitbyid/{sku_id}",
72
- config=self._config.with_overrides(**kwargs),
72
+ config=self.client.config.with_overrides(**kwargs),
73
73
  response_class=VTEXResponse,
74
74
  )
75
75
 
@@ -90,7 +90,7 @@ class CatalogAPI(BaseAPI):
90
90
  MIN_PAGE_SIZE,
91
91
  ),
92
92
  },
93
- config=self._config.with_overrides(**kwargs),
93
+ config=self.client.config.with_overrides(**kwargs),
94
94
  response_class=VTEXPaginatedListResponse,
95
95
  )
96
96
 
@@ -103,7 +103,7 @@ class CatalogAPI(BaseAPI):
103
103
  method="GET",
104
104
  environment=self.ENVIRONMENT,
105
105
  endpoint=f"/api/catalog_system/pub/category/tree/{levels}",
106
- config=self._config.with_overrides(**kwargs),
106
+ config=self.client.config.with_overrides(**kwargs),
107
107
  response_class=VTEXResponse,
108
108
  )
109
109
 
@@ -112,6 +112,6 @@ class CatalogAPI(BaseAPI):
112
112
  method="GET",
113
113
  environment=self.ENVIRONMENT,
114
114
  endpoint=f"/api/catalog/pvt/category/{category_id}",
115
- config=self._config.with_overrides(**kwargs),
115
+ config=self.client.config.with_overrides(**kwargs),
116
116
  response_class=VTEXResponse,
117
117
  )
@@ -40,6 +40,6 @@ class CheckoutAPI(BaseAPI):
40
40
  "postalCode": postal_code,
41
41
  "geoCoordinates": geo_coordinates,
42
42
  }),
43
- config=self._config.with_overrides(**kwargs),
43
+ config=self.client.config.with_overrides(**kwargs),
44
44
  response_class=VTEXResponse,
45
45
  )
@@ -1,4 +1,5 @@
1
- from typing import Any, Type, Union
1
+ from datetime import datetime
2
+ from typing import Any, List, Type, Union
2
3
 
3
4
  from httpx._types import (
4
5
  CookieTypes,
@@ -11,6 +12,7 @@ from httpx._types import (
11
12
 
12
13
  from .._dto import VTEXResponseType
13
14
  from .._types import HTTPMethodType
15
+ from .._utils import to_datetime
14
16
  from .base import BaseAPI
15
17
 
16
18
 
@@ -46,6 +48,31 @@ class CustomAPI(BaseAPI):
46
48
  data=data,
47
49
  content=content,
48
50
  files=files,
49
- config=self._config.with_overrides(**kwargs),
51
+ config=self.client.config.with_overrides(**kwargs),
50
52
  response_class=response_class,
51
53
  )
54
+
55
+ def get_account_name(self) -> str:
56
+ return self.client.license_manager.get_account().data["account_name"]
57
+
58
+ def get_account_creation_date(self) -> datetime:
59
+ return to_datetime(
60
+ self.client.license_manager.get_account().data["creation_date"],
61
+ )
62
+
63
+ def get_main_seller(self) -> str:
64
+ return "1"
65
+
66
+ def get_market_place_sellers(self) -> List[str]:
67
+ return [
68
+ seller["seller_id"]
69
+ for seller in self.client.catalog.list_sellers(seller_type=1).items
70
+ if seller["seller_id"] != "1"
71
+ ]
72
+
73
+ def get_franchise_sellers(self) -> List[str]:
74
+ return [
75
+ seller["seller_id"]
76
+ for seller in
77
+ self.client.catalog.list_sellers(seller_type=2).items
78
+ ]
@@ -17,6 +17,6 @@ class LicenseManagerAPI(BaseAPI):
17
17
  method="GET",
18
18
  environment=self.ENVIRONMENT,
19
19
  endpoint="/api/vlm/account",
20
- config=self._config.with_overrides(**kwargs),
20
+ config=self.client.config.with_overrides(**kwargs),
21
21
  response_class=VTEXResponse,
22
22
  )
@@ -38,7 +38,7 @@ class LogisticsAPI(BaseAPI):
38
38
  MIN_PAGE_SIZE,
39
39
  ),
40
40
  },
41
- config=self._config.with_overrides(**kwargs),
41
+ config=self.client.config.with_overrides(**kwargs),
42
42
  response_class=VTEXPaginatedListResponse,
43
43
  )
44
44
 
@@ -51,7 +51,7 @@ class LogisticsAPI(BaseAPI):
51
51
  method="GET",
52
52
  environment=self.ENVIRONMENT,
53
53
  endpoint=f"/api/logistics/pvt/shipping-policies/{shipping_policy_id}",
54
- config=self._config.with_overrides(**kwargs),
54
+ config=self.client.config.with_overrides(**kwargs),
55
55
  response_class=VTEXResponse,
56
56
  )
57
57
 
@@ -72,7 +72,7 @@ class LogisticsAPI(BaseAPI):
72
72
  MIN_PAGE_SIZE,
73
73
  ),
74
74
  },
75
- config=self._config.with_overrides(**kwargs),
75
+ config=self.client.config.with_overrides(**kwargs),
76
76
  response_class=VTEXPaginatedListResponse,
77
77
  )
78
78
 
@@ -85,7 +85,7 @@ class LogisticsAPI(BaseAPI):
85
85
  method="GET",
86
86
  environment=self.ENVIRONMENT,
87
87
  endpoint=f"/api/logistics/pvt/configuration/carriers/{carrier_id}",
88
- config=self._config.with_overrides(**kwargs),
88
+ config=self.client.config.with_overrides(**kwargs),
89
89
  response_class=VTEXResponse,
90
90
  )
91
91
 
@@ -106,7 +106,7 @@ class LogisticsAPI(BaseAPI):
106
106
  MIN_PAGE_SIZE,
107
107
  ),
108
108
  },
109
- config=self._config.with_overrides(**kwargs),
109
+ config=self.client.config.with_overrides(**kwargs),
110
110
  response_class=VTEXPaginatedListResponse,
111
111
  )
112
112
 
@@ -115,7 +115,7 @@ class LogisticsAPI(BaseAPI):
115
115
  method="GET",
116
116
  environment=self.ENVIRONMENT,
117
117
  endpoint=f"/api/logistics/pvt/configuration/docks/{dock_id}",
118
- config=self._config.with_overrides(**kwargs),
118
+ config=self.client.config.with_overrides(**kwargs),
119
119
  response_class=VTEXResponse,
120
120
  )
121
121
 
@@ -124,6 +124,6 @@ class LogisticsAPI(BaseAPI):
124
124
  method="GET",
125
125
  environment=self.ENVIRONMENT,
126
126
  endpoint=f"/api/logistics/pvt/inventory/skus/{sku_id}",
127
- config=self._config.with_overrides(**kwargs),
127
+ config=self.client.config.with_overrides(**kwargs),
128
128
  response_class=VTEXResponse,
129
129
  )
@@ -57,6 +57,6 @@ class MasterDataAPI(BaseAPI):
57
57
  headers={
58
58
  "REST-Range": f"resources={(page - 1) * page_size}-{page * page_size}",
59
59
  },
60
- config=self._config.with_overrides(**kwargs),
60
+ config=self.client.config.with_overrides(**kwargs),
61
61
  response_class=VTEXPaginatedListResponse,
62
62
  )
@@ -83,7 +83,7 @@ class OrdersAPI(BaseAPI):
83
83
  environment=self.ENVIRONMENT,
84
84
  endpoint="/api/oms/pvt/orders/",
85
85
  params=params,
86
- config=self._config.with_overrides(**kwargs),
86
+ config=self.client.config.with_overrides(**kwargs),
87
87
  response_class=VTEXPaginatedListResponse,
88
88
  )
89
89
 
@@ -98,7 +98,7 @@ class OrdersAPI(BaseAPI):
98
98
  method="GET",
99
99
  environment=self.ENVIRONMENT,
100
100
  endpoint=f"/api/oms/pvt/orders/{order_id}",
101
- config=self._config.with_overrides(**kwargs),
101
+ config=self.client.config.with_overrides(**kwargs),
102
102
  response_class=VTEXResponse,
103
103
  )
104
104
 
@@ -117,7 +117,7 @@ class OrdersAPI(BaseAPI):
117
117
  MIN_PAGE_SIZE,
118
118
  ),
119
119
  },
120
- config=self._config.with_overrides(**kwargs),
120
+ config=self.client.config.with_overrides(**kwargs),
121
121
  response_class=VTEXListResponse,
122
122
  )
123
123
 
@@ -141,6 +141,6 @@ class OrdersAPI(BaseAPI):
141
141
  environment=self.ENVIRONMENT,
142
142
  endpoint="/api/orders/feed/",
143
143
  json={"handles": handles},
144
- config=self._config.with_overrides(**kwargs),
144
+ config=self.client.config.with_overrides(**kwargs),
145
145
  response_class=VTEXResponse,
146
146
  )
@@ -17,7 +17,7 @@ class PaymentsGatewayAPI(BaseAPI):
17
17
  method="GET",
18
18
  environment=self.ENVIRONMENT,
19
19
  endpoint=f"/api/pvt/transactions/{transaction_id}",
20
- config=self._config.with_overrides(**kwargs),
20
+ config=self.client.config.with_overrides(**kwargs),
21
21
  response_class=VTEXResponse,
22
22
  )
23
23
 
@@ -30,7 +30,7 @@ class PaymentsGatewayAPI(BaseAPI):
30
30
  method="GET",
31
31
  environment=self.ENVIRONMENT,
32
32
  endpoint=f"/api/pvt/transactions/{transaction_id}/interactions",
33
- config=self._config.with_overrides(**kwargs),
33
+ config=self.client.config.with_overrides(**kwargs),
34
34
  response_class=VTEXListResponse,
35
35
  )
36
36
 
@@ -43,7 +43,7 @@ class PaymentsGatewayAPI(BaseAPI):
43
43
  method="GET",
44
44
  environment=self.ENVIRONMENT,
45
45
  endpoint=f"/api/pvt/transactions/{transaction_id}/payments",
46
- config=self._config.with_overrides(**kwargs),
46
+ config=self.client.config.with_overrides(**kwargs),
47
47
  response_class=VTEXListResponse,
48
48
  )
49
49
 
@@ -57,7 +57,7 @@ class PaymentsGatewayAPI(BaseAPI):
57
57
  method="GET",
58
58
  environment=self.ENVIRONMENT,
59
59
  endpoint=f"/api/pvt/transactions/{transaction_id}/payments/{payment_id}",
60
- config=self._config.with_overrides(**kwargs),
60
+ config=self.client.config.with_overrides(**kwargs),
61
61
  response_class=VTEXResponse,
62
62
  )
63
63
 
@@ -70,7 +70,7 @@ class PaymentsGatewayAPI(BaseAPI):
70
70
  method="GET",
71
71
  environment=self.ENVIRONMENT,
72
72
  endpoint=f"/api/pvt/transactions/{transaction_id}/capabilities",
73
- config=self._config.with_overrides(**kwargs),
73
+ config=self.client.config.with_overrides(**kwargs),
74
74
  response_class=VTEXResponse,
75
75
  )
76
76
 
@@ -83,7 +83,7 @@ class PaymentsGatewayAPI(BaseAPI):
83
83
  method="GET",
84
84
  environment=self.ENVIRONMENT,
85
85
  endpoint=f"/api/pvt/transactions/{transaction_id}/cancellations",
86
- config=self._config.with_overrides(**kwargs),
86
+ config=self.client.config.with_overrides(**kwargs),
87
87
  response_class=VTEXResponse,
88
88
  )
89
89
 
@@ -96,7 +96,7 @@ class PaymentsGatewayAPI(BaseAPI):
96
96
  method="GET",
97
97
  environment=self.ENVIRONMENT,
98
98
  endpoint=f"/api/pvt/transactions/{transaction_id}/refunds",
99
- config=self._config.with_overrides(**kwargs),
99
+ config=self.client.config.with_overrides(**kwargs),
100
100
  response_class=VTEXResponse,
101
101
  )
102
102
 
@@ -109,6 +109,6 @@ class PaymentsGatewayAPI(BaseAPI):
109
109
  method="GET",
110
110
  environment=self.ENVIRONMENT,
111
111
  endpoint=f"/api/pvt/transactions/{transaction_id}/settlements",
112
- config=self._config.with_overrides(**kwargs),
112
+ config=self.client.config.with_overrides(**kwargs),
113
113
  response_class=VTEXResponse,
114
114
  )
@@ -1,5 +1,6 @@
1
1
  from typing import Any
2
2
 
3
+ from .. import VTEXListResponse
3
4
  from .._dto import VTEXResponse
4
5
  from .base import BaseAPI
5
6
 
@@ -12,12 +13,21 @@ class PromotionsAndTaxesAPI(BaseAPI):
12
13
 
13
14
  ENVIRONMENT = "vtexcommercestable"
14
15
 
16
+ def list_archived_promotions(self, **kwargs: Any) -> VTEXListResponse:
17
+ return self._request(
18
+ method="GET",
19
+ environment=self.ENVIRONMENT,
20
+ endpoint="api/rnb/pvt/archive/benefits/calculatorconfiguration",
21
+ config=self.client.config.with_overrides(**kwargs),
22
+ response_class=VTEXListResponse,
23
+ )
24
+
15
25
  def list_promotions(self, **kwargs: Any) -> VTEXResponse:
16
26
  return self._request(
17
27
  method="GET",
18
28
  environment=self.ENVIRONMENT,
19
29
  endpoint="api/rnb/pvt/benefits/calculatorconfiguration",
20
- config=self._config.with_overrides(**kwargs),
30
+ config=self.client.config.with_overrides(**kwargs),
21
31
  response_class=VTEXResponse,
22
32
  )
23
33
 
@@ -26,7 +36,7 @@ class PromotionsAndTaxesAPI(BaseAPI):
26
36
  method="GET",
27
37
  environment=self.ENVIRONMENT,
28
38
  endpoint="api/rnb/pvt/taxes/calculatorconfiguration",
29
- config=self._config.with_overrides(**kwargs),
39
+ config=self.client.config.with_overrides(**kwargs),
30
40
  response_class=VTEXResponse,
31
41
  )
32
42
 
@@ -39,6 +49,6 @@ class PromotionsAndTaxesAPI(BaseAPI):
39
49
  method="GET",
40
50
  environment=self.ENVIRONMENT,
41
51
  endpoint=f"/api/rnb/pvt/calculatorconfiguration/{promotion_or_tax_id}",
42
- config=self._config.with_overrides(**kwargs),
52
+ config=self.client.config.with_overrides(**kwargs),
43
53
  response_class=VTEXResponse,
44
54
  )
@@ -5,14 +5,11 @@ from httpx import HTTPStatusError
5
5
  from tenacity import RetryCallState
6
6
 
7
7
 
8
- def get_logger(name: str, logger: Union[Logger, None] = None) -> Logger:
9
- from ._utils import to_snake_case
8
+ def get_logger(name: str, parent: Union[Logger, None] = None) -> Logger:
9
+ if parent:
10
+ return parent.getChild(name)
10
11
 
11
- name = to_snake_case(name)
12
- if logger:
13
- return logger.getChild(name)
14
-
15
- return getLogger(f"vtex.{to_snake_case(name)}")
12
+ return getLogger(f"vtex.{name}")
16
13
 
17
14
 
18
15
  def log_before_retry(
@@ -45,3 +42,8 @@ def log_before_retry(
45
42
  )
46
43
 
47
44
  return retry_log
45
+
46
+
47
+ CLIENT_LOGGER = get_logger(name="client")
48
+ EXCEPTIONS_LOGGER = get_logger(name="exceptions")
49
+ UTILS_LOGGER = get_logger(name="utils")
@@ -3,10 +3,12 @@ from re import compile
3
3
  from typing import Any, Dict, Mapping, Union
4
4
  from uuid import UUID
5
5
 
6
+ from dateutil.parser import parse as parse_datetime
7
+ from dateutil.tz import tzoffset
6
8
  from distutils.util import strtobool
7
9
 
8
10
  from ._constants import APP_KEY_HEADER, APP_TOKEN_HEADER
9
- from ._logging import get_logger
11
+ from ._logging import UTILS_LOGGER
10
12
  from ._sentinels import UNDEFINED
11
13
  from ._types import JSONType
12
14
 
@@ -43,20 +45,15 @@ def to_snake_case(string: str) -> str:
43
45
 
44
46
 
45
47
  def to_snake_case_deep(obj: JSONType) -> JSONType:
46
- logger = get_logger("utils")
47
-
48
48
  if isinstance(obj, dict):
49
49
  snake_cased_obj = {}
50
50
 
51
- for key, value in sorted(
52
- obj.items(),
53
- key=lambda item: [(int(c.isupper()), c.lower()) for c in item[0]],
54
- ):
51
+ for key, value in sorted(obj.items(), key=lambda item: item[0]):
55
52
  if isinstance(key, str):
56
53
  key = to_snake_case(remove_null_bytes(key))
57
54
 
58
55
  while key in snake_cased_obj:
59
- logger.warning(
56
+ UTILS_LOGGER.debug(
60
57
  f"Snake cased key {key} appears multiple times in object",
61
58
  extra={"object": obj, "key": key},
62
59
  )
@@ -87,8 +84,34 @@ def redact_headers(headers: Mapping[str, str]) -> Dict[str, str]:
87
84
  return redacted_headers
88
85
 
89
86
 
87
+ def to_tzinfo(tz: Union[tzinfo, int, None] = None) -> tzinfo:
88
+ if isinstance(tz, tzinfo):
89
+ return tz
90
+
91
+ if isinstance(tz, int):
92
+ return tzoffset(None, tz)
93
+
94
+ return timezone.utc
95
+
96
+
97
+ def to_datetime(
98
+ value: Union[datetime, str],
99
+ use_tz: bool = True,
100
+ tz: Union[tzinfo, int, None] = None,
101
+ ) -> datetime:
102
+ value_as_datetime = value if isinstance(value, datetime) else parse_datetime(value)
103
+
104
+ if not use_tz:
105
+ return value_as_datetime.replace(tzinfo=None)
106
+
107
+ if value_as_datetime.tzinfo and tz is None:
108
+ return value_as_datetime
109
+
110
+ return value_as_datetime.replace(tzinfo=to_tzinfo(tz))
111
+
112
+
90
113
  def now(use_tz: bool = True, tz: Union[tzinfo, None] = None) -> datetime:
91
- return datetime.now((tz or timezone.utc) if use_tz else None)
114
+ return datetime.now(to_tzinfo(tz) if use_tz else None)
92
115
 
93
116
 
94
117
  def three_years_ago(use_tz: bool = True, tz: Union[tzinfo, None] = None) -> datetime:
@@ -1,22 +1,24 @@
1
1
  from functools import cached_property
2
- from typing import Union
2
+ from typing import TYPE_CHECKING, Union
3
3
 
4
- from ._api import (
5
- CatalogAPI,
6
- CheckoutAPI,
7
- CustomAPI,
8
- LicenseManagerAPI,
9
- LogisticsAPI,
10
- MasterDataAPI,
11
- OrdersAPI,
12
- PaymentsGatewayAPI,
13
- PromotionsAndTaxesAPI,
14
- )
15
4
  from ._config import Config # type: ignore[attr-defined]
16
- from ._logging import get_logger
5
+ from ._logging import CLIENT_LOGGER
17
6
  from ._sentinels import UNDEFINED, UndefinedSentinel
18
7
  from ._types import IterableType
19
8
 
9
+ if TYPE_CHECKING:
10
+ from ._api import (
11
+ CatalogAPI,
12
+ CheckoutAPI,
13
+ CustomAPI,
14
+ LicenseManagerAPI,
15
+ LogisticsAPI,
16
+ MasterDataAPI,
17
+ OrdersAPI,
18
+ PaymentsGatewayAPI,
19
+ PromotionsAndTaxesAPI,
20
+ )
21
+
20
22
 
21
23
  class VTEX:
22
24
  """
@@ -38,8 +40,8 @@ class VTEX:
38
40
  retry_logs: Union[bool, UndefinedSentinel] = UNDEFINED,
39
41
  raise_for_status: Union[bool, UndefinedSentinel] = UNDEFINED,
40
42
  ) -> None:
41
- self._logger = get_logger("client")
42
- self._config = Config(
43
+ self.logger = CLIENT_LOGGER
44
+ self.config = Config(
43
45
  account_name=account_name,
44
46
  app_key=app_key,
45
47
  app_token=app_token,
@@ -54,37 +56,46 @@ class VTEX:
54
56
  )
55
57
 
56
58
  @cached_property
57
- def custom(self) -> CustomAPI:
58
- return CustomAPI(config=self._config, logger=self._logger)
59
+ def custom(self) -> "CustomAPI":
60
+ from ._api import CustomAPI
61
+ return CustomAPI(client=self)
59
62
 
60
63
  @cached_property
61
- def catalog(self) -> CatalogAPI:
62
- return CatalogAPI(config=self._config, logger=self._logger)
64
+ def catalog(self) -> "CatalogAPI":
65
+ from ._api import CatalogAPI
66
+ return CatalogAPI(client=self)
63
67
 
64
68
  @cached_property
65
- def checkout(self) -> CheckoutAPI:
66
- return CheckoutAPI(config=self._config, logger=self._logger)
69
+ def checkout(self) -> "CheckoutAPI":
70
+ from ._api import CheckoutAPI
71
+ return CheckoutAPI(client=self)
67
72
 
68
73
  @cached_property
69
- def license_manager(self) -> LicenseManagerAPI:
70
- return LicenseManagerAPI(config=self._config, logger=self._logger)
74
+ def license_manager(self) -> "LicenseManagerAPI":
75
+ from ._api import LicenseManagerAPI
76
+ return LicenseManagerAPI(client=self)
71
77
 
72
78
  @cached_property
73
- def logistics(self) -> LogisticsAPI:
74
- return LogisticsAPI(config=self._config, logger=self._logger)
79
+ def logistics(self) -> "LogisticsAPI":
80
+ from ._api import LogisticsAPI
81
+ return LogisticsAPI(client=self)
75
82
 
76
83
  @cached_property
77
- def master_data(self) -> MasterDataAPI:
78
- return MasterDataAPI(config=self._config, logger=self._logger)
84
+ def master_data(self) -> "MasterDataAPI":
85
+ from ._api import MasterDataAPI
86
+ return MasterDataAPI(client=self)
79
87
 
80
88
  @cached_property
81
- def orders(self) -> OrdersAPI:
82
- return OrdersAPI(config=self._config, logger=self._logger)
89
+ def orders(self) -> "OrdersAPI":
90
+ from ._api import OrdersAPI
91
+ return OrdersAPI(client=self)
83
92
 
84
93
  @cached_property
85
- def payments_gateway(self) -> PaymentsGatewayAPI:
86
- return PaymentsGatewayAPI(config=self._config, logger=self._logger)
94
+ def payments_gateway(self) -> "PaymentsGatewayAPI":
95
+ from ._api import PaymentsGatewayAPI
96
+ return PaymentsGatewayAPI(client=self)
87
97
 
88
98
  @cached_property
89
- def promotions_and_taxes(self) -> PromotionsAndTaxesAPI:
90
- return PromotionsAndTaxesAPI(config=self._config, logger=self._logger)
99
+ def promotions_and_taxes(self) -> "PromotionsAndTaxesAPI":
100
+ from ._api import PromotionsAndTaxesAPI
101
+ return PromotionsAndTaxesAPI(client=self)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes