lsrestclient 3.3.2__py3-none-any.whl → 3.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.
lsrestclient/__init__.py CHANGED
@@ -1,3 +1,5 @@
1
- from .exceptions import *
2
- from .response import *
3
1
  from .client import *
2
+ from .exceptions.ConnectionError import *
3
+ from .exceptions.DownStreamError import *
4
+ from .exceptions.raise_errors import *
5
+ from .response import *
lsrestclient/auth.py CHANGED
@@ -1,7 +1,7 @@
1
- from lsrestclient import LsRestClient, DownStreamError
1
+ from lsrestclient import DownStreamError, LsRestClient
2
2
 
3
3
 
4
- def auth_am_login(**kwargs) -> str:
4
+ def auth_am_login(**kwargs: object) -> str:
5
5
  am = LsRestClient.from_env("AM_API_URL", "am", True)
6
6
  r = am.post("/auth/login", body=kwargs)
7
7
  if r.status_code == 200:
lsrestclient/client.py CHANGED
@@ -1,22 +1,20 @@
1
1
  import os
2
+ import re
2
3
  from enum import Enum
3
- from typing import Optional, Dict, Any
4
+ from typing import Any, ClassVar, Dict, Optional
4
5
  from unittest.mock import MagicMock
5
6
 
6
7
  import lsjsonclasses
7
8
  import requests
8
9
  import requests_cache
9
10
  from requests import Response, Session
10
-
11
- import re
12
-
13
11
  from requests_cache import CachedSession, SQLiteCache
14
12
 
15
- from lsrestclient import (
13
+ import lsrestclient.exceptions.ConnectionError
14
+ from lsrestclient.contexts.bearer_token import bearer_token_context
15
+ from lsrestclient.response import (
16
16
  LsRestClientResponse,
17
- exceptions,
18
17
  )
19
- from lsrestclient.contexts.bearer_token import bearer_token_context
20
18
  from lsrestclient.settings import LsRestClientSettings
21
19
 
22
20
  find_parameters_regex = re.compile("{(.*?)}")
@@ -28,7 +26,7 @@ class LsRestClientBackendEnum(str, Enum):
28
26
 
29
27
 
30
28
  class LsRestClient(object):
31
- _clients = {}
29
+ _clients: ClassVar[dict[str, "LsRestClient"]] = {}
32
30
 
33
31
  @classmethod
34
32
  def from_env(
@@ -36,10 +34,10 @@ class LsRestClient(object):
36
34
  env_name: str,
37
35
  name: Optional[str] = None,
38
36
  required: bool = True,
39
- ):
37
+ ) -> "LsRestClient":
40
38
  """
41
39
  Create an instance of the LsRestClient class using environment variables.
42
- It gets globally saved under the given name, so that it can be reused.
40
+ It gets globally saved under the given name so that it can be reused.
43
41
 
44
42
  :param env_name: The name of the environment variable that holds the base URL.
45
43
  :param name: An optional name for the client instance.
@@ -53,7 +51,7 @@ class LsRestClient(object):
53
51
  return cls(base_url=base_url, name=name)
54
52
 
55
53
  @classmethod
56
- def client(cls, name: str):
54
+ def client(cls, name: str) -> "LsRestClient":
57
55
  """
58
56
  Retrieves the LsRestClient instance with the specified name.
59
57
  If a client with the given name does not exist, an exception is raised.
@@ -66,17 +64,19 @@ class LsRestClient(object):
66
64
  except KeyError:
67
65
  raise Exception(f"LsRestClient with name '{name}' not initialized.")
68
66
 
69
- def __repr__(self):
67
+ def __repr__(self) -> str:
70
68
  return f"<LsRestClient name:'{self.name}' base_url:'{self.base_url}'>"
71
69
 
72
70
  def __init__(
73
71
  self,
74
- base_url: str = None,
72
+ base_url: str | None = None,
75
73
  name: str = "default",
76
- headers: dict = None,
74
+ headers: dict | None = None,
77
75
  ignore_bearer_context: bool = False,
78
76
  cache: bool = False,
79
77
  cache_backend: LsRestClientBackendEnum = LsRestClientBackendEnum.sqlite,
78
+ cache_control: bool = True,
79
+ stale_while_revalidate: bool = True,
80
80
  ) -> None:
