Repository: pydantic/pydantic

Issue:
reusing the same `Field` object in different Models
# 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`.

```py
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.

```bash
$ curl localhost:8000/expected -H "Content-Type: application/json" -d '{}'
{"detail":[{"loc":["body","i","required"],"msg":"field required","type":"value_error.missing"}]}
```

```bash
$ 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.


Discussion:
Hi @mleue ! Indeed it's definitely coming from `pydantic`. Here is the code to reproduce the error without `fastapi`
```python
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
```

Resolving patch:
diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -302,7 +302,7 @@ def infer(
         required: 'BoolUndefined' = Undefined
         if value is Required:
             required = True
-            field_info.default = None
+            value = None
         elif value is not Undefined:
             required = False
         field_info.alias = field_info.alias or field_info_from_config.get('alias')
@@ -312,7 +312,7 @@ def infer(
             type_=annotation,
             alias=field_info.alias,
             class_validators=class_validators,
-            default=field_info.default,
+            default=value,
             default_factory=field_info.default_factory,
             required=required,
             model_config=config,


Test patch:
diff --git a/tests/test_main.py b/tests/test_main.py
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -1095,3 +1095,18 @@ class Foo(BaseModel):
         assert f.foo is None
         assert f.bar is None
         assert f.baz is None
+
+
+def test_reuse_same_field():
+    required_field = Field(...)
+
+    class Model1(BaseModel):
+        required: str = required_field
+
+    class Model2(BaseModel):
+        required: str = required_field
+
+    with pytest.raises(ValidationError):
+        Model1.parse_obj({})
+    with pytest.raises(ValidationError):
+        Model2.parse_obj({})