novaposhta-python-client 0.1.5__tar.gz → 0.1.6__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.
Files changed (18) hide show
  1. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/PKG-INFO +27 -16
  2. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/README.md +26 -15
  3. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/client.py +79 -28
  4. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/pyproject.toml +1 -1
  5. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/LICENSE.md +0 -0
  6. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/__init__.py +0 -0
  7. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/__init__.py +0 -0
  8. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/additional_service.py +0 -0
  9. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/address.py +0 -0
  10. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/base.py +0 -0
  11. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/common.py +0 -0
  12. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/contact_person.py +0 -0
  13. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/counterparty.py +0 -0
  14. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/internet_document.py +0 -0
  15. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/scan_sheet.py +0 -0
  16. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/models/tracking_document.py +0 -0
  17. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/mypi.ini +0 -0
  18. {novaposhta_python_client-0.1.5 → novaposhta_python_client-0.1.6}/novaposhta/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: novaposhta-python-client
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Python client for Nova Poshta API
5
5
  Home-page: https://github.com/semolex/novaposhta-python-client
6
6
  License: MIT
@@ -63,7 +63,9 @@ return_reason = client.additional_service.get_return_reasons()
63
63
 
64
64
  # Print results
65
65
  print(settlements, my_pack_list, return_reason)
66
+ client.close_sync()
66
67
  ```
68
+ Please, close the client whenever you are done with it to avoid resource leaks.
67
69
 
68
70
  You can also use async client:
69
71
 
@@ -71,10 +73,28 @@ You can also use async client:
71
73
  import asyncio
72
74
  from novaposhta.client import NovaPoshtaApi
73
75
 
74
- async_client = NovaPoshtaApi('my-api-token', timeout=30, async_mode=True)
75
- a_address = async_client.address
76
- a_settlement = asyncio.run(a_address.search_settlements(city_name='Київ', limit=5))
77
- print(a_settlement)
76
+ async def use_api_async():
77
+ async_client = NovaPoshtaApi('your_api_key', timeout=30, async_mode=True, raise_for_errors=True)
78
+ address = async_client.address
79
+ settlements = await address.search_settlements(city_name='Київ', limit=5)
80
+ print(settlements)
81
+ await async_client.close_async()
82
+ asyncio.run(use_api_async())
83
+ ```
84
+
85
+ You can use context manager to automatically close the client:
86
+
87
+ ```python
88
+ from novaposhta.client import NovaPoshtaApi
89
+ def use_api_sync():
90
+ with NovaPoshtaApi(api_key='your_api_key', async_mode=False) as api:
91
+ # Do something with the API
92
+ pass
93
+
94
+ async def use_api_async():
95
+ async with NovaPoshtaApi(api_key='your_api_key', async_mode=True) as api:
96
+ # Do something with the API
97
+ pass
78
98
  ```
79
99
 
80
100
  ## Error handling
@@ -84,7 +104,7 @@ import httpx
84
104
  from novaposhta.client import NovaPoshtaApi, InvalidAPIKeyError, APIRequestError
85
105
 
86
106
  # Instantiate the client
87
- client = NovaPoshtaApi('my-api-token', timeout=30, raise_for_errors=True)
107
+ client = NovaPoshtaApi('your_api_key', timeout=30, raise_for_errors=True)
88
108
 
89
109
  try:
90
110
  client.common.get_cargo_types()
@@ -107,16 +127,7 @@ follows the same interface:
107
127
  from novaposhta.client import NovaPoshtaApi
108
128
  import my_http_client
109
129
 
110
- client = NovaPoshtaApi('my-api-token', http_client=my_http_client.Client)
111
- ```
112
-
113
- Custom client should support context manager, e.g:
114
-
115
- ```python
116
- with self.http_client() as client:
117
- response = client.post(
118
- self.api_endpoint, json=request, headers=HEADERS, timeout=self.timeout
119
- )
130
+ client = NovaPoshtaApi('your_api_key', http_client=my_http_client.Client)
120
131
  ```
121
132
 
122
133
  ### Adding New Methods
@@ -39,7 +39,9 @@ return_reason = client.additional_service.get_return_reasons()
39
39
 
40
40
  # Print results
41
41
  print(settlements, my_pack_list, return_reason)
42
+ client.close_sync()
42
43
  ```
44
+ Please, close the client whenever you are done with it to avoid resource leaks.
43
45
 
44
46
  You can also use async client:
45
47
 
@@ -47,10 +49,28 @@ You can also use async client:
47
49
  import asyncio
48
50
  from novaposhta.client import NovaPoshtaApi
49
51
 
