Repository: pydantic/pydantic

Issue:
Tuple field triggers error checking inheritance
### 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

# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
             pydantic version: 1.7.2
            pydantic compiled: True
                 install path: /home/alexv/.local/share/virtualenvs/datacrystals-F4r2dbjD/lib/python3.8/site-packages/pydantic
               python version: 3.8.2 (default, Apr 27 2020, 15:53:34)  [GCC 9.3.0]
                     platform: Linux-5.4.0-7634-generic-x86_64-with-glibc2.29
     optional deps. installed: ['typing-extensions']
```

I didn't yet investigate what is happening here, but this looks like something that should be working...
 
```py
from pydantic.dataclasses import dataclass
import typing
@dataclass
class wrappingTuple:
    field: typing.Tuple

print(wrappingTuple(field=(0,1))
```
triggers :
```    
Traceback (most recent call last):
  File "pydantic/validators.py", line 615, in pydantic.validators.find_validators
TypeError: issubclass() arg 1 must be a class
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "<input>", line 2, in <module>
  File "pydantic/dataclasses.py", line 216, in pydantic.dataclasses.dataclass
  File "pydantic/dataclasses.py", line 211, in pydantic.dataclasses.dataclass.wrap
  File "pydantic/dataclasses.py", line 147, in pydantic.dataclasses._process_class
  File "pydantic/main.py", line 925, in pydantic.main.create_model
  File "pydantic/main.py", line 262, in pydantic.main.ModelMetaclass.__new__
  File "pydantic/fields.py", line 315, in pydantic.fields.ModelField.infer
  File "pydantic/fields.py", line 284, in pydantic.fields.ModelField.__init__
  File "pydantic/fields.py", line 362, in pydantic.fields.ModelField.prepare
  File "pydantic/fields.py", line 538, in pydantic.fields.ModelField.populate_validators
  File "pydantic/validators.py", line 624, in find_validators
RuntimeError: error checking inheritance of typing.Tuple (type: Tuple)
```

However this works fine : 
```py
from pydantic.dataclasses import dataclass
import typing
@dataclass
class wrappingTuple:
    field: tuple

print(wrappingTuple(field=(0,1))
```
```
wrappingTuple(field=(0, 1))
```

and this as well : 
```py
from pydantic.dataclasses import dataclass
import typing
@dataclass
class wrappingTuple:
    field: typing.List

print(wrappingTuple(field=[0,1])
```
```
wrappingTuple(field=[0, 1])
```


Discussion:

Resolving patch:
diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -346,7 +346,6 @@ def prepare(self) -> None:
         Note: this method is **not** idempotent (because _type_analysis is not idempotent),
         e.g. calling it it multiple times may modify the field and configure it incorrectly.
         """
-
         self._set_default_and_type()
         if self.type_.__class__ == ForwardRef:
             # self.type_ is currently a ForwardRef and there's nothing we can do now,
@@ -448,14 +447,19 @@ def _type_analysis(self) -> None:  # noqa: C901 (ignore complexity)
             return
 
         if issubclass(origin, Tuple):  # type: ignore
-            self.shape = SHAPE_TUPLE
-            self.sub_fields = []
-            for i, t in enumerate(get_args(self.type_)):
-                if t is Ellipsis:
-                    self.type_ = get_args(self.type_)[0]
-                    self.shape = SHAPE_TUPLE_ELLIPSIS
-                    return
-                self.sub_fields.append(self._create_sub_type(t, f'{self.name}_{i}'))
+            # origin == Tuple without item type
+            if not get_args(self.type_):
+                self.type_ = Any
+                self.shape = SHAPE_TUPLE_ELLIPSIS
+            else:
+                self.shape = SHAPE_TUPLE
+                self.sub_fields = []
+                for i, t in enumerate(get_args(self.type_)):
+                    if t is Ellipsis:
+                        self.type_ = get_args(self.type_)[0]
+                        self.shape = SHAPE_TUPLE_ELLIPSIS
+                        return
+                    self.sub_fields.append(self._create_sub_type(t, f'{self.name}_{i}'))
             return
 
         if issubclass(origin, List):
@@ -605,6 +609,8 @@ def _validate_sequence_like(  # noqa: C901 (ignore complexity)
             e: errors_.PydanticTypeError
             if self.shape == SHAPE_LIST:
                 e = errors_.ListError()
+            elif self.shape in (SHAPE_TUPLE, SHAPE_TUPLE_ELLIPSIS):
+                e = errors_.TupleError()
             elif self.shape == SHAPE_SET:
                 e = errors_.SetError()
             elif self.shape == SHAPE_FROZENSET:


Test patch:
diff --git a/tests/test_types.py b/tests/test_types.py
--- a/tests/test_types.py
+++ b/tests/test_types.py
@@ -2309,21 +2309,24 @@ def test_generic_without_params():
     class Model(BaseModel):
         generic_list: List
         generic_dict: Dict
+        generic_tuple: Tuple
 
-    m = Model(generic_list=[0, 'a'], generic_dict={0: 'a', 'a': 0})
-    assert m.dict() == {'generic_list': [0, 'a'], 'generic_dict': {0: 'a', 'a': 0}}
+    m = Model(generic_list=[0, 'a'], generic_dict={0: 'a', 'a': 0}, generic_tuple=(1, 'q'))
+    assert m.dict() == {'generic_list': [0, 'a'], 'generic_dict': {0: 'a', 'a': 0}, 'generic_tuple': (1, 'q')}
 
 
 def test_generic_without_params_error():
     class Model(BaseModel):
         generic_list: List
         generic_dict: Dict
+        generic_tuple: Tuple
 
     with pytest.raises(ValidationError) as exc_info:
-        Model(generic_list=0, generic_dict=0)
+        Model(generic_list=0, generic_dict=0, generic_tuple=0)
     assert exc_info.value.errors() == [
         {'loc': ('generic_list',), 'msg': 'value is not a valid list', 'type': 'type_error.list'},
         {'loc': ('generic_dict',), 'msg': 'value is not a valid dict', 'type': 'type_error.dict'},
+        {'loc': ('generic_tuple',), 'msg': 'value is not a valid tuple', 'type': 'type_error.tuple'},
     ]