81
81
  """Class representing a REST client for JSON API."""
82
82
  if cache:
@@ -93,7 +93,12 @@ class LsRestClient(object):
93
93
  else:
94
94
  backend = SQLiteCache(f".cache/{name}")
95
95
 
96
- self._session = CachedSession(backend=backend, cache_control=True, filter_fn=self.cache_filter)
96
+ self._session = CachedSession(
97
+ backend=backend,
98
+ cache_control=cache_control,
99
+ filter_fn=self.cache_filter,
100
+ stale_while_revalidate=stale_while_revalidate,
101
+ )
97
102
 
98
103
  else:
99
104
  self._session = Session()
@@ -104,7 +109,11 @@ class LsRestClient(object):
104
109
  self.base_headers = {"content-type": "application/json"}
105
110
 
106
111
  with bearer_token_context() as bearer_token:
107
- bearer_headers = {"Authorization": f"Bearer {bearer_token}"} if bearer_token is not None else {}
112
+ bearer_headers = (
113
+ {"Authorization": f"Bearer {bearer_token}"}
114
+ if bearer_token is not None
115
+ else {}
116
+ )
108
117
  self.base_headers.update(bearer_headers)
109
118
  if headers is not None:
110
119
  self.base_headers.update(headers)
@@ -113,7 +122,7 @@ class LsRestClient(object):
113
122
  super().__init__()
114
123
  self._clients[name] = self
115
124
 
116
- def clear_cache(self):
125
+ def clear_cache(self) -> None:
117
126
  if not isinstance(self._session, CachedSession):
118
127
  raise Exception("Cache not enabled.")
119
128
  self._session.cache.clear()
@@ -129,7 +138,7 @@ class LsRestClient(object):
129
138
  def mock_name(client_name: str, method: str, url: str) -> str:
130
139
  return f"{client_name}_{method.upper()}_{url}"
131
140
 
132
- def url_parse_params(self, url: str, params: Optional[dict] = None):
141
+ def url_parse_params(self, url: str, params: Optional[dict] = None) -> str:
133
142
  if params is None:
134
143
  params = {}
135
144
 
@@ -157,7 +166,9 @@ class LsRestClient(object):
157
166
 
158
167
  return f"{self.base_url}{url}"
159
168
 
160
- def caller(self, method: str, url: str, *args, **kwargs) -> LsRestClientResponse:
169
+ def caller(
170
+ self, method: str, url: str, *args: Any, **kwargs: Any
171
+ ) -> LsRestClientResponse:
161
172
  # check mocks
162
173
  mock = self._mocks.get(self.mock_name(self.name, method, url), None)
163
174
  func = mock if mock is not None else self.request
@@ -167,16 +178,17 @@ class LsRestClient(object):
167
178
  # but only just before calling func, because of mock path
168
179
  url = self.url_parse_params(url, kwargs.get("params", {}))
169
180
 
181
+ # noinspection PyTypeChecker
170
182
  return func(method, url, *args, **kwargs)
171
183
 
172
184
  def request(
173
185
  self,
174
186
  method: str,
175
187
  url: str,
176
- *args,
188
+ *args: list,
177
189
  params: Optional[Dict[str, Any]] = None,
178
190
  body: Optional[Dict[str, Any]] = None,
179
- **kwargs,
191
+ **kwargs: dict,
180
192
  ) -> LsRestClientResponse: # pragma: no cover
181
193
  """
182
194
  :param method: The HTTP method to be used for the request.
@@ -237,10 +249,10 @@ class LsRestClient(object):
237
249
  self,
238
250
  method: str,
239
251
  url: str,
240
- *args,
252
+ *args: list,
241
253
  params: Optional[Dict[str, Any]] = None,
242
- **kwargs,
243
- ):
254
+ **kwargs: dict,
255
+ ) -> LsRestClientResponse:
244
256
  full_url = self.full_url(url, params)
245
257
 
246
258
  try:
@@ -263,9 +275,9 @@ class LsRestClient(object):
263
275
  return response
264
276
 
265
277
  except requests.ConnectionError:
266
- raise exceptions.ConnectionError(url=full_url)
278
+ raise lsrestclient.exceptions.ConnectionError.ConnectionError(url=full_url)
267
279
 
268
- def get(self, *args, **kwargs) -> LsRestClientResponse:
280
+ def get(self, *args: Any, **kwargs: Any) -> LsRestClientResponse:
269
281
  """
270
282
  Send a GET request to the specified URL.
271
283
 
@@ -276,7 +288,7 @@ class LsRestClient(object):
276
288
 
277
289
  return self.caller("GET", *args, **kwargs)
278
290
 
279
- def post(self, *args, **kwargs) -> LsRestClientResponse:
291
+ def post(self, *args: Any, **kwargs: Any) -> LsRestClientResponse:
280
292
  """
281
293
  This method is used to send a POST request using the LSRestClient class.
282
294
 
@@ -286,7 +298,7 @@ class LsRestClient(object):
286
298
  """
287
299
  return self.caller("POST", *args, **kwargs)
288
300
 
289
- def put(self, *args, **kwargs) -> LsRestClientResponse:
301
+ def put(self, *args: Any, **kwargs: Any) -> LsRestClientResponse:
290
302
  """
291
303
  This method is used to send a PUT request using the LSRestClient class.
292
304
 
@@ -296,7 +308,7 @@ class LsRestClient(object):
296
308
  """
297
309
  return self.caller("PUT", *args, **kwargs)
298
310
 
299
- def patch(self, *args, **kwargs) -> LsRestClientResponse:
311
+ def patch(self, *args: Any, **kwargs: Any) -> LsRestClientResponse:
300
312
  """
301
313
  Send a PATCH request to the specified URL with the provided arguments.
302
314
 
@@ -306,7 +318,7 @@ class LsRestClient(object):
306
318
  """
307
319
  return self.caller("PATCH", *args, **kwargs)
308
320
 
309
- def delete(self, *args, **kwargs) -> LsRestClientResponse:
321
+ def delete(self, *args: Any, **kwargs: Any) -> LsRestClientResponse:
310
322
  """
311
323
  Deletes a resource using the DELETE method.
312
324
 
@@ -316,7 +328,7 @@ class LsRestClient(object):
316
328
  """
317
329
  return self.caller("DELETE", *args, **kwargs)
318
330
 
319
- def options(self, *args, **kwargs) -> LsRestClientResponse:
331
+ def options(self, *args: Any, **kwargs: Any) -> LsRestClientResponse:
320
332
  """
321
333
  Send an OPTIONS request using the LsRestClient.
322
334
 
@@ -340,16 +352,16 @@ class LsRestClient(object):
340
352
  """
341
353
  return self.request("HEAD", *args, **kwargs)
342
354
 
343
- def mock(self, mock_name: str, mock: MagicMock):
355
+ def mock(self, mock_name: str, mock: MagicMock) -> None:
344
356
  self._mocks[mock_name] = mock
345
357
 
346
- def unmock(self, mock_name: str):
358
+ def unmock(self, mock_name: str) -> None:
347
359
  if mock_name in self._mocks:
348
360
  del self._mocks[mock_name]
349
361
 
350
362
 
351
363
  class LsRestClientTestClient(LsRestClient):
352
- def __init__(self, test_client: Any, name: str = "test-client") -> None:
364
+ def __init__(self, test_client: Any, name: str = "test-client") -> None: # noqa: ANN401
353
365
  super().__init__(base_url=None, name=name)
354
366
  self.test_client = test_client
355
367
 
@@ -357,9 +369,13 @@ class LsRestClientTestClient(LsRestClient):
357
369
  self,
358
370
  method: str,
359
371
  url: str,
360
- *args,
372
+ *args: Any,
361
373
  params: Optional[Dict[str, Any]] = None,
362
- **kwargs,
363
- ):
374
+ **kwargs: Any,
375
+ ) -> LsRestClientResponse:
364
376
  r = self.test_client.request(method, url, *args, params=params, **kwargs)
