Repository: pydantic/pydantic

Issue:
arbitrary_types_allowed not respected when validating stdlib dataclasses
### Checks

* [x] I added a descriptive title to this issue
* [x] I have searched (google, github) for similar issues and couldn't find anything
* [x] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

<!-- Sorry to sound so draconian, but every second saved replying to issues is time spend improving pydantic :-) -->

# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
             pydantic version: 1.7
            pydantic compiled: True
                 install path: /Users/ines/Repos/explosion/spacy/.env37/lib/python3.7/site-packages/pydantic
               python version: 3.7.2 (default, Oct  6 2019, 23:51:55)  [Clang 10.0.1 (clang-1001.0.46.4)]
                     platform: Darwin-19.5.0-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions']
```
<!-- or if you're using pydantic prior to v1.3, manually include: OS, python version and pydantic version -->

<!-- Please read the [docs](https://pydantic-docs.helpmanual.io/) and search through issues to
confirm your bug hasn't already been reported. -->

<!-- Where possible please include a self-contained code snippet describing your bug: -->

As of v1.7, Pydantic validates dataclasses and their contents, but it fails if the dataclass specifies arbitrary types (which is pretty common in our code bases). Here's an example:

```py
from typing import List
from dataclasses import dataclass
from pydantic import BaseModel

class ArbitraryType:
    def __init__(self):
        ...

@dataclass
class Test:
    foo: ArbitraryType
    bar: List[ArbitraryType]


class TestModel(BaseModel):
    a: ArbitraryType  # this is fine
    b: Test  # this raises RuntimeError

    class Config:
        arbitrary_types_allowed = True
```

Even though the `BaseModel` subclass sets `arbitrary_types_allowed` to `True`, this configuration doesn't seem to be taken into account when validating the dataclass fields. 

Adding custom validation to our dataclasses isn't really an option, since we wouldn't want those Pydantic specifics to leak into the rest of the code base. I'm also wondering whether there should be an option to _not_ validate stdlib dataclasses as Pydantic dataclasses and just use a basic instance check instead, like it previously did (?) before v1.7?


Comments:

Patch:
diff --git a/docs/examples/dataclasses_arbitrary_types_allowed.py b/docs/examples/dataclasses_arbitrary_types_allowed.py
new file mode 100644
--- /dev/null
+++ b/docs/examples/dataclasses_arbitrary_types_allowed.py
@@ -0,0 +1,42 @@
+import dataclasses
+
+import pydantic
+
+
+class ArbitraryType:
+    def __init__(self, value):
+        self.value = value
+
+    def __repr__(self):
+        return f'ArbitraryType(value={self.value!r})'
+
+
+@dataclasses.dataclass
+class DC:
+    a: ArbitraryType
+    b: str
+
+
+# valid as it is a builtin dataclass without validation
+my_dc = DC(a=ArbitraryType(value=3), b='qwe')
+
+try:
+    class Model(pydantic.BaseModel):
+        dc: DC
+        other: str
+
+    Model(dc=my_dc, other='other')
+except RuntimeError as e:  # invalid as it is now a pydantic dataclass
+    print(e)
+
+
+class Model(pydantic.BaseModel):
+    dc: DC
+    other: str
+
+    class Config:
+        arbitrary_types_allowed = True
+
+
+m = Model(dc=my_dc, other='other')
+print(repr(m))
diff --git a/docs/examples/dataclasses_stdlib_inheritance.py b/docs/examples/dataclasses_stdlib_inheritance.py
new file mode 100644
--- /dev/null
+++ b/docs/examples/dataclasses_stdlib_inheritance.py
@@ -0,0 +1,27 @@
+import dataclasses
+
+import pydantic
+
+
+@dataclasses.dataclass
+class Z:
+    z: int
+
+
+@dataclasses.dataclass
+class Y(Z):
+    y: int = 0
+
+
+@pydantic.dataclasses.dataclass
+class X(Y):
+    x: int = 0
+
+
+foo = X(x=b'1', y='2', z='3')
+print(foo)
+
+try:
+    X(z='pika')
+except pydantic.ValidationError as e:
+    print(e)
diff --git a/pydantic/dataclasses.py b/pydantic/dataclasses.py
--- a/pydantic/dataclasses.py
+++ b/pydantic/dataclasses.py
@@ -8,7 +8,7 @@
 from .utils import ClassAttribute
 
 if TYPE_CHECKING:
-    from .main import BaseModel  # noqa: F401
+    from .main import BaseConfig, BaseModel  # noqa: F401
     from .typing import CallableGenerator
 
     DataclassT = TypeVar('DataclassT', bound='Dataclass')
@@ -120,7 +120,9 @@ def _pydantic_post_init(self: 'Dataclass', *initvars: Any) -> None:
     # ```
     # with the exact same fields as the base dataclass
     if is_builtin_dataclass(_cls):
