{
  "version": 1,
  "format": "json",
  "kind": "generation",
  "output": "<root>/models.py",
  "files": [
    {
      "path": "models.py",
      "content": "# first\n# second\n\nfrom __future__ import annotations\n\nfrom pydantic import BaseModel, RootModel\n\n\nclass Item(BaseModel):\n    id: int | None = None\n\n\nclass ItemsGetResponse(RootModel[list[Item]]):\n    root: list[Item]\n"
    },
    {
      "path": "server/README.md",
      "content": "# Inline\n\nThe `server` package serves the Inline API with FastAPI.\ndatamodel-code-generator generated it from the OpenAPI document, together with the `models` models of the `pydantic_v2.BaseModel` backend.\nGeneration overwrites every file of the package, as it does the models: keep your code outside the package, in the `services` modules of [Next steps](#next-steps), and regenerate the package instead of editing it; see [Regenerating](#regenerating).\n\nFastAPI server generation is experimental.\nThe server supports the `pydantic_v2.BaseModel` and `pydantic_v2.dataclass` model backends, while client generation supports all five.\n\n## Next steps\n\n`main.py` serves the application: it imports your implementation of each router group from the `services` package beside this package, and passes them to `create_app`.\nGeneration writes each of these modules that is missing, with a stub for each method that raises `NotImplementedError`, and never overwrites or deletes one.\n\n| Module | File | Defines |\n| --- | --- | --- |\n| `services.items` | `../services/items.py` | `class Items(ItemsService)` |\n| `services.users` | `../services/users.py` | `class Users(UsersService)` |\n\nThe file paths are relative to this README.\nReplace each stub with your code, then run the application with an ASGI server, from the directory that holds the top-level package (add `--app-dir src` for a `src` layout):\n\n```console\nuv add uvicorn\nuv run uvicorn server.main:app --reload\n```\n\n`fastapi dev` runs it too: `uv add \"fastapi[standard]\"`, then `uv run fastapi dev` with the path of `main.py`, beside this README.\nTo pass other instances, such as fakes in tests, call `create_app` yourself; see [Implementing the services](#implementing-the-services).\n\n### `services.items`\n\n```python\n\"\"\"Implement ItemsService of server.services; server.main imports Items from this module.\n\ndatamodel-code-generator wrote this module once, with a stub for each method, and never overwrites it. Generating the\nserver again updates the Protocol, so type checkers point at the methods to change.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport models\nfrom fastapi.responses import Response\nfrom server import HTTPResult\nfrom server.services import ItemsService\n\n\nclass Items(ItemsService):\n    \"\"\"Implement the items operations.\"\"\"\n\n    def list_items(\n        self,\n    ) -> models.ItemsGetResponse | HTTPResult[models.ItemsGetResponse] | Response:\n        \"\"\"\n        Handle GET /items.\n        \"\"\"\n        raise NotImplementedError\n```\n\n### `services.users`\n\n```python\n\"\"\"Implement UsersService of server.services; server.main imports Users from this module.\n\ndatamodel-code-generator wrote this module once, with a stub for each method, and never overwrites it. Generating the\nserver again updates the Protocol, so type checkers point at the methods to change.\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom fastapi.responses import Response\nfrom server import HTTPResult\nfrom server.services import UsersService\n\n\nclass Users(UsersService):\n    \"\"\"Implement the users operations.\"\"\"\n\n    def list_users(\n        self,\n    ) -> None | HTTPResult[None] | Response:\n        \"\"\"\n        Handle GET /users.\n        \"\"\"\n        raise NotImplementedError\n```\n\n## Dependencies\n\nThe package needs these distributions at run time:\n\n- `fastapi>=0.141.1`\n- `pydantic>=2.14.0`\n- `typing-extensions>=4.16`\n\nAdd them to your project with the command each generation prints:\n\n```console\nuv add \"fastapi>=0.141.1\" \"pydantic>=2.14.0\" \"typing-extensions>=4.16\"\n```\n\nRunning the application also needs an ASGI server: `uvicorn`, or `fastapi[standard]` for `fastapi dev`, as in [Next steps](#next-steps).\n\n## Operations\n\n| Service | Method | HTTP method | Path | Operation reference |\n| --- | --- | --- | --- | --- |\n| `ItemsService` | `list_items` | GET | `/items` | `/paths/~1items/get` |\n| `UsersService` | `list_users` | GET | `/users` | `/paths/~1users/get` |\n\n`operation_dependencies` takes the method names, the keys of `OperationDependencies`; the per-operation generation settings, such as `--server-handler-modes`, take the operation references.\n\n## Implementing the services\n\n`services.py` declares a Protocol for each router group, with an abstract method for each operation of the group.\nA method takes the operation's arguments as keywords, with `None` for an optional parameter or body the request omits, and returns the value to send, an `HTTPResult` with another declared status, headers, or both, or a `Response` sent as it is.\n`main.py` passes an instance of each group's class to `create_app` under the group's name.\nSubclass the Protocol, so that type checkers report a missing or mismatched method and Python refuses to create an instance while a method is missing; any other object with the same methods is checked where you pass it.\nThe package looks each method up when it registers the routes, and refuses a coroutine function where the operation's handler mode needs a plain method, or the reverse, and a method that cannot take the keyword arguments of its operation; type checkers check their types.\n\nCall `create_app` yourself to pass other instances.\nTests pass fakes, as this pytest test does with FastAPI's `TestClient`, which needs `httpx2`: each fake subclasses your class of its group and overrides the methods the test calls.\nAn application that builds its services with arguments, such as a database pool or settings, calls `create_app` in a module of its own and runs that module's application instead of `main.py`'s.\n\n```python\nfrom fastapi.testclient import TestClient\n\nfrom server import create_app\nfrom services.items import Items\nfrom services.users import Users\n\n\nclass FakeItems(Items):\n    \"\"\"Override the methods the test calls, such as `list_items`.\"\"\"\n\n\nclass FakeUsers(Users):\n    \"\"\"Override the methods the test calls, such as `list_users`.\"\"\"\n\n\ndef test_app() -> None:\n    with TestClient(create_app(items=FakeItems(), users=FakeUsers())) as client:\n        ...\n```\n\n`create_app` passes its other keyword arguments, such as `lifespan`, `middleware`, or `dependencies`, to `FastAPI`, over the title, version, and other metadata of the source document.\nTo keep your own `FastAPI` application, include the router:\n\n```python\nfrom fastapi import FastAPI\n\nfrom server import build_router\nfrom services.items import Items\nfrom services.users import Users\n\napp = FastAPI()\napp.include_router(build_router(items=Items(), users=Users()))\n```\n\n## Served OpenAPI document\n\n`create_app` serves the part of the source document the selected operations use, which generation writes into `_generated/openapi.json`; the application reads it on the first request for it.\n`_generated/openapi.json` is package data, so a distribution that holds the package must include it: Hatchling, uv_build, poetry-core, pdm-backend, and flit_core include it by default, while setuptools needs it in `package-data` or `MANIFEST.in`.\n`create_app(..., source_openapi=False)` serves FastAPI's own document instead, built from the routes and the models they declare, in which an optional parameter or request body is `anyOf` of its type and `null`.\nAn application of your own that includes `build_router(...)` serves FastAPI's document unless it calls `serve_source_openapi(app)`, imported from `server`.\n\n## Validation\n\nThe models are the contract: FastAPI validates parameters, bodies, and responses with the generated model types, so the model generation settings decide how strictly a value follows the OpenAPI document.\nParameter styles, parameter types, and media types that FastAPI cannot read, such as deepObject parameters or cookie arrays, strict integers, numbers, and booleans, text and binary bodies, and multipart forms, pass through generated adapters.\nAn adapter parses the HTTP syntax, then validates the value with the model's `TypeAdapter`; it answers `400` for malformed syntax, `415` for an undeclared media type, and `422`, with FastAPI's error records, for an invalid value.\nA repeated single value is taken as FastAPI takes it, by adapters too: the last query value, cookie, form field, and object member, and the first header.\nA cookie parameter with a single value arrives as the request sent it, without percent-decoding.\nAdapters accept integers and numbers as JSON writes them and booleans as `true` or `false`, which is fewer spellings than FastAPI accepts for the parameters it reads.\n\n## Production settings\n\nA request that fails validation answers `422` with FastAPI's `{\"detail\": [...]}` records.\n`create_app` keeps the `type`, `loc`, and `msg` of each record and leaves out the `input` and `ctx` FastAPI adds, and pydantic's `url`, so the response does not return the rejected value as such.\n`loc` and `msg` are pydantic's and can still hold text the client chose: a mapping key or an unexpected field name, a discriminator tag, or the message of a validator of your own.\nAn application of your own that includes `build_router(...)` keeps FastAPI's records; register the same handler with `app.add_exception_handler(RequestValidationError, validation_error_handler)`, importing `validation_error_handler` from `server`.\nTo send other error bodies, pass FastAPI's `exception_handlers` to `create_app`; its entry for `RequestValidationError` replaces the package's.\nA result that fails its response model answers `500` without details, and the error, with the values, goes to the server log, as in any FastAPI application.\n`create_app(..., docs_url=None, redoc_url=None, openapi_url=None)` removes `/docs`, `/redoc`, and `/openapi.json`.\nThe `server` response header belongs to the ASGI server, not to the application: uvicorn leaves it out with `--no-server-header`.\n\n## Regenerating\n\nRun the same generation again whenever the OpenAPI document changes; the `--check` option reports the files it would change without writing them.\nGeneration overwrites every generated file, restoring any you edited or deleted, and never deletes one: delete the modules of removed operations yourself, which `--check` lists as extra files.\nWhen an operation is added, removed, or changed, its method in `services.py` changes with it, so type checkers point at the implementations to update, and Python refuses to create an instance of a subclass that lacks a new method.\nGeneration writes only the missing modules of `services`: a new router group gets its module with stubs, and the module of a renamed or removed group stays for you to move or delete.\nThe `services` package belongs to this server alone, as the docstring of its `__init__.py` records: generation refuses another server package beside this one, in a later run or in the same batch, since that package would import its implementations from it too, whatever the docstring says.\nPut each server package under a parent package of its own.\nA server package renamed or moved within the parent package, or spelled from another import root, takes the package over while no other generated server package is beside it, and generation rewrites the docstring to name it, as `--check` reports and a notice says.\nAfter a take-over, the modules of `services` still import the server package they were written for, as in `from <old package>.services import ...`: update those imports to `server` yourself, since generation never rewrites them.\nEach generation prints the `uv add` command that adds the runtime dependencies of the package to your project;\nrun it again when a new version of datamodel-code-generator changes them.\n"
    },
    {
      "path": "server/__init__.py",
      "content": "# first\n# second\n\n\"\"\"FastAPI server package server, generated by datamodel-code-generator.\"\"\"\n\nfrom ._runtime.server.responses import HTTPResult\nfrom .application import (\n    OperationDependencies,\n    build_router,\n    create_app,\n    serve_source_openapi,\n    validation_error_handler,\n)\n\n__all__ = [\n    \"HTTPResult\",\n    \"OperationDependencies\",\n    \"build_router\",\n    \"create_app\",\n    \"serve_source_openapi\",\n    \"validation_error_handler\",\n]\n"
    },
    {
      "path": "server/_generated/__init__.py",
      "content": "# first\n# second\n\n\"\"\"Generated plans of this package.\"\"\"\n"
    },
    {
      "path": "server/_generated/contract.py",
      "content": "# first\n# second\n\n\"\"\"Operation plans of this package; regenerate them instead of editing.\"\"\"\n\nfrom __future__ import annotations\n\nfrom collections.abc import Sequence\nfrom typing import Final, TypedDict\n\nimport models\nfrom fastapi import params\n\nfrom .._runtime.server.responses import Declared, OperationResponses\n\nOperationDependencies = TypedDict(\n    'OperationDependencies',\n    {\n        'list_items': Sequence[params.Depends],\n        'list_users': Sequence[params.Depends],\n    },\n    total=False,\n)\n\n\nclass ListItems:\n    \"\"\"Plans of the list_items operation.\"\"\"\n\n    RESPONSES: Final = OperationResponses(\n        responses={'200': Declared(media_type='application/json', model=models.ItemsGetResponse)},\n    )\n\n\nclass ListUsers:\n    \"\"\"Plans of the list_users operation.\"\"\"\n\n    RESPONSES: Final = OperationResponses(\n        responses={'204': Declared()},\n        primary=204,\n    )\n"
    },
    {
      "path": "server/_generated/openapi.json",
      "content": "{\n \"openapi\": \"3.0.3\",\n \"info\": {\n  \"title\": \"Inline\",\n  \"version\": \"1.0.0\"\n },\n \"paths\": {\n  \"/items\": {\n   \"get\": {\n    \"operationId\": \"listItems\",\n    \"tags\": [\n     \"items\"\n    ],\n    \"responses\": {\n     \"200\": {\n      \"description\": \"Items\",\n      \"content\": {\n       \"application/json\": {\n        \"schema\": {\n         \"type\": \"array\",\n         \"items\": {\n          \"$ref\": \"#/components/schemas/Item\"\n         }\n        }\n       }\n      }\n     }\n    }\n   }\n  },\n  \"/users\": {\n   \"get\": {\n    \"operationId\": \"listUsers\",\n    \"tags\": [\n     \"users\"\n    ],\n    \"responses\": {\n     \"204\": {\n      \"description\": \"None\"\n     }\n    }\n   }\n  }\n },\n \"components\": {\n  \"schemas\": {\n   \"Item\": {\n    \"type\": \"object\",\n    \"properties\": {\n     \"id\": {\n      \"type\": \"integer\"\n     }\n    }\n   }\n  }\n }\n}\n"
    },
    {
      "path": "server/_generated/openapi.py",
      "content": "# first\n# second\n\n\"\"\"Serve the source OpenAPI document of the selected operations, which `openapi.json` beside this module holds.\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nfrom importlib.resources import files\nfrom typing import TYPE_CHECKING, Any\n\nfrom .._runtime.server.openapi import serve_openapi\n\nif TYPE_CHECKING:\n    from collections.abc import Mapping\n\n    from fastapi import FastAPI\n\n\ndef document() -> dict[str, Any]:\n    \"\"\"Return a new copy of the source document, read from `openapi.json` beside this module.\n\n    A build that left the file out of the package fails here, on the document's first request.\n    \"\"\"\n    package = __name__.rpartition(\".\")[0]\n    try:\n        text = (files(package) / \"openapi.json\").read_text(encoding=\"utf-8\")\n    except FileNotFoundError as error:\n        msg = (\n            f\"openapi.json of {package} is missing: include _generated/openapi.json\"\n            \" as package data when building the package, such as with setuptools\"\n            \" package-data or MANIFEST.in\"\n        )\n        raise FileNotFoundError(msg) from error\n    loaded: dict[str, Any] = json.loads(text)\n    return loaded\n\n\ndef serve_source_openapi(\n    app: FastAPI,\n    *,\n    prefix: str = \"\",\n    metadata: Mapping[str, Any] | None = None,\n) -> None:\n    \"\"\"Serve the source document instead of FastAPI's, read on its first request.\n\n    Its paths take `prefix`, and the FastAPI settings in `metadata`, such as `title`, replace its own.\n    \"\"\"\n    serve_openapi(app, document, prefix=prefix, metadata=metadata)\n"
    },
    {
      "path": "server/_runtime/__init__.py",
      "content": "# first\n# second\n"
    },
    {
      "path": "server/_runtime/model_codecs/__init__.py",
      "content": "# first\n# second\n"
    },
    {
      "path": "server/_runtime/model_codecs/errors.py",
      "content": "# first\n# second\n\n\"\"\"Common model-codec errors; none of them carries the rejected value.\"\"\"\n\nfrom __future__ import annotations\n\n\nclass CodecError(Exception):\n    \"\"\"Base class for every model-codec failure.\"\"\"\n\n\nclass ParameterEncodingError(CodecError):\n    \"\"\"Report a parameter value that its declared style cannot represent reversibly.\"\"\"\n\n\nclass MalformedError(CodecError):\n    \"\"\"Report HTTP text that its style, percent-encoding, charset, or media framing cannot read.\"\"\"\n"
    },
    {
      "path": "server/_runtime/model_codecs/media.py",
      "content": "# first\n# second\n\n\"\"\"HTTP tokens, status keys and media-type identity, plus ordinary JSON, text, and URL-encoded form representations.\"\"\"\n\nfrom __future__ import annotations\n\nimport codecs\nimport json\nimport re\nfrom collections.abc import Callable, Container, Iterable, Mapping\nfrom dataclasses import dataclass\nfrom decimal import Decimal\nfrom math import isfinite\nfrom typing import Final, Literal, TypeAlias, TypeVar, cast\nfrom urllib.parse import quote, unquote_to_bytes\n\nfrom typing_extensions import Self, TypeAliasType, TypeIs\n\nfrom .errors import MalformedError, ParameterEncodingError\n\n__all__ = (\n    \"BODYLESS_STATUSES\",\n    \"ERROR_STATUSES\",\n    \"JSON_MEDIA_TYPE\",\n    \"LENIENT_QUOTED\",\n    \"NOT_MODIFIED\",\n    \"NO_CONTENT\",\n    \"OK\",\n    \"QUOTED\",\n    \"REDIRECT_STATUSES\",\n    \"STATUSES\",\n    \"SUCCESS_STATUSES\",\n    \"SWITCHING_PROTOCOLS\",\n    \"TCHARS\",\n    \"TOKEN\",\n    \"FieldPlan\",\n    \"JSONKind\",\n    \"JSONScalar\",\n    \"JSONValue\",\n    \"LexicalKind\",\n    \"MediaKind\",\n    \"MediaOrder\",\n    \"Unparsed\",\n    \"ascii_digits\",\n    \"bodyless\",\n    \"charset\",\n    \"declaring\",\n    \"decode_form\",\n    \"decode_text\",\n    \"encode_form\",\n    \"essence\",\n    \"fields_without\",\n    \"finite\",\n    \"form_encode\",\n    \"form_pairs\",\n    \"is_token\",\n    \"json_bytes\",\n    \"json_integer\",\n    \"json_number\",\n    \"json_text\",\n    \"json_value\",\n    \"lexical\",\n    \"media_kind\",\n    \"media_parts\",\n    \"media_range\",\n    \"most_specific\",\n    \"normalize_media_type\",\n    \"normalized\",\n    \"percent_decode\",\n    \"plain\",\n    \"range_key\",\n    \"split_form\",\n    \"status_key\",\n    \"typed\",\n    \"unquoted\",\n)\n\nJSONValue = TypeAliasType(\"JSONValue\", \"bool | int | float | str | list[JSONValue] | dict[str, JSONValue] | None\")\nJSONScalar = TypeAliasType(\"JSONScalar\", \"bool | int | float | str | None\")\n\nJSONKind = Literal[\"object\", \"array\", \"string\", \"number\", \"boolean\"]\nLexicalKind = Literal[\"string\", \"integer\", \"number\", \"boolean\"]\nMediaKind = Literal[\"json\", \"text\", \"form\", \"multipart\", \"binary\"]\nMediaOrder: TypeAlias = Literal[\"specific\", \"declared\"]\nT = TypeVar(\"T\")\n\nTCHARS: Final = r\"[!#$%&'*+.^_`|~0-9A-Za-z-]+\"\nTOKEN: Final = re.compile(TCHARS)\nJSON_MEDIA_TYPE: Final = \"application/json\"\nQUOTED: Final = r'\"(?:[\\t !#-\\[\\]-~\\x80-\\xff]|\\\\[\\t -~\\x80-\\xff])*\"'\nLENIENT_QUOTED: Final = r'\"(?:[^\"\\\\]|\\\\.)*\"'\n\"\"\"A quoted string of a MIME header field as a multipart part's Content-Disposition is read: any character but a double\nquote or a backslash, and any escaped one but a line feed, between double quotes. Row `legacy-lenient-quoted-string`: a\ncache helper reads Cache-Control with it too.\"\"\"\nSTATUSES: Final = range(100, 600)\nSUCCESS_STATUSES: Final = range(200, 300)\nREDIRECT_STATUSES: Final = range(300, 400)\nERROR_STATUSES: Final = range(400, 600)\nSWITCHING_PROTOCOLS: Final = 101\nOK: Final = 200\nNO_CONTENT: Final = 204\nNOT_MODIFIED: Final = 304\nBODYLESS_STATUSES: Final = frozenset({NO_CONTENT, 205, NOT_MODIFIED})\n_MEDIA: Final = re.compile(rf\"[ \\t]*(?P<type>{TCHARS})/(?P<subtype>{TCHARS})[ \\t]*\")\n_PARAMETER: Final = re.compile(rf\";[ \\t]*(?P<name>{TCHARS})=(?P<value>{TCHARS}|{QUOTED})[ \\t]*\")\n_MEDIA_ERRORS: Final = (\n    \"A media type must be a token/token essence\",\n    \"A media type parameter must be a token=value pair\",\n)\n_INTEGER: Final = re.compile(r\"-?(?:0|[1-9][0-9]*)\")\n_NUMBER: Final = re.compile(r\"-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\")\n_TRIPLET: Final = re.compile(rb\"%[0-9A-Fa-f]{2}\")\n_ESCAPED: Final = re.compile(r\"\\\\(.)\")\n_FORM_SAFE: Final = \"*-._\"\n_SCALARS: Final = frozenset({bool, int, float, str, type(None)})\n\n_NESTING: Final = \"A wire value must not be nested beyond the interpreter recursion limit\"\n_SURROGATES: Final = \"A wire string must not contain lone surrogates\"\n_NOT_JSON: Final = \"A wire value must be made of JSON values and string keys\"\n_CIRCULAR: Final = \"A wire value must not refer to itself\"\n_NON_FINITE: Final = \"A wire number must be finite\"\n_TOO_LARGE: Final = \"A wire integer must not exceed the interpreter's decimal conversion limit\"\n_VALUE_ERRORS: Final = ((\"Circular reference\", _CIRCULAR), (\"Out of range float\", _NON_FINITE))\n_JSON_ERRORS: Final = (RecursionError, TypeError, ValueError)\n\n\n@dataclass(frozen=True, slots=True)\nclass FieldPlan:\n    \"\"\"Declare one form or object member's lexical kind and whether it repeats.\"\"\"\n\n    name: str\n    kind: LexicalKind = \"string\"\n    repeated: bool = False\n\n\ndef json_text(\n    value: object,\n    *,\n    ascii_only: bool = False,\n    sort_keys: bool = False,\n    errors: Literal[\"runtime\", \"legacy-python-json-errors\"] = \"runtime\",\n) -> str:\n    \"\"\"Serialize ordinary JSON builtins as compact JSON text, escaping non-ASCII text when asked.\n\n    The errors are the runtime's own, with the same messages on every Python version: ValueError for a circular\n    reference, a non-finite number, an integer over the interpreter's decimal conversion limit, or a value nested\n    beyond the recursion limit, and TypeError for a value or key that is not JSON. `errors=\"legacy-python-json-errors\"`\n    lets the standard library's errors through with its messages, as a server writes a body without a model.\n    \"\"\"\n    caught = _JSON_ERRORS if errors == \"runtime\" else ()\n    try:\n        return json.dumps(value, sort_keys=sort_keys, separators=(\",\", \":\"), ensure_ascii=ascii_only, allow_nan=False)\n    except caught as error:\n        if isinstance(error, TypeError):\n            raise TypeError(_NOT_JSON) from None\n        message = (\n            _NESTING\n            if isinstance(error, RecursionError)\n            else next((text for prefix, text in _VALUE_ERRORS if str(error).startswith(prefix)), _TOO_LARGE)\n        )\n        raise ValueError(message) from None\n\n\ndef json_bytes(value: object, *, ascii_only: bool = False, sort_keys: bool = False) -> bytes:\n    \"\"\"Serialize ordinary JSON builtins as compact UTF-8 bytes, escaping non-ASCII text when asked.\n\n    The errors are those of `json_text`, and a lone surrogate raises ValueError.\n    \"\"\"\n    text = json_text(value, ascii_only=ascii_only, sort_keys=sort_keys)\n    try:\n        return text.encode()\n    except UnicodeEncodeError:\n        raise ValueError(_SURROGATES) from None\n\n\ndef json_value(\n    content: str | bytes,\n    *,\n    constants: Literal[\"accept\", \"refuse\"] = \"accept\",\n    floats: Literal[\"float\", \"decimal\"] = \"float\",\n) -> JSONValue:\n    \"\"\"Parse ordinary JSON into its builtin values without model validation.\n\n    `constants=\"refuse\"` raises ValueError for NaN and the infinities, which a saved value could not hold (`int` of\n    their names refuses them); `floats=\"decimal\"` reads a number with a fraction or an exponent as the Decimal its\n    text spells, where a float may have rounded it.\n    \"\"\"\n    return cast(\n        \"JSONValue\",\n        json.loads(\n            content,\n            parse_constant=int if constants == \"refuse\" else None,\n            parse_float=Decimal if floats == \"decimal\" else None,\n        ),\n    )\n\n\nclass Unparsed(str):  # ruff: ignore[subclass-builtin] - Validating backends receive it as ordinary text.\n    \"\"\"Text of a declared integer, number, or boolean that is not its canonical JSON literal.\"\"\"\n\n    __slots__ = (\"kind\",)\n    kind: LexicalKind\n\n    def __new__(cls, text: str, kind: LexicalKind) -> Self:\n        \"\"\"Keep the text with the kind it was declared as.\"\"\"\n        unparsed = super().__new__(cls, text)\n        unparsed.kind = kind\n        return unparsed\n\n\ndef plain(value: object, *, strict: bool = False) -> JSONValue:\n    \"\"\"Turn parsed form and header containers into builtins a native backend accepts.\n\n    Text that is not its kind's JSON literal stays text for a backend that validates it, and is refused when strict.\n    \"\"\"\n    if type(value) in _SCALARS:\n        return cast(\"JSONValue\", value)\n    if isinstance(value, Mapping):\n        return {\n            cast(\"str\", key): plain(item, strict=strict) for key, item in cast(\"Mapping[object, object]\", value).items()\n        }\n    if isinstance(value, (list, tuple)):\n        return [plain(item, strict=strict) for item in cast(\"list[object] | tuple[object, ...]\", value)]\n    if not isinstance(value, Unparsed):\n        return cast(\"JSONValue\", value)\n    if strict:\n        msg = f\"Invalid {value.kind} literal: {str(value)!r}\"\n        raise ValueError(msg)\n    return str(value)\n\n\ndef status_key(status: int, keys: Container[str]) -> str | None:\n    \"\"\"Return the declared response key a status selects: exact, then its hundreds range, then default.\"\"\"\n    return next((key for key in (str(status), range_key(status), \"default\") if key in keys), None)\n\n\ndef declaring(status: int, responses: Mapping[str, T]) -> T | None:\n    \"\"\"Return the value of the declared response key a status selects in a table keyed by response keys, or None.\"\"\"\n    return None if (key := status_key(status, responses)) is None else responses[key]\n\n\ndef range_key(status: int) -> str:\n    \"\"\"Return the key of the hundreds range a status falls in, such as 2XX for 204.\"\"\"\n    return f\"{status // 100}XX\"\n\n\ndef bodyless(status: int, *, head: bool = False, informational: bool = True) -> bool:\n    \"\"\"Return whether a response never carries content: one to HEAD, a 204, 205 or 304, and a 1XX one.\n\n    `informational=False` reads a status below 200 as one that may carry content (the client plan's row).\n    \"\"\"\n    return head or status in BODYLESS_STATUSES or (informational and status < SUCCESS_STATUSES.start)\n\n\ndef media_parts(value: str, errors: tuple[str, str] = _MEDIA_ERRORS) -> tuple[str, str, list[tuple[str, str]]]:\n    \"\"\"Split a media type into lowercase type and subtype and its lowercase parameter names with their raw values.\n\n    `errors` holds the ValueError messages for a malformed essence and for a malformed parameter.\n    \"\"\"\n    if (essence := _MEDIA.match(value)) is None:\n        raise ValueError(errors[0])\n    parameters: list[tuple[str, str]] = []\n    position = essence.end()\n    while position < len(value):\n        if (parameter := _PARAMETER.match(value, position)) is None:\n            raise ValueError(errors[1])\n        parameters.append((parameter[\"name\"].lower(), parameter[\"value\"]))\n        position = parameter.end()\n    return essence[\"type\"].lower(), essence[\"subtype\"].lower(), parameters\n\n\ndef is_token(text: str) -> bool:\n    \"\"\"Return whether text is an HTTP token as a whole, such as a method, a header field name or a cookie name.\"\"\"\n    return TOKEN.fullmatch(text) is not None\n\n\ndef fields_without(fields: Iterable[tuple[str, str]], names: Container[str]) -> list[tuple[str, str]]:\n    \"\"\"Return header fields in order without those whose name, in lowercase, is one of the given lowercase names.\"\"\"\n    return [(name, value) for name, value in fields if name.lower() not in names]\n\n\ndef unquoted(value: str) -> str:\n    \"\"\"Return the text of a parameter value: a quoted string without its quotes and escapes, a token as written.\"\"\"\n    return _ESCAPED.sub(r\"\\1\", value[1:-1]) if value.startswith('\"') else value\n\n\ndef normalize_media_type(value: str) -> str:\n    \"\"\"Return lowercase type/subtype and parameter names, keeping parameter order and values.\"\"\"\n    kind, subtype, parameters = media_parts(value)\n    return \"; \".join([f\"{kind}/{subtype}\", *(f\"{name}={text}\" for name, text in parameters)])\n\n\ndef normalized(media_type: str) -> str | None:\n    \"\"\"Return a media type in its normalized form, or None when it is not a media type.\"\"\"\n    try:\n        return normalize_media_type(media_type)\n    except ValueError:\n        return None\n\n\ndef essence(media_type: str) -> str:\n    \"\"\"Return a media type without its parameters.\"\"\"\n    return media_type.partition(\";\")[0]\n\n\ndef media_range(media_type: str) -> bool:\n    \"\"\"Return whether a media type is a range such as image/* or */*.\"\"\"\n    return \"*\" in essence(media_type)\n\n\ndef most_specific(received: str, declared: Iterable[str], *, order: MediaOrder = \"specific\") -> str | None:\n    \"\"\"Return the declared media type a received one falls under: itself, then its essence, type/*, and */*.\n\n    Among the declarations of one of these, the first without parameters wins (#4185); `order=\"declared\"` instead takes\n    the first declaration of the most specific one in declared order (the client's row).\n    \"\"\"\n    declared = tuple(declared)\n    if received in declared:\n        return received\n    bare = essence(received)\n    candidates = (bare, f\"{bare.partition('/')[0]}/*\", \"*/*\")\n    if order == \"declared\":\n        return next((media for candidate in candidates for media in declared if essence(media) == candidate), None)\n    return min((media for media in declared if essence(media) in candidates), key=_specificity, default=None)\n\n\ndef _specificity(media_type: str) -> tuple[int, bool]:\n    \"\"\"Rank a declared media type: fewer `*` first, then one without parameters.\"\"\"\n    return essence(media_type).count(\"*\"), \";\" in media_type\n\n\ndef media_kind(media_type: str) -> MediaKind:\n    \"\"\"Classify a normalized media type by its builtin representation.\"\"\"\n    kind, _, subtype = essence(media_type).partition(\"/\")\n    match kind, subtype:\n        case \"application\", \"json\":\n            return \"json\"\n        case _, _ if subtype.endswith(\"+json\"):\n            return \"json\"\n        case \"application\", \"x-www-form-urlencoded\":\n            return \"form\"\n        case \"multipart\", _:\n            return \"multipart\"\n        case \"text\", _:\n            return \"text\"\n        case _:\n            return \"binary\"\n\n\ndef charset(media_type: str, *, as_written: bool = False) -> str:\n    \"\"\"Return the codec name a raw media type's charset selects, UTF-8 when it names none or an unknown one.\n\n    With `as_written`, the media type is a normalized one and the charset's value is returned as it is written, which\n    a server then refuses in `decode_text` when it names no codec.\n    \"\"\"\n    if as_written:\n        return next(\n            (\n                parameter[\"value\"].strip('\"')\n                for parameter in _PARAMETER.finditer(media_type)\n                if parameter[\"name\"] == \"charset\"\n            ),\n            \"utf-8\",\n        )\n    for parameter in media_type.split(\";\")[1:]:\n        name, _, value = parameter.strip().partition(\"=\")\n        if name.lower() == \"charset\":\n            try:\n                return codecs.lookup(value.strip('\"')).name\n            except LookupError:\n                break\n    return \"utf-8\"\n\n\ndef decode_text(data: bytes, encoding: str = \"utf-8\") -> str:\n    \"\"\"Decode a text body in its selected charset without normalizing its contents.\"\"\"\n    try:\n        return data.decode(encoding)\n    except (LookupError, UnicodeError):\n        message = \"Text must be UTF-8\" if encoding == \"utf-8\" else f\"Text must be {encoding}\"\n        raise MalformedError(message) from None\n\n\ndef finite(value: object) -> None:\n    \"\"\"Refuse a non-finite float or Decimal, alone or in lists, tuples, and mappings, as no JSON number writes it.\"\"\"\n    match value:\n        case float() if not isfinite(value):\n            raise ParameterEncodingError(_NON_FINITE)\n        case Decimal() if not value.is_finite():\n            raise ParameterEncodingError(_NON_FINITE)\n        case list() | tuple():\n            for item in cast(\"Iterable[object]\", value):\n                finite(item)\n        case Mapping():\n            for item in cast(\"Mapping[object, object]\", value).values():\n                finite(item)\n        case _:\n            pass\n\n\ndef json_integer(value: object) -> TypeIs[int]:\n    \"\"\"Return whether a value is an integer as JSON reads one: an int that is not a bool.\"\"\"\n    return isinstance(value, int) and not isinstance(value, bool)\n\n\ndef json_number(value: object) -> TypeIs[int | float]:\n    \"\"\"Return whether a value is a number as JSON reads one: an int or a float that is not a bool.\"\"\"\n    return isinstance(value, (int, float)) and not isinstance(value, bool)\n\n\ndef lexical(value: object, kind: LexicalKind) -> str:\n    \"\"\"Format one native JSON scalar for a parameter or form field.\"\"\"\n    if (text := _lexical_text(value, kind)) is None:\n        msg = f\"The {type(value).__name__} value does not have the {kind} lexical kind\"\n        raise ParameterEncodingError(msg)\n    return text\n\n\ndef _lexical_text(value: object, kind: LexicalKind) -> str | None:\n    match value:\n        case bool():\n            return \"true\" if value else \"false\"\n        case str():\n            return value\n        case int() | float() | Decimal():\n            finite(value)\n            return _numeral(value, kind) or _numeral(value, \"number\")\n        case _:\n            return None\n\n\ndef _numeral(value: float | Decimal, kind: LexicalKind) -> str | None:\n    match value:\n        case int() if kind in {\"integer\", \"number\"}:\n            return _integer_text(value)\n        case float() if kind == \"integer\" and value.is_integer():\n            return str(int(value))\n        case Decimal() if kind == \"integer\" and value == (integral := value.to_integral_value()):\n            return format(integral, \"f\")\n        case Decimal() if kind == \"number\":\n            return str(value)\n        case float() if kind == \"number\":\n            return repr(value)\n        case _:\n            return None\n\n\ndef _integer_text(value: int) -> str:\n    try:\n        return str(value)\n    except ValueError:\n        msg = \"An integer exceeds the interpreter's decimal conversion limit\"\n        raise ParameterEncodingError(msg) from None\n\n\ndef ascii_digits(text: str) -> bool:\n    \"\"\"Return whether text is one or more ASCII decimal digits, the DIGIT run of HTTP counts and delays.\"\"\"\n    return text.isascii() and text.isdigit()\n\n\ndef typed(text: str, kind: LexicalKind) -> JSONScalar:\n    \"\"\"Decode a canonical JSON literal of the declared kind, leaving any other text to the model.\"\"\"\n    if kind == \"string\":\n        return text\n    if kind == \"boolean\":\n        return text == \"true\" if text in {\"true\", \"false\"} else Unparsed(text, kind)\n    if _INTEGER.fullmatch(text):\n        try:\n            return int(text)\n        except ValueError:\n            return Unparsed(text, kind)\n    return float(text) if kind == \"number\" and _NUMBER.fullmatch(text) else Unparsed(text, kind)\n\n\ndef percent_decode(raw: bytes, *, plus: bool) -> str:\n    \"\"\"Decode percent triplets exactly once and require the result to be UTF-8.\"\"\"\n    if plus:\n        raw = raw.replace(b\"+\", b\" \")\n    if raw.count(b\"%\") != len(_TRIPLET.findall(raw)):\n        msg = \"A percent sign must start a percent-encoded octet\"\n        raise MalformedError(msg)\n    try:\n        return unquote_to_bytes(raw).decode(\"utf-8\")\n    except UnicodeDecodeError:\n        msg = \"Percent-decoded octets must be UTF-8\"\n        raise MalformedError(msg) from None\n\n\ndef form_encode(text: str) -> str:\n    \"\"\"Apply the application/x-www-form-urlencoded byte serializer to one name or value.\"\"\"\n    return quote(text, safe=_FORM_SAFE + \" \").replace(\" \", \"+\").replace(\"~\", \"%7E\")\n\n\ndef encode_form(\n    value: object,\n    fields: tuple[FieldPlan, ...],\n    additional: FieldPlan | None,\n    styled: Mapping[str, Callable[[JSONValue], Iterable[str]]] | None = None,\n) -> bytes:\n    \"\"\"Serialize a flat object as ordered URL-encoded pairs, repeating array members and leaving out None ones.\n\n    A form cannot write null, so a None member is left out as an unset one is. A member in `styled` writes its own\n    pairs, as its encoding's query parameter style or content does, and no two members may then write the same name.\n    \"\"\"\n    if not isinstance(value, Mapping):\n        msg = \"A URL-encoded form value must be an object\"\n        raise ParameterEncodingError(msg)\n    declared = {field.name: field for field in fields}\n    pairs: list[str] = []\n    owners: dict[str, str] = {}\n    for name, item in cast(\"Mapping[str, JSONValue]\", value).items():\n        if item is None:\n            continue\n        if styled and (style := styled.get(name)) is not None:\n            written = list(style(item))\n            keys = [percent_decode(pair.partition(\"=\")[0].encode(\"ascii\"), plus=True) for pair in written]\n        else:\n            field = declared.get(name, additional)\n            kind = \"string\" if field is None else field.kind\n            written = [f\"{form_encode(name)}={form_encode(lexical(member, kind))}\" for member in _members(item)]\n            keys = [name]\n        if styled and any(owners.setdefault(key, name) != name for key in keys):\n            msg = \"Two URL-encoded form members write the same name\"\n            raise ParameterEncodingError(msg)\n        pairs.extend(written)\n    return \"&\".join(pairs).encode(\"ascii\")\n\n\ndef _members(value: object) -> tuple[object, ...]:\n    return tuple(cast(\"list[object] | tuple[object, ...]\", value)) if isinstance(value, (list, tuple)) else (value,)\n\n\ndef split_form(raw: bytes) -> tuple[tuple[bytes, bytes], ...]:\n    \"\"\"Split URL-encoded bytes into ordered raw name/value pairs, skipping empty sequences.\"\"\"\n    return tuple((name, value) for name, _, value in (part.partition(b\"=\") for part in raw.split(b\"&\") if part))\n\n\ndef form_pairs(raw: bytes) -> tuple[tuple[str, str], ...]:\n    \"\"\"Split URL-encoded bytes into ordered name/value pairs, each percent-decoded with a plus sign as a space.\"\"\"\n    return tuple((percent_decode(name, plus=True), percent_decode(value, plus=True)) for name, value in split_form(raw))\n\n\ndef decode_form(raw: bytes, fields: tuple[FieldPlan, ...], additional: FieldPlan | None) -> JSONValue:\n    \"\"\"Split URL-encoded text for native model conversion: repeated fields as lists, a single value by its last.\"\"\"\n    declared = {field.name: field for field in fields}\n    result: dict[str, JSONValue] = {}\n    for name, text in form_pairs(raw):\n        field = declared.get(name, additional)\n        value = typed(text, \"string\" if field is None else field.kind)\n        match result.get(name):\n            case list() as values:\n                values.append(value)\n            case None if field is not None and field.repeated:\n                result[name] = [value]\n            case _:\n                result[name] = value\n    return result\n"
    },
    {
      "path": "server/_runtime/model_codecs/parameters.py",
      "content": "# first\n# second\n\n\"\"\"OpenAPI parameter plans, and their styles and content written as HTTP text.\"\"\"\n\nfrom __future__ import annotations\n\nimport re\nfrom collections.abc import Callable, Mapping\nfrom dataclasses import dataclass\nfrom typing import Final, Literal, TypeAlias, cast\nfrom urllib.parse import quote\n\nfrom .errors import ParameterEncodingError\nfrom .media import (\n    FieldPlan,\n    JSONValue,\n    LexicalKind,\n    encode_form,\n    finite,\n    is_token,\n    json_bytes,\n    json_text,\n    lexical,\n    media_kind,\n)\n\n__all__ = (\n    \"OWS\",\n    \"PATH_SAFE\",\n    \"PLACEHOLDER\",\n    \"ParameterLocation\",\n    \"ParameterPlan\",\n    \"ValueShape\",\n    \"builtin_content\",\n    \"cookie_octets\",\n    \"header_text\",\n    \"pairs\",\n    \"parameter_key\",\n    \"part_pairs\",\n    \"path_text\",\n    \"percent_encoded\",\n    \"query_pairs\",\n    \"querystring\",\n)\n\nParameterLocation: TypeAlias = Literal[\"path\", \"query\", \"querystring\", \"header\", \"cookie\"]\nValueShape: TypeAlias = Literal[\"scalar\", \"array\", \"object\"]\n\nPLACEHOLDER: Final = re.compile(r\"\\{([^{}]*)\\}\")\n\"\"\"A placeholder of a path or server URL template, `{name}`, with its name as the group.\"\"\"\nPATH_SAFE: Final = \"/:@!$&'()*+,;=\"\n\"\"\"The characters besides unreserved ones that the literal text of a path keeps: `/` and those of RFC 3986's pchar.\"\"\"\n_RESERVED: Final = \":/?#[]@!$&'()*+,;=\"\n_PATH_KEPT: Final = \"/?#[],;=\"\n_QUERY_KEPT: Final = \"#&+=[],\"\n_TRIPLET: Final = re.compile(r\"(%[0-9A-Fa-f]{2})\")\n_DELIMITERS: Final = {\"spaceDelimited\": (\"%20\", \" \"), \"pipeDelimited\": (\"%7C\", \"|\")}\n_STYLES: Final = {\n    \"path\": frozenset({\"simple\", \"label\", \"matrix\"}),\n    \"query\": frozenset({\"form\", \"spaceDelimited\", \"pipeDelimited\", \"deepObject\"}),\n    \"header\": frozenset({\"simple\"}),\n    \"cookie\": frozenset({\"form\", \"cookie\"}),\n}\n_NOT_HEADER_TEXT: Final = re.compile(r\"[^\\t\\x20-\\x7E]\")\n_COOKIE_OCTETS: Final = re.compile(r\"[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*\")\nOWS: Final = \" \\t\"\n_UNENCODABLE: Final = \"A parameter value is text that UTF-8 cannot encode, such as a lone surrogate\"\n\n\n@dataclass(frozen=True, slots=True, kw_only=True)\nclass ParameterPlan:\n    \"\"\"Describe one effective parameter: location, style or content media, and lexical kinds.\"\"\"\n\n    location: ParameterLocation\n    name: str\n    style: str | None = None\n    explode: bool = False\n    required: bool = False\n    allow_reserved: bool = False\n    content_media_type: str | None = None\n    shape: ValueShape = \"scalar\"\n    kind: LexicalKind = \"string\"\n    fields: tuple[FieldPlan, ...] = ()\n    additional: FieldPlan | None = None\n    reserved_names: tuple[str, ...] = ()\n\n    def __post_init__(self) -> None:\n        \"\"\"Reject style, content, and shape combinations without a reversible builtin form.\n\n        A header needs a name that is a token, and so does a cookie sent as it is, a single value or one of the cookie\n        style.\n        \"\"\"\n        if not _reversible(self):\n            content = \"\" if self.content_media_type is None else f\" with content {self.content_media_type!r}\"\n            msg = f\"{self.location} parameter style {self.style!r}{content} has no builtin form for {self.shape} values\"\n            raise ValueError(msg)\n        if self.location == \"header\" and not is_token(self.name):\n            msg = f\"header name {self.name!r} is not a token, which every header field name must be\"\n            raise ValueError(msg)\n        if self.location == \"cookie\" and (self.style == \"cookie\" or self.shape == \"scalar\") and not is_token(self.name):\n            msg = f\"cookie parameter name {self.name!r} is not a token, which a cookie sent as it is needs\"\n            raise ValueError(msg)\n\n\ndef parameter_key(location: str, name: str) -> tuple[str, str]:\n    \"\"\"Return what identifies a parameter of a request: its location and name, a header's name in lower case.\n\n    Header field names are case-insensitive (RFC 9110), so two header parameters, targets or credentials that differ\n    only in case name the same field.\n    \"\"\"\n    return location, name.lower() if location == \"header\" else name\n\n\ndef builtin_content(location: ParameterLocation, media_type: str) -> bool:\n    \"\"\"Return whether a builtin codec carries parameter content of this media type in this location.\"\"\"\n    match media_kind(media_type):\n        case \"json\" | \"text\":\n            return location != \"cookie\"\n        case \"form\":\n            return location == \"querystring\"\n        case _:\n            return False\n\n\ndef _reversible(plan: ParameterPlan) -> bool:\n    if plan.content_media_type is not None:\n        return plan.style is None and builtin_content(plan.location, plan.content_media_type)\n    if plan.style is None or plan.style not in _STYLES.get(plan.location, ()):\n        return False\n    match plan.style, plan.shape, plan.explode:\n        case \"spaceDelimited\" | \"pipeDelimited\", shape, explode:\n            return shape != \"scalar\" and not explode\n        case \"deepObject\", shape, explode:\n            return shape == \"object\" and explode\n        case _, \"array\" | \"object\", False:\n            return plan.location != \"cookie\"\n        case _:\n            return True\n\n\n_Entry: TypeAlias = tuple[str | None, str]\n\n\ndef _entries(plan: ParameterPlan, value: JSONValue) -> list[_Entry]:\n    match plan.shape, value:\n        case _, None:\n            msg = \"JSON null cannot be written by a style-based parameter\"\n            raise ParameterEncodingError(msg)\n        case \"scalar\", _:\n            return [(None, lexical(value, plan.kind))]\n        case \"array\", tuple() | list():\n            return [(None, lexical(item, plan.kind)) for item in value]\n        case \"object\", Mapping():\n            return [(key, lexical(item, \"string\")) for key, item in value.items() if item is not None]\n        case _:\n            pass\n    msg = \"The value does not have the parameter's declared shape\"\n    raise ParameterEncodingError(msg)\n\n\ndef percent_encoded(text: str, safe: str) -> str:\n    \"\"\"Return a text percent-encoded but for unreserved and safe characters, keeping its percent-encoded octets.\"\"\"\n    return \"\".join(part if index % 2 else quote(part, safe=safe) for index, part in enumerate(_TRIPLET.split(text)))\n\n\ndef _percent(plan: ParameterPlan, kept: str) -> Callable[[str], str]:\n    if not plan.allow_reserved:\n        return lambda text: quote(text, safe=\"\")\n    safe = \"\".join(char for char in _RESERVED if char not in kept)\n    return lambda text: percent_encoded(text, safe)\n\n\ndef _encoded(entries: list[_Entry], encode: Callable[[str], str]) -> list[_Entry]:\n    return [(None if key is None else encode(key), encode(text)) for key, text in entries]\n\n\ndef _joined(entries: list[_Entry], *, separator: str = \",\", pair: str = \",\") -> str:\n    if not (joined := separator.join(text if key is None else f\"{key}{pair}{text}\" for key, text in entries)):\n        msg = \"An empty delimited value cannot be distinguished from an empty container\"\n        raise ParameterEncodingError(msg)\n    return joined\n\n\ndef _matrix(name: str, value: str) -> str:\n    return f\";{name}={value}\" if value else f\";{name}\"\n\n\ndef _encode_path(plan: ParameterPlan, entries: list[_Entry]) -> str:\n    encoded = _encoded(entries, encode := _percent(plan, _PATH_KEPT))\n    name = encode(plan.name)\n    match plan.style, plan.shape, plan.explode:\n        case \"simple\", \"scalar\", _:\n            text = encoded[0][1]\n        case \"simple\", _, explode:\n            text = _joined(encoded, pair=\"=\" if explode else \",\")\n        case \"label\", \"scalar\", _:\n            text = f\".{encoded[0][1]}\"\n        case \"label\", _, True:\n            if any(\".\" in part for entry in encoded for part in entry if part is not None):\n                msg = \"An exploded label value cannot contain its '.' delimiter\"\n                raise ParameterEncodingError(msg)\n            text = f\".{_joined(encoded, separator='.', pair='=')}\"\n        case \"label\", _, False:\n            text = f\".{_joined(encoded)}\"\n        case \"matrix\", \"scalar\", _:\n            text = _matrix(name, encoded[0][1])\n        case \"matrix\", _, True:\n            text = \"\".join(_matrix(name if key is None else key, value) for key, value in encoded)\n        case _:\n            text = f\";{name}={_joined(encoded)}\"\n    return text\n\n\ndef _encode_query(plan: ParameterPlan, entries: list[_Entry], *, raw: bool = False) -> list[_Entry]:\n    \"\"\"Return a query style's pairs, percent-encoded unless `raw` asks for the text form-data parts carry.\n\n    Raw text cannot escape a delimiter, so a value or member name that holds the one its style joins with is refused.\n    \"\"\"\n    encode: Callable[[str], str] = (lambda text: text) if raw else _percent(plan, _QUERY_KEPT)\n    encoded = entries if raw else _encoded(entries, encode)\n    name = encode(plan.name)\n    match plan.style, plan.shape, plan.explode:\n        case \"form\", \"scalar\", _:\n            return [(name, encoded[0][1])]\n        case \"form\", _, True:\n            return [(name if key is None else key, text) for key, text in encoded]\n        case (\"spaceDelimited\" | \"pipeDelimited\") as style, _, _:\n            delimiter, character = _DELIMITERS[style]\n            if any(character in part for entry in entries for part in entry if part is not None):\n                msg = \"A delimited query value cannot contain its own delimiter\"\n                raise ParameterEncodingError(msg)\n            separator = character if raw else delimiter\n            return [(name, _joined(encoded, separator=separator, pair=separator))]\n        case \"deepObject\", _, _:\n            return [(encode(f\"{plan.name}[{key}]\"), text) for (key, _), (_, text) in zip(entries, encoded, strict=True)]\n        case _ if raw and any(\",\" in part for entry in entries for part in entry if part is not None):\n            msg = \"A comma-delimited form-data value cannot contain a comma\"\n            raise ParameterEncodingError(msg)\n        case _:\n            pass\n    return [(name, _joined(encoded))]\n\n\ndef header_text(text: str) -> bool:\n    \"\"\"Return whether a text is a header value every recipient reads alike, as RFC 9110 writes one.\n\n    It holds HTAB, SP, and visible ASCII only, without whitespace at either end.\n    \"\"\"\n    return not _NOT_HEADER_TEXT.search(text) and text == text.strip(OWS)\n\n\ndef cookie_octets(text: str) -> bool:\n    \"\"\"Return whether a text is a cookie value sent as it is, unquoted cookie octets as RFC 6265 writes them.\n\n    It holds visible ASCII only, without `\"`, `,`, `;`, or a backslash.\n    \"\"\"\n    return _COOKIE_OCTETS.fullmatch(text) is not None\n\n\ndef _header_text(text: str, *, item: bool) -> str:\n    if not header_text(text) or (item and \",\" in text):\n        msg = \"A header value contains control characters, non-ASCII text, surrounding whitespace, or a list delimiter\"\n        raise ParameterEncodingError(msg)\n    return text\n\n\ndef _encode_header(plan: ParameterPlan, entries: list[_Entry]) -> str:\n    if plan.shape == \"scalar\":\n        return _header_text(entries[0][1], item=False)\n    checked = [\n        (None if key is None else _header_text(key, item=True), _header_text(text, item=True)) for key, text in entries\n    ]\n    if plan.explode and any(\"=\" in key for key, _ in checked if key is not None):\n        msg = \"An exploded header member name cannot contain '='\"\n        raise ParameterEncodingError(msg)\n    return _joined(checked, pair=\"=\" if plan.explode else \",\")\n\n\ndef _encode_cookie(plan: ParameterPlan, entries: list[_Entry]) -> list[_Entry]:\n    pairs = [(plan.name if key is None else key, text) for key, text in entries]\n    if plan.style == \"form\" and plan.shape != \"scalar\":\n        return [(quote(key, safe=\"\"), quote(text, safe=\"\")) for key, text in pairs]\n    if not all(is_token(key) and cookie_octets(text) for key, text in pairs):\n        msg = \"A cookie name must be a token and its value unquoted cookie octets\"\n        raise ParameterEncodingError(msg)\n    return list(pairs)\n\n\ndef _content(plan: ParameterPlan, value: JSONValue) -> str:\n    match media_kind(plan.content_media_type or \"\"), value:\n        case \"json\", _:\n            finite(value)\n            data = json_text(value).encode()\n            text = data.decode()\n            if plan.location != \"header\":\n                return text\n            return (text if data.isascii() else json_bytes(value, ascii_only=True).decode()).replace(\"\\x7f\", \"\\\\u007f\")\n        case \"text\", str():\n            return value\n        case _:\n            pass\n    msg = \"The parameter content media or value is not builtin\"\n    raise ParameterEncodingError(msg)\n\n\ndef _querystring_text(plan: ParameterPlan, value: JSONValue) -> str:\n    if media_kind(plan.content_media_type or \"\") == \"form\":\n        return encode_form(value, plan.fields, plan.additional).decode(\"ascii\")\n    return quote(_content(plan, value), safe=\"\")\n\n\ndef querystring(plan: ParameterPlan, value: object) -> str:\n    \"\"\"Return a querystring parameter's whole encoded query, without its leading question mark.\"\"\"\n    try:\n        text = _querystring_text(plan, cast(\"JSONValue\", value))\n    except UnicodeEncodeError:\n        raise ParameterEncodingError(_UNENCODABLE) from None\n    if text:\n        return text\n    msg = \"An explicit querystring value cannot encode to an empty query\"\n    raise ParameterEncodingError(msg)\n\n\ndef _style_pairs(plan: ParameterPlan, value: JSONValue) -> list[_Entry]:\n    \"\"\"Return a style's pairs of a value; an empty array or object writes none, as an omitted value does.\n\n    A style cannot write null, so an object member of None is left out as an unset one is. A path segment cannot be\n    omitted, so a path parameter refuses an empty array or object.\n    \"\"\"\n    if not (entries := _entries(plan, value)):\n        if plan.location == \"path\":\n            msg = \"An empty array or object cannot fill a path segment\"\n            raise ParameterEncodingError(msg)\n        return []\n    match plan.location:\n        case \"path\":\n            return [(None, _encode_path(plan, entries))]\n        case \"query\":\n            return _encode_query(plan, entries)\n        case \"header\":\n            return [(plan.name, _encode_header(plan, entries))]\n        case _:\n            pass\n    return _encode_cookie(plan, entries)\n\n\ndef _content_pairs(plan: ParameterPlan, value: JSONValue) -> list[_Entry]:\n    text = _content(plan, value)\n    match plan.location:\n        case \"path\":\n            return [(None, quote(text, safe=\"\"))]\n        case \"query\":\n            return [(quote(plan.name, safe=\"\"), quote(text, safe=\"\"))]\n        case _:\n            pass\n    return [(plan.name, _header_text(text, item=False))]\n\n\ndef pairs(plan: ParameterPlan, value: object) -> list[tuple[str | None, str]]:\n    \"\"\"Return a parameter's ordered encoded names and texts in its location: the style's pairs, or its content.\n\n    Text that UTF-8 cannot encode, such as a lone surrogate, raises ParameterEncodingError, as any value its style or\n    content cannot write does.\n    \"\"\"\n    try:\n        return (_style_pairs if plan.content_media_type is None else _content_pairs)(plan, cast(\"JSONValue\", value))\n    except UnicodeEncodeError:\n        raise ParameterEncodingError(_UNENCODABLE) from None\n\n\ndef path_text(plan: ParameterPlan, value: object) -> str:\n    \"\"\"Return the text a path parameter's value substitutes for its placeholder in the path template.\"\"\"\n    return \"\".join(text for _, text in pairs(plan, value))\n\n\ndef query_pairs(plan: ParameterPlan, value: object) -> tuple[str, ...]:\n    \"\"\"Return a query or cookie parameter's ordered name=value pairs as a query, form, or Cookie header carries them.\"\"\"\n    return tuple(f\"{key}={text}\" for key, text in pairs(plan, value))\n\n\ndef part_pairs(plan: ParameterPlan, value: object) -> tuple[tuple[str, str], ...]:\n    \"\"\"Return a query parameter's ordered names and values as form-data parts carry them, without percent-encoding.\"\"\"\n    if not (entries := _entries(plan, cast(\"JSONValue\", value))):\n        return ()\n    return tuple((plan.name if key is None else key, text) for key, text in _encode_query(plan, entries, raw=True))\n"
    },
    {
      "path": "server/_runtime/server/__init__.py",
      "content": "# first\n# second\n\n\"\"\"FastAPI server runtime of a generated package: request adapters, response dispatch, and HTTP results.\"\"\"\n"
    },
    {
      "path": "server/_runtime/server/application.py",
      "content": "# first\n# second\n\n\"\"\"Register a generated router's operations on one APIRouter, with the services that implement them.\"\"\"\n\nfrom __future__ import annotations\n\nimport inspect\nimport sys\nfrom collections.abc import Awaitable, Callable, Coroutine, Iterable, Mapping, MutableMapping, Sequence\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any, Final, NoReturn, TypeAlias, TypeGuard, TypeVar, cast\nfrom urllib.parse import unquote_to_bytes\n\nfrom fastapi import APIRouter\nfrom fastapi.encoders import jsonable_encoder\nfrom fastapi.exceptions import HTTPException, RequestValidationError\nfrom fastapi.params import Depends\nfrom fastapi.routing import APIRoute\nfrom starlette.concurrency import run_in_threadpool\nfrom starlette.responses import JSONResponse\nfrom starlette.routing import Match\nfrom typing_extensions import TypeIs\n\nif TYPE_CHECKING:\n    from starlette.requests import Request\n    from starlette.responses import Response\n    from starlette.types import Receive, Scope, Send\n\nMethodT = TypeVar(\"MethodT\")\n_REQUEST_VALUES: Final = frozenset({\"input\", \"ctx\", \"url\"})\n_LOCATIONS: Final = {\"path\": 0, \"query\": 1, \"header\": 2, \"cookie\": 3}\n\"\"\"The order of FastAPI's records by location; a body comes after every parameter.\"\"\"\n_REJECTED: Final = \"datamodel_code_generator.rejected\"\n_SLASH: Final = \"\\udc2f\"\n\"\"\"Stands for an encoded slash while a route matches; no decoded path holds a lone surrogate.\"\"\"\n\n\nclass RawPathRouter(APIRouter):\n    \"\"\"An APIRouter that matches its routes with each slash the raw path encodes kept inside its segment.\n\n    FastAPI matches and handles an included router through these methods, once per request; a path without an encoded\n    slash, or whose raw path does not spell it, goes through them unchanged. So does a path that selects a route the\n    router's user added, such as a mount or a Starlette route, which receives the decoded path as FastAPI routes it.\n    \"\"\"\n\n    def matches(self, scope: Scope) -> tuple[Match, Scope]:\n        \"\"\"Match the routes against the path with its encoded slashes marked.\"\"\"\n        if (marked := self._marked(scope)) is None:\n            return super().matches(scope)\n        _, match, child_scope = marked\n        return match, child_scope\n\n    async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:\n        \"\"\"Select the route by the path with its encoded slashes marked; the route puts the slashes back.\"\"\"\n        if (marked := self._marked(scope)) is None:\n            await super().handle(scope, receive, send)\n            return\n        decoded, scope[\"path\"] = scope[\"path\"], marked[0]\n        try:\n            await super().handle(scope, receive, send)\n        finally:\n            scope[\"path\"] = decoded\n\n    def _marked(self, scope: Scope) -> tuple[str, Match, Scope] | None:\n        \"\"\"Return the marked path and its match, unless it selects a route other than a RawPathRoute.\"\"\"\n        if (path := _segmented(scope)) is None:\n            return None\n        match, child_scope = super().matches({**scope, \"path\": path})\n        if match is not Match.NONE and not isinstance(child_scope.get(\"route\"), RawPathRoute):\n            return None\n        return path, match, child_scope\n\n\ndef malformed_request() -> HTTPException:\n    \"\"\"Return the error for request data that no declared parameter or media form can represent.\"\"\"\n    return HTTPException(status_code=400, detail=\"Invalid request\")\n\n\nclass ParameterReader:\n    \"\"\"A dependency that reads parameters FastAPI cannot: its route reports the records it rejects with FastAPI's.\"\"\"\n\n    __slots__ = ()\n\n\nclass _RejectedReadError(RequestValidationError, AttributeError):\n    \"\"\"The records of a Rejected value raised by reading a parameter value from it, which FastAPI answers with 422.\n\n    It is an AttributeError too, as reading an attribute raises it.\n    \"\"\"\n\n\n@dataclass(frozen=True, slots=True)\nclass Rejected:\n    \"\"\"The records of the parameters a request carries in forms their declarations reject, left by a ParameterReader.\n\n    Whichever raises them first takes them: the route with FastAPI's own records, or the endpoint when FastAPI found\n    none, through `accepted` or by reading a value of the record it stands for, as a route of a custom template that\n    leaves `accepted` out does before it calls the method.\n    \"\"\"\n\n    records: list[dict[str, object]]\n\n    def take(self) -> list[dict[str, object]]:\n        \"\"\"Return the records, leaving none to raise again.\"\"\"\n        records = self.records.copy()\n        self.records.clear()\n        return records\n\n    def __getattr__(self, name: str) -> NoReturn:\n        \"\"\"Raise the records for a parameter value read from the record; a special name is missing, as elsewhere.\"\"\"\n        if name.startswith(\"__\"):\n            raise AttributeError(name)\n        raise _RejectedReadError(self.take())\n\n\ndef reject(scope: MutableMapping[str, Any], records: list[dict[str, object]]) -> Rejected:\n    \"\"\"Leave the records of rejected parameters on a request's scope, and return them as a Rejected value.\"\"\"\n    scope[_REJECTED] = rejected = Rejected(records)\n    return rejected\n\n\nclass RawPathRoute(APIRoute):\n    \"\"\"An APIRoute of a RawPathRouter: it puts the slashes back in the path and its values before the endpoint runs.\n\n    A route with a ParameterReader dependency reports the records the reader leaves with FastAPI's own, and one with\n    header or cookie parameters that FastAPI reads answers 400 for a request whose value of one of them is not ASCII,\n    as a reader answers for the headers and cookies it reads.\n    \"\"\"\n\n    def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:\n        \"\"\"Return FastAPI's handler, which checks the text of its headers and raises a reader's records with its own.\"\"\"\n        handler = super().get_route_handler()\n        endpoint = self.dependant  # codespell:ignore dependant\n        headers = _names(endpoint.header_params, lower=True)\n        cookies = _names(endpoint.cookie_params, lower=False)\n        readers = any(isinstance(dependency.call, ParameterReader) for dependency in endpoint.dependencies)\n        if not (headers or cookies or readers):\n            return handler\n\n        async def reported(request: Request) -> Response:\n            if (headers or cookies) and not _ascii(request.scope[\"headers\"], headers, cookies):\n                raise malformed_request()\n            try:\n                return await handler(request)\n            except RequestValidationError as error:\n                if not isinstance(left := request.scope.get(_REJECTED), Rejected) or not (records := left.take()):\n                    raise\n                merged = sorted([*error.errors(), *records], key=_location)\n                raise RequestValidationError(merged, body=error.body, endpoint_ctx=error.endpoint_ctx) from None\n\n        return reported\n\n    async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:\n        \"\"\"Restore the decoded path and the path parameter values, then handle the request.\"\"\"\n        if _SLASH in (path := scope[\"path\"]):\n            scope[\"path\"] = path.replace(_SLASH, \"/\")\n            scope[\"path_params\"] = {\n                name: value.replace(_SLASH, \"/\") if isinstance(value, str) else value\n                for name, value in scope[\"path_params\"].items()\n            }\n        await super().handle(scope, receive, send)\n\n\ndef wire_named(names: Mapping[str, str]) -> type[RawPathRoute]:\n    \"\"\"Return a RawPathRoute class whose validation errors locate renamed path placeholders by their wire names.\n\n    FastAPI reads a path parameter by the name its placeholder has in the route path, and locates its records by that\n    name. `names` gives the wire name of each renamed placeholder FastAPI reads; only a request that fails validation\n    looks one up, before any exception handler receives the error.\n    \"\"\"\n\n    class WireNamedRoute(RawPathRoute):\n        def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:\n            handler = super().get_route_handler()\n\n            async def named(request: Request) -> Response:\n                try:\n                    return await handler(request)\n                except RequestValidationError as error:\n                    for record in error.errors():\n                        match record:\n                            case {\"loc\": (\"path\", str(), *_)} if (wire := names.get(record[\"loc\"][1])) is not None:\n                                record[\"loc\"] = (\"path\", wire, *record[\"loc\"][2:])\n                            case _:\n                                pass\n                    raise\n\n            return named\n\n    return WireNamedRoute\n\n\ndef _names(fields: Iterable[Any], *, lower: bool) -> frozenset[bytes]:\n    \"\"\"Return the names FastAPI reads parameters by, as raw header bytes: header names compare case-insensitively.\"\"\"\n    return frozenset((field.alias.lower() if lower else field.alias).encode(\"latin-1\", \"replace\") for field in fields)\n\n\ndef _ascii(lines: Iterable[tuple[bytes, bytes]], headers: frozenset[bytes], cookies: frozenset[bytes]) -> bool:\n    \"\"\"Return whether the request's values of the named headers and cookies are ASCII, as RFC 9110 and 6265 write them.\n\n    A cookie is found as Starlette finds it: a `;`-separated pair of a `Cookie` header, its name stripped.\n    \"\"\"\n    for name, value in lines:\n        if value.isascii():\n            continue\n        if name in headers or (\n            name == b\"cookie\"\n            and any(\n                separator and key.strip() in cookies and not text.isascii()\n                for key, separator, text in (pair.partition(b\"=\") for pair in value.split(b\";\"))\n            )\n        ):\n            return False\n    return True\n\n\ndef _location(record: Mapping[str, Any]) -> int:\n    \"\"\"Return where a record's location comes in FastAPI's order: path, query, header, and cookie, then the rest.\"\"\"\n    return _LOCATIONS.get((record.get(\"loc\") or (\"\",))[0], len(_LOCATIONS))\n\n\ndef _segmented(scope: Scope) -> str | None:\n    \"\"\"Return the path with the slashes its raw path encodes after the root path marked, or None without any.\"\"\"\n    raw: bytes = scope.get(\"raw_path\") or b\"\"\n    if raw.find(b\"%2F\") < 0 and raw.find(b\"%2f\") < 0:\n        return None\n    path: str = scope[\"path\"]\n    segments = (unquote_to_bytes(segment).decode(errors=\"replace\") for segment in raw.split(b\"/\"))\n    marked = \"/\".join(segment.replace(\"/\", _SLASH) for segment in segments)\n    plain = marked.replace(_SLASH, \"/\")\n    if not path.endswith(plain):\n        return None\n    offset = len(path) - len(plain)\n    root = scope.get(\"root_path\", \"\")\n    start = max(offset, len(root) if path.startswith(root) else 0)\n    tail = marked[start - offset :]\n    if _SLASH not in tail:\n        return None\n    return path[:start] + tail\n\n\ndef _coroutine_function(value: object) -> TypeGuard[Callable[..., Awaitable[object]]]:\n    \"\"\"Return whether calling a value, a function or an object with an async __call__, returns a coroutine.\"\"\"\n    return inspect.iscoroutinefunction(value) or inspect.iscoroutinefunction(getattr(value, \"__call__\", None))  # noqa: B004\n\n\ndef _awaitable(authorize: Callable[..., object]) -> Callable[..., Awaitable[object]]:\n    \"\"\"Return an authorize callback to await: a coroutine function as it is, any other run in the threadpool.\n\n    An awaitable that the other returns is awaited too, so its result or its rejection is the callback's.\n    \"\"\"\n    if _coroutine_function(authorize):\n        return authorize\n\n    async def threaded(requirements: object, credentials: object) -> object:\n        result = await run_in_threadpool(authorize, requirements, credentials)\n        return await result if inspect.isawaitable(result) else result\n\n    return threaded\n\n\n@dataclass(frozen=True, slots=True, kw_only=True)\nclass Wiring:\n    \"\"\"What route adders connect: the services by group, the authorize callback, and operation dependencies.\"\"\"\n\n    services: Mapping[str, Any]\n    authorize: object\n    dependencies: Mapping[str, Sequence[Depends]]\n\n    def authorizer(self) -> Callable[..., Awaitable[object]]:\n        \"\"\"Return the authorize callback to await, which a secured operation needs before it is registered.\"\"\"\n        if not callable(authorize := self.authorize):\n            msg = \"An authorize callback is required because the selected operations use security\"\n            raise TypeError(msg)\n        return _awaitable(authorize)\n\n\nRoute: TypeAlias = tuple[str, Callable[[APIRouter, Wiring], None]]\n\n\nasync def validation_error_handler(  # noqa: RUF029 - Starlette runs a synchronous handler in the threadpool.\n    _: Request, error: Exception\n) -> JSONResponse:\n    \"\"\"Answer 422 with the type, location, and message of each of FastAPI's records, without its input and context.\n\n    The error is the RequestValidationError the handler is registered for; Starlette types every handler's as Exception.\n    \"\"\"\n    errors = cast(\"RequestValidationError\", error).errors()\n    records = [{key: value for key, value in record.items() if key not in _REQUEST_VALUES} for record in errors]\n    return JSONResponse({\"detail\": jsonable_encoder(records)}, status_code=422)\n\n\ndef error_handlers(exception_handlers: Mapping[Any, Any] | None) -> dict[Any, Any]:\n    \"\"\"Return an application's exception handlers: validation_error_handler, under the caller's own handlers.\"\"\"\n    return {RequestValidationError: validation_error_handler, **(exception_handlers or {})}\n\n\ndef checked(\n    method: MethodT, label: str, keywords: tuple[str, ...] | None = None, *, asynchronous: bool = False\n) -> MethodT:\n    \"\"\"Return a service method for its operation, refusing one that its route cannot call as the route calls it.\n\n    A coroutine function where a plain one runs, or the reverse, would skip the method body or fail after it ran, and a\n    signature that does not take the keyword arguments the route passes, `keywords`, would fail on every request:\n    either stops the registration. A wider signature, with defaults or `**kwargs`, takes them. A route of a custom\n    template that names no keywords is not checked for them, and neither is a callable without a signature.\n    \"\"\"\n    if _coroutine_function(method) is not asynchronous:\n        kinds = (\"a coroutine function\", \"a plain method\")\n        found, needed = reversed(kinds) if asynchronous else kinds\n        msg = f\"{label} is {found}, but the operation's handler mode needs {needed}\"\n        raise TypeError(msg)\n    if keywords is None:\n        return method\n    try:\n        signature = _signature(cast(\"Callable[..., object]\", method))\n    except ValueError:\n        return method\n    try:\n        signature.bind(**dict.fromkeys(keywords))\n    except TypeError as error:\n        name = getattr(method, \"__qualname__\", repr(method))\n        passed = \", \".join(keywords) or \"none\"\n        msg = f\"{label}, {name}, cannot take the keyword arguments its route passes ({passed}): {error}\"\n        raise TypeError(msg) from None\n    return method\n\n\ndef _signature(method: Callable[..., object]) -> inspect.Signature:\n    \"\"\"Return a method's own signature, not that of a function it wraps, without evaluating its annotations.\"\"\"\n    if sys.version_info >= (3, 14):  # pragma: >=3.14 cover\n        from annotationlib import Format  # noqa: PLC0415\n\n        return inspect.signature(method, follow_wrapped=False, annotation_format=Format.FORWARDREF)\n    return inspect.signature(method, follow_wrapped=False)  # pragma: <3.14 cover\n\n\ndef missing_implementation(error: ImportError, implementations: Mapping[str, str]) -> None:\n    \"\"\"Raise an error naming what to write when the entrypoint could not import a module or name of yours.\n\n    `implementations` maps each module the entrypoint imports to the class or function it imports from it. Any other\n    import error, such as one in a module that an implementation imports, returns for the caller to re-raise unchanged.\n    Files are named where they are, relative to the working directory when they lie inside it.\n    \"\"\"\n    package = __name__.partition(\"._runtime.\")[0]\n    entrypoint = f\"{package}.main\"\n    root = Path(str(sys.modules[package].__file__)).parent\n    readme = f\"see Next steps in {_shown(root / 'README.md')}\"\n    name = error.name or \"\"\n    if isinstance(error, ModuleNotFoundError):\n        missing = {\n            module: item for module, item in implementations.items() if name in {module, module.rpartition(\".\")[0]}\n        }\n        if not missing:\n            return\n        files = [] if name in missing else [_shown(_file(root, package, name).with_suffix(\"\") / \"__init__.py\")]\n        files.extend(f\"{_shown(_file(root, package, module))} defining {item}\" for module, item in missing.items())\n        msg = (\n            f\"No module named {name!r}: create {', '.join(files)}, which {entrypoint} imports. Generating the \"\n            f\"server again writes missing modules with stubs; {readme}\"\n        )\n    elif (\n        (item := implementations.get(name)) is not None\n        and getattr(error, \"name_from\", item) == item\n        and not hasattr(module := sys.modules.get(name), item)\n    ):\n        where = _shown(Path(str(getattr(module, \"__file__\", None) or _file(root, package, name))))\n        msg = f\"{name} defines no {item}, which {entrypoint} imports: define it in {where}; {readme}\"\n    else:\n        return\n    raise ImportError(msg, name=name) from error\n\n\ndef _file(root: Path, package: str, module: str) -> Path:\n    \"\"\"Return the file a module of the package's parent package would have, beside the package's directory.\"\"\"\n    parent = package.rpartition(\".\")[0]\n    return root.parent.joinpath(*module.removeprefix(f\"{parent}.\" if parent else \"\").split(\".\")).with_suffix(\".py\")\n\n\ndef _shown(path: Path) -> str:\n    \"\"\"Return a path relative to the working directory when it lies inside it.\"\"\"\n    return (path.relative_to(cwd) if path.is_relative_to(cwd := Path.cwd()) else path).as_posix()\n\n\ndef _is_sequence(value: object) -> TypeIs[Sequence[object]]:\n    return isinstance(value, Sequence)\n\n\ndef build(  # noqa: PLR0913\n    routes: tuple[Route, ...],\n    *,\n    services: Mapping[str, Any],\n    authorize: object = None,\n    dependencies: Sequence[Depends],\n    operation_dependencies: Mapping[str, Any] | None,\n    prefix: str,\n) -> APIRouter:\n    \"\"\"Register the routes in order on a new router; each looks its service's method up as it registers.\n\n    The router is a RawPathRouter, so a percent-encoded slash stays inside the path parameter it belongs to.\n\n    The service Protocols and FastAPI check the services and settings. Refused here is what would otherwise drop a\n    dependency or an authorization without an error: a dependency for a method the router does not have, or one\n    that is no sequence of Depends, and, by the secured routes, a missing authorize callback.\n    \"\"\"\n    own = operation_dependencies or {}\n    if unknown := sorted(own.keys() - {name for name, _ in routes}):\n        msg = f\"operation_dependencies names no operation of this router: {', '.join(unknown)}\"\n        raise ValueError(msg)\n    for name, items in own.items():\n        if not (_is_sequence(items) and all(isinstance(item, Depends) for item in items)):\n            msg = f\"operation_dependencies[{name!r}] must be a sequence of Depends(...) values\"\n            raise TypeError(msg)\n    wiring = Wiring(services=services, authorize=authorize, dependencies=own)\n    router = RawPathRouter(prefix=prefix, dependencies=dependencies, route_class=RawPathRoute)\n    for _, add in routes:\n        add(router, wiring)\n    return router\n"
    },
    {
      "path": "server/_runtime/server/openapi.py",
      "content": "# first\n# second\n\n\"\"\"Serve a document of the application's own, such as the source OpenAPI document, instead of FastAPI's.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Any, Final, cast\n\nif TYPE_CHECKING:\n    from collections.abc import Callable, Mapping\n\n    from fastapi import FastAPI\n\n_INFO: Final = {\n    \"title\": \"title\",\n    \"version\": \"version\",\n    \"summary\": \"summary\",\n    \"description\": \"description\",\n    \"terms_of_service\": \"termsOfService\",\n    \"contact\": \"contact\",\n    \"license_info\": \"license\",\n}\n_PATHS: Final = \"#/paths/\"\n_LITERALS: Final = frozenset({\"value\", \"example\", \"default\", \"enum\", \"const\"})\n_ROOT: Final = {\"servers\": \"servers\", \"openapi_tags\": \"tags\", \"openapi_external_docs\": \"externalDocs\"}\n\n\ndef serve_openapi(\n    app: FastAPI,\n    load: Callable[[], dict[str, Any]],\n    *,\n    prefix: str = \"\",\n    metadata: Mapping[str, Any] | None = None,\n) -> None:\n    \"\"\"Make the application's document the one `load` returns, loaded on its first request and kept.\n\n    Its paths take the prefix the routes were included under, as in FastAPI's own document, and so do the references\n    and link operationRefs that name a path. The FastAPI settings in `metadata` that describe the application, such as\n    `title` or `servers`, replace the document's when they are set, as FastAPI leaves unset ones out. FastAPI's\n    documentation endpoints serve it as they serve FastAPI's own, the root path's server included. A document the\n    application built before is dropped.\n    \"\"\"\n    given = metadata or {}\n\n    def openapi() -> dict[str, Any]:\n        if not app.openapi_schema:\n            document = load()\n            if prefix:\n                document = cast(\"dict[str, Any]\", _prefixed(document, prefix))\n                document[\"paths\"] = {f\"{prefix}{path}\": item for path, item in document.get(\"paths\", {}).items()}\n            if info := {key: given[name] for name, key in _INFO.items() if given.get(name)}:\n                document[\"info\"] = {**document.get(\"info\", {}), **info}\n            document.update({key: given[name] for name, key in _ROOT.items() if given.get(name)})\n            app.openapi_schema = document\n        return app.openapi_schema\n\n    app.openapi_schema = None\n    setattr(app, \"openapi\", openapi)  # ruff: ignore[set-attr-with-constant] - FastAPI's documented way to replace the document.\n\n\ndef _prefixed(value: object, prefix: str) -> object:\n    \"\"\"Return a document value whose references and operationRefs into the document's paths name prefixed paths.\n\n    Literal data, such as examples, defaults, and extensions, stays as it is.\n    \"\"\"\n    if isinstance(value, list):\n        return [_prefixed(item, prefix) for item in cast(\"list[object]\", value)]\n    if not isinstance(value, dict):\n        return value\n    prefixed = {\n        key: item if _literal(key, item) else _prefixed(item, prefix)\n        for key, item in cast(\"dict[str, object]\", value).items()\n    }\n    for key in (\"$ref\", \"operationRef\"):\n        if isinstance(ref := prefixed.get(key), str) and ref.startswith(_PATHS):\n            prefixed[key] = _PATHS + prefix.replace(\"~\", \"~0\").replace(\"/\", \"~1\") + ref[len(_PATHS) :]\n    return prefixed\n\n\ndef _literal(key: str, value: object) -> bool:\n    \"\"\"Return whether a member holds literal data: an example value, a default, an enum, a const, or an extension.\n\n    A map of examples holds Example Objects, whose `value` is literal; a list of examples is a schema's.\n    \"\"\"\n    return key in _LITERALS or key.startswith(\"x-\") or (key == \"examples\" and isinstance(value, list))\n"
    },
    {
      "path": "server/_runtime/server/responses.py",
      "content": "# first\n# second\n\n\"\"\"HTTP results, and the declared responses an operation sends results and bare values as.\"\"\"\n\nfrom __future__ import annotations\n\nimport inspect\nfrom collections.abc import Callable, Coroutine, Iterable, Mapping\nfrom dataclasses import dataclass, field\nfrom typing import Final, Generic, Literal, cast\n\nfrom fastapi.encoders import jsonable_encoder\nfrom fastapi.exceptions import ResponseValidationError\nfrom pydantic import TypeAdapter, ValidationError\nfrom starlette.responses import Response\nfrom typing_extensions import TypeIs, TypeVar\n\nfrom ..model_codecs.media import JSON_MEDIA_TYPE, REDIRECT_STATUSES, bodyless, declaring, is_token, json_text\nfrom ..model_codecs.parameters import header_text\n\nBodyT_co = TypeVar(\"BodyT_co\", covariant=True)\n\n\n@dataclass(frozen=True, slots=True)\nclass HTTPResult(Generic[BodyT_co]):\n    \"\"\"Send one declared response: its status, an optional body of the declared type, and extra headers.\n\n    Without a body, a success response that declares content sends None through its model, as a bare value is sent:\n    `null` where the model accepts null, a validation error where it does not. A response whose JSON accepts null\n    sends `null` on any status, and any other response sends no body.\n    \"\"\"\n\n    status_code: int\n    body: BodyT_co | None = None\n    headers: Mapping[str, str] | None = None\n\n\n@dataclass(frozen=True, slots=True, kw_only=True)\nclass Declared:\n    \"\"\"One declared response: its default media type with that type's kind and charset, and the model its body takes.\n\n    A response that declares no content has no media type; a body sent under it anyway is JSON.\n    `null` says the body is JSON of a type that accepts null, so the response sends None as `null` instead of no body.\n    `dump` writes a JSON body by the model's adapter, for a model whose adapter's own dump leaves out what it holds.\n    The model's adapter is built when the response first sends a body; a concurrent first send builds an equal one.\n    \"\"\"\n\n    media_type: str | None = None\n    kind: Literal[\"json\", \"text\", \"form\", \"multipart\", \"binary\"] = \"json\"\n    charset: str = \"utf-8\"\n    model: object = None\n    null: bool = False\n    dump: Callable[[TypeAdapter[object], object], bytes] | None = None\n    _adapter: TypeAdapter[object] | None = field(default=None, init=False, repr=False, compare=False)\n\n    def adapter(self) -> TypeAdapter[object] | None:\n        \"\"\"Return the adapter of the body model, building and keeping it on first use, or None without a model.\"\"\"\n        if (adapter := self._adapter) is None and (model := self.model) is not None:\n            built: TypeAdapter[object] = TypeAdapter(cast(\"type[object]\", model))\n            object.__setattr__(self, \"_adapter\", built)  # noqa: PLC2801 - Keep the adapter on the frozen value.\n            return built\n        return adapter\n\n    def sends_none(self, status: int) -> bool:\n        \"\"\"Return whether the response sends None as a body: JSON that accepts null, or content of a success status.\"\"\"\n        return self.null or (self.media_type is not None and status < REDIRECT_STATUSES.start)\n\n\n_UNDECLARED: Final = Declared()\n\n\n@dataclass(frozen=True, slots=True, kw_only=True)\nclass OperationResponses:\n    \"\"\"An operation's declared responses by status key, and the status of a bare value the route sends itself.\n\n    FastAPI's response_model sends the bare value of an operation without that status. `primary_media` is the media\n    a bare value takes when it is chosen over the default media of the response that declares that status. `bare` is\n    False for an operation without a primary response, which refuses a bare value.\n    \"\"\"\n\n    responses: Mapping[str, Declared]\n    primary: int | None = None\n    primary_media: Declared | None = None\n    head: bool = False\n    bare: bool = True\n\n    def find(self, status: int) -> Declared | None:\n        \"\"\"Return the response that declares a status: exact, then the same status class, then default.\"\"\"\n        return declaring(status, self.responses)\n\n\ndef dispatch(value: object, plan: OperationResponses) -> object:\n    \"\"\"Pass a Response through, send an HTTPResult as its declared response, and leave a bare value to FastAPI.\n\n    An operation whose primary response FastAPI does not send sends a bare value as that response, and an operation\n    without a primary response refuses one.\n    \"\"\"\n    if isinstance(value, Response):\n        return value\n    if _is_result(value):\n        return _respond(value.status_code, value.body, value.headers, plan)\n    if plan.primary is not None:\n        return _respond(plan.primary, value, None, plan, plan.primary_media)\n    if plan.bare:\n        return value\n    msg = \"The method returned a value for an operation without a primary response; return an HTTPResult\"\n    raise _failure(msg)\n\n\ndef _is_result(value: object) -> TypeIs[HTTPResult[object]]:\n    return isinstance(value, HTTPResult)\n\n\ndef _respond(\n    status: int,\n    body: object,\n    headers: Mapping[str, str] | None,\n    plan: OperationResponses,\n    chosen: Declared | None = None,\n) -> Response:\n    \"\"\"Send a body as its declared response, raw bytes of a `text/*` one under its media type without a charset added.\n\n    Starlette labels every `text/*` body without a charset UTF-8, which only text the response encodes itself is.\n    \"\"\"\n    if headers:\n        _check_headers(headers.items())\n    declared = chosen or plan.find(status) or _UNDECLARED\n    if (body is None and not declared.sends_none(status)) or bodyless(status, head=plan.head):\n        if inspect.isawaitable(body):\n            raise _unawaited(body)\n        return Response(status_code=status, headers=headers)\n    media_type = declared.media_type or JSON_MEDIA_TYPE\n    if isinstance(content := _content(declared, body), str):\n        return Response(_encoded(declared, content), status_code=status, media_type=media_type, headers=headers)\n    if declared.kind == \"json\" or not media_type.startswith(\"text/\"):\n        return Response(content, status_code=status, media_type=media_type, headers=headers)\n    response = Response(content, status_code=status, headers=headers)\n    response.headers.setdefault(\"content-type\", media_type)\n    return response\n\n\ndef _check_headers(headers: Iterable[tuple[object, object]]) -> None:\n    \"\"\"Refuse a result's header whose name is not a token or whose value is not header text, as RFC 9110 writes them.\n\n    Header text, as the generated client sends it, is HTAB, SP, and visible ASCII, without whitespace at either end.\n    A result's headers may hold other values than its annotation says, such as bytes.\n    \"\"\"\n    for name, value in headers:\n        if not (isinstance(name, str) and is_token(name)):\n            msg = f\"The response header name {name!r} is not a token\"\n            raise _failure(msg)\n        if not (isinstance(value, str) and header_text(value)):\n            msg = f\"The {name} response header is not header text\"\n            raise _failure(msg)\n\n\ndef _unawaited(body: object) -> TypeError:\n    \"\"\"Return the error for an awaitable result that a response without a body would drop before it ran.\"\"\"\n    if isinstance(body, Coroutine):\n        body.close()\n    return TypeError(\"The method returned an awaitable for a response without a body; nothing awaited it\")\n\n\ndef _content(declared: Declared, body: object) -> str | bytes:\n    \"\"\"Return the text of a body to encode in the declared charset, or the bytes to send as they are.\n\n    A text body's model writes its value as its JSON text, an enum member as its value.\n    \"\"\"\n    json_media = declared.kind == \"json\"\n    if (adapter := declared.adapter()) is None:\n        payload = (\n            json_text(jsonable_encoder(body, by_alias=True, exclude_unset=True), errors=\"legacy-python-json-errors\")\n            if json_media\n            else body\n        )\n    else:\n        try:\n            value = adapter.validate_python(body)\n        except ValidationError as error:\n            raise ResponseValidationError(error.errors(include_url=False)) from error\n        if json_media:\n            if (dump := declared.dump) is None:\n                return adapter.dump_json(value, by_alias=True, exclude_unset=True)\n            return dump(adapter, value)\n        payload = adapter.dump_python(value, mode=\"json\" if declared.kind == \"text\" else \"python\", by_alias=True)\n    if isinstance(payload, (str, bytes)):\n        return payload\n    msg = f\"A {declared.media_type} body must be a string or bytes\"\n    raise _failure(msg)\n\n\ndef _encoded(declared: Declared, text: str) -> bytes:\n    try:\n        return text.encode(declared.charset)\n    except (LookupError, UnicodeError) as error:\n        msg = f\"The text body cannot be encoded as {declared.media_type}\"\n        raise _failure(msg) from error\n\n\ndef _failure(message: str) -> ResponseValidationError:\n    \"\"\"Return the error for a handler result that no declared response accepts.\"\"\"\n    return ResponseValidationError([{\"type\": \"value_error\", \"loc\": (\"response\",), \"msg\": message}])\n"
    },
    {
      "path": "server/application.py",
      "content": "# first\n# second\n\n\"\"\"Build the router and the application of every selected operation from the services that implement them.\"\"\"\n\nfrom collections.abc import Sequence\nfrom typing import Any, Final\n\nfrom fastapi import APIRouter, FastAPI, params\n\nfrom ._generated.contract import OperationDependencies\nfrom ._generated.openapi import serve_source_openapi\nfrom ._runtime.server.application import build, error_handlers, validation_error_handler\nfrom .routers import items, users\nfrom .services import ItemsService, UsersService\n\nROUTES: Final = (\n    *items.LITERAL_ROUTES,\n    *users.LITERAL_ROUTES,\n    *items.TEMPLATED_ROUTES,\n    *users.TEMPLATED_ROUTES,\n)\nINFO: Final[dict[str, Any]] = {'title': 'Inline', 'version': '1.0.0'}\n\n\ndef build_router(\n    *,\n    items: ItemsService,\n    users: UsersService,\n    dependencies: Sequence[params.Depends] = (),\n    operation_dependencies: OperationDependencies | None = None,\n    prefix: str = \"\",\n) -> APIRouter:\n    \"\"\"Register every operation on a new router, literal paths first.\"\"\"\n    return build(\n        ROUTES,\n        services={'items': items, 'users': users},\n        dependencies=dependencies,\n        operation_dependencies=operation_dependencies,\n        prefix=prefix,\n    )\n\n\ndef create_app(\n    *,\n    items: ItemsService,\n    users: UsersService,\n    operation_dependencies: OperationDependencies | None = None,\n    prefix: str = \"\",\n    source_openapi: bool = True,\n    **fastapi_kwargs: Any,\n) -> FastAPI:\n    \"\"\"Create the application with every operation, passing the other keyword arguments to FastAPI.\n\n    Validation errors leave out the request's values, unless exception_handlers handles RequestValidationError. The\n    application serves the source OpenAPI document of its operations, or FastAPI's own with source_openapi=False.\n    \"\"\"\n    fastapi_kwargs[\"exception_handlers\"] = error_handlers(fastapi_kwargs.get(\"exception_handlers\"))\n    app = FastAPI(**{**INFO, **fastapi_kwargs})\n    app.include_router(\n        build_router(\n            items=items,\n            users=users,\n            operation_dependencies=operation_dependencies,\n            prefix=prefix,\n        )\n    )\n    if source_openapi:\n        serve_source_openapi(app, prefix=prefix, metadata=fastapi_kwargs)\n    return app\n\n\n__all__ = [\n    'OperationDependencies',\n    'build_router',\n    'create_app',\n    'serve_source_openapi',\n    'validation_error_handler',\n]\n"
    },
    {
      "path": "server/main.py",
      "content": "# first\n# second\n\n\"\"\"Serve the application with your services: `uvicorn server.main:app`.\n\nGeneration overwrites this module. It imports your implementations from services, as Next steps in README.md\ndescribes, and passes them to create_app; to pass others, such as fakes in tests, call create_app yourself.\n\"\"\"\n\nfrom ._runtime.server.application import missing_implementation\nfrom .application import create_app\n\ntry:\n    from services.items import Items\n    from services.users import Users\nexcept ImportError as error:\n    missing_implementation(\n        error,\n        {\n            'services.items': 'Items',\n            'services.users': 'Users',\n        },\n    )\n    raise\n\napp = create_app(\n    items=Items(),\n    users=Users(),\n)\n"
    },
    {
      "path": "server/py.typed",
      "content": ""
    },
    {
      "path": "server/routers/__init__.py",
      "content": "# first\n# second\n\n\"\"\"Router groups of this package.\"\"\"\n"
    },
    {
      "path": "server/routers/items.py",
      "content": "# first\n# second\n\n\"\"\"Endpoints of the items operations; regenerate them instead of editing.\"\"\"\n\nfrom collections.abc import Sequence\nfrom typing import Final\n\nimport models\nfrom fastapi import APIRouter, params\n\nfrom .._generated import contract\nfrom .._generated.contract import OperationDependencies\nfrom .._runtime.server.application import Wiring, build, checked\nfrom .._runtime.server.responses import dispatch\nfrom ..services import ItemsService\n\n\ndef _add_list_items(\n    router: APIRouter,\n    wiring: Wiring,\n) -> None:\n    items: ItemsService = wiring.services['items']\n    list_items_handler = checked(\n        items.list_items,\n        'The items.list_items method of GET /items',\n        (),\n    )\n\n    def list_items() -> object:\n        return dispatch(\n            list_items_handler(),\n            contract.ListItems.RESPONSES,\n        )\n\n    router.add_api_route(\n        '/items',\n        list_items,\n        methods=['GET'],\n        status_code=200,\n        response_model=models.ItemsGetResponse,\n        response_model_by_alias=True,\n        response_model_exclude_unset=True,\n        operation_id='listItems',\n        tags=['items'],\n        response_description='Items',\n        dependencies=wiring.dependencies.get('list_items'),\n    )\n\n\nLITERAL_ROUTES: Final = (\n    ('list_items', _add_list_items),\n)\nTEMPLATED_ROUTES: Final = ()\n\n\ndef build_router(\n    *,\n    items: ItemsService,\n    dependencies: Sequence[params.Depends] = (),\n    operation_dependencies: OperationDependencies | None = None,\n    prefix: str = \"\",\n) -> APIRouter:\n    \"\"\"Register the items operations on a new router, literal paths first.\"\"\"\n    return build(\n        (*LITERAL_ROUTES, *TEMPLATED_ROUTES),\n        services={'items': items},\n        dependencies=dependencies,\n        operation_dependencies=operation_dependencies,\n        prefix=prefix,\n    )\n"
    },
    {
      "path": "server/routers/users.py",
      "content": "# first\n# second\n\n\"\"\"Endpoints of the users operations; regenerate them instead of editing.\"\"\"\n\nfrom collections.abc import Sequence\nfrom typing import Final\n\nfrom fastapi import APIRouter, params\nfrom fastapi.responses import Response\n\nfrom .._generated import contract\nfrom .._generated.contract import OperationDependencies\nfrom .._runtime.server.application import Wiring, build, checked\nfrom .._runtime.server.responses import dispatch\nfrom ..services import UsersService\n\n\ndef _add_list_users(\n    router: APIRouter,\n    wiring: Wiring,\n) -> None:\n    users: UsersService = wiring.services['users']\n    list_users_handler = checked(\n        users.list_users,\n        'The users.list_users method of GET /users',\n        (),\n    )\n\n    def list_users() -> object:\n        return dispatch(\n            list_users_handler(),\n            contract.ListUsers.RESPONSES,\n        )\n\n    router.add_api_route(\n        '/users',\n        list_users,\n        methods=['GET'],\n        status_code=204,\n        response_model=None,\n        response_class=Response,\n        operation_id='listUsers',\n        tags=['users'],\n        response_description='None',\n        dependencies=wiring.dependencies.get('list_users'),\n    )\n\n\nLITERAL_ROUTES: Final = (\n    ('list_users', _add_list_users),\n)\nTEMPLATED_ROUTES: Final = ()\n\n\ndef build_router(\n    *,\n    users: UsersService,\n    dependencies: Sequence[params.Depends] = (),\n    operation_dependencies: OperationDependencies | None = None,\n    prefix: str = \"\",\n) -> APIRouter:\n    \"\"\"Register the users operations on a new router, literal paths first.\"\"\"\n    return build(\n        (*LITERAL_ROUTES, *TEMPLATED_ROUTES),\n        services={'users': users},\n        dependencies=dependencies,\n        operation_dependencies=operation_dependencies,\n        prefix=prefix,\n    )\n"
    },
    {
      "path": "server/services.py",
      "content": "# first\n# second\n\n\"\"\"Service interfaces of this package's router groups; regenerate them instead of editing.\"\"\"\n\nfrom __future__ import annotations\n\nfrom abc import abstractmethod\nfrom typing import Protocol\n\nimport models\nfrom fastapi.responses import Response\n\nfrom ._runtime.server.responses import HTTPResult\n\n\nclass ItemsService(Protocol):\n    \"\"\"Implement the items operations: subclass this Protocol, or give an object its methods.\"\"\"\n\n    @abstractmethod\n    def list_items(\n        self,\n    ) -> models.ItemsGetResponse | HTTPResult[models.ItemsGetResponse] | Response:\n        \"\"\"\n        Handle GET /items.\n        \"\"\"\n\n\nclass UsersService(Protocol):\n    \"\"\"Implement the users operations: subclass this Protocol, or give an object its methods.\"\"\"\n\n    @abstractmethod\n    def list_users(\n        self,\n    ) -> None | HTTPResult[None] | Response:\n        \"\"\"\n        Handle GET /users.\n        \"\"\"\n"
    }
  ],
  "target": {
    "package": "server",
    "dependencies": [
      "fastapi>=0.141.1",
      "pydantic>=2.14.0",
      "typing-extensions>=4.16"
    ],
    "readme": "server/README.md",
    "entrypoint": {
      "app": "server.main:app",
      "path": "server/main.py"
    },
    "implementation": [
      {
        "module": "services.items",
        "name": "Items",
        "path": "services/items.py",
        "created": true
      },
      {
        "module": "services.users",
        "name": "Users",
        "path": "services/users.py",
        "created": true
      }
    ]
  }
}
