Skip to content

Commit

Permalink
Shorter Params Syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalik committed Oct 1, 2023
1 parent 631c8b9 commit 9cb132c
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 134 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/test_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,4 @@ jobs:
- name: Ruff
run: ruff ninja tests
- name: mypy
run: mypy ninja

run: mypy ninja tests/mypy_test.py
28 changes: 26 additions & 2 deletions ninja/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Django Ninja - Fast Django REST framework"""

__version__ = "1.0b1"
__version__ = "1.0b2"


from pydantic import Field
Expand All @@ -10,7 +10,23 @@
from ninja.main import NinjaAPI
from ninja.openapi.docs import Redoc, Swagger
from ninja.orm import ModelSchema
from ninja.params_functions import Body, Cookie, File, Form, Header, Path, Query
from ninja.params import (
Body,
BodyEx,
Cookie,
CookieEx,
File,
FileEx,
Form,
FormEx,
Header,
HeaderEx,
P,
Path,
PathEx,
Query,
QueryEx,
)
from ninja.router import Router
from ninja.schema import Schema

Expand All @@ -25,7 +41,15 @@
"Header",
"Path",
"Query",
"BodyEx",
"CookieEx",
"FileEx",
"FormEx",
"HeaderEx",
"PathEx",
"QueryEx",
"Router",
"P",
"Schema",
"ModelSchema",
"FilterSchema",
Expand Down
2 changes: 1 addition & 1 deletion ninja/openapi/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from ninja.constants import NOT_SET
from ninja.operation import Operation
from ninja.params_models import TModel, TModels
from ninja.params.models import TModel, TModels
from ninja.schema import NinjaGenerateJsonSchema
from ninja.types import DictStrAny
from ninja.utils import normalize_path
Expand Down
2 changes: 1 addition & 1 deletion ninja/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from ninja.compatibility.util import async_to_sync
from ninja.constants import NOT_SET
from ninja.errors import AuthenticationError, ConfigError, ValidationError
from ninja.params_models import TModels
from ninja.params.models import TModels
from ninja.schema import Schema
from ninja.signature import ViewSignature, is_async
from ninja.types import DictStrAny
Expand Down
105 changes: 0 additions & 105 deletions ninja/params.py

This file was deleted.

113 changes: 113 additions & 0 deletions ninja/params/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar

from typing_extensions import Annotated

from ninja.params import functions as param_functions

__all__ = [
"Body",
"Cookie",
"File",
"Form",
"Header",
"Path",
"Query",
"BodyEx",
"CookieEx",
"FileEx",
"FormEx",
"HeaderEx",
"PathEx",
"QueryEx",
"Router",
"P",
]


class ParamShortcut:
def __init__(self, base_func: Callable) -> None:
self._base_func = base_func

def __call__(self, *args: Any, **kwargs: Any) -> Any:
return self._base_func(*args, **kwargs)

def __getitem__(self, args: Any) -> Any:
if isinstance(args, tuple):
return Annotated[args[0], self._base_func(**args[1])]
return Annotated[args, self._base_func()]


if TYPE_CHECKING: # pragma: nocover
# mypy cheats
T = TypeVar("T")
Body = Annotated[T, param_functions.Body()]
Cookie = Annotated[T, param_functions.Cookie()]
File = Annotated[T, param_functions.File()]
Form = Annotated[T, param_functions.Form()]
Header = Annotated[T, param_functions.Header()]
Path = Annotated[T, param_functions.Path()]
Query = Annotated[T, param_functions.Query()]
# mypy does not like to extend already annotated params
# with extra annotation (so need to cheat with these XXX-Ex types):
from typing_extensions import Annotated as BodyEx
from typing_extensions import Annotated as CookieEx
from typing_extensions import Annotated as FileEx
from typing_extensions import Annotated as FormEx
from typing_extensions import Annotated as HeaderEx
from typing_extensions import Annotated as PathEx
from typing_extensions import Annotated as QueryEx
else:
Body = ParamShortcut(param_functions.Body)
Cookie = ParamShortcut(param_functions.Cookie)
File = ParamShortcut(param_functions.File)
Form = ParamShortcut(param_functions.Form)
Header = ParamShortcut(param_functions.Header)
Path = ParamShortcut(param_functions.Path)
Query = ParamShortcut(param_functions.Query)
# mypy does not like to extend already annotated params
# with extra annotation (so need to cheat with these XXX-Ex types):
BodyEx = Body
CookieEx = Cookie
FileEx = File
FormEx = Form
HeaderEx = Header
PathEx = Path
QueryEx = Query


def P(
*,
alias: Optional[str] = None,
title: Optional[str] = None,
description: Optional[str] = None,
gt: Optional[float] = None,
ge: Optional[float] = None,
lt: Optional[float] = None,
le: Optional[float] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = None,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
include_in_schema: bool = True,
**extra: Any,
) -> Dict[str, Any]:
"Arguments for BodyEx, QueryEx, etc."
return dict(
alias=alias,
title=title,
description=description,
gt=gt,
ge=ge,
lt=lt,
le=le,
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
deprecated=deprecated,
include_in_schema=include_in_schema,
**extra,
)
22 changes: 11 additions & 11 deletions ninja/params_functions.py → ninja/params/functions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Yeah, this is a bit strange
# but the whole point of this module is to make mypy and typehints happy
# what it basically does makes function XXX that create instance of params.XXX
# what it basically does makes function XXX that create instance of models.XXX
# and annotates function with result = Any
# idea from https://github.com/tiangolo/fastapi/blob/master/fastapi/param_functions.py
from typing import Any, Dict, Optional

from ninja import params
from ninja.params import models


def Path( # noqa: N802
Expand All @@ -27,8 +27,8 @@ def Path( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.Path(
default=default,
return models.Path(
default,
alias=alias,
title=title,
description=description,
Expand Down Expand Up @@ -66,8 +66,8 @@ def Query( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.Query(
default=default,
return models.Query(
default,
alias=alias,
title=title,
description=description,
Expand Down Expand Up @@ -105,7 +105,7 @@ def Header( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.Header(
return models.Header(
default,
alias=alias,
title=title,
Expand Down Expand Up @@ -144,7 +144,7 @@ def Cookie( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.Cookie(
return models.Cookie(
default,
alias=alias,
title=title,
Expand Down Expand Up @@ -183,7 +183,7 @@ def Body( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.Body(
return models.Body(
default,
alias=alias,
title=title,
Expand Down Expand Up @@ -222,7 +222,7 @@ def Form( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.Form(
return models.Form(
default,
alias=alias,
title=title,
Expand Down Expand Up @@ -261,7 +261,7 @@ def File( # noqa: N802
include_in_schema: bool = True,
**extra: Any,
) -> Any:
return params.File(
return models.File(
default,
alias=alias,
title=title,
Expand Down
Loading

0 comments on commit 9cb132c

Please sign in to comment.