mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
PY-77433 Fix resolving qualified names in field_specifiers argument of @dataclass_transform
Previously, we mistakenly tried to resolve qualified names listed in the `field_specifiers` argument of @dataclass_transform in the same scope where the dataclass itself is defined, not where the actual decorator application is located. Thus, if in the file where the dataclass is defined, a field specifier was imported differently than where @dataclass_transform was applied, we couldn't recognize a field specifier call in the RHS of an assignment as such and took it for an ordinary field default value. In particular, this is what happened with pydantic dataclasses. `pydantic.fields.Field` is usually imported as just `pydantic.Field` where user dataclasses are defined, but imported with an alias and set in the `field_specifiers` argument as `PydanticModelField` in `pydantic._internal._model_construction` where `ModelMetaclass` is defined. It was accidentally broken in f15a07836e7aeac7c46b489b4742e8248a0e6ef4 to support decorating class methods with dataclass_transform (see testData/inspections/PyDataclassInspection/DataclassTransformFieldsOrder/decorator.py). Until PyResolveUtil.resolveQualifiedNameInScope automatically traverses through containing scopes looking for a name, the file containing decorator application seems like a safe trade-off for the scope, because field specifiers are normally defined or imported somewhere at the top level. (cherry picked from commit de9afeb0831a52f058453fe678de229d41c26a4d) IJ-CR-151380 GitOrigin-RevId: b6576ec7b72ea1e19e93b6190372a5168003c396
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a45d559f88
commit
ab6adac4d4
@@ -1,7 +1,9 @@
|
||||
from typing import dataclass_transform
|
||||
|
||||
import dt_field
|
||||
|
||||
@dataclass_transform()
|
||||
|
||||
@dataclass_transform(field_specifiers=(dt_field.DataclassField,))
|
||||
class DataclassBase:
|
||||
def __init_subclass__(cls, **kwargs):
|
||||
import dataclasses
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
from dt_base import DataclassBase
|
||||
from dt_field import DataclassField
|
||||
|
||||
|
||||
class RecordViaBaseClass(DataclassBase, kw_only=True):
|
||||
id: int
|
||||
name: str
|
||||
name: str = DataclassField()
|
||||
address: str | None = DataclassField(default=None)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import dataclasses
|
||||
|
||||
|
||||
class DataclassField:
|
||||
def __init__(self,
|
||||
*,
|
||||
kw_only=dataclasses.MISSING,
|
||||
default=dataclasses.MISSING,
|
||||
default_factory=dataclasses.MISSING):
|
||||
...
|
||||
@@ -1,7 +1,9 @@
|
||||
from dt_decorator import my_dt_decorator
|
||||
from dt_field import DataclassField
|
||||
|
||||
|
||||
@my_dt_decorator(kw_only=True)
|
||||
class RecordViaDecorator:
|
||||
id: int
|
||||
name: str
|
||||
name: str = DataclassField()
|
||||
address: str | None = DataclassField(default=None)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from typing import dataclass_transform, Callable
|
||||
|
||||
import dt_field
|
||||
|
||||
@dataclass_transform()
|
||||
|
||||
@dataclass_transform(field_specifiers=(dt_field.DataclassField,))
|
||||
def my_dt_decorator(**kwargs) -> Callable[[type], type]:
|
||||
import dataclasses
|
||||
return dataclasses.dataclass(**kwargs) # type: ignore
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import dataclasses
|
||||
|
||||
|
||||
class DataclassField:
|
||||
def __init__(self,
|
||||
*,
|
||||
kw_only=dataclasses.MISSING,
|
||||
default=dataclasses.MISSING,
|
||||
default_factory=dataclasses.MISSING):
|
||||
...
|
||||
@@ -1,6 +1,8 @@
|
||||
from dt_base import DataclassBase
|
||||
from dt_field import DataclassField
|
||||
|
||||
|
||||
class RecordViaMetaClass(DataclassBase, kw_only=True):
|
||||
id: int
|
||||
name: str
|
||||
name: str = DataclassField()
|
||||
address: str | None = DataclassField(default=None)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import dataclasses
|
||||
|
||||
|
||||
class DataclassField:
|
||||
def __init__(self,
|
||||
*,
|
||||
kw_only=dataclasses.MISSING,
|
||||
default=dataclasses.MISSING,
|
||||
default_factory=dataclasses.MISSING):
|
||||
...
|
||||
@@ -1,7 +1,9 @@
|
||||
from typing import dataclass_transform
|
||||
|
||||
import dt_field
|
||||
|
||||
@dataclass_transform()
|
||||
|
||||
@dataclass_transform(field_specifiers=(dt_field.DataclassField,))
|
||||
class DataclassMeta(type):
|
||||
def __new__(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user