# server/__init__.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""FastAPI server package server, generated by datamodel-code-generator."""

from ._runtime.server.responses import HTTPResult
from .application import (
    OperationDependencies,
    build_router,
    create_app,
    serve_source_openapi,
    validation_error_handler,
)

__all__ = [
    "HTTPResult",
    "OperationDependencies",
    "build_router",
    "create_app",
    "serve_source_openapi",
    "validation_error_handler",
]
# server/application.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""Customized: Build the router and the application of every selected operation from the services that implement them."""

from collections.abc import Sequence
from typing import Any, Final

from fastapi import APIRouter, FastAPI, params

from ._generated.contract import OperationDependencies
from ._generated.openapi import serve_source_openapi
from ._runtime.server.application import build, error_handlers, validation_error_handler
from .routers import animals, store
from .services import AnimalsService, StoreService

ROUTES: Final = (
    *animals.LITERAL_ROUTES,
    *store.LITERAL_ROUTES,
    *animals.TEMPLATED_ROUTES,
    *store.TEMPLATED_ROUTES,
)
INFO: Final[dict[str, Any]] = {'title': 'Pets', 'version': '1.0'}


def build_router(
    *,
    animals: AnimalsService,
    store: StoreService,
    dependencies: Sequence[params.Depends] = (),
    operation_dependencies: OperationDependencies | None = None,
    prefix: str = "",
) -> APIRouter:
    """Check the services and settings, then register every operation, literal paths first."""
    return build(
        ROUTES,
        services={'animals': animals, 'store': store},
        dependencies=dependencies,
        operation_dependencies=operation_dependencies,
        prefix=prefix,
    )


def create_app(
    *,
    animals: AnimalsService,
    store: StoreService,
    operation_dependencies: OperationDependencies | None = None,
    prefix: str = "",
    source_openapi: bool = True,
    **fastapi_kwargs: Any,
) -> FastAPI:
    """Create the application with every operation."""
    app = FastAPI(**{**INFO, **fastapi_kwargs})
    app.include_router(
        build_router(
            animals=animals,
            store=store,
            operation_dependencies=operation_dependencies,
            prefix=prefix,
        )
    )
    return app


__all__ = [
    'OperationDependencies',
    'build_router',
    'create_app',
    'serve_source_openapi',
    'validation_error_handler',
]
# server/main.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""Serve the application with your services: `uvicorn server.main:app`.

Generation overwrites this module. It imports your implementations from services, as Next steps in README.md
describes, and passes them to create_app; to pass others, such as fakes in tests, call create_app yourself.
"""

from ._runtime.server.application import missing_implementation
from .application import create_app

try:
    from services.animals import Animals
    from services.store import Store
except ImportError as error:
    missing_implementation(
        error,
        {
            'services.animals': 'Animals',
            'services.store': 'Store',
        },
    )
    raise

app = create_app(
    animals=Animals(),
    store=Store(),
)
# server/routers/__init__.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""Router groups of this package."""
# server/routers/animals.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""Endpoints of the animals operations; regenerate them instead of editing."""

from collections.abc import Sequence
from typing import Annotated, Final
from uuid import UUID

import models
from fastapi import APIRouter, Body, Cookie, Header, Path, Query, Request, params
from fastapi.responses import Response
from pydantic import AwareDatetime, Field

from .._generated import contract
from .._generated.contract import OperationDependencies
from .._runtime.server.application import Wiring, build, checked
from .._runtime.server.responses import dispatch
from ..services import AnimalsService


def _add_list_all(
    router: APIRouter,
    wiring: Wiring,
) -> None:
    animals: AnimalsService = wiring.services['animals']
    list_all_handler = checked(
        animals.list_all,
        'The animals.list_all method of GET /pets',
        ('request', 'page_size', 'tags', 'kind', 'trace', 'since', 'session'),
    )

    def list_all(
        *,
        request: Request,
        page_size: Annotated[int, Field(ge=1, le=100), Query(alias='limit', description='Page size.')] = 20,
        tags: Annotated[list[str] | None, Query(alias='tags')] = None,
        kind: Annotated[models.PetsGetQueryKindParameter | None, Query(alias='kind')] = None,
        trace: Annotated[UUID | None, Header(alias='X-Request-Id', convert_underscores=False)] = None,
        since: Annotated[AwareDatetime | None, Query(alias='since')] = None,
        session: Annotated[str | None, Cookie(alias='session')] = None,
    ) -> object:
        return dispatch(
            list_all_handler(
                request=request,
                page_size=page_size,
                tags=tags,
                kind=kind,
                trace=trace,
                since=since,
                session=session,
            ),
            contract.ListAll.RESPONSES,
        )

    router.add_api_route(
        '/pets',
        list_all,
        methods=['GET'],
        status_code=200,
        response_model=models.PetsGetResponse,
        response_model_by_alias=True,
        response_model_exclude_unset=True,
        operation_id='listPets',
        tags=['pets'],
        response_description='The pets.',
        dependencies=wiring.dependencies.get('list_all'),
    )


