Skip to content

Commit

Permalink
Fix ClassVar forward ref inherited from parent class (#9097)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmojaki committed Mar 25, 2024
1 parent f794f65 commit 4af968d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
6 changes: 5 additions & 1 deletion pydantic/_internal/_typing_extra.py
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations as _annotations

import dataclasses
import re
import sys
import types
import typing
Expand Down Expand Up @@ -146,7 +147,10 @@ def is_classvar(ann_type: type[Any]) -> bool:

# this is an ugly workaround for class vars that contain forward references and are therefore themselves
# forward references, see #3679
if ann_type.__class__ == typing.ForwardRef and ann_type.__forward_arg__.startswith('ClassVar['): # type: ignore
if ann_type.__class__ == typing.ForwardRef and re.match(
r'(\w+\.)?ClassVar\[',
ann_type.__forward_arg__, # type: ignore
):
return True

return False
Expand Down
18 changes: 18 additions & 0 deletions tests/test_main.py
Expand Up @@ -3163,3 +3163,21 @@ class Model(BaseModel):
'input': {'not a str or int'},
},
]


def test_inherited_class_vars(create_module):
@create_module
def module():
import typing

from pydantic import BaseModel

class Base(BaseModel):
CONST1: 'typing.ClassVar[str]' = 'a'
CONST2: 'ClassVar[str]' = 'b'

class Child(module.Base):
pass

assert Child.CONST1 == 'a'
assert Child.CONST2 == 'b'
4 changes: 4 additions & 0 deletions tests/test_typing.py
Expand Up @@ -91,7 +91,11 @@ def test_is_literal_with_typing_literal():
'ann_type,extepcted',
(
(None, False),
(ForwardRef('Other[int]'), False),
(ForwardRef('Other[ClassVar[int]]'), False),
(ForwardRef('ClassVar[int]'), True),
(ForwardRef('t.ClassVar[int]'), True),
(ForwardRef('typing.ClassVar[int]'), True),
(ClassVar[int], True),
),
)
Expand Down

0 comments on commit 4af968d

Please sign in to comment.