From 0cb148129fac9c5fda976bba1d444139aec6ef6f Mon Sep 17 00:00:00 2001 From: Daniil Kalinin Date: Wed, 16 Oct 2024 14:28:41 +0200 Subject: [PATCH] [python] dataclass_transform: use the annotated class as a resolve anchor for resolving the field specifiers (cherry picked from commit f15a07836e7aeac7c46b489b4742e8248a0e6ef4) GitOrigin-RevId: edf8399741cc5d62ba2fb04f9314eb620f83abae --- .../com/jetbrains/python/codeInsight/PyDataclasses.kt | 2 +- .../DataclassTransformFieldsOrder/a.py | 9 ++++++++- .../DataclassTransformFieldsOrder/decorator.py | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/PyDataclasses.kt b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/PyDataclasses.kt index 49ff8157e204..4d682985a0c2 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/PyDataclasses.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/PyDataclasses.kt @@ -566,7 +566,7 @@ private fun resolveDataclassParameters( if (dataclassTransformStub != null) { val resolvedFieldSpecifiers = dataclassTransformStub.fieldSpecifiers - .flatMap { PyResolveUtil.resolveQualifiedNameInScope(it, ScopeUtil.getScopeOwner(dataclassTransformDecorator)!!, context) } + .flatMap { PyResolveUtil.resolveQualifiedNameInScope(it, ScopeUtil.getScopeOwner(pyClass)!!, context) } .filterIsInstance() .mapNotNull { it.qualifiedName } .map { QualifiedName.fromDottedString(it) } diff --git a/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/a.py b/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/a.py index 825a10ca2847..f22af75376d0 100644 --- a/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/a.py +++ b/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/a.py @@ -1,8 +1,9 @@ import dataclasses from typing import ClassVar -from decorator import my_dataclass, my_field, MyField +from decorator import my_dataclass, my_field, MyField, registry +reg = registry() @my_dataclass() class A1: @@ -106,3 +107,9 @@ class D1: class E1: foo = "bar" # <- has no type annotation, so doesn't count. baz: str + +# see https://docs.sqlalchemy.org/en/20/orm/dataclasses.html +@reg.mapped_as_dataclass +class B5: + a: int = MyField(default_factory=int) + b: int = MyField() diff --git a/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/decorator.py b/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/decorator.py index c493969b4931..9c4185d48f07 100644 --- a/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/decorator.py +++ b/python/testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/decorator.py @@ -11,6 +11,12 @@ class MyField: def __init__(self, **kwargs): ... +class registry: + @dataclass_transform(field_specifiers=(my_field, MyField,)) + def mapped_as_dataclass(**kwargs) -> Callable[[type[T]], type[T]]: + ... + + @dataclass_transform(field_specifiers=(my_field, MyField,)) def my_dataclass(**kwargs) -> Callable[[type[T]], type[T]]: