lsrestclient 3.1.1__py3-none-any.whl → 3.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.
- lsrestclient/client.py +47 -3
- lsrestclient/lsfastapi.py +40 -0
- lsrestclient/response.py +15 -5
- lsrestclient/settings.py +11 -0
- {lsrestclient-3.1.1.dist-info → lsrestclient-3.3.0.dist-info}/METADATA +7 -5
- {lsrestclient-3.1.1.dist-info → lsrestclient-3.3.0.dist-info}/RECORD +8 -6
- {lsrestclient-3.1.1.dist-info → lsrestclient-3.3.0.dist-info}/WHEEL +0 -0
- {lsrestclient-3.1.1.dist-info → lsrestclient-3.3.0.dist-info}/entry_points.txt +0 -0
lsrestclient/client.py
CHANGED
@@ -1,23 +1,33 @@
|
|
1
1
|
import os
|
2
|
+
from enum import Enum
|
2
3
|
from typing import Optional, Dict, Any
|
3
4
|
from unittest.mock import MagicMock
|
4
5
|
|
5
6
|
import lsjsonclasses
|
6
7
|
import requests
|
7
|
-
|
8
|
+
import requests_cache
|
9
|
+
from requests import Response, Session
|
8
10
|
|
9
11
|
import re
|
10
12
|
|
13
|
+
from requests_cache import CachedSession, SQLiteCache
|
14
|
+
|
11
15
|
from lsrestclient import (
|
12
16
|
LsRestClientResponse,
|
13
17
|
exceptions,
|
14
18
|
)
|
15
19
|
from lsrestclient.contexts.bearer_token import bearer_token_context
|
20
|
+
from lsrestclient.settings import LsRestClientSettings
|
16
21
|
|
17
22
|
find_parameters_regex = re.compile("{(.*?)}")
|
18
23
|
|
19
24
|
|
20
|
-
class
|
25
|
+
class LsRestClientBackendEnum(str, Enum):
|
26
|
+
sqlite = "sqlite"
|
27
|
+
redis = "redis"
|
28
|
+
|
29
|
+
|
30
|
+
class LsRestClient(object):
|
21
31
|
_clients = {}
|
22
32
|
|
23
33
|
@classmethod
|
@@ -65,8 +75,28 @@ class LsRestClient(Session):
|
|
65
75
|
name: str = "default",
|
66
76
|
headers: dict = None,
|
67
77
|
ignore_bearer_context: bool = False,
|
78
|
+
cache: bool = False,
|
79
|
+
cache_backend: LsRestClientBackendEnum = LsRestClientBackendEnum.sqlite,
|
68
80
|
) -> None:
|
69
81
|
"""Class representing a REST client for JSON API."""
|
82
|
+
if cache:
|
83
|
+
if cache_backend == LsRestClientBackendEnum.redis:
|
84
|
+
settings = LsRestClientSettings()
|
85
|
+
backend = requests_cache.RedisCache(
|
86
|
+
namespace=f"lsrestclient_{name}",
|
87
|
+
host=settings.redis_host,
|
88
|
+
port=settings.redis_port,
|
89
|
+
db=settings.redis_db,
|
90
|
+
ttl=settings.redis_ttl,
|
91
|
+
ttl_offset=settings.redis_ttl_offset,
|
92
|
+
)
|
93
|
+
else:
|
94
|
+
backend = SQLiteCache(f".cache/{name}")
|
95
|
+
|
96
|
+
self._session = CachedSession(backend=backend, cache_control=True, filter_fn=self.cache_filter)
|
97
|
+
|
98
|
+
else:
|
99
|
+
self._session = Session()
|
70
100
|
|
71
101
|
self._mocks = {}
|
72
102
|
self.base_url = base_url
|
@@ -83,6 +113,13 @@ class LsRestClient(Session):
|
|
83
113
|
super().__init__()
|
84
114
|
self._clients[name] = self
|
85
115
|
|
116
|
+
def cache_filter(self, response: Response) -> bool:
|
117
|
+
settings = LsRestClientSettings()
|
118
|
+
cache_control = response.headers.get("Cache-Control")
|
119
|
+
if not cache_control and settings.insert_no_cache:
|
120
|
+
return False
|
121
|
+
return True
|
122
|
+
|
86
123
|
@staticmethod
|
87
124
|
def mock_name(client_name: str, method: str, url: str) -> str:
|
88
125
|
return f"{client_name}_{method.upper()}_{url}"
|
@@ -203,7 +240,14 @@ class LsRestClient(Session):
|
|
203
240
|
|
204
241
|
try:
|
205
242
|
# noinspection PyArgumentList
|
206
|
-
requests_response = requests.request(
|
243
|
+
# requests_response = requests.request(
|
244
|
+
# method.upper(),
|
245
|
+
# full_url,
|
246
|
+
# *args,
|
247
|
+
# params=params,
|
248
|
+
# **kwargs,
|
249
|
+
# )
|
250
|
+
requests_response = self._session.request(
|
207
251
|
method.upper(),
|
208
252
|
full_url,
|
209
253
|
*args,
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from lsrestclient import LsRestClient
|
4
|
+
import logging
|
5
|
+
|
6
|
+
log = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
|
9
|
+
class LsFastApiClientBase(ABC):
|
10
|
+
_client = None
|
11
|
+
client_name = None
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
pass
|
15
|
+
|
16
|
+
@classmethod
|
17
|
+
def client(cls) -> LsRestClient:
|
18
|
+
# noinspection PyBroadException
|
19
|
+
try:
|
20
|
+
cls._client = LsRestClient.client(cls.client_name)
|
21
|
+
except Exception as e: # pragma: no cover
|
22
|
+
# noinspection PyArgumentList
|
23
|
+
cls._client = cls.register()
|
24
|
+
return cls._client
|
25
|
+
|
26
|
+
@classmethod
|
27
|
+
def register(cls, base_url: str = None) -> LsRestClient:
|
28
|
+
# noinspection PyArgumentList
|
29
|
+
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())
|
31
|
+
return cls._client
|
32
|
+
|
33
|
+
@classmethod
|
34
|
+
def health(cls):
|
35
|
+
return cls.client().get("/healthz")
|
36
|
+
|
37
|
+
@classmethod
|
38
|
+
@abstractmethod
|
39
|
+
def base_url(cls):
|
40
|
+
raise NotImplementedError
|
lsrestclient/response.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import datetime
|
1
2
|
from dataclasses import dataclass
|
2
3
|
from typing import Optional
|
3
4
|
|
@@ -5,6 +6,7 @@ import lsjsonclasses
|
|
5
6
|
import pydash
|
6
7
|
from requests import Response
|
7
8
|
from requests.structures import CaseInsensitiveDict
|
9
|
+
from requests_cache import CachedResponse
|
8
10
|
|
9
11
|
|
10
12
|
@dataclass
|
@@ -16,6 +18,11 @@ class LsRestClientResponse:
|
|
16
18
|
status_code: int
|
17
19
|
content: str
|
18
20
|
headers: CaseInsensitiveDict
|
21
|
+
created_at: datetime.datetime | None = None
|
22
|
+
expires: datetime.datetime | None = None
|
23
|
+
cache_key: str | None = None
|
24
|
+
revalidated: bool | None = None
|
25
|
+
from_cache: bool | None = False
|
19
26
|
|
20
27
|
_json: Optional[dict] = None
|
21
28
|
|
@@ -43,11 +50,14 @@ class LsRestClientResponse:
|
|
43
50
|
else:
|
44
51
|
content = response.content.decode("utf8" if encoding is None else encoding)
|
45
52
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
ret = cls(status_code=response.status_code, content=content, headers=response.headers)
|
54
|
+
if isinstance(response, CachedResponse):
|
55
|
+
ret.created_at = response.created_at
|
56
|
+
ret.expires = response.expires
|
57
|
+
ret.cache_key = response.cache_key
|
58
|
+
ret.revalidated = response.revalidated
|
59
|
+
ret.from_cache = response.from_cache
|
60
|
+
return ret
|
51
61
|
|
52
62
|
@classmethod
|
53
63
|
def from_dict(cls, status_code: int = 200, data: dict = None, headers: CaseInsensitiveDict = None):
|
lsrestclient/settings.py
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
2
|
+
|
3
|
+
|
4
|
+
class LsRestClientSettings(BaseSettings):
|
5
|
+
model_config = SettingsConfigDict(env_prefix="lsrestclient_")
|
6
|
+
insert_no_cache: bool = True
|
7
|
+
redis_host: str = "localhost"
|
8
|
+
redis_port: int = 6379
|
9
|
+
redis_db: int = 10
|
10
|
+
redis_ttl: bool = True
|
11
|
+
redis_ttl_offset: int = 3600
|
@@ -1,17 +1,19 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: lsrestclient
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.3.0
|
4
4
|
Summary: REST Api Client
|
5
5
|
Author: mba
|
6
6
|
Author-email: bartel@electronic-shop.lu
|
7
|
-
Requires-Python: >=3.
|
7
|
+
Requires-Python: >=3.12,<4.0
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
|
-
|
10
|
-
Classifier: Programming Language :: Python :: 3.10
|
11
|
-
Classifier: Programming Language :: Python :: 3.11
|
9
|
+
Provides-Extra: redis
|
12
10
|
Requires-Dist: lsjsonclasses (>=2.0.1,<3.0.0)
|
11
|
+
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
12
|
+
Requires-Dist: pydantic-settings (>=2.10.1,<3.0.0)
|
13
13
|
Requires-Dist: pydash (>4.0.0)
|
14
|
+
Requires-Dist: redis (>=6.4.0,<7.0.0) ; extra == "redis"
|
14
15
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
16
|
+
Requires-Dist: requests-cache (>=1.2.1,<2.0.0)
|
15
17
|
Requires-Dist: webexception (>=1.0.5,<2.0.0)
|
16
18
|
Description-Content-Type: text/markdown
|
17
19
|
|
@@ -1,13 +1,15 @@
|
|
1
1
|
lsrestclient/__init__.py,sha256=lI62SHmG0m-iukB5UEwdN5dO4cKnDasOt-TmR1rgaWI,72
|
2
2
|
lsrestclient/auth.py,sha256=IC6niEht-xB_wC7da0HIeM05Ha785qhls-Q39P6dMHQ,467
|
3
|
-
lsrestclient/client.py,sha256=
|
3
|
+
lsrestclient/client.py,sha256=Nd3QQ9g0EOhcemJRnuGXpY_eeho5Cn2JNRMmGVeIDpc,13435
|
4
4
|
lsrestclient/contexts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
lsrestclient/contexts/bearer_token.py,sha256=GZZOzAI2Ng_9DvFCbhv1Wwb8wJ1AYCca3fQeNtt2NaU,753
|
6
6
|
lsrestclient/exceptions.py,sha256=exJd1BfygNkkAqekmWepVXvXlMiOInVzPRnq7TmPURs,2149
|
7
7
|
lsrestclient/fixtures.py,sha256=dFkAYQXL6xqTOwRofb03Nsu_cIjq1sG10Rh8dxWfz9s,239
|
8
|
+
lsrestclient/lsfastapi.py,sha256=AkeJI4zcJTYGgj625OY_ae_aFi9BBiZP6xy85NxJXJ8,1064
|
8
9
|
lsrestclient/mock.py,sha256=Ya12F0t5sXHTSt-X4jDDj5ILJx6y6QaBAMXutQMsIRI,1376
|
9
|
-
lsrestclient/response.py,sha256=
|
10
|
-
lsrestclient
|
11
|
-
lsrestclient-3.
|
12
|
-
lsrestclient-3.
|
13
|
-
lsrestclient-3.
|
10
|
+
lsrestclient/response.py,sha256=4DYeN9e7phcrbm0QwwQS7uBI-sTDq7bKkP28BRWCzqA,2704
|
11
|
+
lsrestclient/settings.py,sha256=qRhQYFCOA8sKhejrd7r47Q4Vo6mQjLbXko7jv3_889A,350
|
12
|
+
lsrestclient-3.3.0.dist-info/METADATA,sha256=ZK5YCDx-_upxS0K9u9eKBpqNiY3DnF9EsVjUEZYNjdw,6816
|
13
|
+
lsrestclient-3.3.0.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
14
|
+
lsrestclient-3.3.0.dist-info/entry_points.txt,sha256=7lN1XN3lq5Jv5PlpOdIlFrLlFlwzE5MaEWSgMhKASOM,47
|
15
|
+
lsrestclient-3.3.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|