panther 4.3.5__py3-none-any.whl → 4.3.7__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.
- panther/__init__.py +1 -1
- panther/_load_configs.py +12 -8
- panther/_utils.py +1 -1
- panther/cli/monitor_command.py +20 -3
- panther/monitoring.py +3 -13
- panther/response.py +0 -1
- {panther-4.3.5.dist-info → panther-4.3.7.dist-info}/METADATA +18 -6
- {panther-4.3.5.dist-info → panther-4.3.7.dist-info}/RECORD +12 -12
- {panther-4.3.5.dist-info → panther-4.3.7.dist-info}/WHEEL +1 -1
- {panther-4.3.5.dist-info → panther-4.3.7.dist-info}/entry_points.txt +0 -0
- {panther-4.3.5.dist-info → panther-4.3.7.dist-info/licenses}/LICENSE +0 -0
- {panther-4.3.5.dist-info → panther-4.3.7.dist-info}/top_level.txt +0 -0
panther/__init__.py
CHANGED
panther/_load_configs.py
CHANGED
@@ -154,22 +154,26 @@ def load_middlewares(_configs: dict, /) -> None:
|
|
154
154
|
# Collect Middlewares
|
155
155
|
for middleware in _configs.get('MIDDLEWARES') or []:
|
156
156
|
if not isinstance(middleware, list | tuple):
|
157
|
-
|
157
|
+
path_or_type = middleware
|
158
|
+
data = {}
|
158
159
|
|
159
|
-
|
160
|
-
|
160
|
+
elif len(middleware) == 1:
|
161
|
+
path_or_type = middleware[0]
|
161
162
|
data = {}
|
162
163
|
|
163
164
|
elif len(middleware) > 2:
|
164
165
|
raise _exception_handler(field='MIDDLEWARES', error=f'{middleware} too many arguments')
|
165
166
|
|
166
167
|
else:
|
167
|
-
|
168
|
+
path_or_type, data = middleware
|
168
169
|
|
169
|
-
|
170
|
-
middleware_class =
|
171
|
-
|
172
|
-
|
170
|
+
if callable(path_or_type):
|
171
|
+
middleware_class = path_or_type
|
172
|
+
else:
|
173
|
+
try:
|
174
|
+
middleware_class = import_class(path_or_type)
|
175
|
+
except (AttributeError, ModuleNotFoundError):
|
176
|
+
raise _exception_handler(field='MIDDLEWARES', error=f'{path_or_type} is not a valid middleware path')
|
173
177
|
|
174
178
|
if issubclass(middleware_class, BaseMiddleware) is False:
|
175
179
|
raise _exception_handler(field='MIDDLEWARES', error='is not a sub class of BaseMiddleware')
|
panther/_utils.py
CHANGED
@@ -49,7 +49,7 @@ def read_multipart_form_data(boundary: str, body: bytes) -> dict:
|
|
49
49
|
if row in (b'', b'--'):
|
50
50
|
continue
|
51
51
|
|
52
|
-
if match := re.match(pattern=field_pattern, string=row):
|
52
|
+
if match := re.match(pattern=field_pattern, string=row, flags=re.DOTALL):
|
53
53
|
_, field_name, _, value = match.groups()
|
54
54
|
data[field_name.decode('utf-8')] = value.decode('utf-8')
|
55
55
|
|
panther/cli/monitor_command.py
CHANGED
@@ -19,7 +19,7 @@ from panther.configs import config
|
|
19
19
|
with contextlib.suppress(ImportError):
|
20
20
|
from watchfiles import watch
|
21
21
|
|
22
|
-
|
22
|
+
logger = logging.getLogger('panther')
|
23
23
|
|
24
24
|
|
25
25
|
class Monitoring:
|
@@ -30,7 +30,7 @@ class Monitoring:
|
|
30
30
|
def monitor(self) -> None:
|
31
31
|
if error := self.initialize():
|
32
32
|
# Don't continue if initialize() has error
|
33
|
-
|
33
|
+
logger.error(error)
|
34
34
|
return
|
35
35
|
|
36
36
|
with (
|
@@ -51,7 +51,10 @@ class Monitoring:
|
|
51
51
|
|
52
52
|
for _ in watching:
|
53
53
|
for line in f.readlines():
|
54
|
-
|
54
|
+
# line = date_time | method | path | ip:port | response_time(seconds) | status
|
55
|
+
columns = line.split('|')
|
56
|
+
columns[4] = self._clean_response_time(float(columns[4]))
|
57
|
+
self.rows.append(columns)
|
55
58
|
live.update(self.generate_table())
|
56
59
|
|
57
60
|
def initialize(self) -> str:
|
@@ -100,5 +103,19 @@ class Monitoring:
|
|
100
103
|
lines = (os.get_terminal_size()[1] - 6) // 2
|
101
104
|
self.rows = deque(self.rows, maxlen=lines)
|
102
105
|
|
106
|
+
@classmethod
|
107
|
+
def _clean_response_time(cls, response_time: int) -> str:
|
108
|
+
time_unit = ' s'
|
109
|
+
|
110
|
+
if response_time < 0.01:
|
111
|
+
response_time = response_time * 1_000
|
112
|
+
time_unit = 'ms'
|
113
|
+
|
114
|
+
elif response_time >= 10:
|
115
|
+
response_time = response_time / 60
|
116
|
+
time_unit = ' m'
|
117
|
+
|
118
|
+
return f'{round(response_time, 4)} {time_unit}'
|
119
|
+
|
103
120
|
|
104
121
|
monitor = Monitoring().monitor
|
panther/monitoring.py
CHANGED
@@ -11,7 +11,7 @@ logger = logging.getLogger('monitoring')
|
|
11
11
|
class Monitoring:
|
12
12
|
"""
|
13
13
|
Create Log Message Like Below:
|
14
|
-
|
14
|
+
date_time | method | path | ip:port | response_time(seconds) | status
|
15
15
|
"""
|
16
16
|
def __init__(self, is_ws: bool = False):
|
17
17
|
self.is_ws = is_ws
|
@@ -30,15 +30,5 @@ class Monitoring:
|
|
30
30
|
|
31
31
|
async def after(self, status: int | Literal['Accepted', 'Rejected', 'Closed'], /):
|
32
32
|
if config.MONITORING:
|
33
|
-
response_time = perf_counter() - self.start_time
|
34
|
-
|
35
|
-
|
36
|
-
if response_time < 0.01:
|
37
|
-
response_time = response_time * 1_000
|
38
|
-
time_unit = 'ms'
|
39
|
-
|
40
|
-
elif response_time >= 10:
|
41
|
-
response_time = response_time / 60
|
42
|
-
time_unit = ' m'
|
43
|
-
|
44
|
-
logger.info(f'{self.log} | {round(response_time, 4)} {time_unit} | {status}')
|
33
|
+
response_time = perf_counter() - self.start_time # Seconds
|
34
|
+
logger.info(f'{self.log} | {response_time} | {status}')
|
panther/response.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: panther
|
3
|
-
Version: 4.3.
|
3
|
+
Version: 4.3.7
|
4
4
|
Summary: Fast & Friendly, Web Framework For Building Async APIs
|
5
5
|
Home-page: https://github.com/alirn76/panther
|
6
6
|
Author: Ali RajabNezhad
|
@@ -14,16 +14,13 @@ Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Requires-Python: >=3.10
|
15
15
|
Description-Content-Type: text/markdown
|
16
16
|
License-File: LICENSE
|
17
|
-
Requires-Dist: pantherdb~=2.1.
|
17
|
+
Requires-Dist: pantherdb~=2.1.1
|
18
18
|
Requires-Dist: pydantic~=2.8.2
|
19
19
|
Requires-Dist: rich~=13.7.1
|
20
20
|
Requires-Dist: uvicorn~=0.27.1
|
21
21
|
Requires-Dist: pytz~=2024.1
|
22
22
|
Requires-Dist: Jinja2~=3.1
|
23
23
|
Requires-Dist: httptools~=0.6.1
|
24
|
-
Provides-Extra: dev
|
25
|
-
Requires-Dist: ruff~=0.1.9; extra == "dev"
|
26
|
-
Requires-Dist: pytest~=8.3.3; extra == "dev"
|
27
24
|
Provides-Extra: full
|
28
25
|
Requires-Dist: redis==5.0.1; extra == "full"
|
29
26
|
Requires-Dist: motor~=3.5.0; extra == "full"
|
@@ -33,6 +30,21 @@ Requires-Dist: ruff~=0.1.9; extra == "full"
|
|
33
30
|
Requires-Dist: websockets~=12.0; extra == "full"
|
34
31
|
Requires-Dist: cryptography~=42.0.8; extra == "full"
|
35
32
|
Requires-Dist: watchfiles~=0.21.0; extra == "full"
|
33
|
+
Provides-Extra: dev
|
34
|
+
Requires-Dist: ruff~=0.1.9; extra == "dev"
|
35
|
+
Requires-Dist: pytest~=8.3.3; extra == "dev"
|
36
|
+
Dynamic: author
|
37
|
+
Dynamic: author-email
|
38
|
+
Dynamic: classifier
|
39
|
+
Dynamic: description
|
40
|
+
Dynamic: description-content-type
|
41
|
+
Dynamic: home-page
|
42
|
+
Dynamic: license
|
43
|
+
Dynamic: license-file
|
44
|
+
Dynamic: provides-extra
|
45
|
+
Dynamic: requires-dist
|
46
|
+
Dynamic: requires-python
|
47
|
+
Dynamic: summary
|
36
48
|
|
37
49
|
|
38
50
|
[](https://pypi.org/project/panther/) [](https://pypi.org/project/panther/) [](https://codecov.io/github/AliRn76/panther) [](https://pepy.tech/project/panther) [](https://github.com/alirn76/panther/blob/main/LICENSE)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
panther/__init__.py,sha256=
|
2
|
-
panther/_load_configs.py,sha256=
|
3
|
-
panther/_utils.py,sha256=
|
1
|
+
panther/__init__.py,sha256=ieTrfZ28yavW624_mcO0QGrokuaqfgnFnOuwWJOlh2Q,110
|
2
|
+
panther/_load_configs.py,sha256=NMQxKMMjkV6J3rxH5tfCTaZ6Rie7xzx-knEByXEtCUQ,10166
|
3
|
+
panther/_utils.py,sha256=wrpD6G-GCcuojrKMaLXHquxNkILaOGSBRA3k3TWF31w,4126
|
4
4
|
panther/app.py,sha256=aVVoUihLMo7rofKetw95HPq2B92a-AI9KooxFpbuTec,8158
|
5
5
|
panther/authentications.py,sha256=gf7BVyQ8vXKhiumJAtD0aAK7uIHWx_snbOKYAKrYuVw,5677
|
6
6
|
panther/background_tasks.py,sha256=HBYubDIiO_673cl_5fqCUP9zzimzRgRkDSkag9Msnbs,7656
|
@@ -14,11 +14,11 @@ panther/file_handler.py,sha256=I94tpbtTVniBnnUMkFr3Eis6kPDt8sLzS5u8TzFrR5I,1323
|
|
14
14
|
panther/generics.py,sha256=D2ia7M4ML15kMZiuCIMpL7ZfQhMmKpqE4wCmuRE-q4Y,7233
|
15
15
|
panther/logging.py,sha256=SGgF9faQM1QmbmMPVc6m1DY-TbV329kTD8BuzGLx3I0,2073
|
16
16
|
panther/main.py,sha256=UgzsXKC1zhtBfVIDELa9axDkWPCtVVU3aAWJpYkxTOs,9075
|
17
|
-
panther/monitoring.py,sha256=
|
17
|
+
panther/monitoring.py,sha256=C0tYBKGci6QR33CN-MixMzCP24ka0a6V0AU2H1sS4HU,1026
|
18
18
|
panther/pagination.py,sha256=ANJrEF0q1nVAfD33I4nZfUUxFcETzJb01gIhbZX3HEw,1639
|
19
19
|
panther/permissions.py,sha256=9-J5vzvEKa_PITwEVQbZZv8PG2FOu05YBlD5yMrKcfc,348
|
20
20
|
panther/request.py,sha256=F9ZiAWSse7_6moAzqdoFInUN4zTKlzijh9AdU9w3Jfw,1673
|
21
|
-
panther/response.py,sha256=
|
21
|
+
panther/response.py,sha256=iauz2akIq6O3k_XheH6uS38fYdS6X3GTWakGBsYCTp4,8697
|
22
22
|
panther/routings.py,sha256=1eqbjubLnUUEQRlz8mIF464ImvCMjyasiekHBtxEQoQ,6218
|
23
23
|
panther/serializer.py,sha256=5O5dypP9ys0qTKrjwaXONmOqCfDHoXY1q5ajsirFjM8,9083
|
24
24
|
panther/status.py,sha256=Gc_PnYrHfInTsZpGbqiCfDB-py1C7Rh8KMdb6Lq9Exs,3346
|
@@ -29,7 +29,7 @@ panther/websocket.py,sha256=YRWgc_FUrv94-dnM2nm41EDgCsqZHxQ1N53Gma7c9s0,1452
|
|
29
29
|
panther/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
panther/cli/create_command.py,sha256=mT5GFzsTYZbzqShNHlw_UIkMcWLw9btm2mTwcg7TlfI,10292
|
31
31
|
panther/cli/main.py,sha256=pCqnOTazgMhTvFHTugutIsiFXueU5kx2VmGngwAl54Q,1679
|
32
|
-
panther/cli/monitor_command.py,sha256=
|
32
|
+
panther/cli/monitor_command.py,sha256=KQUGu3L_PDmM0b5Ygy_eeKQmGPM3r8-WkLxUdmS9cBE,3982
|
33
33
|
panther/cli/run_command.py,sha256=yWcDoWC-c4ph4M5EDj0jvR9xSjh-apG5r6-NpDdArUo,2195
|
34
34
|
panther/cli/template.py,sha256=hVkY1A3HZDVGEZzRkMtYte6FagKGTAxoFeG0wot7Zn4,5320
|
35
35
|
panther/cli/utils.py,sha256=g_Xkvh_GCFrc3Remgp02lVi3YkmCAvcNKuAY_QvBTLI,5290
|
@@ -49,9 +49,9 @@ panther/panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
panther/panel/apis.py,sha256=COsbwKZyTgyHvHYbpDfusifAH9ojMS3z1KhZCt9M-Ms,2428
|
50
50
|
panther/panel/urls.py,sha256=JiV-H4dWE-m_bfaTTVxzOxTvJmOWhyLOvcbM7xU3Bn4,240
|
51
51
|
panther/panel/utils.py,sha256=0Rv79oR5IEqalqwpRKQHMn1p5duVY5mxMqDKiA5mWx4,437
|
52
|
-
panther-4.3.
|
53
|
-
panther-4.3.
|
54
|
-
panther-4.3.
|
55
|
-
panther-4.3.
|
56
|
-
panther-4.3.
|
57
|
-
panther-4.3.
|
52
|
+
panther-4.3.7.dist-info/licenses/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
|
53
|
+
panther-4.3.7.dist-info/METADATA,sha256=IbS9tbiZ8efCfjNwfe1P27w_0EJtq0IdJwfYwIp0IXg,6955
|
54
|
+
panther-4.3.7.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
|
55
|
+
panther-4.3.7.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
|
56
|
+
panther-4.3.7.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
|
57
|
+
panther-4.3.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|