Repository: samuelcolvin/pydantic
Pull request #3411 (2021-11-12 16:23:33)

Fix "dataclasess" typos
<!-- Thank you for your contribution! -->
<!-- Unless your change is trivial, please create an issue to discuss the change before creating a PR -->
<!-- See https://pydantic-docs.helpmanual.io/contributing/ for help on Contributing -->

## Change Summary

Trivial typo fixes in docs.

## Checklist

* [ ] Unit tests for the changes exist
* [ ] Tests pass on CI and coverage remains at 100%
* [x] Documentation reflects the changes where applicable
* [ ] `changes/<pull request or issue id>-<github username>.md` file added describing change
  (see [changes/README.md](https://github.com/samuelcolvin/pydantic/blob/master/changes/README.md) for details)
* [x] My PR is ready to review, **please add a comment including the phrase "please review" to assign reviewers**


cjwatson: please review

Patch:
diff --git a/changes/3401-uriyyo.md b/changes/3401-uriyyo.md
new file mode 100644
index 000000000..7b46117f5
--- /dev/null
+++ b/changes/3401-uriyyo.md
@@ -0,0 +1,1 @@
+Fix issue when pydantic fail to parse `typing.ClassVar` string type annotation.
\ No newline at end of file
diff --git a/docs/mypy_plugin.md b/docs/mypy_plugin.md
index 842078056..437454b4e 100644
--- a/docs/mypy_plugin.md
+++ b/docs/mypy_plugin.md
@@ -55,8 +55,8 @@ There are other benefits too! See below for more details.
   cf. [ORM mode](usage/models.md#orm-mode-aka-arbitrary-class-instances)
 
 #### Generate a signature for `dataclasses`
-* classes decorated with [`@pydantic.dataclasess.dataclass`](usage/dataclasses.md) are type checked the same as standard python dataclasses
-* The `@pydantic.dataclasess.dataclass` decorator accepts a `config` keyword argument which has the same meaning as [the `Config` sub-class](usage/model_config.md).
+* classes decorated with [`@pydantic.dataclasses.dataclass`](usage/dataclasses.md) are type checked the same as standard python dataclasses
+* The `@pydantic.dataclasses.dataclass` decorator accepts a `config` keyword argument which has the same meaning as [the `Config` sub-class](usage/model_config.md).
 
 ### Optional Capabilities:
 #### Prevent the use of required dynamic aliases
diff --git a/pydantic/typing.py b/pydantic/typing.py
index 156db0b5f..5797432ec 100644
--- a/pydantic/typing.py
+++ b/pydantic/typing.py
@@ -332,7 +332,9 @@ def resolve_annotations(raw_annotations: Dict[str, Type[Any]], module_name: Opti
     annotations = {}
     for name, value in raw_annotations.items():
         if isinstance(value, str):
-            if sys.version_info >= (3, 7):
+            if (3, 10) > sys.version_info >= (3, 9, 8) or sys.version_info >= (3, 10, 1):
+                value = ForwardRef(value, is_argument=False, is_class=True)
+            elif sys.version_info >= (3, 7):
                 value = ForwardRef(value, is_argument=False)
             else:
                 value = ForwardRef(value)


Test patch:
diff --git a/tests/test_forward_ref.py b/tests/test_forward_ref.py
index 95595fcbf..692a33d2f 100644
--- a/tests/test_forward_ref.py
+++ b/tests/test_forward_ref.py
@@ -519,3 +519,20 @@ def test_nested_forward_ref():
     NestedTuple.update_forward_refs()
     obj = NestedTuple.parse_obj({'x': ('1', {'x': ('2', {'x': ('3', None)})})})
     assert obj.dict() == {'x': (1, {'x': (2, {'x': (3, None)})})}
+
+
+@skip_pre_37
+def test_class_var_as_string(create_module):
+    module = create_module(
+        # language=Python
+        """
+from __future__ import annotations
+from typing import ClassVar
+from pydantic import BaseModel
+
+class Model(BaseModel):
+    a: ClassVar[int]
+"""
+    )
+
+    assert module.Model.__class_vars__ == {'a'}