365
- return LsRestClientResponse(status_code=r.status_code, content=r.content.decode("utf8"), headers=r.headers)
377
+ return LsRestClientResponse(
378
+ status_code=r.status_code,
379
+ content=r.content.decode("utf8"),
380
+ headers=r.headers,
381
+ )
@@ -1,12 +1,14 @@
1
1
  import contextlib
2
2
  import contextvars
3
- from typing import Optional
3
+ from typing import Any, Generator, Optional
4
4
 
5
- bearer_token_value: contextvars.ContextVar[Optional[str]] = contextvars.ContextVar("bearer_token_value", default=None)
5
+ bearer_token_value: contextvars.ContextVar[Optional[str]] = contextvars.ContextVar(
6
+ "bearer_token_value", default=None
7
+ )
6
8
 
7
9
 
8
10
  @contextlib.contextmanager
9
- def bearer_token_provider(bearer_token: str):
11
+ def bearer_token_provider(bearer_token: str) -> Generator[None, Any, None]:
10
12
  """
11
13
  :param bearer_token: The bearer token to set.
12
14
  :return: A context manager that sets the bearer token and resets it when the context is exited.
@@ -17,7 +19,7 @@ def bearer_token_provider(bearer_token: str):
17
19
 
18
20
 
19
21
  @contextlib.contextmanager
20
- def bearer_token_context():
22
+ def bearer_token_context() -> Generator[str | None, Any, None]:
21
23
  """
22
24
  Context manager for handling bearer token.
23
25
 
@@ -0,0 +1,22 @@
1
+ from typing import Optional
2
+
3
+
4
+ class ConnectionError(Exception):
5
+ """Exception class for connection errors.
6
+
7
+ Args:
8
+ url (Optional[str]): The URL that the connection could not be established to.
9
+
10
+ Attributes:
11
+ url (Optional[str]): The URL that the connection could not be established to.
12
+
13
+ Raises:
14
+ ConnectionError: If a connection could not be established to the given URL.
15
+
16
+ """
17
+
18
+ url: str
19
+
20
+ def __init__(self, url: Optional[str] = None) -> None:
21
+ self.url = url
22
+ super().__init__(f"Connection could not be established to '{url}'")
@@ -0,0 +1,12 @@
1
+ class DownStreamError(Exception):
2
+ status_code: int
3
+ url: str
4
+ content: str
5
+
6
+ def __init__(self, url: str, status_code: int, content: str) -> None:
7
+ self.url = url
8
+ self.status_code = status_code
9
+ self.content = content
10
+ super().__init__(
11
+ f"Downstream error calling {self.url}. {self.status_code} {self.content}"
12
+ )
File without changes
@@ -0,0 +1,44 @@
1
+ import contextlib
2
+ import logging
3
+ from typing import List, Optional, Type
4
+
5
+ import pydash
6
+ from webexception.webexception import WebException
7
+
8
+ from lsrestclient.response import LsRestClientResponse
9
+
10
+ log = logging.getLogger(__name__)
11
+
12
+
13
+ @contextlib.contextmanager
14
+ def raise_errors( # noqa: ANN201
15
+ r: LsRestClientResponse, exceptions: Optional[List[Type[Exception]]] = None
16
+ ):
17
+ if exceptions is None:
18
+ exceptions_by_class = {}
19
+ else:
20
+ exceptions_by_class = {e.__name__: e for e in exceptions}
21
+
22
+ if r.status_code < 399:
23
+ yield r
24
+ else:
25
+ try:
26
+ json = r.json()
27
+ except Exception:
28
+ log.error(r.content)
29
+ raise WebException(status_code=r.status_code, detail=r.content)
30
+
31
+ detail = pydash.get(json, "detail", json)
32
+ error_class = pydash.get(detail, "error_class", None)
33
+ if error_class is not None:
34
+ payload = pydash.get(detail, "error_payload", {})
35
+ else:
36
+ error_class = pydash.get(detail, "ERROR_CLASS", None)
37
+ payload = {}
38
+
39
+ if error_class in exceptions_by_class:
40
+ # noinspection PyArgumentList
41
+ e = exceptions_by_class[error_class](**payload)
42
+ raise e
43
+ # backend errors
44
+ raise WebException(status_code=r.status_code, detail=detail)
lsrestclient/fixtures.py CHANGED
@@ -1,10 +1,12 @@
1
- from lsrestclient.mock import lsrestclient_mock_context
1
+ from typing import Any, Generator
2
+
3
+ from lsrestclient.mock import LsRestClientMocker, lsrestclient_mock_context
2
4
 