50
- async_client = NovaPoshtaApi('my-api-token', timeout=30, async_mode=True)
51
- a_address = async_client.address
52
- a_settlement = asyncio.run(a_address.search_settlements(city_name='Київ', limit=5))
53
- print(a_settlement)
52
+ async def use_api_async():
53
+ async_client = NovaPoshtaApi('your_api_key', timeout=30, async_mode=True, raise_for_errors=True)
54
+ address = async_client.address
55
+ settlements = await address.search_settlements(city_name='Київ', limit=5)
56
+ print(settlements)
57
+ await async_client.close_async()
58
+ asyncio.run(use_api_async())
59
+ ```
60
+
61
+ You can use context manager to automatically close the client:
62
+
63
+ ```python
64
+ from novaposhta.client import NovaPoshtaApi
65
+ def use_api_sync():
66
+ with NovaPoshtaApi(api_key='your_api_key', async_mode=False) as api:
67
+ # Do something with the API
68
+ pass
69
+
70
+ async def use_api_async():
71
+ async with NovaPoshtaApi(api_key='your_api_key', async_mode=True) as api:
72
+ # Do something with the API
73
+ pass
54
74
  ```
55
75
 
56
76
  ## Error handling
@@ -60,7 +80,7 @@ import httpx
60
80
  from novaposhta.client import NovaPoshtaApi, InvalidAPIKeyError, APIRequestError
61
81
 
62
82
  # Instantiate the client
63
- client = NovaPoshtaApi('my-api-token', timeout=30, raise_for_errors=True)
83
+ client = NovaPoshtaApi('your_api_key', timeout=30, raise_for_errors=True)
64
84
 
65
85
  try:
66
86
  client.common.get_cargo_types()
@@ -83,16 +103,7 @@ follows the same interface:
83
103
  from novaposhta.client import NovaPoshtaApi
84
104
  import my_http_client
85
105
 
86
- client = NovaPoshtaApi('my-api-token', http_client=my_http_client.Client)
87
- ```
88
-
89
- Custom client should support context manager, e.g:
90
-
91
- ```python
92
- with self.http_client() as client:
93
- response = client.post(
94
- self.api_endpoint, json=request, headers=HEADERS, timeout=self.timeout
95
- )
106
+ client = NovaPoshtaApi('your_api_key', http_client=my_http_client.Client)
96
107
  ```
97
108
 
98
109
  ### Adding New Methods
@@ -1,20 +1,20 @@
1
1
  """Client for Nova Poshta API. """
2
2
 
3
+ from typing import Type, TypeVar, Optional, Callable
4
+
3
5
  import httpx
4
6
 
5
- from .models.base import BaseModel
7
+ from .models.additional_service import AdditionalService
6
8
  from .models.address import Address
7
- from .models.counterparty import Counterparty
8
- from .models.contact_person import ContactPerson
9
- from .models.scan_sheet import ScanSheet
9
+ from .models.base import BaseModel
10
10
  from .models.common import Common
11
- from .models.additional_service import AdditionalService
11
+ from .models.contact_person import ContactPerson
12
+ from .models.counterparty import Counterparty
12
13
  from .models.internet_document import InternetDocument
14
+ from .models.scan_sheet import ScanSheet
13
15
  from .models.tracking_document import TrackingDocument
14
16
  from .types import DictStrAny, MaybeAsync
15
17
 
16
- from typing import Type, TypeVar, Union
17
-
18
18
  HEADERS = {"Content-Type": "application/json"}
19
19
 
20
20
  BaseModelType = TypeVar("BaseModelType", bound=BaseModel)
@@ -29,14 +29,17 @@ class NovaPoshtaApi:
29
29
  https://developers.novaposhta.ua/documentation
30
30
  """
31
31
 
32
+ sync_http_client: Optional[httpx.Client] = None
33
+ async_http_client: Optional[httpx.AsyncClient] = None
34
+
32
35
  def __init__(
33
36
  self,
34
- api_key,
35
- api_endpoint="https://api.novaposhta.ua/v2.0/json/",
37
+ api_key: str,
38
+ api_endpoint: str = "https://api.novaposhta.ua/v2.0/json/",
36
39
  http_client=httpx,
37
- timeout=10,
38
- raise_for_errors=False,
39
- async_mode=False,
40
+ timeout: int = 10,
41
+ raise_for_errors: bool = False,
42
+ async_mode: bool = False,
40
43
  ):
41
44
  """
42
45
  Initialize Nova Poshta API client.
