From 51e9f1b48b325ec20cb1bd7dd94df5714d5bb6e7 Mon Sep 17 00:00:00 2001 From: Grigoriev Semyon <33061489+grigoriev-semyon@users.noreply.github.com> Date: Sat, 26 Aug 2023 17:00:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80?= =?UTF-8?q?=D1=8B=20=D0=B2=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D1=81=D0=B5=20=D0=BA=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=B3=D0=BE=D1=80=D0=B8=D0=B8=20=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_routes/test_category.py | 6 +++--- userdata_api/__main__.py | 7 ++++--- userdata_api/routes/category.py | 31 ++++++++++++++++++++++-------- userdata_api/routes/param.py | 11 ++++++----- userdata_api/routes/source.py | 11 ++++++----- userdata_api/schemas/category.py | 2 ++ 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/tests/test_routes/test_category.py b/tests/test_routes/test_category.py index d10dde4..27c3f9a 100644 --- a/tests/test_routes/test_category.py +++ b/tests/test_routes/test_category.py @@ -38,7 +38,7 @@ def test_create_with_no_scopes(client, dbsession): dbsession.commit() -@pytest.mark.authenticated("userdata.category.read") +@pytest.mark.authenticated() def test_get(client, dbsession, category): _category = category() response = client.get(f"/category/{_category.id}") @@ -49,7 +49,7 @@ def test_get(client, dbsession, category): assert response.json()["name"] == _category.name -@pytest.mark.authenticated("userdata.category.read") +@pytest.mark.authenticated() def test_get_all(client, dbsession, category): category1 = category() category2 = category() @@ -89,7 +89,7 @@ def test_update(client, dbsession, category): assert _category.update_scope == old_update_scope -@pytest.mark.authenticated("userdata.category.delete", "userdata.category.read") +@pytest.mark.authenticated("userdata.category.delete") def test_delete(client, dbsession, category): _category = category() response = client.delete(f"/category/{_category.id}") diff --git a/userdata_api/__main__.py b/userdata_api/__main__.py index 6b5ec55..40bab42 100644 --- a/userdata_api/__main__.py +++ b/userdata_api/__main__.py @@ -2,9 +2,6 @@ import uvicorn -from userdata_api.routes.base import app -from worker.consumer import process - def get_args(): parser = argparse.ArgumentParser() @@ -20,6 +17,10 @@ def get_args(): args = get_args() match args.instance: case "api": + from userdata_api.routes.base import app + uvicorn.run(app) case "worker": + from worker.consumer import process + process() diff --git a/userdata_api/routes/category.py b/userdata_api/routes/category.py index 01ae6cd..017be8a 100644 --- a/userdata_api/routes/category.py +++ b/userdata_api/routes/category.py @@ -1,7 +1,9 @@ +from typing import Literal + from auth_lib.fastapi import UnionAuth -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Query, Request from fastapi_sqlalchemy import db -from pydantic import parse_obj_as +from pydantic.type_adapter import TypeAdapter from userdata_api.exceptions import AlreadyExists from userdata_api.models.db import Category @@ -29,13 +31,13 @@ async def create_category( if Category.query(session=db.session).filter(Category.name == category_inp.name).all(): raise AlreadyExists(Category, category_inp.name) category = Category.create(session=db.session, **category_inp.dict()) - return CategoryGet.from_orm(category) + return CategoryGet.model_validate(category) @category.get("/{id}", response_model=CategoryGet) async def get_category( id: int, - _: dict[str, str] = Depends(UnionAuth(scopes=["userdata.category.read"], allow_none=False, auto_error=True)), + _: dict[str, str] = Depends(UnionAuth(scopes=[], allow_none=False, auto_error=True)), ) -> CategoryGet: """ Получить категорию @@ -47,16 +49,29 @@ async def get_category( return CategoryGet.model_validate(category) -@category.get("", response_model=list[CategoryGet]) +@category.get("", response_model=list[CategoryGet], response_model_exclude_none=True) async def get_categories( - _: dict[str, str] = Depends(UnionAuth(scopes=["userdata.category.read"], allow_none=False, auto_error=True)) + query: list[Literal["param"]] = Query(default=[]), + _: dict[str, str] = Depends(UnionAuth(scopes=[], allow_none=False, auto_error=True)), ) -> list[CategoryGet]: + result = [] + for category in Category.query(session=db.session).all(): + to_append = category.dict() + if "param" in query: + to_append["params"] = [] + for param in category.params: + to_append["params"].append(param.dict()) + result.append(to_append) """ Получить все категории + :param query: Лист query параметров. + Если ничего не указано то вернет просто список категорий + Параметр 'param' - если указан, то в каждой категории будет список ее параметров :param _: Аутентифиуация :return: Список категорий. В каждой ноде списка - информация о скоупах, которые нужны для получения пользовательских данных этой категории """ - return parse_obj_as(list[CategoryGet], Category.query(session=db.session).all()) + type_adapter = TypeAdapter(list[CategoryGet]) + return type_adapter.validate_python(result) @category.patch("/{id}", response_model=CategoryGet) @@ -75,7 +90,7 @@ async def patch_category( :return: CategoryGet - обновленную категорию """ category: Category = Category.get(id, session=db.session) - return CategoryGet.from_orm(Category.update(id, session=db.session, **category_inp.dict(exclude_unset=True))) + return CategoryGet.model_validate(Category.update(id, session=db.session, **category_inp.dict(exclude_unset=True))) @category.delete("/{id}", response_model=StatusResponseModel) diff --git a/userdata_api/routes/param.py b/userdata_api/routes/param.py index 92de9af..4a0b714 100644 --- a/userdata_api/routes/param.py +++ b/userdata_api/routes/param.py @@ -3,7 +3,7 @@ from auth_lib.fastapi import UnionAuth from fastapi import APIRouter, Depends, Request from fastapi_sqlalchemy import db -from pydantic import parse_obj_as +from pydantic.type_adapter import TypeAdapter from userdata_api.exceptions import AlreadyExists, ObjectNotFound from userdata_api.models.db import Category, Param @@ -32,7 +32,7 @@ async def create_param( Category.get(category_id, session=db.session) if Param.query(session=db.session).filter(Param.category_id == category_id, Param.name == param_inp.name).all(): raise AlreadyExists(Param, param_inp.name) - return ParamGet.from_orm(Param.create(session=db.session, **param_inp.dict(), category_id=category_id)) + return ParamGet.model_validate(Param.create(session=db.session, **param_inp.dict(), category_id=category_id)) @param.get("/{id}", response_model=ParamGet) @@ -46,7 +46,7 @@ async def get_param(id: int, category_id: int) -> ParamGet: res = Param.query(session=db.session).filter(Param.id == id, Param.category_id == category_id).one_or_none() if not res: raise ObjectNotFound(Param, id) - return ParamGet.from_orm(res) + return ParamGet.model_validate(res) @param.get("", response_model=list[ParamGet]) @@ -56,7 +56,8 @@ async def get_params(category_id: int) -> list[ParamGet]: :param category_id: Айди категории :return: list[ParamGet] - список полученных параметров """ - return parse_obj_as(list[ParamGet], Param.query(session=db.session).filter(Param.category_id == category_id).all()) + type_adapter = TypeAdapter(list[ParamGet]) + return type_adapter.validate_python(Param.query(session=db.session).filter(Param.category_id == category_id).all()) @param.patch("/{id}", response_model=ParamGet) @@ -82,7 +83,7 @@ async def patch_param( return ParamGet.from_orm( Param.update(id, session=db.session, **param_inp.dict(exclude_unset=True), category_id=category_id) ) - return ParamGet.from_orm(Param.update(id, session=db.session, **param_inp.dict(exclude_unset=True))) + return ParamGet.model_validate(Param.update(id, session=db.session, **param_inp.dict(exclude_unset=True))) @param.delete("/{id}", response_model=StatusResponseModel) diff --git a/userdata_api/routes/source.py b/userdata_api/routes/source.py index 1f16ea0..9de4ca9 100644 --- a/userdata_api/routes/source.py +++ b/userdata_api/routes/source.py @@ -3,7 +3,7 @@ from auth_lib.fastapi import UnionAuth from fastapi import APIRouter, Depends, Request from fastapi_sqlalchemy import db -from pydantic import parse_obj_as +from pydantic.type_adapter import TypeAdapter from userdata_api.exceptions import AlreadyExists from userdata_api.models.db import Source @@ -30,7 +30,7 @@ async def create_source( source = Source.query(session=db.session).filter(Source.name == source_inp.name).all() if source: raise AlreadyExists(Source, source_inp.name) - return SourceGet.from_orm(Source.create(session=db.session, **source_inp.dict())) + return SourceGet.model_validate(Source.create(session=db.session, **source_inp.dict())) @source.get("/{id}", response_model=SourceGet) @@ -40,7 +40,7 @@ async def get_source(id: int) -> SourceGet: :param id: Айди источника :return: SourceGet - полученный источник """ - return SourceGet.from_orm(Source.get(id, session=db.session)) + return SourceGet.model_validate(Source.get(id, session=db.session)) @source.get("", response_model=list[SourceGet]) @@ -49,7 +49,8 @@ async def get_sources() -> list[SourceGet]: Получить все источники данных :return: list[SourceGet] - список источников данных """ - return parse_obj_as(list[SourceGet], Source.query(session=db.session).all()) + type_adapter = TypeAdapter(list[SourceGet]) + return type_adapter.validate_python(Source.query(session=db.session).all()) @source.patch("/{id}", response_model=SourceGet) @@ -67,7 +68,7 @@ async def patch_source( :param _: Аутентификация :return: SourceGet - обновленный источник данных """ - return SourceGet.from_orm(Source.update(id, session=db.session, **source_inp.dict(exclude_unset=True))) + return SourceGet.model_validate(Source.update(id, session=db.session, **source_inp.dict(exclude_unset=True))) @source.delete("/{id}", response_model=StatusResponseModel) diff --git a/userdata_api/schemas/category.py b/userdata_api/schemas/category.py index 0b37af3..a8ee20e 100644 --- a/userdata_api/schemas/category.py +++ b/userdata_api/schemas/category.py @@ -1,6 +1,7 @@ from pydantic import constr from .base import Base +from .param import ParamGet from .types.scope import Scope @@ -18,3 +19,4 @@ class CategoryPatch(Base): class CategoryGet(CategoryPost): id: int + params: list[ParamGet] | None = None