Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reusing the same Field object in different Models #1412

Closed
mleue opened this issue Apr 22, 2020 · 2 comments · Fixed by #1413
Closed

reusing the same Field object in different Models #1412

mleue opened this issue Apr 22, 2020 · 2 comments · Fixed by #1413
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@mleue
Copy link

mleue commented Apr 22, 2020

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.5
            pydantic compiled: True
                 install path: /home/neuro/.local/share/virtualenvs/tmp--yQIjN1Q/lib/python3.7/site-packages/pydantic
               python version: 3.7.5 (default, Dec  3 2019, 16:12:26)  [GCC 9.2.0]
                     platform: Linux-5.6.2-arch1-2-x86_64-with-arch
     optional deps. installed: []

With pydantic 1.5 I've run into some issues with shared fields in different models. Unfortunately I can only recreate the issue when using the models in fastAPI endpoints. It's definitely a change in pydantic that introduced the issue (if I downgrade back to 1.4, the issue disappears), but it might be due to some quirky way that fastAPI is using pydantic models. In that case I'm happy to reraise the issue in the fastAPI project.

The problem I'm seeing is that if I reuse a required Field(...) in two separate models, only the first model correctly tells me that a required input is missing. The second model gets (incorrectly) instantiated with the required value set to None.

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()
required_field = Field(...)


class Model1(BaseModel):
    required: str = required_field


class Model2(BaseModel):
    required: str = required_field


@app.post("/expected")
async def expected(i: Model1):
    return i


@app.post("/unexpected")
async def unexpected(i: Model2):
    return i

Now if you fire some requests, you can see the weird difference in behavior between the /expected and /unexpected endpoint.

$ curl localhost:8000/expected -H "Content-Type: application/json" -d '{}'
{"detail":[{"loc":["body","i","required"],"msg":"field required","type":"value_error.missing"}]}
$ curl localhost:8000/unexpected -H "Content-Type: application/json" -d '{}'
{"required":null}

Maybe you can think of some change to Field between 1.4 and 1.5 that could be behind this weird behavior? If not I'm happy to try and isolate the problem some more and look into exactly how fastAPI is using the pydantic models and what might go wrong there.

Thanks in advance for any help.

@mleue mleue added the bug V1 Bug related to Pydantic V1.X label Apr 22, 2020
@PrettyWood
Copy link
Member

PrettyWood commented Apr 22, 2020

Hi @mleue ! Indeed it's definitely coming from pydantic. Here is the code to reproduce the error without fastapi

from pydantic import BaseModel, Field

required_field = Field(...)

class Model1(BaseModel):
    required: str = required_field


class Model2(BaseModel):
    required: str = required_field

# m1 = Model1.parse_obj({})  # Raises an error
m2 = Model2.parse_obj({})  # Should raise an error but doesn't

@mleue
Copy link
Author

mleue commented Apr 22, 2020

Wow. I can only say: "that was fast".
Thanks both of you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants