Repository: pydantic/pydantic

Issue:
Model signature generation makes incorrect signature for models with extras allowed and `data` attribute in spec 
# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
             pydantic version: 1.5
            pydantic compiled: False
                 install path: /home/jrootjunior/.cache/pypoetry/virtualenvs/aiogram-BAWpo_Vh-py3.8/lib/python3.8/site-packages/pydantic
               python version: 3.8.2 (default, Apr  8 2020, 14:31:25)  [GCC 9.3.0]
                     platform: Linux-5.6.3-arch1-1-x86_64-with-glibc2.2.5
     optional deps. installed: ['typing-extensions']
```

## Explanation
Feature from #1034 breaks things when model has `data` attribute and extra arguments is allowed and this attribute is not the last one in class.

## Code snippet
```py
import inspect
from typing import Optional

from pydantic import BaseModel, Extra


class MyObject(BaseModel):
    foo: Optional[str] = None
    data: Optional[str] = None
    bar: Optional[str] = None

    class Config:
        extra = Extra.allow
```
## Caused an exception
```py
Traceback (most recent call last):
  File "/home/jrootjunior/work/aiogram3/expetiment.py", line 7, in <module>
    class MyObject(BaseModel):
  File "/home/jrootjunior/.cache/pypoetry/virtualenvs/aiogram-BAWpo_Vh-py3.8/lib/python3.8/site-packages/pydantic/main.py", line 303, in __new__
    cls.__signature__ = generate_model_signature(cls.__init__, fields, config)
  File "/home/jrootjunior/.cache/pypoetry/virtualenvs/aiogram-BAWpo_Vh-py3.8/lib/python3.8/site-packages/pydantic/utils.py", line 185, in generate_model_signature
    return Signature(parameters=list(merged_params.values()), return_annotation=None)
  File "/usr/lib/python3.8/inspect.py", line 2785, in __init__
    raise ValueError(msg)
ValueError: wrong parameter order: variadic keyword parameter before keyword-only parameter
```

## Information from debugger

As i see the `data` argument has incorrect signature:
![image](https://user-images.githubusercontent.com/6726423/80035891-77366c80-84f9-11ea-9b4c-e3c7c498d8a3.png)



Discussion:

Resolving patch:
diff --git a/pydantic/utils.py b/pydantic/utils.py
--- a/pydantic/utils.py
+++ b/pydantic/utils.py
@@ -174,13 +174,31 @@ def generate_model_signature(
 
             # TODO: replace annotation with actual expected types once #1055 solved
             kwargs = {'default': field.default} if not field.required else {}
-            merged_params[param_name] = Parameter(param_name, Parameter.KEYWORD_ONLY, annotation=field.type_, **kwargs)
+            merged_params[param_name] = Parameter(
+                param_name, Parameter.KEYWORD_ONLY, annotation=field.outer_type_, **kwargs
+            )
 
     if config.extra is config.extra.allow:
         use_var_kw = True
 
     if var_kw and use_var_kw:
-        merged_params[var_kw.name] = var_kw
+        # Make sure the parameter for extra kwargs
+        # does not have the same name as a field
+        default_model_signature = [
+            ('__pydantic_self__', Parameter.POSITIONAL_OR_KEYWORD),
+            ('data', Parameter.VAR_KEYWORD),
+        ]
+        if [(p.name, p.kind) for p in present_params] == default_model_signature:
+            # if this is the standard model signature, use extra_data as the extra args name
+            var_kw_name = 'extra_data'
+        else:
+            # else start from var_kw
+            var_kw_name = var_kw.name
+
+        # generate a name that's definitely unique
+        while var_kw_name in fields:
+            var_kw_name += '_'
+        merged_params[var_kw_name] = var_kw.replace(name=var_kw_name)
 
     return Signature(parameters=list(merged_params.values()), return_annotation=None)
 


Test patch:
diff --git a/tests/test_model_signature.py b/tests/test_model_signature.py
--- a/tests/test_model_signature.py
+++ b/tests/test_model_signature.py
@@ -71,7 +71,7 @@ def test_invalid_identifiers_signature():
     )
     assert _equals(str(signature(model)), '(*, valid_identifier: int = 123, yeah: int = 0) -> None')
     model = create_model('Model', **{'123 invalid identifier!': 123, '!': Field(0, alias='yeah')})
-    assert _equals(str(signature(model)), '(*, yeah: int = 0, **data: Any) -> None')
+    assert _equals(str(signature(model)), '(*, yeah: int = 0, **extra_data: Any) -> None')
 
 
 def test_use_field_name():
@@ -82,3 +82,47 @@ class Config:
             allow_population_by_field_name = True
 
     assert _equals(str(signature(Foo)), '(*, foo: str) -> None')
+
+
+def test_extra_allow_no_conflict():
+    class Model(BaseModel):
+        spam: str
+
+        class Config:
+            extra = Extra.allow
+
+    assert _equals(str(signature(Model)), '(*, spam: str, **extra_data: Any) -> None')
+
+
+def test_extra_allow_conflict():
+    class Model(BaseModel):
+        extra_data: str
+
+        class Config:
+            extra = Extra.allow
+
+    assert _equals(str(signature(Model)), '(*, extra_data: str, **extra_data_: Any) -> None')
+
+
+def test_extra_allow_conflict_twice():
+    class Model(BaseModel):
+        extra_data: str
+        extra_data_: str
+
+        class Config:
+            extra = Extra.allow
+
+    assert _equals(str(signature(Model)), '(*, extra_data: str, extra_data_: str, **extra_data__: Any) -> None')
+
+
+def test_extra_allow_conflict_custom_signature():
+    class Model(BaseModel):
+        extra_data: int
+
+        def __init__(self, extra_data: int = 1, **foobar: Any):
+            super().__init__(extra_data=extra_data, **foobar)
+
+        class Config:
+            extra = Extra.allow
+
+    assert _equals(str(signature(Model)), '(extra_data: int = 1, **foobar: Any) -> None')