panther 1.3.2__py3-none-any.whl → 1.4.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.
panther/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from .main import Panther
2
2
 
3
- __version__ = '1.3.2'
3
+ __version__ = '1.4.0'
4
4
 
5
5
 
6
6
  def version():
panther/cli/template.py CHANGED
@@ -65,6 +65,8 @@ USER_MODEL = 'panther.db.models.User'
65
65
 
66
66
  MONITORING = True
67
67
 
68
+ LOG_QUERIES = True
69
+
68
70
  URLs = 'core/urls.py'
69
71
  """ % datetime.now().date().isoformat()
70
72
 
panther/configs.py CHANGED
@@ -15,6 +15,7 @@ class JWTConfig:
15
15
  class Config(TypedDict):
16
16
  base_dir: Path
17
17
  monitoring: bool
18
+ log_queries: bool
18
19
  urls: dict
19
20
  middlewares: list
20
21
  reversed_middlewares: list
@@ -28,7 +29,8 @@ class Config(TypedDict):
28
29
 
29
30
  config: Config = {
30
31
  'base_dir': Path(),
31
- 'monitoring': True,
32
+ 'monitoring': False,
33
+ 'log_queries': False,
32
34
  'secret_key': None,
33
35
  'urls': {},
34
36
  'middlewares': [],
@@ -3,7 +3,7 @@ from typing import TypeVar
3
3
  import bson
4
4
 
5
5
  from panther.db.connection import db # NOQA: F401
6
- from panther.db.utils import clean_object_id_in_dicts, merge_dicts, query_logger
6
+ from panther.db.utils import clean_object_id_in_dicts, merge_dicts, log_query
7
7
 
8
8
  # TODO: Not sure about this bounding
9
9
  T = TypeVar('T', bound='BaseMongoDBQuery')
@@ -12,7 +12,6 @@ T = TypeVar('T', bound='BaseMongoDBQuery')
12
12
  class BaseMongoDBQuery:
13
13
 
14
14
  @classmethod
15
- @query_logger
16
15
  def get_one(cls: type[T], _data: dict = None, /, **kwargs) -> T:
17
16
  clean_object_id_in_dicts(_data, kwargs)
18
17
  _query = merge_dicts(_data, kwargs)
@@ -20,14 +19,12 @@ class BaseMongoDBQuery:
20
19
  return cls(**obj) if obj else None
21
20
 
22
21
  @classmethod
23
- @query_logger
24
22
  def count(cls, _data: dict = None, /, **kwargs) -> int:
25
23
  clean_object_id_in_dicts(_data, kwargs)
26
24
  _query = merge_dicts(_data, kwargs)
27
25
  return eval(f'db.session.{cls.__name__}.count_documents(_query)')
28
26
 
29
27
  @classmethod
30
- @query_logger
31
28
  def list(cls, _data: dict = None, /, **kwargs):
32
29
  clean_object_id_in_dicts(_data, kwargs)
33
30
  _query = merge_dicts(_data, kwargs)
@@ -35,32 +32,27 @@ class BaseMongoDBQuery:
35
32
  return [cls(**obj) for obj in result]
36
33
 
37
34
  @classmethod
38
- @query_logger
39
35
  def create(cls, _data: dict = None, **kwargs) -> bson.objectid.ObjectId:
40
36
  _query = merge_dicts(_data, kwargs)
41
37
  return eval(f'db.session.{cls.__name__}.insert_one(_query)').inserted_id
42
38
 
43
- @query_logger
44
39
  def delete(self) -> bool:
45
40
  _filter = {'_id': self._id}
46
41
  result = eval(f'db.session.{self.__class__.__name__}.delete_one(_filter)')
47
42
  return bool(result.deleted_count)
48
43
 
49
44
  @classmethod
50
- @query_logger
51
45
  def delete_one(cls, **kwargs) -> bool:
52
46
  clean_object_id_in_dicts(kwargs)
53
47
  result = eval(f'db.session.{cls.__name__}.delete_one(kwargs)')
54
48
  return bool(result.deleted_count)
55
49
 
56
50
  @classmethod
57
- @query_logger
58
51
  def delete_many(cls, **kwargs) -> int:
59
52
  clean_object_id_in_dicts(kwargs)
60
53
  result = eval(f'db.session.{cls.__name__}.delete_many(kwargs)')
61
54
  return result.deleted_count
62
55
 
63
- @query_logger
64
56
  def update(self, _data: dict = None, **kwargs) -> dict:
65
57
  for field, value in (_data or kwargs).items():
66
58
  if hasattr(self, field):
@@ -70,7 +62,6 @@ class BaseMongoDBQuery:
70
62
  return eval(f'db.session.{self.__class__.__name__}.update_one(_filter, _update)')
71
63
 
72
64
  @classmethod
73
- @query_logger
74
65
  def update_one(cls, _filter, _data: dict = None, /, **kwargs) -> dict:
75
66
  clean_object_id_in_dicts(_filter)
76
67
 
@@ -81,19 +72,16 @@ class BaseMongoDBQuery:
81
72
  return eval(f'db.session.{cls.__name__}.update_one(_filter, _data | _update)')
82
73
 
83
74
  @classmethod
84
- @query_logger
85
75
  def update_many(cls, _filter, **kwargs) -> dict:
86
76
  _update = {'$set': kwargs}
87
77
  return eval(f'db.session.{cls.__name__}.update_many(_filter, _update)')
88
78
 
89
79
  @classmethod
90
- @query_logger
91
80
  def increment(cls, _filter, **kwargs):
92
81
  _update = {'$inc': kwargs}
93
82
  return eval(f'db.session.{cls.__name__}.update_many({_filter}, {_update})')
94
83
 
95
84
  @classmethod
96
- @query_logger
97
85
  def get_or_create(cls, **kwargs) -> tuple[bool, any]:
98
86
  obj = cls.get_one(**kwargs)
99
87
  if obj:
@@ -1,9 +1,8 @@
1
- import operator
2
- from functools import reduce
3
1
  from typing import Self
4
2
  from pydantic import ValidationError
5
3
 
6
4
  from panther.db.connection import db
5
+ from panther.db.utils import merge_dicts
7
6
  from panther.exceptions import DBException
8
7
 
9
8
 
@@ -32,7 +31,7 @@ class BasePantherDBQuery:
32
31
  @classmethod
33
32
  def _merge(cls, *args) -> dict:
34
33
  # TODO: Convert "id" to "_id"
35
- return reduce(operator.ior, filter(None, args), {})
34
+ return merge_dicts(*args)
36
35
 
37
36
  # # # # # Find # # # # #
38
37
  @classmethod
@@ -1,8 +1,9 @@
1
1
  from typing import Self
2
2
 
3
+ from panther.configs import config
4
+ from panther.db.utils import log_query
3
5
  from panther.db.queries.mongodb_queries import BaseMongoDBQuery
4
6
  from panther.db.queries.pantherdb_queries import BasePantherDBQuery
5
- from panther.configs import config
6
7
 
7
8
  if config['db_engine'] == 'pantherdb':
8
9
  BaseQuery = BasePantherDBQuery
@@ -18,6 +19,7 @@ class Query(BaseQuery):
18
19
 
19
20
  # # # # # Find # # # # #
20
21
  @classmethod
22
+ @log_query
21
23
  def find_one(cls, _data: dict = None, /, **kwargs) -> Self | None:
22
24
  """
