Skip to content

Commit

Permalink
Run dataclass plugin before checking type var bounds (#12908)
Browse files Browse the repository at this point in the history
The plugin may add attributes that are needed to perform the bound
check.

Fixes #12876.
  • Loading branch information
JukkaL committed Jun 1, 2022
1 parent f649e2d commit 154ac75
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
7 changes: 3 additions & 4 deletions mypy/semanal_main.py
Expand Up @@ -82,10 +82,10 @@ def semantic_analysis_for_scc(graph: 'Graph', scc: List[str], errors: Errors) ->
# We use patch callbacks to fix up things when we expect relatively few
# callbacks to be required.
apply_semantic_analyzer_patches(patches)
# This pass might need fallbacks calculated above.
check_type_arguments(graph, scc, errors)
# Run class decorator hooks (they requite complete MROs and no placeholders).
apply_class_plugin_hooks(graph, scc, errors)
# This pass might need fallbacks calculated above and the results of hooks.
check_type_arguments(graph, scc, errors)
calculate_class_properties(graph, scc, errors)
check_blockers(graph, scc)
# Clean-up builtins, so that TypeVar etc. are not accessible without importing.
Expand Down Expand Up @@ -133,10 +133,9 @@ def semantic_analysis_for_targets(
process_top_level_function(analyzer, state, state.id,
n.node.fullname, n.node, n.active_typeinfo, patches)
apply_semantic_analyzer_patches(patches)

apply_class_plugin_hooks(graph, [state.id], state.manager.errors)
check_type_arguments_in_targets(nodes, state, state.manager.errors)
calculate_class_properties(graph, [state.id], state.manager.errors)
apply_class_plugin_hooks(graph, [state.id], state.manager.errors)


def restore_saved_attrs(saved_attrs: SavedAttributes) -> None:
Expand Down
18 changes: 18 additions & 0 deletions test-data/unit/check-dataclasses.test
Expand Up @@ -1772,3 +1772,21 @@ c = C()
c2 = C(x=1)
c.x # E: "C" has no attribute "x"
[builtins fixtures/dataclasses.pyi]

[case testDataclassCheckTypeVarBounds]
# flags: --python-version 3.7
from dataclasses import dataclass
from typing import Protocol, Dict, TypeVar, Generic

class DataclassProtocol(Protocol):
__dataclass_fields__: Dict

T = TypeVar("T", bound=DataclassProtocol)

@dataclass
class MyDataclass:
x: int = 1

class MyGeneric(Generic[T]): ...
class MyClass(MyGeneric[MyDataclass]): ...
[builtins fixtures/dataclasses.pyi]
28 changes: 28 additions & 0 deletions test-data/unit/fine-grained.test
Expand Up @@ -9734,6 +9734,7 @@ class C:
[out]
==
main:5: error: Unsupported left operand type for + ("str")

[case testNoneAttribute]
from typing import Generic, TypeVar

Expand All @@ -9759,3 +9760,30 @@ class ExampleClass(Generic[T]):
self.example_attribute = None
[out]
==

[case testDataclassCheckTypeVarBoundsInReprocess]
# flags: --python-version 3.7
from dataclasses import dataclass
from typing import Protocol, Dict, TypeVar, Generic
from m import x

class DataclassProtocol(Protocol):
__dataclass_fields__: Dict

T = TypeVar("T", bound=DataclassProtocol)

@dataclass
class MyDataclass:
x: int = 1

class MyGeneric(Generic[T]): ...
class MyClass(MyGeneric[MyDataclass]): ...

[file m.py]
x: int
[file m.py.2]
x: str

[builtins fixtures/dataclasses.pyi]
[out]
==

0 comments on commit 154ac75

Please sign in to comment.