@@ -50,19 +53,21 @@ class NovaPoshtaApi:
50
53
  """
51
54
  self.api_key = api_key
52
55
  self.api_endpoint = api_endpoint
53
- self.http_client = (
54
- http_client.Client if not async_mode else http_client.AsyncClient
55
- )
56
56
  self.timeout = timeout
57
- self.raise_for_errors = raise_for_errors
58
- self.async_mode = async_mode
59
- self._models_pool = {}
60
-
61
- if self.async_mode:
57
+ self._send: Callable[[DictStrAny], MaybeAsync]
58
+ if async_mode:
59
+ self.async_http_client: Optional[
60
+ httpx.AsyncClient
61
+ ] = http_client.AsyncClient(timeout=timeout)
62
62
  self._send = self._send_async
63
-
64
63
  else:
64
+ self.sync_http_client: Optional[httpx.Client] = http_client.Client(
65
+ timeout=timeout
66
+ )
65
67
  self._send = self._send_sync
68
+ self.raise_for_errors = raise_for_errors
69
+ self.async_mode = async_mode
70
+ self._models_pool: DictStrAny = {}
66
71
 
67
72
  def _send_sync(self, request: DictStrAny) -> DictStrAny:
68
73
  """
@@ -71,9 +76,9 @@ class NovaPoshtaApi:
71
76
  :param request: request dict.
72
77
  :return: response dict.
73
78
  """
74
-
75
- with self.http_client() as client:
76
- response = client.post(**request)
79
+ if not self.sync_http_client:
80
+ raise ValueError("Sync client is not initialized")
81
+ response = self.sync_http_client.post(**request)
77
82
  return self._maybe_check_errors(response.json())
78
83
 
79
84
  async def _send_async(self, request: DictStrAny) -> DictStrAny:
@@ -83,8 +88,9 @@ class NovaPoshtaApi:
83
88
  :param request: request dict.
84
89
  :return: response dict.
85
90
  """
86
- async with self.http_client() as client:
87
- response = await client.post(**request)
91
+ if not self.async_http_client:
92
+ raise ValueError("Async client is not initialized")
93
+ response: httpx.Response = await self.async_http_client.post(**request)
88
94
  return self._maybe_check_errors(response.json())
89
95
 
90
96
  def send(
@@ -127,7 +133,7 @@ class NovaPoshtaApi:
127
133
  self._models_pool[model.name] = model(self)
128
134
  return self._models_pool[model.name]
129
135
 
130
- def get(self, name: str) -> Union[BaseModelType, None]:
136
+ def get(self, name: str) -> Optional[BaseModel]:
131
137
  """
132
138
  Get model from the pool.
133
139
 
@@ -135,7 +141,13 @@ class NovaPoshtaApi:
135
141
  """
136
142
  return self._models_pool.get(name)
137
143
 
138
- def _maybe_check_errors(self, response):
144
+ def _maybe_check_errors(self, response: DictStrAny) -> DictStrAny:
145
+ """
146
+ Check response for errors.
147
+
148
+ :param response: response dict.
149
+ :return: response dict.
150
+ """
139
151
  if not self.raise_for_errors:
140
152
  return response
141
153
 
@@ -148,6 +160,45 @@ class NovaPoshtaApi:
148
160
  else:
149
161
  raise APIRequestError(error)
150
162
 
163
+ def close_sync(self):
164
+ """
165
+ Close sync client.
166
+ """
167
+ if self.sync_http_client:
168
+ self.sync_http_client.close()
169
+
170
+ async def close_async(self):
171
+ """
172
+ Close async client.
173
+ """
174
+ if self.async_http_client:
175
+ await self.async_http_client.aclose()
176
+
177
+ def __enter__(self):
178
+ """
179
+ Enter the context.
180
+ """
181
+ return self
182
+
183
+ def __exit__(self, exc_type, exc_val, exc_tb):
184
+ """
185
+ Exit the context.
186
+ Close the client.
187
+ """
188
+ self.close_sync()
189
+
190
+ async def __aenter__(self):
191
+ """
192
+ Enter the async context.
193
+ """
194
+ return self
195
+
196
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
197
+ """
198
+ Exit the async context.
199
+ """
200
+ await self.close_async()
201
+
151
202
  @property
152
203
  def address(self) -> Address:
153
204
  """
@@ -3,7 +3,7 @@ name = "novaposhta-python-client"
3
3
  packages = [
4
4
  { include = "novaposhta"}
5
5
  ]
6
- version = "0.1.5"
6
+ version = "0.1.6"
7
7
  description = "Python client for Nova Poshta API"
8
8
  authors = ["Oleksii <semolex@live.com>"]
9
9
  license = "MIT"