23
25
  example:
@@ -27,6 +29,7 @@ class Query(BaseQuery):
27
29
  return super().find_one(_data, **kwargs)
28
30
 
29
31
  @classmethod
32
+ @log_query
30
33
  def find(cls, _data: dict = None, /, **kwargs) -> list[Self]:
31
34
  """
32
35
  example:
@@ -37,6 +40,7 @@ class Query(BaseQuery):
37
40
 
38
41
  # # # # # Insert # # # # #
39
42
  @classmethod
43
+ @log_query
40
44
  def insert_one(cls, _data: dict = None, /, **kwargs) -> Self:
41
45
  """
42
46
  example:
@@ -46,10 +50,12 @@ class Query(BaseQuery):
46
50
  return super().insert_one(_data, **kwargs)
47
51
 
48
52
  @classmethod
53
+ @log_query
49
54
  def insert_many(cls, _data: dict = None, **kwargs):
50
55
  return super().insert_many(_data, **kwargs)
51
56
 
52
57
  # # # # # Delete # # # # #
58
+ @log_query
53
59
  def delete(self) -> None:
54
60
  """
55
61
  example:
@@ -60,6 +66,7 @@ class Query(BaseQuery):
60
66
  return super().delete()
61
67
 
62
68
  @classmethod
69
+ @log_query
63
70
  def delete_one(cls, **kwargs) -> bool:
64
71
  """