3
5
  try:
4
6
  import pytest
5
7
 
6
8
  @pytest.fixture
7
- def lsrestclient_mocker():
9
+ def lsrestclient_mocker() -> Generator[LsRestClientMocker, Any, None]:
8
10
  with lsrestclient_mock_context() as mocker:
9
11
  yield mocker
10
12
 
lsrestclient/lsfastapi.py CHANGED
@@ -1,7 +1,8 @@
1
+ import logging
1
2
  from abc import ABC, abstractmethod
3
+ from typing import Any
2
4
 
3
- from lsrestclient import LsRestClient
4
- import logging
5
+ from lsrestclient import LsRestClient, LsRestClientResponse
5
6
 
6
7
  log = logging.getLogger(__name__)
7
8
 
@@ -10,7 +11,7 @@ class LsFastApiClientBase(ABC):
10
11
  _client = None
11
12
  client_name = None
12
13
 
13
- def __init__(self):
14
+ def __init__(self) -> None:
14
15
  pass
15
16
 
16
17
  @classmethod
@@ -18,23 +19,25 @@ class LsFastApiClientBase(ABC):
18
19
  # noinspection PyBroadException
19
20
  try:
20
21
  cls._client = LsRestClient.client(cls.client_name)
21
- except Exception as e: # pragma: no cover
22
+ except Exception: # pragma: no cover
22
23
  # noinspection PyArgumentList
23
24
  cls._client = cls.register()
24
25
  return cls._client
25
26
 
26
27
  @classmethod
27
- def register(cls, base_url: str = None, **kwargs) -> LsRestClient:
28
+ def register(cls, base_url: str | None = None, **kwargs: Any) -> LsRestClient:
28
29
  # noinspection PyArgumentList
29
30
  log.debug(f"Registering {cls.client_name} API client at {base_url}")
30
- cls._client = LsRestClient(name=cls.client_name, base_url=base_url or cls.base_url(), **kwargs)
31
+ cls._client = LsRestClient(
32
+ name=cls.client_name, base_url=base_url or cls.base_url(), **kwargs
33
+ )
31
34
  return cls._client
32
35
 
33
36
  @classmethod
34
- def health(cls):
37
+ def health(cls) -> LsRestClientResponse:
35
38
  return cls.client().get("/healthz")
36
39
 
37
40
  @classmethod
38
41
  @abstractmethod
39
- def base_url(cls):
42
+ def base_url(cls) -> str:
40
43
  raise NotImplementedError
lsrestclient/mock.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import dataclasses
2
2
  from contextlib import contextmanager
3
- from typing import Union
3
+ from typing import Any, Generator, Union
4
4
  from unittest.mock import MagicMock
5
5
 
6
6
  from lsrestclient import LsRestClient
@@ -14,26 +14,35 @@ class LsRestClientMockModel:
14
14
 
15
15
 
16
16
  class LsRestClientMocker(object):
17
- def __init__(self):
17
+ def __init__(self) -> None:
18
18
  super().__init__()
19
19
  self.mocks = {}
20
20
 
21
- def mock(self, client: Union[LsRestClient, str], method: str, url: str, *args, **kwargs):
21
+ def mock(
22
+ self,
23
+ client: Union[LsRestClient, str],
24
+ method: str,
25
+ url: str,
26
+ *args: Any,
27
+ **kwargs: Any,
28
+ ) -> MagicMock:
22
29
  if isinstance(client, str):
23
30
  client = LsRestClient.client(client)
24
31
 
25
32
  mock_name = LsRestClient.mock_name(client.name, method, url)
26
33
  mock = MagicMock(*args, **kwargs)
27
34
  client.mock(mock_name, mock)
28
- self.mocks[mock_name] = LsRestClientMockModel(client=client, mock_name=mock_name, mock=mock)
35
+ self.mocks[mock_name] = LsRestClientMockModel(
36
+ client=client, mock_name=mock_name, mock=mock
37
+ )
29
38
  return mock