-        _cls = type(_cls.__name__, (_cls,), {'__post_init__': _pydantic_post_init})
+        _cls = type(
+            _cls.__name__, (_cls,), {'__annotations__': _cls.__annotations__, '__post_init__': _pydantic_post_init}
+        )
     else:
         _cls.__post_init__ = _pydantic_post_init
     cls: Type['Dataclass'] = dataclasses.dataclass(  # type: ignore
@@ -214,10 +216,10 @@ def wrap(cls: Type[Any]) -> Type['Dataclass']:
     return wrap(_cls)
 
 
-def make_dataclass_validator(_cls: Type[Any], **kwargs: Any) -> 'CallableGenerator':
+def make_dataclass_validator(_cls: Type[Any], config: Type['BaseConfig']) -> 'CallableGenerator':
     """
     Create a pydantic.dataclass from a builtin dataclass to add type validation
     and yield the validators
     """
-    cls = dataclass(_cls, **kwargs)
+    cls = dataclass(_cls, config=config)
     yield from _get_validators(cls)
diff --git a/pydantic/validators.py b/pydantic/validators.py
--- a/pydantic/validators.py
+++ b/pydantic/validators.py
@@ -593,7 +593,7 @@ def find_validators(  # noqa: C901 (ignore complexity)
         yield make_literal_validator(type_)
         return
     if is_builtin_dataclass(type_):
-        yield from make_dataclass_validator(type_)
+        yield from make_dataclass_validator(type_, config)
         return
     if type_ is Enum:
         yield enum_validator


Test patch:
diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py
--- a/tests/test_dataclasses.py
+++ b/tests/test_dataclasses.py
@@ -2,7 +2,7 @@
 from collections.abc import Hashable
 from datetime import datetime
 from pathlib import Path
-from typing import ClassVar, Dict, FrozenSet, Optional
+from typing import ClassVar, Dict, FrozenSet, List, Optional
 
 import pytest
 
@@ -738,3 +738,42 @@ class File:
         'title': 'File',
         'type': 'object',
     }
+
+
+def test_inherit_builtin_dataclass():
+    @dataclasses.dataclass
+    class Z:
+        z: int
+
+    @dataclasses.dataclass
+    class Y(Z):
+        y: int
+
+    @pydantic.dataclasses.dataclass
+    class X(Y):
+        x: int
+
+    pika = X(x='2', y='4', z='3')
+    assert pika.x == 2
+    assert pika.y == 4
+    assert pika.z == 3
+
+
+def test_dataclass_arbitrary():
+    class ArbitraryType:
+        def __init__(self):
+            ...
+
+    @dataclasses.dataclass
+    class Test:
+        foo: ArbitraryType
+        bar: List[ArbitraryType]
+
+    class TestModel(BaseModel):
+        a: ArbitraryType
+        b: Test
+
+        class Config:
+            arbitrary_types_allowed = True
+
+    TestModel(a=ArbitraryType(), b=(ArbitraryType(), [ArbitraryType()]))