def _add_create_pet(
    router: APIRouter,
    wiring: Wiring,
) -> None:
    animals: AnimalsService = wiring.services['animals']
    create_pet_handler = checked(
        animals.create_pet,
        'The animals.create_pet method of POST /pets',
        ('request', 'body'),
        asynchronous=True,
    )

    async def create_pet(
        *,
        request: Request,
        body: Annotated[models.NewPet, Body(media_type='application/json')],
    ) -> object:
        return dispatch(
            await create_pet_handler(
                request=request,
                body=body,
            ),
            contract.CreatePet.RESPONSES,
        )

    router.add_api_route(
        '/pets',
        create_pet,
        methods=['POST'],
        status_code=201,
        response_model=models.Pet,
        response_model_by_alias=True,
        response_model_exclude_unset=True,
        operation_id='createPet',
        tags=['pets'],
        response_description='Created.',
        dependencies=wiring.dependencies.get('create_pet'),
    )


def _add_list_my_pets(
    router: APIRouter,
    wiring: Wiring,
) -> None:
    animals: AnimalsService = wiring.services['animals']
    list_my_pets_handler = checked(
        animals.list_my_pets,
        'The animals.list_my_pets method of GET /pets/mine',
        ('request',),
        asynchronous=True,
    )

    async def list_my_pets(
        *,
        request: Request,
    ) -> object:
        return dispatch(
            await list_my_pets_handler(
                request=request,
            ),
            contract.ListMyPets.RESPONSES,
        )

    router.add_api_route(
        '/pets/mine',
        list_my_pets,
        methods=['GET'],
        status_code=200,
        response_model=models.PetsMineGetResponse,
        response_model_by_alias=True,
        response_model_exclude_unset=True,
        operation_id='listMyPets',
        tags=['pets'],
        response_description="The caller's pets.",
        dependencies=wiring.dependencies.get('list_my_pets'),
    )


def _add_get_pet(
    router: APIRouter,
    wiring: Wiring,
) -> None:
    animals: AnimalsService = wiring.services['animals']
    get_pet_handler = checked(
        animals.get_pet,
        'The animals.get_pet method of GET /pets/{petId}',
        ('request', 'petId'),
        asynchronous=True,
    )

    async def get_pet(
        *,
        request: Request,
        petId: Annotated[int, Field(ge=1), Path(alias='petId')],
    ) -> object:
        return dispatch(
            await get_pet_handler(
                request=request,
                petId=petId,
            ),
            contract.GetPet.RESPONSES,
        )

    router.add_api_route(
        '/pets/{petId}',
        get_pet,
        methods=['GET'],
        status_code=200,
        response_model=models.Pet,
        response_model_by_alias=True,
        response_model_exclude_unset=True,
        operation_id='getPet',
        tags=['pets'],
        response_description='The pet.',
        dependencies=wiring.dependencies.get('get_pet'),
    )


def _add_delete_pet(
    router: APIRouter,
    wiring: Wiring,
) -> None:
    animals: AnimalsService = wiring.services['animals']
    delete_pet_handler = checked(
        animals.delete_pet,
        'The animals.delete_pet method of DELETE /pets/{petId}',
        ('request', 'petId'),
        asynchronous=True,
    )

    async def delete_pet(
        *,
        request: Request,
        petId: Annotated[int, Field(ge=1), Path(alias='petId')],
    ) -> object:
        return dispatch(
            await delete_pet_handler(
                request=request,
                petId=petId,
            ),
            contract.DeletePet.RESPONSES,
        )

    router.add_api_route(
        '/pets/{petId}',
        delete_pet,
        methods=['DELETE'],
        status_code=204,
        response_model=None,
        response_class=Response,
        operation_id='deletePet',
        tags=['pets'],
        response_description='Deleted.',
        dependencies=wiring.dependencies.get('delete_pet'),
    )


LITERAL_ROUTES: Final = (
    ('list_all', _add_list_all),
    ('create_pet', _add_create_pet),
    ('list_my_pets', _add_list_my_pets),
)
TEMPLATED_ROUTES: Final = (
    ('get_pet', _add_get_pet),
    ('delete_pet', _add_delete_pet),
)