65
72
  example:
@@ -69,6 +76,7 @@ class Query(BaseQuery):
69
76
  return super().delete_one(**kwargs)
70
77
 
71
78
  @classmethod
79
+ @log_query
72
80
  def delete_many(cls, **kwargs) -> int:
73
81
  """
74
82
  example:
@@ -78,6 +86,7 @@ class Query(BaseQuery):
78
86
  return super().delete_many(**kwargs)
79
87
 
80
88
  # # # # # Update # # # # #
89
+ @log_query
81
90
  def update(self, **kwargs) -> None:
82
91
  """
83
92
  example:
@@ -88,6 +97,7 @@ class Query(BaseQuery):
88
97
  return super().update(**kwargs)
89
98
 
90
99
  @classmethod
100
+ @log_query
91
101
  def update_one(cls, _filter, _data: dict = None, /, **kwargs) -> bool:
92
102
  """
93
103
  example:
@@ -98,6 +108,7 @@ class Query(BaseQuery):
98
108
  return super().update_one(_filter, _data, **kwargs)
99
109
 
100
110
  @classmethod
111
+ @log_query
101
112
  def update_many(cls, _filter, **kwargs) -> int:
102
113
  """
103
114
  example:
@@ -108,6 +119,7 @@ class Query(BaseQuery):
108
119
 
109
120
  # # # # # Other # # # # #
110
121
  @classmethod
122
+ @log_query
111
123
  def first(cls, _data: dict = None, /, **kwargs) -> Self | None:
112
124
  """
113
125
  It works same as find_one()
@@ -118,6 +130,7 @@ class Query(BaseQuery):
118
130
  return super().first(_data, **kwargs)
119
131
 
120
132
  @classmethod
133
+ @log_query
121
134
  def last(cls, _data: dict = None, /, **kwargs) -> Self | None:
122
135
  """
123
136
  example:
@@ -127,6 +140,7 @@ class Query(BaseQuery):
127
140
  return super().last(_data, **kwargs)
128
141
 
129
142
  @classmethod
143
+ @log_query
130
144
  def count(cls, _data: dict = None, /, **kwargs) -> int:
