Skip to content

Commit

Permalink
Improvement 3.2.4 #52
Browse files Browse the repository at this point in the history
-  Add `all()` query
- Add tests for `pantherdb`, `_load_configs.py`, `status.py`, `Panel`, `multipart`, `request headers`
- Refactor `Headers()` class
- Check `uvloop` installation on `Panther init`
  • Loading branch information
AliRn76 committed Dec 23, 2023
2 parents 376c6aa + 6bddbdf commit 68cb564
Show file tree
Hide file tree
Showing 28 changed files with 1,462 additions and 568 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ jobs:
runs-on: windows-latest
needs: [tests-linux]
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12']

Expand All @@ -62,20 +61,21 @@ jobs:
python -m unittest .\tests\test_caching.py
python -m unittest .\tests\test_cli.py
python -m unittest .\tests\test_mongodb.py
python -m unittest .\tests\multipart.py
python -m unittest .\tests\panel_apis.py
python -m unittest .\tests\test_pantherdb.py
python -m unittest .\tests\test_request_methods.py
python -m unittest .\tests\test_request.py
python -m unittest .\tests\test_routing.py
python -m unittest .\tests\test_run.py
python -m unittest .\tests\test_simple_requests.py
python -m unittest .\tests\test_simple_responses.py
python -m unittest .\tests\test_status.py
python -m unittest .\tests\test_utils.py
tests-macos:
name: Test MacOS Python${{ matrix.python-version }}
runs-on: macos-latest
needs: [tests-linux]
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12']

Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ logs/
build/
*.pdb
.ruff_cache/
docs/site/*
docs/site/*
*coverage*
16 changes: 16 additions & 0 deletions docs/docs/panther_odm.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
users: list[User] = User.find({'id': 1}, name='Ali')
```

### all
- List all the documents
- Example:

```python
users: list[User] = User.all()
```

### insert_one
- Insert only one document into database
- Example:
Expand Down Expand Up @@ -128,3 +136,11 @@ and pass the fields you want to update as `kwargs` or another `dictionary` as `s
```python
user: User = User.find_or_insert(name='Ali')
```

### find_one_or_raise
- Find the match document or Raise an `APIException`
- Example:

```python
user: User = User.find_one_or_raise(name='Ali')
```
7 changes: 7 additions & 0 deletions docs/docs/release_notes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
### 3.2.4
- Add all() query
- Add tests for `pantherdb`, `load_configs()`, `status.py`, `Panel`, `multipart`, `request headers`
- Refactor `Headers()` class
- Check `uvloop` installation on `Panther init`
- Minor Improvement

### 3.2.1
- Minor Improvement

Expand Down
2 changes: 1 addition & 1 deletion panther/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from panther.main import Panther # noqa: F401

__version__ = '3.2.3'
__version__ = '3.2.4'


def version():
Expand Down
19 changes: 16 additions & 3 deletions panther/_load_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,28 @@ def load_middlewares(configs: dict, /) -> list:

middlewares = []

for path, data in configs.get('MIDDLEWARES', []):
for middleware in configs.get('MIDDLEWARES') or []:
if not isinstance(middleware, list | tuple):
raise _exception_handler(field='MIDDLEWARES', error=f'{middleware} should have 2 part: (path, kwargs)')

if len(middleware) == 1:
path = middleware[0]
data = {}

elif len(middleware) > 2:
raise _exception_handler(field='MIDDLEWARES', error=f'{middleware} too many arguments')

else:
path, data = middleware

if path.find('panther.middlewares.db.DatabaseMiddleware') != -1:
config['db_engine'] = data['url'].split(':')[0]
try:
Middleware = import_class(path) # noqa: N806
except AttributeError:
except (AttributeError, ModuleNotFoundError):
raise _exception_handler(field='MIDDLEWARES', error=f'{path} is not a valid middleware path')

if not issubclass(Middleware, BaseMiddleware):
if issubclass(Middleware, BaseMiddleware) is False:
raise _exception_handler(field='MIDDLEWARES', error='is not a sub class of BaseMiddleware')

middlewares.append(Middleware(**data)) # noqa: Py Argument List
Expand Down
2 changes: 1 addition & 1 deletion panther/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def clean_traceback_message(exception: Exception) -> str:
tb = TracebackException(type(exception), exception, exception.__traceback__)
stack = tb.stack.copy()
for t in stack:
if t.filename.find('site-packages') != -1:
if t.filename.find('site-packages/panther') != -1:
tb.stack.remove(t)
_traceback = list(tb.format(chain=False))
return exception if len(_traceback) == 1 else f'{exception}\n' + ''.join(_traceback)
62 changes: 41 additions & 21 deletions panther/base_request.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,54 @@
from collections import namedtuple
from collections.abc import Callable
from dataclasses import dataclass


@dataclass(frozen=True)
class Headers:
accept: str
accept_encoding: str
content_length: int
accept_language: str
authorization: str
content_type: str
user_agent: str
cache_control: str
connection: str
accept: str
content_length: str
content_type: str
host: str
origin: str
pragma: str
referer: str
sec_fetch_dest: str
sec_fetch_mode: str
sec_fetch_site: str
user_agent: str

sec_websocket_version: int
sec_websocket_key: str
upgrade: str
sec_websocket_version: str
sec_websocket_key: str

def __init__(self, headers):
self.__headers = headers
self.__pythonic_headers = {k.lower().replace('-', '_'): v for k, v in headers.items()}

def __getattr__(self, item: str):
if result := self.__pythonic_headers.get(item):
return result
else:
return self.__headers.get(item)

def __getitem__(self, item: str):
if result := self.__headers.get(item):
return result
else:
return self.__pythonic_headers.get(item)

def __str__(self):
items = ', '.join(f'{k}={v}' for k, v in self.__headers.items())
return f'Headers({items})'

__repr__ = __str__

@property
def __dict__(self):
return self.__headers


Address = namedtuple('Client', ['ip', 'port'])
Expand All @@ -37,19 +69,7 @@ def __init__(self, scope: dict, receive: Callable, send: Callable):
def headers(self) -> Headers:
_headers = {header[0].decode('utf-8'): header[1].decode('utf-8') for header in self.scope['headers']}
if self._headers is None:
self._headers = Headers(
accept_encoding=_headers.pop('accept-encoding', None),
content_length=_headers.pop('content_length', None),
authorization=_headers.pop('authorization', None),
content_type=_headers.pop('content-type', None),
user_agent=_headers.pop('user-agent', None),
connection=_headers.pop('connection', None),
accept=_headers.pop('accept', None),
host=_headers.pop('host', None),
sec_websocket_version=_headers.pop('sec_websocket_version', None),
sec_websocket_key=_headers.pop('sec_websocket_key', None),
upgrade=_headers.pop('upgrade', None),
)
self._headers = Headers(_headers)
return self._headers

@property
Expand Down
42 changes: 29 additions & 13 deletions panther/cli/create_command.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import platform
import sys
import time
from pathlib import Path
Expand Down Expand Up @@ -68,19 +69,34 @@ def check_all_directories(base_directory: str) -> str | None:


def load_animation() -> None:
animation = [
'■□□□□□□□□□□',
'■■□□□□□□□□□',
'■■■□□□□□□□□',
'■■■■□□□□□□□',
'■■■■■□□□□□□',
'■■■■■■□□□□□',
'■■■■■■■□□□□',
'■■■■■■■■□□□',
'■■■■■■■■■□□',
'■■■■■■■■■■□',
'■■■■■■■■■■■',
]
if platform.system() == 'Windows':
animation = [
'*0000000000',
'**000000000',
'***00000000',
'****0000000',
'*****000000',
'******00000',
'*******0000',
'********000',
'*********00',
'**********0',
'***********',
]
else:
animation = [
'■□□□□□□□□□□',
'■■□□□□□□□□□',
'■■■□□□□□□□□',
'■■■■□□□□□□□',
'■■■■■□□□□□□',
'■■■■■■□□□□□',
'■■■■■■■□□□□',
'■■■■■■■■□□□',
'■■■■■■■■■□□',
'■■■■■■■■■■□',
'■■■■■■■■■■■',
]

for i in range(len(animation)):
time.sleep(0.2)
Expand Down
43 changes: 19 additions & 24 deletions panther/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from panther.cli.create_command import create
from panther.cli.monitor_command import monitor
from panther.cli.run_command import run
from panther.cli.utils import clean_args, cli_error, cli_info, cli_warning, print_help_message
from panther.cli.utils import cli_error, cli_info, cli_warning, print_help_message


def shell(args: list) -> None:
Expand All @@ -24,7 +24,7 @@ def shell(args: list) -> None:
import bpython
os.system('bpython')
except ImportError as e:
cli_warning(e, 'Hint: "pip install ipython"')
cli_warning(e, 'Hint: "pip install bpython"')
os.system('python')

# Ipython
Expand All @@ -33,7 +33,7 @@ def shell(args: list) -> None:
import IPython
os.system('ipython')
except ImportError as e:
cli_warning(e, 'Hint: "pip install bpython"')
cli_warning(e, 'Hint: "pip install ipython"')
os.system('python')


Expand All @@ -42,24 +42,19 @@ def version() -> None:


def start() -> None:
if len(sys.argv) < 2:
cli_error('Please pass some arguments to the command.')
else:
command = sys.argv and sys.argv[1] or None
args = clean_args(sys.argv[2:])

match command:
case '-h' | '--help':
print_help_message()
case 'create':
create(sys.argv[2:])
case 'run':
run(args)
case 'shell':
shell(sys.argv[2:])
case 'monitor':
monitor()
case 'version':
version()
case _:
cli_error('Invalid Arguments.')
args = sys.argv[2:]
match len(sys.argv) > 1 and sys.argv[1]:
case 'h' | 'help' | '-h' | '--help':
print_help_message()
case 'create':
create(args)
case 'run':
run(args)
case 'shell':
shell(args)
case 'monitor':
monitor()
case 'version':
version()
case _:
cli_error('Invalid Arguments.')
12 changes: 8 additions & 4 deletions panther/cli/run_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import uvicorn

from panther.cli.utils import print_uvicorn_help_message
from panther.cli.utils import print_uvicorn_help_message, clean_args, cli_error


def _handle_commands(args: dict[str, str | None]) -> dict:
Expand Down Expand Up @@ -65,12 +65,16 @@ def _handle_commands(args: dict[str, str | None]) -> dict:
return _command


def run(args: dict[str, str | None]) -> None:
def run(args: list[str]) -> None:
args = clean_args(args)

if any(a in args for a in ['h', 'help', '-h', '--help']):
print_uvicorn_help_message()
return
command = {'app_dir': os.getcwd()}
command.update(_handle_commands(args))
command.update(args)

uvicorn.run('main:app', **command)
try:
uvicorn.run('main:app', **command)
except TypeError as e:
cli_error(e)
Loading

0 comments on commit 68cb564

Please sign in to comment.