def build_router(
    *,
    animals: AnimalsService,
    dependencies: Sequence[params.Depends] = (),
    operation_dependencies: OperationDependencies | None = None,
    prefix: str = "",
) -> APIRouter:
    """Register the animals operations on a new router, literal paths first."""
    return build(
        (*LITERAL_ROUTES, *TEMPLATED_ROUTES),
        services={'animals': animals},
        dependencies=dependencies,
        operation_dependencies=operation_dependencies,
        prefix=prefix,
    )
# server/routers/store.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""Endpoints of the store operations; regenerate them instead of editing."""

from collections.abc import Sequence
from typing import Final

import models
from fastapi import APIRouter, Request, params

from .._generated import contract
from .._generated.contract import OperationDependencies
from .._runtime.server.application import Wiring, build, checked
from .._runtime.server.responses import dispatch
from ..services import StoreService


def _add_get_inventory(
    router: APIRouter,
    wiring: Wiring,
) -> None:
    store: StoreService = wiring.services['store']
    get_inventory_handler = checked(
        store.get_inventory,
        'The store.get_inventory method of GET /store/inventory',
        ('request',),
        asynchronous=True,
    )

    async def get_inventory(
        *,
        request: Request,
    ) -> object:
        return dispatch(
            await get_inventory_handler(
                request=request,
            ),
            contract.GetInventory.RESPONSES,
        )

    router.add_api_route(
        '/store/inventory',
        get_inventory,
        methods=['GET'],
        status_code=200,
        response_model=models.StoreInventoryGetResponse,
        response_model_by_alias=True,
        response_model_exclude_unset=True,
        operation_id='getInventory',
        tags=['store'],
        response_description='Counts by status.',
        dependencies=wiring.dependencies.get('get_inventory'),
    )


LITERAL_ROUTES: Final = (
    ('get_inventory', _add_get_inventory),
)
TEMPLATED_ROUTES: Final = ()


def build_router(
    *,
    store: StoreService,
    dependencies: Sequence[params.Depends] = (),
    operation_dependencies: OperationDependencies | None = None,
    prefix: str = "",
) -> APIRouter:
    """Register the store operations on a new router, literal paths first."""
    return build(
        (*LITERAL_ROUTES, *TEMPLATED_ROUTES),
        services={'store': store},
        dependencies=dependencies,
        operation_dependencies=operation_dependencies,
        prefix=prefix,
    )
# server/services.py
# generated by datamodel-codegen:
#   filename:  pets.yaml

"""Customized: Service interfaces of this package's router groups; regenerate them instead of editing."""

from __future__ import annotations

from abc import abstractmethod
from typing import Protocol
from uuid import UUID

import models
from fastapi import Request
from fastapi.responses import Response
from pydantic import AwareDatetime

from ._runtime.server.responses import HTTPResult


class AnimalsService(Protocol):
    """Implement the animals operations: subclass this Protocol, or give an object its methods."""

    @abstractmethod
    def list_all(
        self,
        *,
        request: Request,
        page_size: int,
        tags: list[str] | None,
        kind: models.PetsGetQueryKindParameter | None,
        trace: UUID | None,
        since: AwareDatetime | None,
        session: str | None,
    ) -> models.PetsGetResponse | HTTPResult[models.PetsGetResponse | models.Error] | Response:
        """
        Handle GET /pets.
        """

    @abstractmethod
    async def create_pet(
        self,
        *,
        request: Request,
        body: models.NewPet,
    ) -> models.Pet | HTTPResult[models.Pet] | Response:
        """
        Handle POST /pets.
        """

    @abstractmethod
    async def list_my_pets(
        self,
        *,
        request: Request,
    ) -> models.PetsMineGetResponse | HTTPResult[models.PetsMineGetResponse] | Response:
        """
        Handle GET /pets/mine.
        """

    @abstractmethod
    async def get_pet(
        self,
        *,
        request: Request,
        petId: int,
    ) -> models.Pet | HTTPResult[models.Pet | models.Error] | Response:
        """
        Handle GET /pets/{petId}.
        """

    @abstractmethod
    async def delete_pet(
        self,
        *,
        request: Request,
        petId: int,
    ) -> None | HTTPResult[None] | Response:
        """
        Handle DELETE /pets/{petId}.
        """


class StoreService(Protocol):
    """Implement the store operations: subclass this Protocol, or give an object its methods."""

    @abstractmethod
    async def get_inventory(
        self,
        *,
        request: Request,
    ) -> models.StoreInventoryGetResponse | HTTPResult[models.StoreInventoryGetResponse] | Response:
        """
        Handle GET /store/inventory.
        """