131
145
  """
132
146
  example:
panther/db/utils.py CHANGED
@@ -4,18 +4,18 @@ from functools import reduce
4
4
  from time import perf_counter
5
5
 
6
6
  from panther.configs import config
7
- from panther.logger import logger
7
+ from panther.logger import query_logger
8
8
 
9
9
 
10
- def query_logger(func):
10
+ def log_query(func):
11
11
  def log(*args, **kwargs):
12
- if config['monitoring'] is False:
12
+ if config['log_queries'] is False:
13
13
  return func(*args, **kwargs)
14
14
  start = perf_counter()
15
15
  response = func(*args, **kwargs)
16
16
  end = perf_counter()
17
17
  class_name = args[0].__name__ if hasattr(args[0], '__name__') else args[0].__class__.__name__
18
- logger.info(f'\033[1mQuery -->\033[0m {class_name}.{func.__name__}() --> {(end - start) * 1_000:.2} ms')
18
+ query_logger.info(f'\033[1mQuery -->\033[0m {class_name}.{func.__name__}() --> {(end - start) * 1_000:.2} ms')
19
19
  return response
20
20
  return log
21
21
 
panther/logger.py CHANGED
@@ -18,6 +18,7 @@ class LogConfig(BaseModel):
18
18
  DEFAULT_LOG_FORMAT: str = '%(levelprefix)s | %(asctime)s | %(message)s'
19
19
  FILE_LOG_FORMAT: str = '%(asctime)s | %(message)s'
20
20
  LOG_LEVEL: str = 'DEBUG'
21
+ MAX_FILE_SIZE: int = 1024 * 1024 * 100 # 100 MB
21
22
 
22
23
  version = 1
23
24
  disable_existing_loggers = False
@@ -39,15 +40,21 @@ class LogConfig(BaseModel):
39
40
  'formatter': 'file_formatter',
40
41
  'filename': LOGS_DIR / 'monitoring.log',
41
42
  'class': 'logging.handlers.RotatingFileHandler',
42
- 'maxBytes': 1024 * 1024 * 100, # 100 MB,
43
+ 'maxBytes': MAX_FILE_SIZE, # 100 MB,
44
+ 'backupCount': 3,
45
+ },
46
+ 'query_file': {
47
+ 'formatter': 'file_formatter',
48
+ 'filename': LOGS_DIR / 'query.log',
49
+ 'class': 'logging.handlers.RotatingFileHandler',
50
+ 'maxBytes': MAX_FILE_SIZE, # 100 MB,
43
51
  'backupCount': 3,
44
52
  },
45
53
  'file': {
46
54
  'formatter': 'file_formatter',
47
- # TODO: Don't know but base_dir.name will return '.' here :\
48
- 'filename': LOGS_DIR / f'{config["base_dir"].name}.log',
55
+ 'filename': LOGS_DIR / f'main.log',
49
56
  'class': 'logging.handlers.RotatingFileHandler',
50
- 'maxBytes': 1024 * 1024 * 100, # 100 MB,
57
+ 'maxBytes': MAX_FILE_SIZE, # 100 MB,
51
58
  'backupCount': 3,
52
59
  },
53
60
  'default': {
@@ -65,13 +72,14 @@ class LogConfig(BaseModel):
65
72
  'handlers': ['monitoring_file'],
66
73
  'level': LOG_LEVEL,
67
74
  },
75
+ 'query': {
76
+ 'handlers': ['default', 'query_file'],
77
+ 'level': LOG_LEVEL,
78
+ },
68
79
  }
69
80
 
70
81
 
71
82
  dictConfig(LogConfig().dict())
72
83
  logger = logging.getLogger('panther')
73
- monitoring = logging.getLogger('monitoring')
74
-
75
- """
76
- [debug, info, warning, error, critical]
77
- """
84
+ query_logger = logging.getLogger('query')
85
+ monitoring_logger = logging.getLogger('monitoring')
panther/main.py CHANGED
@@ -117,6 +117,7 @@ class Panther:
117
117
 
118
118
  # Put Variables In "config"
119
119
  config['monitoring'] = self.settings.get('MONITORING', config['monitoring'])
120
+ config['log_queries'] = self.settings.get('LOG_QUERIES', config['log_queries'])
120
121
  config['default_cache_exp'] = self.settings.get('DEFAULT_CACHE_EXP', config['default_cache_exp'])
121
122
  config['secret_key'] = self._get_secret_key()
122
123
 
@@ -1,8 +1,8 @@
1
1
  from time import perf_counter
2
2
 
3
- from panther.logger import monitoring
4
- from panther.middlewares.base import BaseMiddleware
5
3
  from panther.request import Request
4
+ from panther.logger import monitoring_logger
5
+ from panther.middlewares.base import BaseMiddleware
6
6
 
7
7
 
8
8
  class Middleware(BaseMiddleware):
@@ -21,4 +21,4 @@ class Middleware(BaseMiddleware):
21
21
  but we should put in middlewares chain later ...
22
22
  """
