From 7d98499e773cd758905f509a1314e9f2b88f96ce Mon Sep 17 00:00:00 2001 From: awtkns Date: Sun, 23 Jan 2022 13:22:30 -0800 Subject: [PATCH 1/3] :pencil2: Add Abstract anotation to base router --- fastapi_crudrouter/core/_base.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/fastapi_crudrouter/core/_base.py b/fastapi_crudrouter/core/_base.py index f6379e8..0908f85 100644 --- a/fastapi_crudrouter/core/_base.py +++ b/fastapi_crudrouter/core/_base.py @@ -1,3 +1,4 @@ +from abc import abstractmethod from typing import Any, Callable, Generic, List, Optional, Type, Union from fastapi import APIRouter, HTTPException @@ -176,23 +177,29 @@ def remove_api_route(self, path: str, methods: List[str]) -> None: ): self.routes.remove(route) + @abstractmethod def _get_all(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - raise NotImplementedError + pass + @abstractmethod def _get_one(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - raise NotImplementedError + pass + @abstractmethod def _create(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - raise NotImplementedError + pass + @abstractmethod def _update(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - raise NotImplementedError + pass + @abstractmethod def _delete_one(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - raise NotImplementedError + pass + @abstractmethod def _delete_all(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - raise NotImplementedError + pass def _raise(self, e: Exception, status_code: int = 422) -> HTTPException: raise HTTPException(422, ", ".join(e.args)) from e From 8aaa71f0a4c611a5c46264a83ade79ef296a08ea Mon Sep 17 00:00:00 2001 From: awtkns Date: Tue, 25 Jan 2022 23:17:25 -0800 Subject: [PATCH 2/3] :white_check_mark: Update Base Class Tests --- fastapi_crudrouter/core/_base.py | 12 ++++++------ tests/test_base.py | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fastapi_crudrouter/core/_base.py b/fastapi_crudrouter/core/_base.py index 0908f85..376d54e 100644 --- a/fastapi_crudrouter/core/_base.py +++ b/fastapi_crudrouter/core/_base.py @@ -179,27 +179,27 @@ def remove_api_route(self, path: str, methods: List[str]) -> None: @abstractmethod def _get_all(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - pass + raise NotImplementedError @abstractmethod def _get_one(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - pass + raise NotImplementedError @abstractmethod def _create(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - pass + raise NotImplementedError @abstractmethod def _update(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - pass + raise NotImplementedError @abstractmethod def _delete_one(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - pass + raise NotImplementedError @abstractmethod def _delete_all(self, *args: Any, **kwargs: Any) -> Callable[..., Any]: - pass + raise NotImplementedError def _raise(self, e: Exception, status_code: int = 422) -> HTTPException: raise HTTPException(422, ", ".join(e.args)) from e diff --git a/tests/test_base.py b/tests/test_base.py index 9d44667..ace1c40 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,15 +1,16 @@ import pytest from fastapi import APIRouter, FastAPI + from fastapi_crudrouter import ( GinoCRUDRouter, MemoryCRUDRouter, OrmarCRUDRouter, SQLAlchemyCRUDRouter, + DatabasesCRUDRouter, ) # noinspection PyProtectedMember from fastapi_crudrouter.core._base import CRUDGenerator - from tests import Potato @@ -19,9 +20,10 @@ def test_router_type(): assert issubclass(MemoryCRUDRouter, APIRouter) assert issubclass(OrmarCRUDRouter, APIRouter) assert issubclass(GinoCRUDRouter, APIRouter) + assert issubclass(DatabasesCRUDRouter, APIRouter) -def test_get_one(): +def test_raise_not_implemented(): app = FastAPI() def foo(*args, **kwargs): @@ -30,8 +32,6 @@ def bar(): return bar - foo()() - methods = CRUDGenerator.get_routes() for m in methods: From 2c18c90abf04b145f097da22044fa71e3ab3d52b Mon Sep 17 00:00:00 2001 From: awtkns Date: Wed, 26 Jan 2022 19:24:54 -0800 Subject: [PATCH 3/3] :white_check_mark: Make CRUDGenerator subclass ABC --- fastapi_crudrouter/core/_base.py | 4 ++-- fastapi_crudrouter/core/_utils.py | 2 +- tests/test_base.py | 38 +++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/fastapi_crudrouter/core/_base.py b/fastapi_crudrouter/core/_base.py index 376d54e..e45d33f 100644 --- a/fastapi_crudrouter/core/_base.py +++ b/fastapi_crudrouter/core/_base.py @@ -1,4 +1,4 @@ -from abc import abstractmethod +from abc import ABC, abstractmethod from typing import Any, Callable, Generic, List, Optional, Type, Union from fastapi import APIRouter, HTTPException @@ -10,7 +10,7 @@ NOT_FOUND = HTTPException(404, "Item not found") -class CRUDGenerator(Generic[T], APIRouter): +class CRUDGenerator(Generic[T], APIRouter, ABC): schema: Type[T] create_schema: Type[T] update_schema: Type[T] diff --git a/fastapi_crudrouter/core/_utils.py b/fastapi_crudrouter/core/_utils.py index 118047b..ef3562e 100644 --- a/fastapi_crudrouter/core/_utils.py +++ b/fastapi_crudrouter/core/_utils.py @@ -33,7 +33,7 @@ def schema_factory( } name = schema_cls.__name__ + name - schema = create_model(__model_name=name, **fields) # type: ignore + schema: Type[T] = create_model(__model_name=name, **fields) # type: ignore return schema diff --git a/tests/test_base.py b/tests/test_base.py index ace1c40..399ec14 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,3 +1,6 @@ +from abc import ABC +from typing import Type + import pytest from fastapi import APIRouter, FastAPI @@ -14,13 +17,30 @@ from tests import Potato -def test_router_type(): - assert issubclass(CRUDGenerator, APIRouter) - assert issubclass(SQLAlchemyCRUDRouter, APIRouter) - assert issubclass(MemoryCRUDRouter, APIRouter) - assert issubclass(OrmarCRUDRouter, APIRouter) - assert issubclass(GinoCRUDRouter, APIRouter) - assert issubclass(DatabasesCRUDRouter, APIRouter) +@pytest.fixture( + params=[ + GinoCRUDRouter, + SQLAlchemyCRUDRouter, + MemoryCRUDRouter, + OrmarCRUDRouter, + GinoCRUDRouter, + DatabasesCRUDRouter, + ] +) +def subclass(request) -> Type[CRUDGenerator]: + return request.param + + +def test_router_is_subclass_of_crud_generator(subclass): + assert issubclass(subclass, CRUDGenerator) + + +def test_router_is_subclass_of_api_router(subclass): + assert issubclass(subclass, APIRouter) + + +def test_base_class_is_abstract(): + assert issubclass(CRUDGenerator, ABC) def test_raise_not_implemented(): @@ -35,9 +55,7 @@ def bar(): methods = CRUDGenerator.get_routes() for m in methods: - with pytest.raises(NotImplementedError): + with pytest.raises(TypeError): app.include_router(CRUDGenerator(schema=Potato)) setattr(CRUDGenerator, f"_{m}", foo) - - app.include_router(CRUDGenerator(schema=Potato))