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 CHANGED
@@ -1,6 +1,6 @@
1
1
  from panther.main import Panther # noqa: F401
2
2
 
3
- __version__ = '4.3.5'
3
+ __version__ = '4.3.7'
4
4
 
5
5
 
6
6
  def version():
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
- raise _exception_handler(field='MIDDLEWARES', error=f'{middleware} should have 2 part: (path, kwargs)')
157
+ path_or_type = middleware
158
+ data = {}
158
159
 
159
- if len(middleware) == 1:
160
- path = middleware[0]
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
- path, data = middleware
168
+ path_or_type, data = middleware
168
169
 
169
- try:
170
- middleware_class = import_class(path)
171
- except (AttributeError, ModuleNotFoundError):
172
- raise _exception_handler(field='MIDDLEWARES', error=f'{path} is not a valid middleware path')
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
 
@@ -19,7 +19,7 @@ from panther.configs import config
19
19
  with contextlib.suppress(ImportError):
20
20
  from watchfiles import watch
21
21
 
22
- loggerr = logging.getLogger('panther')
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
- loggerr.error(error)
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
- self.rows.append(line.split('|'))
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
- date time | method | path | ip:port | response_time [ms, s] | status
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
- time_unit = ' s'
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
@@ -13,7 +13,6 @@ else:
13
13
 
14
14
  import orjson as json
15
15
  from pydantic import BaseModel
16
- from jinja2 import Environment, FileSystemLoader
17
16
 
18
17
  from panther import status
19
18
  from panther.configs import config
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: panther
3
- Version: 4.3.5
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.0
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
  [![PyPI](https://img.shields.io/pypi/v/panther?label=PyPI)](https://pypi.org/project/panther/) [![PyVersion](https://img.shields.io/pypi/pyversions/panther.svg)](https://pypi.org/project/panther/) [![codecov](https://codecov.io/github/AliRn76/panther/graph/badge.svg?token=YWFQA43GSP)](https://codecov.io/github/AliRn76/panther) [![Downloads](https://static.pepy.tech/badge/panther/month)](https://pepy.tech/project/panther) [![license](https://img.shields.io/github/license/alirn76/panther.svg)](https://github.com/alirn76/panther/blob/main/LICENSE)
@@ -1,6 +1,6 @@
1
- panther/__init__.py,sha256=UJP3FufxNFIxwJDwS3VMJjiDNeagB0sRjhRqiRnTnWw,110
2
- panther/_load_configs.py,sha256=tVzUB8WqwkOcsRbs1T4vhaKICPbDlXelr5h7LVdVupU,10079
3
- panther/_utils.py,sha256=uufhLXT_TdiQacrcCV-Jr12ET7uqaiX2E3Y9AzbVfDQ,4109
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=y1F3c8FJlnmooM-m1nSyOTa9eWq0v1nHnmw9zz-4Kls,1314
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=mzJjCKWhfDRaW4JNlIeulGymRYJbLKcs9tA7ChCu3YA,8746
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=sbnxQOSy0Q6GB-ELrfyoY6S-ZwgbI7eZyKx7YkvrEas,3383
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.5.dist-info/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
53
- panther-4.3.5.dist-info/METADATA,sha256=XT3S_mACyba0AlZbjR5I4GcF0AR1ngURQXl5dCwy2Go,6695
54
- panther-4.3.5.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
55
- panther-4.3.5.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
56
- panther-4.3.5.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
57
- panther-4.3.5.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (80.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5