panther 5.0.0b2__py3-none-any.whl → 5.0.0b4__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 +46 -37
- panther/_utils.py +49 -34
- panther/app.py +96 -97
- panther/authentications.py +97 -50
- panther/background_tasks.py +98 -124
- panther/base_request.py +16 -10
- panther/base_websocket.py +8 -8
- panther/caching.py +16 -80
- panther/cli/create_command.py +17 -16
- panther/cli/main.py +1 -1
- panther/cli/monitor_command.py +11 -6
- panther/cli/run_command.py +5 -71
- panther/cli/template.py +7 -7
- panther/cli/utils.py +58 -69
- panther/configs.py +70 -72
- panther/db/connections.py +18 -24
- panther/db/cursor.py +0 -1
- panther/db/models.py +24 -8
- panther/db/queries/base_queries.py +2 -5
- panther/db/queries/mongodb_queries.py +17 -20
- panther/db/queries/pantherdb_queries.py +1 -1
- panther/db/queries/queries.py +26 -8
- panther/db/utils.py +1 -1
- panther/events.py +25 -14
- panther/exceptions.py +2 -7
- panther/file_handler.py +1 -1
- panther/generics.py +11 -8
- panther/logging.py +2 -1
- panther/main.py +12 -13
- panther/middlewares/cors.py +67 -0
- panther/middlewares/monitoring.py +5 -3
- panther/openapi/urls.py +2 -2
- panther/openapi/utils.py +3 -3
- panther/openapi/views.py +20 -37
- panther/pagination.py +4 -2
- panther/panel/apis.py +2 -7
- panther/panel/urls.py +2 -6
- panther/panel/utils.py +9 -5
- panther/panel/views.py +17 -23
- panther/permissions.py +2 -1
- panther/request.py +2 -1
- panther/response.py +53 -47
- panther/routings.py +12 -12
- panther/serializer.py +19 -20
- panther/test.py +73 -58
- panther/throttling.py +68 -3
- panther/utils.py +5 -11
- {panther-5.0.0b2.dist-info → panther-5.0.0b4.dist-info}/METADATA +1 -1
- panther-5.0.0b4.dist-info/RECORD +75 -0
- panther/monitoring.py +0 -34
- panther-5.0.0b2.dist-info/RECORD +0 -75
- {panther-5.0.0b2.dist-info → panther-5.0.0b4.dist-info}/WHEEL +0 -0
- {panther-5.0.0b2.dist-info → panther-5.0.0b4.dist-info}/entry_points.txt +0 -0
- {panther-5.0.0b2.dist-info → panther-5.0.0b4.dist-info}/licenses/LICENSE +0 -0
- {panther-5.0.0b2.dist-info → panther-5.0.0b4.dist-info}/top_level.txt +0 -0
panther/throttling.py
CHANGED
@@ -1,11 +1,76 @@
|
|
1
1
|
from collections import defaultdict
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from datetime import timedelta
|
3
|
+
from datetime import datetime, timedelta
|
4
4
|
|
5
|
-
|
5
|
+
from panther.db.connections import redis
|
6
|
+
from panther.exceptions import ThrottlingAPIError
|
7
|
+
from panther.request import Request
|
8
|
+
from panther.utils import round_datetime
|
9
|
+
|
10
|
+
# In-memory fallback storage for when Redis is unavailable
|
11
|
+
_fallback_throttle_storage = defaultdict(int)
|
6
12
|
|
7
13
|
|
8
14
|
@dataclass(repr=False, eq=False)
|
9
|
-
class
|
15
|
+
class Throttle:
|
10
16
|
rate: int
|
11
17
|
duration: timedelta
|
18
|
+
|
19
|
+
@property
|
20
|
+
def time_window(self) -> datetime:
|
21
|
+
return round_datetime(datetime.now(), self.duration)
|
22
|
+
|
23
|
+
def build_cache_key(self, request: Request) -> str:
|
24
|
+
"""
|
25
|
+
Generate a unique cache key based on time window, user or IP, and path.
|
26
|
+
This method is intended to be overridden by subclasses to customize throttling logic.
|
27
|
+
"""
|
28
|
+
identifier = request.user.id if request.user else request.client.ip
|
29
|
+
return f'{self.time_window}-{identifier}-{request.path}'
|
30
|
+
|
31
|
+
async def get_request_count(self, request: Request) -> int:
|
32
|
+
"""
|
33
|
+
Get the current request count for this key from Redis or fallback memory.
|
34
|
+
"""
|
35
|
+
key = self.build_cache_key(request)
|
36
|
+
|
37
|
+
if redis.is_connected:
|
38
|
+
value = await redis.get(key)
|
39
|
+
return int(value) if value else 0
|
40
|
+
|
41
|
+
return _fallback_throttle_storage.get(key, 0)
|
42
|
+
|
43
|
+
async def increment_request_count(self, request: Request) -> None:
|
44
|
+
"""
|
45
|
+
Increment the request count for this key and ensure TTL is set in Redis.
|
46
|
+
"""
|
47
|
+
key = self.build_cache_key(request)
|
48
|
+
|
49
|
+
if redis.is_connected:
|
50
|
+
count = await redis.incrby(key, amount=1)
|
51
|
+
if count == 1:
|
52
|
+
ttl = int(self.duration.total_seconds())
|
53
|
+
await redis.expire(key, ttl)
|
54
|
+
else:
|
55
|
+
_fallback_throttle_storage[key] += 1
|
56
|
+
|
57
|
+
async def check_and_increment(self, request: Request) -> None:
|
58
|
+
"""
|
59
|
+
Main throttling logic:
|
60
|
+
- Raises ThrottlingAPIError if limit exceeded.
|
61
|
+
- Otherwise increments the request count.
|
62
|
+
"""
|
63
|
+
count = await self.get_request_count(request)
|
64
|
+
remaining = self.rate - count - 1
|
65
|
+
reset_time = self.time_window + self.duration
|
66
|
+
retry_after = int((reset_time - datetime.now()).total_seconds())
|
67
|
+
|
68
|
+
if remaining < 0:
|
69
|
+
raise ThrottlingAPIError(
|
70
|
+
headers={
|
71
|
+
'Retry-After': str(retry_after),
|
72
|
+
'X-RateLimit-Reset': str(int(reset_time.timestamp())),
|
73
|
+
},
|
74
|
+
)
|
75
|
+
|
76
|
+
await self.increment_request_count(request)
|
panther/utils.py
CHANGED
@@ -33,7 +33,7 @@ def load_env(env_file: str | Path, /) -> dict[str, str]:
|
|
33
33
|
raise ValueError(f'"{env_file}" is not a file.') from None
|
34
34
|
|
35
35
|
with open(env_file) as file:
|
36
|
-
for line in file
|
36
|
+
for line in file:
|
37
37
|
striped_line = line.strip()
|
38
38
|
if not striped_line.startswith('#') and '=' in striped_line:
|
39
39
|
key, value = striped_line.split('=', 1)
|
@@ -53,7 +53,7 @@ def generate_secret_key() -> str:
|
|
53
53
|
return base64.urlsafe_b64encode(os.urandom(32)).decode()
|
54
54
|
|
55
55
|
|
56
|
-
def round_datetime(dt: datetime, delta: timedelta):
|
56
|
+
def round_datetime(dt: datetime, delta: timedelta) -> datetime:
|
57
57
|
"""
|
58
58
|
Example:
|
59
59
|
>>> round_datetime(datetime(2024, 7, 15, 13, 22, 11, 562159), timedelta(days=2))
|
@@ -67,6 +67,7 @@ def round_datetime(dt: datetime, delta: timedelta):
|
|
67
67
|
|
68
68
|
>>> round_datetime(datetime(2024, 7, 18, 13, 22, 11, 562159), timedelta(days=2))
|
69
69
|
datetime.datetime(2024, 7, 18, 0, 0)
|
70
|
+
|
70
71
|
"""
|
71
72
|
return datetime.min + round((dt - datetime.min) / delta) * delta
|
72
73
|
|
@@ -87,19 +88,12 @@ def scrypt(password: str, salt: bytes, digest: bool = False) -> str | bytes:
|
|
87
88
|
h_len: The length in octets of the hash function (32 for SHA256).
|
88
89
|
mf_len: The length in octets of the output of the mixing function (SMix below). Defined as r * 128 in RFC7914.
|
89
90
|
"""
|
90
|
-
n = 2
|
91
|
+
n = 2**14 # 16384
|
91
92
|
r = 8
|
92
93
|
p = 10
|
93
94
|
dk_len = 64
|
94
95
|
|
95
|
-
derived_key = hashlib.scrypt(
|
96
|
-
password=password.encode(),
|
97
|
-
salt=salt,
|
98
|
-
n=n,
|
99
|
-
r=r,
|
100
|
-
p=p,
|
101
|
-
dklen=dk_len
|
102
|
-
)
|
96
|
+
derived_key = hashlib.scrypt(password=password.encode(), salt=salt, n=n, r=r, p=p, dklen=dk_len)
|
103
97
|
if digest:
|
104
98
|
return hashlib.md5(derived_key).hexdigest()
|
105
99
|
return derived_key
|
@@ -0,0 +1,75 @@
|
|
1
|
+
panther/__init__.py,sha256=X4CUQB2xphMKSsHepAZPm5n5K0uNc-zhZt9i3Hs_jN8,115
|
2
|
+
panther/_load_configs.py,sha256=9SMiJm4N5wOZYYpM5BfchvHuTg7PZOmvfIkiloUQLDk,11283
|
3
|
+
panther/_utils.py,sha256=5UN0DBNTEqHejK6EOnG9IYyH1gK9OvGXYlNp5G0iFuU,4720
|
4
|
+
panther/app.py,sha256=1WsVwzWZBxA5lO6v18Renq9oYqySY0gRFFT42cPkbFY,11409
|
5
|
+
panther/authentications.py,sha256=JdCeXKvo6iHmxeXsZEmFvXQsLkI149g1dIR_md6blV8,7844
|
6
|
+
panther/background_tasks.py,sha256=A__lY4IijGbRD9GKtbUK_c8cChtFW0jPaxoQHJ25bsk,7539
|
7
|
+
panther/base_request.py,sha256=MkzTv_Si4scJFZgHRaZurwjN6KthrKf1aqIN8u811z0,4950
|
8
|
+
panther/base_websocket.py,sha256=tCazsv5ILt-8wqYfsRB0NwXUIb-_wdeSTEBt3xjbneg,11000
|
9
|
+
panther/caching.py,sha256=nNyY6rZ9fnvsH44pk4eNaLuBYBDKw5CV6HC-7FAn6zM,2288
|
10
|
+
panther/configs.py,sha256=Hg-4B9mD4QL5aALEd7NJ8bTMikJWS1dhVtKe0n42Buc,3834
|
11
|
+
panther/events.py,sha256=-AFsJwZe9RpQ9xQQArUfqCPjv4ZRaFZ0shzTuO5WmWc,1576
|
12
|
+
panther/exceptions.py,sha256=QubEyGPnKlo4e7dR_SU2JbRB20vZ42LcUH3JvmOK5Xg,2231
|
13
|
+
panther/file_handler.py,sha256=6zXe36eaCyqtZFX2bMT9xl8tjimoHMcD7csLoPx_8EA,1323
|
14
|
+
panther/generics.py,sha256=v66yp6-jNdXh7EW5U-1g_f0zrp8_KaGr6OcbXsYbuzM,7318
|
15
|
+
panther/logging.py,sha256=g-RUuyCveqdMrEQXWIjIPZi2jYCJmOmZV8TvD_uMrEU,2075
|
16
|
+
panther/main.py,sha256=0i5HoJ4IGY2bF25lK1V6x7_f-boxceVz6zLj6Q6vTi8,7557
|
17
|
+
panther/pagination.py,sha256=bQEpf-FMil6zOwGuGD6VEowht2_13sT5jl-Cflwo_-E,1644
|
18
|
+
panther/permissions.py,sha256=UdPHVZYLWIYaf94OauE1QdVlj66_iE8B3rb336MBBcU,400
|
19
|
+
panther/request.py,sha256=IVuDdLdceCzo2vmICnWwoD2ag1eNc09C5XHZnULQxUw,1888
|
20
|
+
panther/response.py,sha256=k8ZQ6BIKuLc3vRRfSunm7twGixD6145ByWloSAqOrQQ,10495
|
21
|
+
panther/routings.py,sha256=QwE7EyQD1wdgXS8JK80tV36tIrrBR7fRZ1OkhpA8m7s,6482
|
22
|
+
panther/serializer.py,sha256=SrVROW9HyZS2QZDwlcrs_5npByIk-4bijm6_vAj2M24,9064
|
23
|
+
panther/status.py,sha256=Gc_PnYrHfInTsZpGbqiCfDB-py1C7Rh8KMdb6Lq9Exs,3346
|
24
|
+
panther/test.py,sha256=EReFLKhDtOoGQVTPSdtI31xi-u4SfwirA179G9_rIAE,7374
|
25
|
+
panther/throttling.py,sha256=EnU9PtulAwNTxsheun-s-kjJ1YL3jgj0bpxe8jGowlQ,2630
|
26
|
+
panther/utils.py,sha256=H2DrUz62ULv9BA6XdSJbaArRZG1ZQoJZmaFMXBvq_4c,4252
|
27
|
+
panther/websocket.py,sha256=er44pGU3Zm-glj4imS5l1Qdk7WNc_3Jpq7SPkeApPlM,1532
|
28
|
+
panther/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
|
+
panther/cli/create_command.py,sha256=iIAzS8C8rFKQ1idVSR5SMYRHWcwK09EYEqIqcBiiVXQ,10336
|
30
|
+
panther/cli/main.py,sha256=xWFxu_9cbrzsxgrkj0SrT2QUny3GMgJJuuAzK2OnR_M,1518
|
31
|
+
panther/cli/monitor_command.py,sha256=1hhPZNXGzvl-XXM0wwJol4dUwVgX3d00r3oV1mvNcS0,4462
|
32
|
+
panther/cli/run_command.py,sha256=ZInQQGV-QaLS7XUEUPqP_3iR2Nrto9unaOvYAs3mF9M,356
|
33
|
+
panther/cli/template.py,sha256=C3jb6m_NQRzur-_DNtEKiptMYtxTvd5MNM1qIgpFMNA,5331
|
34
|
+
panther/cli/utils.py,sha256=SjqggWpgGVH_JiMNQFnXPWzoMYxIHI2p9WO3-c59wU4,5542
|
35
|
+
panther/db/__init__.py,sha256=w9lEL0vRqb18Qx_iUJipUR_fi5GQ5uVX0DWycx14x08,50
|
36
|
+
panther/db/connections.py,sha256=AJpl7qgPuUTqDvuGW6VkLPRhNwrgTVoIDak3i7uI4GY,3982
|
37
|
+
panther/db/cursor.py,sha256=glFyfVriOmluajlq77u7cKF2Gnmo6iF5qLqT63yeigg,1783
|
38
|
+
panther/db/models.py,sha256=6WvWb9NkxZz7Srw0YCdZeIDNZt68nSEkuOoazh-Efm0,3250
|
39
|
+
panther/db/utils.py,sha256=GiRQ4t9csEFKmGViej7dyfZaaiWMdTAQeWzdoCWTJac,1574
|
40
|
+
panther/db/queries/__init__.py,sha256=uF4gvBjLBJ-Yl3WLqoZEVNtHCVhFRKW3_Vi44pJxDNI,45
|
41
|
+
panther/db/queries/base_queries.py,sha256=GFPEvSV7SGAVpJFHiIkhfKBf0xkLsyXvmW7bRI88HOU,3738
|
42
|
+
panther/db/queries/mongodb_queries.py,sha256=FTWcJc5vDy163Pn-_vyeeRlljs8SOKlARQ_gi3AvBtc,13389
|
43
|
+
panther/db/queries/pantherdb_queries.py,sha256=GlRRFvbaeVR3x2dYqlQIvsWxAWUcPflZ2u6kuJYvSIM,4620
|
44
|
+
panther/db/queries/queries.py,sha256=nhjrFk02O-rLUZ5slS3jHZ9wnxPrFLmiAZLaeVePKiA,12408
|
45
|
+
panther/middlewares/__init__.py,sha256=8VXd-K3L0a5ZkGb-NUipn3K8wxWAVIiOM7fQrcm_dTM,87
|
46
|
+
panther/middlewares/base.py,sha256=V5PuuemMCrQslIBK-sER4YZGdSDMzRFhZHjRUiIkhbY,721
|
47
|
+
panther/middlewares/cors.py,sha256=g4ougecREr88wnBSHziCeIVyIUnP0rYEs4-Izbf8tBI,3032
|
48
|
+
panther/middlewares/monitoring.py,sha256=ebkk84be6cGnUxi0IETnzKoYsGC2O_4kAarZ1cRynnA,1487
|
49
|
+
panther/openapi/__init__.py,sha256=UAkcGDxOltOkZwx3vZjigwfHUdb4xnidC6e_Viezfv4,47
|
50
|
+
panther/openapi/urls.py,sha256=HrYkS2sPgiTB6JpRCZaAwOSrw9lWa8EsfGJXZsp0B_0,78
|
51
|
+
panther/openapi/utils.py,sha256=_wAhTbcXvtXTMGjOUGcKm9sjDfoNhUFFsxHdrlEmguI,6492
|
52
|
+
panther/openapi/views.py,sha256=sUhjY9odz2kT_Xzl7MAyC4ARDsvPLHrH8lzNTo_Zf5U,3405
|
53
|
+
panther/openapi/templates/openapi.html,sha256=VAaJytOBFuR1rvGXOxbXOoJlurbeAl-VuTZu7Hk6LLs,889
|
54
|
+
panther/panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
|
+
panther/panel/apis.py,sha256=0OWwiySdSinjYFVs6r97nVaSDO51DZ9f2VlEWAM87-E,2364
|
56
|
+
panther/panel/middlewares.py,sha256=xOYpIsy-fqc8OuieePLviUxmR6Tsu-kg3UtgerUKyHo,379
|
57
|
+
panther/panel/urls.py,sha256=10BEdB81sNSOxWKFdcAwA2AGV1ddgen4ntXcSk2nx6U,253
|
58
|
+
panther/panel/utils.py,sha256=hwHtRYiea8FNjLGhEAAyX7-1LlCSUV-4pHslG79PLCY,4258
|
59
|
+
panther/panel/views.py,sha256=go7qQwRliKOiYcQ2uJUluTRNqUh9q7KmuXc4y1eH8Q8,5040
|
60
|
+
panther/panel/templates/base.html,sha256=kHDzfmlIf14eLrZHymIHdywr36W7cJXKtqFpVhw-x34,327
|
61
|
+
panther/panel/templates/create.html,sha256=2cKjWpNElv390PPYzoI7MGqVjgy9692x3vpxwAJE7GE,581
|
62
|
+
panther/panel/templates/create.js,sha256=zO_GfaHnjVI25zx4wGhUPA7aEkCukKMpabJfuiOib7c,40180
|
63
|
+
panther/panel/templates/detail.html,sha256=wFuePktVNchECgPhMxlXjX_KH3tqQvVsTTUmtOWsqjA,1490
|
64
|
+
panther/panel/templates/home.html,sha256=vSVHoCWeqY4AhQiC-UVAvu10m2bINneO6_PLyOS9R4Q,238
|
65
|
+
panther/panel/templates/home.js,sha256=bC8io0iKdAftSvrapkwx7ZPAbVq3UzapV9sv5uWa8FY,849
|
66
|
+
panther/panel/templates/login.html,sha256=W6V1rgHAno7yTbP6Il38ZvJp4LdlJ8BjM4UuyPkjaTA,1625
|
67
|
+
panther/panel/templates/sidebar.html,sha256=XikovZsJrth0nvKogvZoh3Eb2Bq7xdeGTlsdlyud450,618
|
68
|
+
panther/panel/templates/table.html,sha256=fWdaIHEHAuwuPaAfOtXkD-3yvSocyDmtys00_D2yRh8,2176
|
69
|
+
panther/panel/templates/table.js,sha256=MTdf77571Gtmg4l8HkY-5fM-utIL3lc0O8hv6vLBCYk,10414
|
70
|
+
panther-5.0.0b4.dist-info/licenses/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
|
71
|
+
panther-5.0.0b4.dist-info/METADATA,sha256=2NiQy6W9FrVHUevwkWiTVcoJGUy7Z5dT_iKPKjZN7bI,7026
|
72
|
+
panther-5.0.0b4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
73
|
+
panther-5.0.0b4.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
|
74
|
+
panther-5.0.0b4.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
|
75
|
+
panther-5.0.0b4.dist-info/RECORD,,
|
panther/monitoring.py
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
from time import perf_counter
|
3
|
-
from typing import Literal
|
4
|
-
|
5
|
-
from panther.base_request import BaseRequest
|
6
|
-
from panther.configs import config
|
7
|
-
|
8
|
-
logger = logging.getLogger('monitoring')
|
9
|
-
|
10
|
-
|
11
|
-
class Monitoring:
|
12
|
-
"""
|
13
|
-
Create Log Message Like Below:
|
14
|
-
date_time | method | path | ip:port | response_time(seconds) | status
|
15
|
-
"""
|
16
|
-
def __init__(self, is_ws: bool = False):
|
17
|
-
self.is_ws = is_ws
|
18
|
-
|
19
|
-
async def before(self, request: BaseRequest):
|
20
|
-
if config.MONITORING:
|
21
|
-
ip, port = request.client
|
22
|
-
|
23
|
-
if self.is_ws:
|
24
|
-
method = 'WS'
|
25
|
-
else:
|
26
|
-
method = request.scope['method']
|
27
|
-
|
28
|
-
self.log = f'{method} | {request.path} | {ip}:{port}'
|
29
|
-
self.start_time = perf_counter()
|
30
|
-
|
31
|
-
async def after(self, status: int | Literal['Accepted', 'Rejected', 'Closed'], /):
|
32
|
-
if config.MONITORING:
|
33
|
-
response_time = perf_counter() - self.start_time # Seconds
|
34
|
-
logger.info(f'{self.log} | {response_time} | {status}')
|
panther-5.0.0b2.dist-info/RECORD
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
panther/__init__.py,sha256=EN8vI-Orve2wCHyNc_rtgpC7s2UUCP2lWlN3nc3w3Oc,115
|
2
|
-
panther/_load_configs.py,sha256=1mMZeULMIgCxuPIXjNCdMPpqpjBm_rf4IgiD7Zk5MWs,10964
|
3
|
-
panther/_utils.py,sha256=nJK4QdTB9SmcVoRKy3hRvcdvceVGlBQ-MQG38j1BLc8,4130
|
4
|
-
panther/app.py,sha256=x8UsN3Ct2LfnvyXHkX_yIimBV73W19sL5xxF3RSRaMw,11074
|
5
|
-
panther/authentications.py,sha256=LK-4fESiGnot2kwxg5qm5RXTOOcqOnMTQ-HL4UBtc0g,6259
|
6
|
-
panther/background_tasks.py,sha256=HBYubDIiO_673cl_5fqCUP9zzimzRgRkDSkag9Msnbs,7656
|
7
|
-
panther/base_request.py,sha256=j87aeRFlR8Ix8Nrl0vehuL9QTkKtx7IVG8euUwGXh6U,4606
|
8
|
-
panther/base_websocket.py,sha256=tqdbDwCJmyonUNAp5-XeIcjxZjALfDwviAbYKU6mY24,11003
|
9
|
-
panther/caching.py,sha256=0UWg2xlTkyTKcf6rMjf-oZIE_kJWpPfpKKaDOCZxazg,4299
|
10
|
-
panther/configs.py,sha256=Ge2GlMxkG9UY5ySp_7hvXy_kV6_ipHv1uKoL_L3Tntc,3408
|
11
|
-
panther/events.py,sha256=tJvqkUA_Zs-tO_6ZpBmP_KkreFeM70fX8A7V6bCJUsU,1360
|
12
|
-
panther/exceptions.py,sha256=UEwpIIG57zNEm2CouU5Bi_mSUWYNEXi2FKqhjhMc4js,2288
|
13
|
-
panther/file_handler.py,sha256=I94tpbtTVniBnnUMkFr3Eis6kPDt8sLzS5u8TzFrR5I,1323
|
14
|
-
panther/generics.py,sha256=NVq43L8rz1jtMYD66O3p0DR295fiiongjq8bPIqBLeE,7261
|
15
|
-
panther/logging.py,sha256=SGgF9faQM1QmbmMPVc6m1DY-TbV329kTD8BuzGLx3I0,2073
|
16
|
-
panther/main.py,sha256=aEDGWjOe2rABEYyEkPGKLt4m45lJM6hEOGKYCiEHxk8,7599
|
17
|
-
panther/monitoring.py,sha256=C0tYBKGci6QR33CN-MixMzCP24ka0a6V0AU2H1sS4HU,1026
|
18
|
-
panther/pagination.py,sha256=VvvNsMObIarjUx9F8T91TX-9A2Ymy18Ms_hB60lZdEA,1641
|
19
|
-
panther/permissions.py,sha256=9-J5vzvEKa_PITwEVQbZZv8PG2FOu05YBlD5yMrKcfc,348
|
20
|
-
panther/request.py,sha256=Ho2tKvwZSKA4_sklZQNE9hjFuVrbt0O5R6sZ1HtCfI0,1861
|
21
|
-
panther/response.py,sha256=Wq90Tt6Bt0NLi6QDXwkdovqR2cvz2_SqmGTRIKFDbos,9958
|
22
|
-
panther/routings.py,sha256=Hcug2JZXwqR44PDSgkvG9v2dUgSNDJEIbm8E7t4Q72U,6414
|
23
|
-
panther/serializer.py,sha256=R5U9H75QRbyCq_CI_i9STlnAKit-DDEPH6-AZ2RyDmA,9085
|
24
|
-
panther/status.py,sha256=Gc_PnYrHfInTsZpGbqiCfDB-py1C7Rh8KMdb6Lq9Exs,3346
|
25
|
-
panther/test.py,sha256=RsQtP5IURLWR__BihOjruWoX3NscmGDqDqj1CfAb3bI,7037
|
26
|
-
panther/throttling.py,sha256=mVa_mGv6w_Ad7LLtV4eG5QpDwwNsk4QjFFi0mIHQBnE,231
|
27
|
-
panther/utils.py,sha256=92t9NFjzdswN133utDc2ovPgOZzqy_nF4bbrb5DDuY0,4307
|
28
|
-
panther/websocket.py,sha256=er44pGU3Zm-glj4imS5l1Qdk7WNc_3Jpq7SPkeApPlM,1532
|
29
|
-
panther/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
|
-
panther/cli/create_command.py,sha256=3_2xGWzJjdhCCgQHYvn7ikCl12wqTw6jT_Pu2EvfZWc,10344
|
31
|
-
panther/cli/main.py,sha256=XvkKMJsi-wvWO7GJsDQng7RShK8UnnKICu3c1H9OFNY,1517
|
32
|
-
panther/cli/monitor_command.py,sha256=ga8-6shrq0cz3Lo6ueSPZuetkLFdypesVO6fVQE01KM,4219
|
33
|
-
panther/cli/run_command.py,sha256=yWcDoWC-c4ph4M5EDj0jvR9xSjh-apG5r6-NpDdArUo,2195
|
34
|
-
panther/cli/template.py,sha256=ZIU4hLy9aNGCtUMt0LS8zoUf6daYQrLDteN-iLkIWTI,5349
|
35
|
-
panther/cli/utils.py,sha256=84W0bS-FPoJf3BsgOei2OBeoflcxXwy99Gft0ujF1Ss,5355
|
36
|
-
panther/db/__init__.py,sha256=w9lEL0vRqb18Qx_iUJipUR_fi5GQ5uVX0DWycx14x08,50
|
37
|
-
panther/db/connections.py,sha256=8QHQ_tmni4gfLHQCR7jmBFfvFgJCOrTQXdQiDRJRuv0,4205
|
38
|
-
panther/db/cursor.py,sha256=EvjVyOIkg_uynX5vCpVFpAzAw0Yb_R0II8mKgqBN_7c,1784
|
39
|
-
panther/db/models.py,sha256=gmqWjqbDE6DggTmUnqAipi9l0JfmDgiXttr9qCKK208,2793
|
40
|
-
panther/db/utils.py,sha256=ZZa3TMkuRtssl5ZRItFLonyxvMFsTq4fmTD4BblhLDA,1589
|
41
|
-
panther/db/queries/__init__.py,sha256=uF4gvBjLBJ-Yl3WLqoZEVNtHCVhFRKW3_Vi44pJxDNI,45
|
42
|
-
panther/db/queries/base_queries.py,sha256=GG3F9qFrIl6ibzvbjfDonztJvkUbjzPYHo8PNcdcj-0,3775
|
43
|
-
panther/db/queries/mongodb_queries.py,sha256=QCP1ibnd-x8js8XIC4nhgdfiJAj1606CkpSQ_-j2y8Y,13394
|
44
|
-
panther/db/queries/pantherdb_queries.py,sha256=h6LNsEk7srJw-dpqTl46ZSAO5BLFGVymQ4JnU75B4zM,4611
|
45
|
-
panther/db/queries/queries.py,sha256=sTa0m9q8tf2ugbFDmj4GRfRQOyNFmSBFfDqIVcRjKIM,12433
|
46
|
-
panther/middlewares/__init__.py,sha256=8VXd-K3L0a5ZkGb-NUipn3K8wxWAVIiOM7fQrcm_dTM,87
|
47
|
-
panther/middlewares/base.py,sha256=V5PuuemMCrQslIBK-sER4YZGdSDMzRFhZHjRUiIkhbY,721
|
48
|
-
panther/middlewares/monitoring.py,sha256=pxbRiM20grCNyAJZwouAOe3gLbdveSObStJF5WdCFyA,1486
|
49
|
-
panther/openapi/__init__.py,sha256=UAkcGDxOltOkZwx3vZjigwfHUdb4xnidC6e_Viezfv4,47
|
50
|
-
panther/openapi/urls.py,sha256=99f7hx_z65Vw6p9Kg-Vz5hU9_FlIhJeVnA1-CPm1TTI,70
|
51
|
-
panther/openapi/utils.py,sha256=YxBA9HUShgoH0MphW27xL_qS0uIA0gQsh705hxnJlYE,6504
|
52
|
-
panther/openapi/views.py,sha256=5B1BifNeUojLVs3ygk7KOEjUSnsMllslSdFgsPgd8yA,3908
|
53
|
-
panther/openapi/templates/openapi.html,sha256=VAaJytOBFuR1rvGXOxbXOoJlurbeAl-VuTZu7Hk6LLs,889
|
54
|
-
panther/panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
|
-
panther/panel/apis.py,sha256=COsbwKZyTgyHvHYbpDfusifAH9ojMS3z1KhZCt9M-Ms,2428
|
56
|
-
panther/panel/middlewares.py,sha256=xOYpIsy-fqc8OuieePLviUxmR6Tsu-kg3UtgerUKyHo,379
|
57
|
-
panther/panel/urls.py,sha256=xLEy1qA4MWOLApkecyz1FxDefNthOUCqYft5XsctKys,387
|
58
|
-
panther/panel/utils.py,sha256=UFDPmST-c5T-pa5bg4wBIzZMgQIgAqervL4ojOeofq8,4219
|
59
|
-
panther/panel/views.py,sha256=VnmKwkiuBgbIIFsqAqcqfOn8S5N837Y1TUH_2U6PkXs,5148
|
60
|
-
panther/panel/templates/base.html,sha256=kHDzfmlIf14eLrZHymIHdywr36W7cJXKtqFpVhw-x34,327
|
61
|
-
panther/panel/templates/create.html,sha256=2cKjWpNElv390PPYzoI7MGqVjgy9692x3vpxwAJE7GE,581
|
62
|
-
panther/panel/templates/create.js,sha256=zO_GfaHnjVI25zx4wGhUPA7aEkCukKMpabJfuiOib7c,40180
|
63
|
-
panther/panel/templates/detail.html,sha256=wFuePktVNchECgPhMxlXjX_KH3tqQvVsTTUmtOWsqjA,1490
|
64
|
-
panther/panel/templates/home.html,sha256=vSVHoCWeqY4AhQiC-UVAvu10m2bINneO6_PLyOS9R4Q,238
|
65
|
-
panther/panel/templates/home.js,sha256=bC8io0iKdAftSvrapkwx7ZPAbVq3UzapV9sv5uWa8FY,849
|
66
|
-
panther/panel/templates/login.html,sha256=W6V1rgHAno7yTbP6Il38ZvJp4LdlJ8BjM4UuyPkjaTA,1625
|
67
|
-
panther/panel/templates/sidebar.html,sha256=XikovZsJrth0nvKogvZoh3Eb2Bq7xdeGTlsdlyud450,618
|
68
|
-
panther/panel/templates/table.html,sha256=fWdaIHEHAuwuPaAfOtXkD-3yvSocyDmtys00_D2yRh8,2176
|
69
|
-
panther/panel/templates/table.js,sha256=MTdf77571Gtmg4l8HkY-5fM-utIL3lc0O8hv6vLBCYk,10414
|
70
|
-
panther-5.0.0b2.dist-info/licenses/LICENSE,sha256=2aF1hL2aC0zRPjzUkSxJUzZbn2_uLoOkn7DHjzZni-I,1524
|
71
|
-
panther-5.0.0b2.dist-info/METADATA,sha256=2vCEzF7CRa35QMey3KB_c1tV5edvWU3oOwq2sa6b3hw,7026
|
72
|
-
panther-5.0.0b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
73
|
-
panther-5.0.0b2.dist-info/entry_points.txt,sha256=6GPxYFGuzVfNB4YpHFJvYex6iWah5_tLnirAHwj2Qsg,51
|
74
|
-
panther-5.0.0b2.dist-info/top_level.txt,sha256=VbBs02JGXTIoHMzsX-eLOk2MCbBZzQbLhWiYpI7xI2g,8
|
75
|
-
panther-5.0.0b2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|