diff --git a/docs/docs/configs.md b/docs/docs/configs.md index 7961a051..f4b5562b 100644 --- a/docs/docs/configs.md +++ b/docs/docs/configs.md @@ -100,3 +100,15 @@ It should be dotted address of your `shutdown` function this function can be `sync` or `async` _Example:_ `URLS = 'core.configs.shutdown'` + +--- +### [AUTO_REFORMAT](https://pantherpy.github.io/auto_reformat) +> Type: `bool` (Default: `False`) + +It will reformat your code on every reload (on every change if you run the project with `--reload`) + +You may want to write your custom `ruff.toml` in root of your project. + +Reference: [https://docs.astral.sh/ruff/formatter/](https://docs.astral.sh/ruff/formatter/) + +_Example:_ `AUTO_REFORMAT = True` diff --git a/docs/docs/release_notes.md b/docs/docs/release_notes.md index 0be78389..d7f0dcd1 100644 --- a/docs/docs/release_notes.md +++ b/docs/docs/release_notes.md @@ -1,3 +1,6 @@ +### 3.3.0 +- Add Auto Reformat Code + ### 3.2.4 - Add all() query - Add tests for `pantherdb`, `load_configs()`, `status.py`, `Panel`, `multipart`, `request headers` @@ -5,9 +8,6 @@ - Check `uvloop` installation on `Panther init` - Minor Improvement -### 3.2.1 -- Minor Improvement - ### 3.2.1 - Move `Startup` to `__call__` diff --git a/example/app/apis.py b/example/app/apis.py index c9c6b896..0884dc41 100644 --- a/example/app/apis.py +++ b/example/app/apis.py @@ -5,24 +5,23 @@ from app.models import User from app.serializers import ( FileSerializer, + ImageSerializer, UserInputSerializer, UserOutputSerializer, UserUpdateSerializer, - ImageSerializer, ) from core.permissions import UserPermission from panther import status from panther.app import API, GenericAPI from panther.authentications import JWTAuthentication -from panther.background_tasks import background_tasks, BackgroundTask +from panther.background_tasks import BackgroundTask, background_tasks from panther.db.connection import redis from panther.request import Request from panther.response import HTMLResponse, Response from panther.throttling import Throttling from panther.websocket import close_websocket_connection, send_message_to_websocket - logger = logging.getLogger('panther') @@ -173,10 +172,9 @@ async def run_background_tasks_api(): async def hello(name: str): time.sleep(5) print(f'Done {name}') + task = ( - BackgroundTask(hello, 'ali1') - .interval(2) - .every_seconds(2) + BackgroundTask(hello, 'ali1').interval(2).every_seconds(2) # .on_time(datetime.time(hour=19, minute=18, second=10)) ) background_tasks.add_task(task) diff --git a/example/app/urls.py b/example/app/urls.py index 90ffe69a..e4987447 100644 --- a/example/app/urls.py +++ b/example/app/urls.py @@ -9,6 +9,7 @@ async def test(*args, **kwargs): return Response(data={'detail': 'this is for test'}) + urls = { 'none-class/': ReturnNone, 'none/': return_none, diff --git a/example/core/configs.py b/example/core/configs.py index 534ae912..51dcc6a2 100644 --- a/example/core/configs.py +++ b/example/core/configs.py @@ -57,12 +57,14 @@ async def startup(): - print('inside startup function') + print('Starting Up') async def shutdown(): - print('inside shutdown function') + print('Shutting Down') STARTUP = 'core.configs.startup' SHUTDOWN = 'core.configs.shutdown' + +AUTO_REFORMAT = True diff --git a/example/single_file_example.py b/example/single_file_example.py index a658e2f0..d9228883 100644 --- a/example/single_file_example.py +++ b/example/single_file_example.py @@ -6,17 +6,18 @@ async def hello_world_api(): return {'detail': 'Hello World'} + url_routing = { '/': hello_world_api, } def startup(): - print("Its startup") + print('Its startup') def shutdown(): - print("Its shutdown") + print('Its shutdown') app = Panther(__name__, configs=__name__, urls=url_routing, startup=startup, shutdown=shutdown) diff --git a/panther/__init__.py b/panther/__init__.py index d3b1f361..459cee86 100644 --- a/panther/__init__.py +++ b/panther/__init__.py @@ -1,6 +1,6 @@ from panther.main import Panther # noqa: F401 -__version__ = '3.2.5' +__version__ = '3.3.0' def version(): diff --git a/panther/_load_configs.py b/panther/_load_configs.py index 6364454b..06a8d0c7 100644 --- a/panther/_load_configs.py +++ b/panther/_load_configs.py @@ -28,6 +28,7 @@ 'load_jwt_config', 'load_startup', 'load_shutdown', + 'load_auto_reformat', 'collect_all_models', 'load_urls', 'load_panel_urls', @@ -133,6 +134,10 @@ def load_shutdown(configs: dict, /) -> Callable: return configs.get('SHUTDOWN') and import_class(configs['SHUTDOWN']) +def load_auto_reformat(configs: dict, /) -> bool: + return configs.get('AUTO_REFORMAT', config['auto_reformat']) + + def collect_all_models() -> list[dict]: """Collecting all models for panel APIs""" from panther.db.models import Model diff --git a/panther/configs.py b/panther/configs.py index dbd4dd59..46c1d439 100644 --- a/panther/configs.py +++ b/panther/configs.py @@ -49,6 +49,7 @@ class Config(TypedDict): has_ws: bool startup: Callable shutdown: Callable + auto_reformat: bool config: Config = { @@ -72,4 +73,5 @@ class Config(TypedDict): 'has_ws': False, 'startup': None, 'shutdown': None, + 'auto_reformat': False, } diff --git a/panther/main.py b/panther/main.py index 9194a439..b632f57b 100644 --- a/panther/main.py +++ b/panther/main.py @@ -1,6 +1,7 @@ import asyncio import contextlib import logging +import subprocess import sys import types from collections.abc import Callable @@ -44,6 +45,9 @@ def __init__(self, name: str, configs=None, urls: dict | None = None, startup: C logger.error(clean_traceback_message(e)) sys.exit() + # Reformat Code + self.reformat_code() + # Monitoring self.monitoring = Monitoring(is_active=config['monitoring']) @@ -77,6 +81,7 @@ def load_configs(self) -> None: config['jwt_config'] = load_jwt_config(self._configs_module) config['startup'] = load_startup(self._configs_module) config['shutdown'] = load_shutdown(self._configs_module) + config['auto_reformat'] = load_auto_reformat(self._configs_module) config['models'] = collect_all_models() # Initialize Background Tasks @@ -113,6 +118,12 @@ def _create_ws_connections_instance(self): else: self.ws_redis_connection = None + @classmethod + def reformat_code(cls): + if config['auto_reformat']: + subprocess.run(['ruff', 'format', config['base_dir']]) + subprocess.run(['ruff', 'check', '--select', 'I', '--fix', config['base_dir']]) + async def __call__(self, scope: dict, receive: Callable, send: Callable) -> None: """ 1.