panther 4.2.3__py3-none-any.whl → 4.2.5__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.2.3'
3
+ __version__ = '4.2.5'
4
4
 
5
5
 
6
6
  def version():
panther/cli/utils.py CHANGED
@@ -142,7 +142,7 @@ def print_info(config: Config):
142
142
  if config.HAS_WS:
143
143
  try:
144
144
  import gunicorn
145
- gunicorn_msg = f'{h} * You have WS so make sure to run gunicorn with --preload{h}\n'
145
+ gunicorn_msg = f'{h} * You have WS, so make sure to run gunicorn with --preload{h}\n'
146
146
  except ImportError:
147
147
  pass
148
148
 
panther/db/connections.py CHANGED
@@ -75,7 +75,7 @@ class MongoDBConnection(BaseDatabaseConnection):
75
75
 
76
76
  class PantherDBConnection(BaseDatabaseConnection):
77
77
  def init(self, path: str | None = None, encryption: bool = False):
78
- params = {'db_name': str(path), 'return_dict': True, 'return_cursor': True}
78
+ params = {'db_name': path, 'return_dict': True, 'return_cursor': True}
79
79
  if encryption:
80
80
  try:
81
81
  import cryptography
@@ -114,6 +114,8 @@ class BaseMongoDBQuery(BaseQuery):
114
114
  else:
115
115
  update_query['$set'] = update_query.get('$set', {})
116
116
  update_query['$set'][field] = value
117
+ if isinstance(value, dict):
118
+ value = type(getattr(self, field))(**value)
117
119
  setattr(self, field, value)
118
120
 
119
121
  await db.session[self.__class__.__name__].update_one({'_id': self._id}, update_query)
@@ -96,6 +96,8 @@ class BasePantherDBQuery(BaseQuery):
96
96
  self._validate_data(data=kwargs, is_updating=True)
97
97
 
98
98
  for field, value in document.items():
99
+ if isinstance(value, dict):
100
+ value = type(getattr(self, field))(**value)
99
101
  setattr(self, field, value)
100
102
  db.session.collection(self.__class__.__name__).update_one({'_id': self._id}, **document)
101
103
 
@@ -2,6 +2,7 @@ import sys
2
2
  from typing import Sequence, Iterable
3
3
 
4
4
  from pantherdb import Cursor as PantherDBCursor
5
+ from pydantic import BaseModel
5
6
 
6
7
  from panther.configs import QueryObservable
7
8
  from panther.db.cursor import Cursor
@@ -364,6 +365,26 @@ class Query(BaseQuery):
364
365
 
365
366
  raise NotFoundAPIError(detail=f'{cls.__name__} Does Not Exist')
366
367
 
368
+ @classmethod
369
+ async def exists(cls, _filter: dict | None = None, /, **kwargs) -> bool:
370
+ """
371
+ Check if document exists in collection or not
372
+
373
+ Example:
374
+ -------
375
+ >>> from app.models import User
376
+
377
+ >>> await User.exists(age=18, name='Ali')
378
+ or
379
+ >>> await User.exists({'age': 18, 'name': 'Ali'})
380
+ or
381
+ >>> await User.exists({'age': 18}, name='Ali')
382
+ """
383
+ if await cls.count(_filter, **kwargs) > 0:
384
+ return True
385
+ else:
386
+ return False
387
+
367
388
  async def save(self) -> None:
368
389
  """
369
390
  Save the document
@@ -382,7 +403,12 @@ class Query(BaseQuery):
382
403
  >>> user = User(name='Ali')
383
404
  >>> await user.save()
384
405
  """
385
- document = {field: getattr(self, field) for field in self.model_fields_set if field != 'request'}
406
+ document = {
407
+ field: getattr(self, field).model_dump()
408
+ if issubclass(type(getattr(self, field)), BaseModel)
409
+ else getattr(self, field)
410
+ for field in self.model_fields_set if field != 'request'
411
+ }
386
412
 
387
413
  if self.id:
388
414
  await self.update(document)
panther/logging.py CHANGED
@@ -64,10 +64,5 @@ LOGGING = {
64
64
  'handlers': ['default', 'query_file'],
65
65
  'level': 'DEBUG',
66
66
  },
67
- 'uvicorn.error': {
68
- 'handlers': ['default'],
69
- 'level': 'INFO',
70
- 'propagate': False,
71
- },
72
67
  }
73
68
  }
panther/utils.py CHANGED
@@ -50,6 +50,20 @@ def generate_secret_key() -> str:
50
50
 
51
51
 
52
52
  def round_datetime(dt: datetime, delta: timedelta):
