Fastapi: [BUG] NewType breaks OpenAPI generation

Created on 13 Aug 2019  路  6Comments  路  Source: tiangolo/fastapi

Describe the bug
FastAPI fails to generate openapi.json when the schema contains types declared with typing.NewType

To Reproduce
Steps to reproduce the behavior:

  1. Create a file failme.py with contents:
from typing import NewType
from fastapi import FastAPI, Query, Body

app = FastAPI()

Identifier = NewType("Identifier", int)

@app.post("/inpath/{num}")
async def inpath(num: Identifier) -> str:
    return f"2*num={2*num}"

@app.post("/inquery/")
async def inquery(num: Identifier = Query(...)) -> str:
    return f"2*num={2*num}"

@app.post("/inbody/")
async def inbody(num: Identifier = Body(...)) -> str:
    return f"2*num={2*num}"
  1. Run the app:
uvloop failme:app
  1. Navigate to http://127.0.0.1:8000/docs
  2. The documentation is not rendered in the web page. The command line shows the error:
[...]
  File ".../lib/python3.7/site-packages/fastapi/applications.py", line 87, in openapi
    return JSONResponse(self.openapi())
  File ".../lib/python3.7/site-packages/fastapi/applications.py", line 79, in openapi
    openapi_prefix=self.openapi_prefix,
  File ".../lib/python3.7/site-packages/fastapi/openapi/utils.py", line 254, in get_openapi
    result = get_openapi_path(route=route, model_name_map=model_name_map)
  File ".../lib/python3.7/site-packages/fastapi/openapi/utils.py", line 163, in get_openapi_path
    all_route_params=all_route_params
  File ".../lib/python3.7/site-packages/fastapi/openapi/utils.py", line 87, in get_openapi_operation_parameters
    "schema": field_schema(param, model_name_map={})[0],
  File "pydantic/schema.py", line 288, in pydantic.schema.field_schema
  File "pydantic/schema.py", line 518, in pydantic.schema.field_type_schema
  File "pydantic/schema.py", line 745, in pydantic.schema.field_singleton_schema
TypeError: issubclass() arg 1 must be a class

Expected behavior
The OpenAPI documentation to be rendered rendered.

Screenshots
image

Environment:

  • OS: Linux
  • FastAPI Version 0.35.0

    • Python version: 3.7.3

bug

Most helpful comment

FYI: Resolved in #463

All 6 comments

This seems to be an upstream bug: samuelcolvin/pydantic#545

The bug was fixed in: samuelcolvin/pydantic#649

So upgrading to the most recent pydantic version should fix the problem. #423 seems to handle this. Looking forward to it :slightly_smiling_face:

But #423 is closed without merge. It's sad. @tiangolo

@Victor-Savu @xyb #423 was replaced with a different PR upgrading to newer pydantic. It is now merged; as of 0.38 NewType works for schema generation.

FYI: Resolved in #463

Thanks guys for the report, @dmontagu for the fix, and @Victor-Savu for reporting back/closing the issue. :tada: :rocket:

Its not working together with parameters validation.

user_id_path = Path(..., title='The ID of the User to get', ge=1)
UserId = NewType('UserId', int)

@users_router.get(
    path='/{user_id}',
    response_model=UserResponseModel,
    responses={404: {'model': NotFoundModel}},
)
async def get_user(user_id: UserId = user_id_path) -> UserResponseModel:
    return await User.get_or_404(user_id)

Traceback

Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/uvicorn/subprocess.py", line 62, in subprocess_started
    target(sockets=sockets)
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/uvicorn/main.py", line 382, in run
    loop.run_until_complete(self.serve(sockets=sockets))
  File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/uvicorn/main.py", line 389, in serve
    config.load()
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/uvicorn/config.py", line 288, in load
    self.loaded_app = import_from_string(self.app)
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/uvicorn/importer.py", line 20, in import_from_string
    module = importlib.import_module(module_str)
  File "/home/pentusha/.venvs/backend2/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "./api/asgi.py", line 1, in <module>
    from .main import get_app
  File "./api/main.py", line 5, in <module>
    from api.users.views import users_router
  File "./api/users/views.py", line 18, in <module>
    async def get_user(user_id: UserId = user_id_path) -> UserResponseModel:
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/fastapi/routing.py", line 514, in decorator
    self.add_api_route(
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/fastapi/routing.py", line 453, in add_api_route
    route = route_class(
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/fastapi/routing.py", line 370, in __init__
    self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/fastapi/dependencies/utils.py", line 291, in get_dependant
    param_field = get_param_field(
  File "/home/pentusha/.venvs/backend2/lib/python3.8/site-packages/fastapi/dependencies/utils.py", line 375, in get_param_field
    annotation = get_annotation_from_field_info(annotation, field_info, param_name)
  File "pydantic/schema.py", line 801, in pydantic.schema.get_annotation_from_field_info
ValueError: On field "user_id" the following field constraints are set but not enforced: ge. 
For more details see https://pydantic-docs.helpmanual.io/usage/schema/#unenforced-field-constraints
Was this page helpful?
0 / 5 - 0 ratings