23
23
  response_time = (perf_counter() - self.start_time) * 1_000
24
- monitoring.info(f'{self.log} | {response_time: .3} ms | {status_code}')
24
+ monitoring_logger.info(f'{self.log} | {response_time: .3} ms | {status_code}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: panther
3
- Version: 1.3.2
3
+ Version: 1.4.0
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,12 +1,12 @@
1
- panther/__init__.py,sha256=3wbCCpx1wHKORMYkcXcuf3nk18M7HyPkxPsnmModdlE,89
1
+ panther/__init__.py,sha256=ViOJcmBWhbt9e0b1kOj-Y3RfqE4-sRmE9jJ0CwqE-FM,89
2
2
  panther/_utils.py,sha256=Ltev6PCrTWHTWSQcWNfHMWDof1_MXODTAcDaGwflgXo,3667
3
3
  panther/app.py,sha256=tojfQaU8x5pZa7m8XS4m9fR7D5sIe_-d96hD2ccBINo,5469
4
4
  panther/authentications.py,sha256=FCRQL3xqN1Tla2vZsOY8-qXwPhnZBFsujJ-R7CeaW7w,2350
5
5
  panther/caching.py,sha256=qCqb-IaXD1T7VU0AzJVMoXawb366ZYob9kblDUT-7sM,2452
6
- panther/configs.py,sha256=UU2ePtjM0dT6C1p63l0EE9w0FPCDpUTOHbDPOkFHJRM,926
6
+ panther/configs.py,sha256=bRGRy772Rxjb3RunEBBvfa9LCNCmgcc2TKkfbNTK0GM,975
7
7
  panther/exceptions.py,sha256=c1MeSo7_uwDuqoBcjKTFyXz17uXP5iZ3bM0Sp5Stvhw,769
8
- panther/logger.py,sha256=fb6RdDN908Em_fmbE7yDpViWn-LQ4egvbid_obBZN70,2168
9
- panther/main.py,sha256=oQu4v_c8Iip1TrXmRtxHx7j4qYiYrNimMoAXMicOZ9g,7372
8
+ panther/logger.py,sha256=1skaZg4w55mTh4pSrCohkGp-7dg62lyEIoFAJKMP5L8,2499
9
+ panther/main.py,sha256=Aa43X3ZEonPrJ4Mj5ACEyGmJl-BbsHcPyKj3fDe2E4k,7460
10
10
  panther/request.py,sha256=Ix1podGHCU5NlUCT9Emc79GOITKEw623ldpTw3oZm68,4383
11
11
  panther/response.py,sha256=zzfe8vsPSnydN-_peJTizlnmnawxlNbJFU9zvXppYTk,1025
12
12
  panther/routings.py,sha256=sV3xWksKYb3_95BTDOtSqouroHkB98ExoNkgWT1t7jE,4422
@@ -17,24 +17,24 @@ panther/cli/create_command.py,sha256=cUPMzXJnwsa2J1eGetWYUnbEL5GEEe5x-_wG3fA3rLg
17
17
  panther/cli/main.py,sha256=TttHOr0jA2rkLxCCtpW3ES9x4dDpq5AS32dMN0VwoW0,891
18
18
  panther/cli/monitor_command.py,sha256=wR6Ti8-2-LuLhfPzdXH77g7xlNQAL5flpBoVwu9qdoE,2458
19
19
  panther/cli/run_command.py,sha256=SdguosH7Orlh-8x8eZK_EWrv8MPnXFKzqxruTHYdHqk,1501
20
- panther/cli/template.py,sha256=XssIjmb98tECumKC0wqE4b61_tpzFi9TXv6jzGtrlFg,2297
20
+ panther/cli/template.py,sha256=KhehW5nzovQzbW75J1lpAAQcIsqucqU4IXQXpVWBj5M,2317
21
21
  panther/cli/utils.py,sha256=QKQ5_qLWtTjpLY0lZ6yt2vDlc2H0jF6HFe3F-8YNJDg,8225
22
22
  panther/db/__init__.py,sha256=lOgqqRkGMzMSS1WS8D7lTChTr9ikIB5ImRPmucOhCyc,54
23
23
  panther/db/connection.py,sha256=BoqTetHcWn2cmjo1ELDoFFGkGlvJw6qDuBorKSe8ru0,2097
24
24
  panther/db/models.py,sha256=vnhFtVONqhCkTkFMOSz_rTDmAAxNcegPoxk1p5SljLc,1028
25
- panther/db/utils.py,sha256=ed_wCy8tga6CLgGjUDe-GZvXZzVrLoUxPQukJvhrdo4,1209
25
+ panther/db/utils.py,sha256=6ndrZ9reaVTqnbFhX8MjOYtcrcPSY7UywAbDquY4eEg,1219
26
26
  panther/db/queries/__init__.py,sha256=BMffHS9RbHE-AUAeT9C5uY3L-hpDh0WGRduDUQ9Kpuc,41
27
- panther/db/queries/mongodb_queries.py,sha256=CHum1VDxVHt9fqa97CCvOijxSEWycEDiibcuoq0mJow,3447
28
- panther/db/queries/pantherdb_queries.py,sha256=FjmRILq2hPAuK_NSaJ6UuCqLhUSIfH9sVoG7BsKk_hw,3864
29
- panther/db/queries/queries.py,sha256=dVjp-P5z6fgIj0jrKW2C2GHQE3Wlx_6IRvgpsg6zH6A,3900
27
+ panther/db/queries/mongodb_queries.py,sha256=qFW1tsxnyh459rFOOD-jPTZwhDFh6q6qSttA_a4ryaw,3228
28
+ panther/db/queries/pantherdb_queries.py,sha256=CEKxBcFZo4PmcleE87Jw1PrujtOB-emd20mqzHI1IKw,3834
29
+ panther/db/queries/queries.py,sha256=yG5B_qg4cNL8nDkeJtJ0RRj4EH5dEMC-2jNIk4I1eS0,4134
30
30
  panther/middlewares/__init__.py,sha256=7RtHuS-MfybnJc6pcBSGhi9teXNhDsnJ3n7h_cXSkJk,66
31
31
  panther/middlewares/base.py,sha256=Php29ckITeGZm6GfauFG3i61bcsb4qoU8RpPLTqsfls,240
32
32
  panther/middlewares/db.py,sha256=C_PevTIaMykJl0NaaMYEfwE_oLdSLfKW2HR9UoPN1dU,508
33
- panther/middlewares/monitoring.py,sha256=WpB_DGPBLC0OSOHCFkFc5R3FlO6PTZ83C-px1Frm254,838
33
+ panther/middlewares/monitoring.py,sha256=CbGNJ4Ja-m9Wq3Ytv7RFyd-Qj9Ft6cYqBZZncCAxccs,852
34
34
  panther/middlewares/redis.py,sha256=_XIvPAOrVl74UoiA6-Xz8hSfWoeuM2Y1e74xeyvW0I4,1126
35
- panther-1.3.2.dist-info/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
36
- panther-1.3.2.dist-info/METADATA,sha256=W1d6VHYUjlE_vHl4aEFr93fKXcqXgMRBRp8XyCTMme0,5124
37
- panther-1.3.2.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
38
- panther-1.3.2.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
39
- panther-1.3.2.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
40
- panther-1.3.2.dist-info/RECORD,,
35
+ panther-1.4.0.dist-info/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
36
+ panther-1.4.0.dist-info/METADATA,sha256=AnzClL3p1FGVv2WWYBoSfJdMrIG3If4tq43T4zXx_Sk,5124
37
+ panther-1.4.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
38
+ panther-1.4.0.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
39
+ panther-1.4.0.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
40
+ panther-1.4.0.dist-info/RECORD,,