53
+ """
54
+ Example:
55
+ >>> round_datetime(datetime(2024, 7, 15, 13, 22, 11, 562159), timedelta(days=2))
56
+ datetime.datetime(2024, 7, 16, 0, 0)
57
+
58
+ >>> round_datetime(datetime(2024, 7, 16, 13, 22, 11, 562159), timedelta(days=2))
59
+ datetime.datetime(2024, 7, 16, 0, 0)
60
+
61
+ >>> round_datetime(datetime(2024, 7, 17, 13, 22, 11, 562159), timedelta(days=2))
62
+ datetime.datetime(2024, 7, 18, 0, 0)
63
+
64
+ >>> round_datetime(datetime(2024, 7, 18, 13, 22, 11, 562159), timedelta(days=2))
65
+ datetime.datetime(2024, 7, 18, 0, 0)
66
+ """
53
67
  return datetime.min + round((dt - datetime.min) / delta) * delta
54
68
 
55
69
 
panther/websocket.py CHANGED
@@ -27,6 +27,12 @@ class GenericWebsocket(Websocket):
27
27
  """
28
28
  return await super().send(data=data)
29
29
 
30
+ async def close(self, code: int = status.WS_1000_NORMAL_CLOSURE, reason: str = ''):
31
+ """
32
+ Called whenever server or client, wants to close the connection
33
+ """
34
+ return await super().close(code=code, reason=reason)
35
+
30
36
 
31
37
  async def send_message_to_websocket(connection_id: str, data: any):
32
38
  await config.WEBSOCKET_CONNECTIONS.publish(connection_id=connection_id, action='send', data=data)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: panther
3
- Version: 4.2.3
3
+ Version: 4.2.5
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
@@ -1,4 +1,4 @@
1
- panther/__init__.py,sha256=Nnh-BbkFDE8VPq-rwqN77nqyR2APRJ19ZXjzrBrNX6c,110
1
+ panther/__init__.py,sha256=zgKwp0ZZMtz_3Ih_Rd9y7QJinvbePp_Lp5OSfG9pUoM,110
2
2
  panther/_load_configs.py,sha256=AVkoixkUFkBQiTmrLrwCmg0eiPW2U_Uw2EGNEGQRfnI,9281
3
3
  panther/_utils.py,sha256=j0rwIxTf0rtcZAAD-1nGE-_bWpvinyKtnwt3uO0hMmY,4330
4
4
  panther/app.py,sha256=e2eb4sXIaBje5vpcm4pbvvEO_sj83pLfBHCIZJFFX38,8222
@@ -12,7 +12,7 @@ panther/events.py,sha256=bxDqrfiNNBlvD03vEk2LDK4xbMzTMFVcgAjx2ein7mI,1158
12
12
  panther/exceptions.py,sha256=7rHdJIES2__kqOStIqbHl3Uxask2lzKgLQlkZvvDwFA,1591
13
13
  panther/file_handler.py,sha256=I94tpbtTVniBnnUMkFr3Eis6kPDt8sLzS5u8TzFrR5I,1323
14
14
  panther/generics.py,sha256=D2ia7M4ML15kMZiuCIMpL7ZfQhMmKpqE4wCmuRE-q4Y,7233
15
- panther/logging.py,sha256=k__vzvSrPpr1IsA4OLrBt1JHuRUBXr7ekPlBW0-9rbM,2209
15
+ panther/logging.py,sha256=SGgF9faQM1QmbmMPVc6m1DY-TbV329kTD8BuzGLx3I0,2073
16
16
  panther/main.py,sha256=UbIxwaojvY_vH9nYfBpkulRBqVEj4Lbl81Er4XW_KCY,9334
17
17
  panther/monitoring.py,sha256=y1F3c8FJlnmooM-m1nSyOTa9eWq0v1nHnmw9zz-4Kls,1314
18
18
  panther/pagination.py,sha256=ANJrEF0q1nVAfD33I4nZfUUxFcETzJb01gIhbZX3HEw,1639
@@ -24,34 +24,34 @@ panther/serializer.py,sha256=UX-cVS-11KnxijUhPXsBs_Pb-Sm3EVzUQFTf9bFQT0A,9096
24
24
  panther/status.py,sha256=Gc_PnYrHfInTsZpGbqiCfDB-py1C7Rh8KMdb6Lq9Exs,3346
25
25
  panther/test.py,sha256=RsQtP5IURLWR__BihOjruWoX3NscmGDqDqj1CfAb3bI,7037
26
26
  panther/throttling.py,sha256=mVa_mGv6w_Ad7LLtV4eG5QpDwwNsk4QjFFi0mIHQBnE,231
27
- panther/utils.py,sha256=Iq5q1suIgBBQGO5UctwR4HXs8E6zclXNh5lYc8k1Vjg,3409
28
- panther/websocket.py,sha256=5WLw--Oa-6kGYbeRvO79hjbd0ARFcTTF40-hO_bdjmQ,1206
27
+ panther/utils.py,sha256=6ZkHWm4FniOv-Hufknq2tVclrfIbxyzCL-gDlx6uNaQ,3977
28
+ 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
32
  panther/cli/monitor_command.py,sha256=sbnxQOSy0Q6GB-ELrfyoY6S-ZwgbI7eZyKx7YkvrEas,3383
33
33
  panther/cli/run_command.py,sha256=yWcDoWC-c4ph4M5EDj0jvR9xSjh-apG5r6-NpDdArUo,2195
34
34
  panther/cli/template.py,sha256=hVkY1A3HZDVGEZzRkMtYte6FagKGTAxoFeG0wot7Zn4,5320
35
- panther/cli/utils.py,sha256=Jd4YQ9H6lapVktl7ZmiORt30WVmKI85xcwsY-fMRq3c,5289
35
+ panther/cli/utils.py,sha256=g_Xkvh_GCFrc3Remgp02lVi3YkmCAvcNKuAY_QvBTLI,5290
36
36
  panther/db/__init__.py,sha256=w9lEL0vRqb18Qx_iUJipUR_fi5GQ5uVX0DWycx14x08,50
37
- panther/db/connections.py,sha256=rps48Ic2r3SV2HD3df1OU7C4Pv8j98PVXU1O_FqF9Ak,4210
37
+ panther/db/connections.py,sha256=8QHQ_tmni4gfLHQCR7jmBFfvFgJCOrTQXdQiDRJRuv0,4205
38
38
  panther/db/cursor.py,sha256=jJ6bhz_Zljt3-AoeVdi563e2q3MSDJPP33WVbQk-goE,1287
39
39
  panther/db/models.py,sha256=GRbKXJiwnxQJ_SjuPfXPzA5miH_djZNTPPyqiRp5DI8,2561
40
40
  panther/db/utils.py,sha256=ZZa3TMkuRtssl5ZRItFLonyxvMFsTq4fmTD4BblhLDA,1589
41
41
  panther/db/queries/__init__.py,sha256=uF4gvBjLBJ-Yl3WLqoZEVNtHCVhFRKW3_Vi44pJxDNI,45
42
42
  panther/db/queries/base_queries.py,sha256=8HhdlsSW-lgz3-IrZYfOtHNC3TBWbCNErDR4XE718AY,3764
43
- panther/db/queries/mongodb_queries.py,sha256=4CQRdmgmKFIpnv6xijS0BMJO-Sf5beyuzmw8Z9jLtnA,5599
44
- panther/db/queries/pantherdb_queries.py,sha256=_dA4gXk1IA5jzIy6_6o1zgdZeeka6SPihvQeSkj7h68,4481
45
- panther/db/queries/queries.py,sha256=d6V4whHEYjtufoeqIC5lBNa_FGDW8_7AYeps48ilHDk,11665
43
+ panther/db/queries/mongodb_queries.py,sha256=VLRrUc6kO6YinzEa3mnxzOPv2YyAEh7KjPS4WwzCcRM,5707
44
+ panther/db/queries/pantherdb_queries.py,sha256=c9K3EHvOTZFN-1ZH8LUiK1BSXpEjPR8vaqPt5FuC05U,4581
45
+ panther/db/queries/queries.py,sha256=kijRVOPlafGReWD2tHHbqVf6KyQ5_RDuInTuzwvdw1I,12417
46
46
  panther/middlewares/__init__.py,sha256=ydo0bSadGqa2v7Xy1oCTkF2uXrImedXjiyx2vPTwPhE,66
47
47
  panther/middlewares/base.py,sha256=tX0MBvDBkbsAB_DilRIYvcggSAqCzazRTb9MegZNdlA,843
48
48
  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.2.3.dist-info/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
53
- panther-4.2.3.dist-info/METADATA,sha256=eVG_pGFx9YD_x49hTbwe9XVg-7AzfCOrxPcc-LOIeXs,6532
54
- panther-4.2.3.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
55
- panther-4.2.3.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
56
- panther-4.2.3.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
57
- panther-4.2.3.dist-info/RECORD,,
52
+ panther-4.2.5.dist-info/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
53
+ panther-4.2.5.dist-info/METADATA,sha256=0wjcfmI8VOEtI41AySbErsINBzctgK2kF2-J7LFUqe4,6532
54
+ panther-4.2.5.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
55
+ panther-4.2.5.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
56
+ panther-4.2.5.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
57
+ panther-4.2.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5