We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Concise typing.List type annotation throws error in DataFrameModel.to_schema()
**Describe the bug**

The [Using Data Types directly for Column Type Annotations](https://pandera.readthedocs.io/en/stable/dataframe_models.html#using-data-types-directly-for-column-type-annotations) feature doesn't work for a `typing.List` type as described in [Support for the python typing module](https://pandera.readthedocs.io/en/latest/dtype_validation.html?highlight=typing.List#support-for-the-python-typing-module)

#### Code Sample, a copy-pastable example

```python
from typing import List
import pandera as pa
from pandera.typing import Series

class TodoList(pa.DataFrameModel):
    items: List[str] = pa.Field(description="The scan IDs")

TodoList.to_schema() # throws error
```

This throws the error:
```py
Invalid annotation 'items: typing.List[str]'
```

#### Expected behavior
Should behave exactly the same as having an explicit `Series` data type:
```py
class TodoList(pa.DataFrameModel):
    # here, I wrap it in pa.typing.Series and it works
    items: pa.typing.Series[List[str]] = pa.Field(description="The scan IDs")
```

#### Desktop (please complete the following information):

 - OS: MacOS
 - Version: 14.1



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pandera/api/pandas/model.py`
Content:
```
1 """Class-based api for pandas models."""
2 
3 from typing import (
4     Any,
5     Dict,
6     List,
7     Optional,
8     Tuple,
9     Type,
10     Union,
11 )
12 
13 import pandas as pd
14 from pandera.api.checks import Check
15 from pandera.api.dataframe.model import (
16     DataFrameModel as _DataFrameModel,
17     get_dtype_kwargs,
18 )
19 from pandera.api.dataframe.model_components import FieldInfo
20 from pandera.api.pandas.container import DataFrameSchema
21 from pandera.api.pandas.components import Column, Index, MultiIndex
22 from pandera.api.pandas.model_config import BaseConfig
23 from pandera.errors import SchemaInitError
24 from pandera.typing import AnnotationInfo, INDEX_TYPES, SERIES_TYPES
25 
26 
27 SchemaIndex = Union[Index, MultiIndex]
28 
29 
30 class DataFrameModel(_DataFrameModel[pd.DataFrame, DataFrameSchema]):
31     """Model of a pandas :class:`~pandera.api.pandas.container.DataFrameSchema`.
32 
33     *new in 0.5.0*
34 
35     .. important::
36 
37         This class is the new name for ``SchemaModel``, which will be deprecated
38         in pandera version ``0.20.0``.
39 
40     See the :ref:`User Guide <dataframe-models>` for more.
41     """
42 
43     Config: Type[BaseConfig] = BaseConfig
44 
45     @classmethod
46     def build_schema_(cls, **kwargs) -> DataFrameSchema:
47         multiindex_kwargs = {
48             name[len("multiindex_") :]: value
49             for name, value in vars(cls.__config__).items()
50             if name.startswith("multiindex_")
51         }
52         columns, index = cls._build_columns_index(
53             cls.__fields__, cls.__checks__, **multiindex_kwargs
54         )
55         return DataFrameSchema(
56             columns,
57             index=index,
58             checks=cls.__root_checks__,
59             **kwargs,
60         )
61 
62     @classmethod
63     def _build_columns_index(  # pylint:disable=too-many-locals
64         cls,
65         fields: Dict[str, Tuple[AnnotationInfo, FieldInfo]],
66         checks: Dict[str, List[Check]],
67         **multiindex_kwargs: Any,
68     ) -> Tuple[Dict[str, Column], Optional[Union[Index, MultiIndex]],]:
69         index_count = sum(
70             annotation.origin in INDEX_TYPES
71             for annotation, _ in fields.values()
72         )
73 
74         columns: Dict[str, Column] = {}
75         indices: List[Index] = []
76         for field_name, (annotation, field) in fields.items():
77             field_checks = checks.get(field_name, [])
78             field_name = field.name
79             check_name = getattr(field, "check_name", None)
80 
81             if annotation.metadata:
82                 if field.dtype_kwargs:
83                     raise TypeError(
84                         "Cannot specify redundant 'dtype_kwargs' "
85                         + f"for {annotation.raw_annotation}."
86                         + "\n Usage Tip: Drop 'typing.Annotated'."
87                     )
88                 dtype_kwargs = get_dtype_kwargs(annotation)
89                 dtype = annotation.arg(**dtype_kwargs)  # type: ignore
90             elif annotation.default_dtype:
91                 dtype = annotation.default_dtype
92             else:
93                 dtype = annotation.arg
94 
95             dtype = None if dtype is Any else dtype
96 
97             if (
98                 annotation.is_annotated_type
99                 or annotation.origin is None
100                 or annotation.origin in SERIES_TYPES
101                 or annotation.raw_annotation in SERIES_TYPES
102             ):
103                 if check_name is False:
104                     raise SchemaInitError(
105                         f"'check_name' is not supported for {field_name}."
106                     )
107 
108                 column_kwargs = (
109                     field.column_properties(
110                         dtype,
111                         required=not annotation.optional,
112                         checks=field_checks,
113                         name=field_name,
114                     )
115                     if field
116                     else {}
117                 )
118                 columns[field_name] = Column(**column_kwargs)
119 
120             elif (
121                 annotation.origin in INDEX_TYPES
122                 or annotation.raw_annotation in INDEX_TYPES
123             ):
124                 if annotation.optional:
125                     raise SchemaInitError(
126                         f"Index '{field_name}' cannot be Optional."
127                     )
128 
129                 if check_name is False or (
130                     # default single index
131                     check_name is None
132                     and index_count == 1
133                 ):
134                     field_name = None  # type:ignore
135 
136                 index_kwargs = (
137                     field.index_properties(
138                         dtype,
139                         checks=field_checks,
140                         name=field_name,
141                     )
142                     if field
143                     else {}
144                 )
145                 index = Index(**index_kwargs)
146                 indices.append(index)
147             else:
148                 raise SchemaInitError(
149                     f"Invalid annotation '{field_name}: "
150                     f"{annotation.raw_annotation}'"
151                 )
152 
153         return columns, _build_schema_index(indices, **multiindex_kwargs)
154 
155     @classmethod
156     def to_json_schema(cls):
157         """Serialize schema metadata into json-schema format.
158 
159         :param dataframe_schema: schema to write to json-schema format.
160 
161         .. note::
162 
163             This function is currently does not fully specify a pandera schema,
164             and is primarily used internally to render OpenAPI docs via the
165             FastAPI integration.
166         """
167         schema = cls.to_schema()
168         empty = pd.DataFrame(columns=schema.columns.keys()).astype(
169             {k: v.type for k, v in schema.dtypes.items()}
170         )
171         table_schema = pd.io.json.build_table_schema(empty)
172 
173         def _field_json_schema(field):
174             return {
175                 "type": "array",
176                 "items": {"type": field["type"]},
177             }
178 
179         return {
180             "title": schema.name or "pandera.DataFrameSchema",
181             "type": "object",
182             "properties": {
183                 field["name"]: _field_json_schema(field)
184                 for field in table_schema["fields"]
185             },
186         }
187 
188 
189 SchemaModel = DataFrameModel
190 """
191 Alias for DataFrameModel.
192 
193 .. warning::
194 
195    This subclass is necessary for backwards compatibility, and will be
196    deprecated in pandera version ``0.20.0`` in favor of
197    :py:class:`~pandera.api.pandas.model.DataFrameModel`
198 """
199 
200 
201 def _build_schema_index(
202     indices: List[Index], **multiindex_kwargs: Any
203 ) -> Optional[SchemaIndex]:
204     index: Optional[SchemaIndex] = None
205     if indices:
206         if len(indices) == 1:
207             index = indices[0]
208         else:
209             index = MultiIndex(indices, **multiindex_kwargs)
210     return index
211
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pandera/api/pandas/model.py b/pandera/api/pandas/model.py
--- a/pandera/api/pandas/model.py
+++ b/pandera/api/pandas/model.py
@@ -20,6 +20,7 @@
 from pandera.api.pandas.container import DataFrameSchema
 from pandera.api.pandas.components import Column, Index, MultiIndex
 from pandera.api.pandas.model_config import BaseConfig
+from pandera.engines.pandas_engine import Engine
 from pandera.errors import SchemaInitError
 from pandera.typing import AnnotationInfo, INDEX_TYPES, SERIES_TYPES
 
@@ -78,6 +79,7 @@
             field_name = field.name
             check_name = getattr(field, "check_name", None)
 
+            use_raw_annotation = False
             if annotation.metadata:
                 if field.dtype_kwargs:
                     raise TypeError(
@@ -90,13 +92,21 @@
             elif annotation.default_dtype:
                 dtype = annotation.default_dtype
             else:
-                dtype = annotation.arg
+                try:
+                    # if the raw annotation is accepted by the engine, use it as
+                    # the dtype
+                    Engine.dtype(annotation.raw_annotation)
+                    dtype = annotation.raw_annotation
+                    use_raw_annotation = True
+                except TypeError:
+                    dtype = annotation.arg
 
             dtype = None if dtype is Any else dtype
 
             if (
                 annotation.is_annotated_type
                 or annotation.origin is None
+                or use_raw_annotation
                 or annotation.origin in SERIES_TYPES
                 or annotation.raw_annotation in SERIES_TYPES
             ):

{"golden_diff": "diff --git a/pandera/api/pandas/model.py b/pandera/api/pandas/model.py\n--- a/pandera/api/pandas/model.py\n+++ b/pandera/api/pandas/model.py\n@@ -20,6 +20,7 @@\n from pandera.api.pandas.container import DataFrameSchema\n from pandera.api.pandas.components import Column, Index, MultiIndex\n from pandera.api.pandas.model_config import BaseConfig\n+from pandera.engines.pandas_engine import Engine\n from pandera.errors import SchemaInitError\n from pandera.typing import AnnotationInfo, INDEX_TYPES, SERIES_TYPES\n \n@@ -78,6 +79,7 @@\n             field_name = field.name\n             check_name = getattr(field, \"check_name\", None)\n \n+            use_raw_annotation = False\n             if annotation.metadata:\n                 if field.dtype_kwargs:\n                     raise TypeError(\n@@ -90,13 +92,21 @@\n             elif annotation.default_dtype:\n                 dtype = annotation.default_dtype\n             else:\n-                dtype = annotation.arg\n+                try:\n+                    # if the raw annotation is accepted by the engine, use it as\n+                    # the dtype\n+                    Engine.dtype(annotation.raw_annotation)\n+                    dtype = annotation.raw_annotation\n+                    use_raw_annotation = True\n+                except TypeError:\n+                    dtype = annotation.arg\n \n             dtype = None if dtype is Any else dtype\n \n             if (\n                 annotation.is_annotated_type\n                 or annotation.origin is None\n+                or use_raw_annotation\n                 or annotation.origin in SERIES_TYPES\n                 or annotation.raw_annotation in SERIES_TYPES\n             ):\n", "issue": "Concise typing.List type annotation throws error in DataFrameModel.to_schema()\n**Describe the bug**\r\n\r\nThe [Using Data Types directly for Column Type Annotations](https://pandera.readthedocs.io/en/stable/dataframe_models.html#using-data-types-directly-for-column-type-annotations) feature doesn't work for a `typing.List` type as described in [Support for the python typing module](https://pandera.readthedocs.io/en/latest/dtype_validation.html?highlight=typing.List#support-for-the-python-typing-module)\r\n\r\n#### Code Sample, a copy-pastable example\r\n\r\n```python\r\nfrom typing import List\r\nimport pandera as pa\r\nfrom pandera.typing import Series\r\n\r\nclass TodoList(pa.DataFrameModel):\r\n    items: List[str] = pa.Field(description=\"The scan IDs\")\r\n\r\nTodoList.to_schema() # throws error\r\n```\r\n\r\nThis throws the error:\r\n```py\r\nInvalid annotation 'items: typing.List[str]'\r\n```\r\n\r\n#### Expected behavior\r\nShould behave exactly the same as having an explicit `Series` data type:\r\n```py\r\nclass TodoList(pa.DataFrameModel):\r\n    # here, I wrap it in pa.typing.Series and it works\r\n    items: pa.typing.Series[List[str]] = pa.Field(description=\"The scan IDs\")\r\n```\r\n\r\n#### Desktop (please complete the following information):\r\n\r\n - OS: MacOS\r\n - Version: 14.1\r\n\r\n\n", "before_files": [{"content": "\"\"\"Class-based api for pandas models.\"\"\"\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\n\nimport pandas as pd\nfrom pandera.api.checks import Check\nfrom pandera.api.dataframe.model import (\n    DataFrameModel as _DataFrameModel,\n    get_dtype_kwargs,\n)\nfrom pandera.api.dataframe.model_components import FieldInfo\nfrom pandera.api.pandas.container import DataFrameSchema\nfrom pandera.api.pandas.components import Column, Index, MultiIndex\nfrom pandera.api.pandas.model_config import BaseConfig\nfrom pandera.errors import SchemaInitError\nfrom pandera.typing import AnnotationInfo, INDEX_TYPES, SERIES_TYPES\n\n\nSchemaIndex = Union[Index, MultiIndex]\n\n\nclass DataFrameModel(_DataFrameModel[pd.DataFrame, DataFrameSchema]):\n    \"\"\"Model of a pandas :class:`~pandera.api.pandas.container.DataFrameSchema`.\n\n    *new in 0.5.0*\n\n    .. important::\n\n        This class is the new name for ``SchemaModel``, which will be deprecated\n        in pandera version ``0.20.0``.\n\n    See the :ref:`User Guide <dataframe-models>` for more.\n    \"\"\"\n\n    Config: Type[BaseConfig] = BaseConfig\n\n    @classmethod\n    def build_schema_(cls, **kwargs) -> DataFrameSchema:\n        multiindex_kwargs = {\n            name[len(\"multiindex_\") :]: value\n            for name, value in vars(cls.__config__).items()\n            if name.startswith(\"multiindex_\")\n        }\n        columns, index = cls._build_columns_index(\n            cls.__fields__, cls.__checks__, **multiindex_kwargs\n        )\n        return DataFrameSchema(\n            columns,\n            index=index,\n            checks=cls.__root_checks__,\n            **kwargs,\n        )\n\n    @classmethod\n    def _build_columns_index(  # pylint:disable=too-many-locals\n        cls,\n        fields: Dict[str, Tuple[AnnotationInfo, FieldInfo]],\n        checks: Dict[str, List[Check]],\n        **multiindex_kwargs: Any,\n    ) -> Tuple[Dict[str, Column], Optional[Union[Index, MultiIndex]],]:\n        index_count = sum(\n            annotation.origin in INDEX_TYPES\n            for annotation, _ in fields.values()\n        )\n\n        columns: Dict[str, Column] = {}\n        indices: List[Index] = []\n        for field_name, (annotation, field) in fields.items():\n            field_checks = checks.get(field_name, [])\n            field_name = field.name\n            check_name = getattr(field, \"check_name\", None)\n\n            if annotation.metadata:\n                if field.dtype_kwargs:\n                    raise TypeError(\n                        \"Cannot specify redundant 'dtype_kwargs' \"\n                        + f\"for {annotation.raw_annotation}.\"\n                        + \"\\n Usage Tip: Drop 'typing.Annotated'.\"\n                    )\n                dtype_kwargs = get_dtype_kwargs(annotation)\n                dtype = annotation.arg(**dtype_kwargs)  # type: ignore\n            elif annotation.default_dtype:\n                dtype = annotation.default_dtype\n            else:\n                dtype = annotation.arg\n\n            dtype = None if dtype is Any else dtype\n\n            if (\n                annotation.is_annotated_type\n                or annotation.origin is None\n                or annotation.origin in SERIES_TYPES\n                or annotation.raw_annotation in SERIES_TYPES\n            ):\n                if check_name is False:\n                    raise SchemaInitError(\n                        f\"'check_name' is not supported for {field_name}.\"\n                    )\n\n                column_kwargs = (\n                    field.column_properties(\n                        dtype,\n                        required=not annotation.optional,\n                        checks=field_checks,\n                        name=field_name,\n                    )\n                    if field\n                    else {}\n                )\n                columns[field_name] = Column(**column_kwargs)\n\n            elif (\n                annotation.origin in INDEX_TYPES\n                or annotation.raw_annotation in INDEX_TYPES\n            ):\n                if annotation.optional:\n                    raise SchemaInitError(\n                        f\"Index '{field_name}' cannot be Optional.\"\n                    )\n\n                if check_name is False or (\n                    # default single index\n                    check_name is None\n                    and index_count == 1\n                ):\n                    field_name = None  # type:ignore\n\n                index_kwargs = (\n                    field.index_properties(\n                        dtype,\n                        checks=field_checks,\n                        name=field_name,\n                    )\n                    if field\n                    else {}\n                )\n                index = Index(**index_kwargs)\n                indices.append(index)\n            else:\n                raise SchemaInitError(\n                    f\"Invalid annotation '{field_name}: \"\n                    f\"{annotation.raw_annotation}'\"\n                )\n\n        return columns, _build_schema_index(indices, **multiindex_kwargs)\n\n    @classmethod\n    def to_json_schema(cls):\n        \"\"\"Serialize schema metadata into json-schema format.\n\n        :param dataframe_schema: schema to write to json-schema format.\n\n        .. note::\n\n            This function is currently does not fully specify a pandera schema,\n            and is primarily used internally to render OpenAPI docs via the\n            FastAPI integration.\n        \"\"\"\n        schema = cls.to_schema()\n        empty = pd.DataFrame(columns=schema.columns.keys()).astype(\n            {k: v.type for k, v in schema.dtypes.items()}\n        )\n        table_schema = pd.io.json.build_table_schema(empty)\n\n        def _field_json_schema(field):\n            return {\n                \"type\": \"array\",\n                \"items\": {\"type\": field[\"type\"]},\n            }\n\n        return {\n            \"title\": schema.name or \"pandera.DataFrameSchema\",\n            \"type\": \"object\",\n            \"properties\": {\n                field[\"name\"]: _field_json_schema(field)\n                for field in table_schema[\"fields\"]\n            },\n        }\n\n\nSchemaModel = DataFrameModel\n\"\"\"\nAlias for DataFrameModel.\n\n.. warning::\n\n   This subclass is necessary for backwards compatibility, and will be\n   deprecated in pandera version ``0.20.0`` in favor of\n   :py:class:`~pandera.api.pandas.model.DataFrameModel`\n\"\"\"\n\n\ndef _build_schema_index(\n    indices: List[Index], **multiindex_kwargs: Any\n) -> Optional[SchemaIndex]:\n    index: Optional[SchemaIndex] = None\n    if indices:\n        if len(indices) == 1:\n            index = indices[0]\n        else:\n            index = MultiIndex(indices, **multiindex_kwargs)\n    return index\n", "path": "pandera/api/pandas/model.py"}], "after_files": [{"content": "\"\"\"Class-based api for pandas models.\"\"\"\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\n\nimport pandas as pd\nfrom pandera.api.checks import Check\nfrom pandera.api.dataframe.model import (\n    DataFrameModel as _DataFrameModel,\n    get_dtype_kwargs,\n)\nfrom pandera.api.dataframe.model_components import FieldInfo\nfrom pandera.api.pandas.container import DataFrameSchema\nfrom pandera.api.pandas.components import Column, Index, MultiIndex\nfrom pandera.api.pandas.model_config import BaseConfig\nfrom pandera.engines.pandas_engine import Engine\nfrom pandera.errors import SchemaInitError\nfrom pandera.typing import AnnotationInfo, INDEX_TYPES, SERIES_TYPES\n\n\nSchemaIndex = Union[Index, MultiIndex]\n\n\nclass DataFrameModel(_DataFrameModel[pd.DataFrame, DataFrameSchema]):\n    \"\"\"Model of a pandas :class:`~pandera.api.pandas.container.DataFrameSchema`.\n\n    *new in 0.5.0*\n\n    .. important::\n\n        This class is the new name for ``SchemaModel``, which will be deprecated\n        in pandera version ``0.20.0``.\n\n    See the :ref:`User Guide <dataframe-models>` for more.\n    \"\"\"\n\n    Config: Type[BaseConfig] = BaseConfig\n\n    @classmethod\n    def build_schema_(cls, **kwargs) -> DataFrameSchema:\n        multiindex_kwargs = {\n            name[len(\"multiindex_\") :]: value\n            for name, value in vars(cls.__config__).items()\n            if name.startswith(\"multiindex_\")\n        }\n        columns, index = cls._build_columns_index(\n            cls.__fields__, cls.__checks__, **multiindex_kwargs\n        )\n        return DataFrameSchema(\n            columns,\n            index=index,\n            checks=cls.__root_checks__,\n            **kwargs,\n        )\n\n    @classmethod\n    def _build_columns_index(  # pylint:disable=too-many-locals\n        cls,\n        fields: Dict[str, Tuple[AnnotationInfo, FieldInfo]],\n        checks: Dict[str, List[Check]],\n        **multiindex_kwargs: Any,\n    ) -> Tuple[Dict[str, Column], Optional[Union[Index, MultiIndex]],]:\n        index_count = sum(\n            annotation.origin in INDEX_TYPES\n            for annotation, _ in fields.values()\n        )\n\n        columns: Dict[str, Column] = {}\n        indices: List[Index] = []\n        for field_name, (annotation, field) in fields.items():\n            field_checks = checks.get(field_name, [])\n            field_name = field.name\n            check_name = getattr(field, \"check_name\", None)\n\n            use_raw_annotation = False\n            if annotation.metadata:\n                if field.dtype_kwargs:\n                    raise TypeError(\n                        \"Cannot specify redundant 'dtype_kwargs' \"\n                        + f\"for {annotation.raw_annotation}.\"\n                        + \"\\n Usage Tip: Drop 'typing.Annotated'.\"\n                    )\n                dtype_kwargs = get_dtype_kwargs(annotation)\n                dtype = annotation.arg(**dtype_kwargs)  # type: ignore\n            elif annotation.default_dtype:\n                dtype = annotation.default_dtype\n            else:\n                try:\n                    # if the raw annotation is accepted by the engine, use it as\n                    # the dtype\n                    Engine.dtype(annotation.raw_annotation)\n                    dtype = annotation.raw_annotation\n                    use_raw_annotation = True\n                except TypeError:\n                    dtype = annotation.arg\n\n            dtype = None if dtype is Any else dtype\n\n            if (\n                annotation.is_annotated_type\n                or annotation.origin is None\n                or use_raw_annotation\n                or annotation.origin in SERIES_TYPES\n                or annotation.raw_annotation in SERIES_TYPES\n            ):\n                if check_name is False:\n                    raise SchemaInitError(\n                        f\"'check_name' is not supported for {field_name}.\"\n                    )\n\n                column_kwargs = (\n                    field.column_properties(\n                        dtype,\n                        required=not annotation.optional,\n                        checks=field_checks,\n                        name=field_name,\n                    )\n                    if field\n                    else {}\n                )\n                columns[field_name] = Column(**column_kwargs)\n\n            elif (\n                annotation.origin in INDEX_TYPES\n                or annotation.raw_annotation in INDEX_TYPES\n            ):\n                if annotation.optional:\n                    raise SchemaInitError(\n                        f\"Index '{field_name}' cannot be Optional.\"\n                    )\n\n                if check_name is False or (\n                    # default single index\n                    check_name is None\n                    and index_count == 1\n                ):\n                    field_name = None  # type:ignore\n\n                index_kwargs = (\n                    field.index_properties(\n                        dtype,\n                        checks=field_checks,\n                        name=field_name,\n                    )\n                    if field\n                    else {}\n                )\n                index = Index(**index_kwargs)\n                indices.append(index)\n            else:\n                raise SchemaInitError(\n                    f\"Invalid annotation '{field_name}: \"\n                    f\"{annotation.raw_annotation}'\"\n                )\n\n        return columns, _build_schema_index(indices, **multiindex_kwargs)\n\n    @classmethod\n    def to_json_schema(cls):\n        \"\"\"Serialize schema metadata into json-schema format.\n\n        :param dataframe_schema: schema to write to json-schema format.\n\n        .. note::\n\n            This function is currently does not fully specify a pandera schema,\n            and is primarily used internally to render OpenAPI docs via the\n            FastAPI integration.\n        \"\"\"\n        schema = cls.to_schema()\n        empty = pd.DataFrame(columns=schema.columns.keys()).astype(\n            {k: v.type for k, v in schema.dtypes.items()}\n        )\n        table_schema = pd.io.json.build_table_schema(empty)\n\n        def _field_json_schema(field):\n            return {\n                \"type\": \"array\",\n                \"items\": {\"type\": field[\"type\"]},\n            }\n\n        return {\n            \"title\": schema.name or \"pandera.DataFrameSchema\",\n            \"type\": \"object\",\n            \"properties\": {\n                field[\"name\"]: _field_json_schema(field)\n                for field in table_schema[\"fields\"]\n            },\n        }\n\n\nSchemaModel = DataFrameModel\n\"\"\"\nAlias for DataFrameModel.\n\n.. warning::\n\n   This subclass is necessary for backwards compatibility, and will be\n   deprecated in pandera version ``0.20.0`` in favor of\n   :py:class:`~pandera.api.pandas.model.DataFrameModel`\n\"\"\"\n\n\ndef _build_schema_index(\n    indices: List[Index], **multiindex_kwargs: Any\n) -> Optional[SchemaIndex]:\n    index: Optional[SchemaIndex] = None\n    if indices:\n        if len(indices) == 1:\n            index = indices[0]\n        else:\n            index = MultiIndex(indices, **multiindex_kwargs)\n    return index\n", "path": "pandera/api/pandas/model.py"}]}