30
39
 
31
- def unmock_all(self):
40
+ def unmock_all(self) -> None:
32
41
  for mock_name, mock_model in self.mocks.items():
33
42
  mock_model.client.unmock(mock_name)
34
43
  self.mocks = {}
35
44
 
36
- def unmock(self, client: LsRestClient, method: str, url: str):
45
+ def unmock(self, client: LsRestClient, method: str, url: str) -> None:
37
46
  mock_name = LsRestClient.mock_name(client.name, method, url)
38
47
  mock_model = self.mocks[mock_name]
39
48
  mock_model.client.unmock(mock_name)
@@ -41,7 +50,7 @@ class LsRestClientMocker(object):
41
50
 
42
51
 
43
52
  @contextmanager
44
- def lsrestclient_mock_context():
53
+ def lsrestclient_mock_context() -> Generator[LsRestClientMocker, Any, None]:
45
54
  mocker = LsRestClientMocker()
46
55
  yield mocker
47
56
  mocker.unmock_all()
lsrestclient/response.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import datetime
2
2
  from dataclasses import dataclass
3
- from typing import Optional
3
+ from typing import Any, Optional
4
4
 
5
5
  import lsjsonclasses
6
6
  import pydash
@@ -26,13 +26,13 @@ class LsRestClientResponse:
26
26
 
27
27
  _json: Optional[dict] = None
28
28
 
29
- def json(self):
29
+ def json(self) -> dict[str, Any]:
30
30
  if self._json is None and self.content != "":
31
31
  self._json = lsjsonclasses.LSoftJSONDecoder.loads(self.content)
32
32
  return self._json
33
33
 
34
34
  @classmethod
35
- def from_requests_response(cls, response: Response):
35
+ def from_requests_response(cls, response: Response) -> "LsRestClientResponse":
36
36
  """
37
37
  Create an instance of LsRestClientResponse from a requests Response object.
38
38
 
@@ -50,7 +50,9 @@ class LsRestClientResponse:
50
50
  else:
51
51
  content = response.content.decode("utf8" if encoding is None else encoding)
52
52
 
53
- ret = cls(status_code=response.status_code, content=content, headers=response.headers)
53
+ ret = cls(
54
+ status_code=response.status_code, content=content, headers=response.headers
55
+ )
54
56
  if isinstance(response, CachedResponse):
55
57
  ret.created_at = response.created_at
56
58
  ret.expires = response.expires
@@ -60,7 +62,12 @@ class LsRestClientResponse:
60
62
  return ret
61
63
 
62
64
  @classmethod
63
- def from_dict(cls, status_code: int = 200, data: dict = None, headers: CaseInsensitiveDict = None):
65
+ def from_dict(
66
+ cls,
67
+ status_code: int = 200,
68
+ data: dict | None = None,
69
+ headers: CaseInsensitiveDict = None,
70
+ ) -> "LsRestClientResponse":
64
71
  """
65
72
  Converts a dictionary into an instance of the LsRestClientResponse class.
66
73
 
@@ -1,21 +1,19 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: lsrestclient
3
- Version: 3.3.2
3
+ Version: 3.4.1
4
4
  Summary: REST Api Client
5
- Author: mba
6
- Author-email: bartel@electronic-shop.lu
7
- Requires-Python: >=3.12,<4.0
8
- Classifier: Programming Language :: Python :: 3
5
+ Author-email: mba <bartel@electronic-shop.lu>
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: lsjsonclasses<3.0.0,>=2.0.1
8
+ Requires-Dist: pydantic-settings<3.0.0,>=2.10.1
9
+ Requires-Dist: pydantic<3.0.0,>=2.11.7
10
+ Requires-Dist: pydash>4.0.0
11
+ Requires-Dist: redis<7.0.0,>=6.4.0
12
+ Requires-Dist: requests-cache<2.0.0,>=1.2.1
13
+ Requires-Dist: requests<3.0.0,>=2.31.0
14
+ Requires-Dist: webexception<2.0.0,>=1.0.5
9
15
  Provides-Extra: redis
10
- Requires-Dist: fastapi-lsoft (>=1.0.2,<2.0.0)
11
- Requires-Dist: lsjsonclasses (>=2.0.1,<3.0.0)
12
- Requires-Dist: pydantic (>=2.11.7,<3.0.0)
13
- Requires-Dist: pydantic-settings (>=2.10.1,<3.0.0)
14
- Requires-Dist: pydash (>4.0.0)
15
- Requires-Dist: redis (>=6.4.0,<7.0.0) ; extra == "redis"
16
- Requires-Dist: requests (>=2.31.0,<3.0.0)
17
- Requires-Dist: requests-cache (>=1.2.1,<2.0.0)
18
- Requires-Dist: webexception (>=1.0.5,<2.0.0)
16
+ Requires-Dist: redis; extra == 'redis'
19
17
  Description-Content-Type: text/markdown
20
18
 
21
19
  # lsrestclient
@@ -110,4 +108,3 @@ For open source projects, say how it is licensed.
110
108
 
111
109
  ## Project status
112
110
  If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
113
-
@@ -0,0 +1,18 @@
1
+ lsrestclient/__init__.py,sha256=J09z2822ZVQWCfJw9Dz3DrpJY9kvMfZThHIVhEPvovU,169
2
+ lsrestclient/auth.py,sha256=E87G8PXi5mnj_fY5NuILRvQdV_zLVTyBw0ZjpmZDWrI,475
3
+ lsrestclient/client.py,sha256=tng4clgRM9uPpvNZVHfOUpq7Bb6jcPyRsRMDEzs0iik,14353
4
+ lsrestclient/fixtures.py,sha256=huiw8-mnemFHeQGypK9n-OWqutAWZI7sBWWtwQqbYLs,338
5
+ lsrestclient/lsfastapi.py,sha256=7Bnrt8pbojJ7FbBbpHTgf56xdywgfbkYcOU6WkBjGU0,1197
6
+ lsrestclient/mock.py,sha256=ebyI5bD7n0Txzi6FkS7gaAVUPcXHRcy9kDNkivHY0zQ,1560
7
+ lsrestclient/response.py,sha256=qAbCMHi-XX19S7Rc71rl4b31CUqFbK5UpQqiUh8M3M4,2847
8
+ lsrestclient/settings.py,sha256=qRhQYFCOA8sKhejrd7r47Q4Vo6mQjLbXko7jv3_889A,350
9
+ lsrestclient/contexts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ lsrestclient/contexts/bearer_token.py,sha256=hmYmr5hmeliBTrP2n9AmKf1E4Vk61lcSyDrvNTkF6HE,841
11
+ lsrestclient/exceptions/ConnectionError.py,sha256=W0Ys80aElrDAbv-xf4wiMlU-4iJaji5I63V92HUEJnk,601
12
+ lsrestclient/exceptions/DownStreamError.py,sha256=AvxQ8uu9XodRf5njnies9MHFVpzpCdJmNOEe8Z95WVk,375
13
+ lsrestclient/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ lsrestclient/exceptions/raise_errors.py,sha256=LPemwueHxOQwf3WDaM0apI5aRADxNuPxSxAztC8pblc,1323
15
+ lsrestclient-3.4.1.dist-info/METADATA,sha256=zIDRJw9VEcEjeRAYzALXCJWkzCOaCZ53kc1iVi7ZMcg,6752
16
+ lsrestclient-3.4.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ lsrestclient-3.4.1.dist-info/entry_points.txt,sha256=6lmLua-CwRxXMA6iG5veLwIFbtUBhhypD5RI_2lv5Ms,48
18
+ lsrestclient-3.4.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.5.2
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [pytest11]
2
+ lsrestclient = lsrestclient.fixtures
@@ -1,73 +0,0 @@
1
- import contextlib
2
- import logging
3
- from typing import Optional, List, Type
4
-
5
- import pydash
6
- from webexception.webexception import WebException
7
-
8
- log = logging.getLogger(__name__)
9
-
10
-
11
- # noinspection PyShadowingBuiltins
12
- class ConnectionError(Exception):
13
- """Exception class for connection errors.
14
-
15
- Args:
16
- url (Optional[str]): The URL that the connection could not be established to.
17
-
18
- Attributes:
19
- url (Optional[str]): The URL that the connection could not be established to.
20
-
21
- Raises:
22
- ConnectionError: If a connection could not be established to the given URL.
23
-
24
- """
25
-
26
- url: str
27
-
28
- def __init__(self, url: Optional[str] = None) -> None:
29
- self.url = url
30
- super().__init__(f"Connection could not be established to '{url}'")
31
-
32
-
33
- class DownStreamError(Exception):
34
- status_code: int
35
- url: str
36
- content: str
37
-
38
- def __init__(self, url: str, status_code: int, content: str) -> None:
39
- self.url = url
40
- self.status_code = status_code
41
- self.content = content
42
- super().__init__(f"Downstream error calling {self.url}. {self.status_code} {self.content}")
43
-
44
-
45
- @contextlib.contextmanager
46
- def raise_errors(r, exceptions: Optional[List[Type[Exception]]] = None):
47
- if exceptions is None:
48
- exceptions_by_class = {}
49
- else:
50
- exceptions_by_class = {e.__name__: e for e in exceptions}
51
-
52
- if r.status_code < 399:
53
- yield r
54
- else:
55
- try:
56
- json = r.json()
57
- except Exception as e:
58
- log.error(r.content)
59
- raise WebException(status_code=r.status_code, detail=r.content)
60
-
61
- detail = pydash.get(json, "detail", json)
62
- error_class = pydash.get(detail, "error_class", None)
63
- if error_class is not None:
64
- payload = pydash.get(detail, "error_payload", {})
65
- else:
66
- error_class = pydash.get(detail, "ERROR_CLASS", None)
67
- payload = {}
68
-
69
- if error_class in exceptions_by_class:
70
- e = exceptions_by_class[error_class](**payload)
71
- raise e
72
- # backend errors
73
- raise WebException(status_code=r.status_code, detail=detail)
@@ -1,15 +0,0 @@
1
- lsrestclient/__init__.py,sha256=lI62SHmG0m-iukB5UEwdN5dO4cKnDasOt-TmR1rgaWI,72
2
- lsrestclient/auth.py,sha256=IC6niEht-xB_wC7da0HIeM05Ha785qhls-Q39P6dMHQ,467
3
- lsrestclient/client.py,sha256=Hy39JuNz3cxF0hvNhqD63HLPZSvhaHdUNtl5OrYqLzg,13606
4
- lsrestclient/contexts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- lsrestclient/contexts/bearer_token.py,sha256=GZZOzAI2Ng_9DvFCbhv1Wwb8wJ1AYCca3fQeNtt2NaU,753
6
- lsrestclient/exceptions.py,sha256=exJd1BfygNkkAqekmWepVXvXlMiOInVzPRnq7TmPURs,2149
7
- lsrestclient/fixtures.py,sha256=dFkAYQXL6xqTOwRofb03Nsu_cIjq1sG10Rh8dxWfz9s,239
8
- lsrestclient/lsfastapi.py,sha256=Hn-PgV8RKifa0BbNZzbuK-FCVbJpFmUIpItxZbivd0A,1084
9
- lsrestclient/mock.py,sha256=Ya12F0t5sXHTSt-X4jDDj5ILJx6y6QaBAMXutQMsIRI,1376
10
- lsrestclient/response.py,sha256=4DYeN9e7phcrbm0QwwQS7uBI-sTDq7bKkP28BRWCzqA,2704
11
- lsrestclient/settings.py,sha256=qRhQYFCOA8sKhejrd7r47Q4Vo6mQjLbXko7jv3_889A,350
12
- lsrestclient-3.3.2.dist-info/METADATA,sha256=v8XJ4_P3hN9TgI9JSR_JxgBh-tU79vQ4SsvqVxQWGtI,6862
13
- lsrestclient-3.3.2.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
14
- lsrestclient-3.3.2.dist-info/entry_points.txt,sha256=7lN1XN3lq5Jv5PlpOdIlFrLlFlwzE5MaEWSgMhKASOM,47
15
- lsrestclient-3.3.2.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- [pytest11]
2
- lsrestclient=lsrestclient.fixtures
3
-