Dataclass transform change init False

This commit is contained in:
Eric Masseran
2025-03-18 00:30:50 +01:00
parent e140523211
commit 999332ef77
3 changed files with 61 additions and 3 deletions

View File

@@ -296,7 +296,9 @@ class ClassMixin:
continue continue
# All inherited behave like dataclass # All inherited behave like dataclass
if is_dataclass_transform_with_init: if is_dataclass_transform_with_init and (
isinstance(cls, ClassValue) and not cls._has_init_false()
):
param_names.extend( param_names.extend(
get_dataclass_param_names(cls) get_dataclass_param_names(cls)
) )
@@ -557,6 +559,27 @@ class ClassValue(ClassMixin, FunctionAndClassBase, metaclass=CachedMetaClass):
return values return values
return NO_VALUES return NO_VALUES
def _has_init_false(self) -> bool:
"""
It returns ``True`` if ``class X(init=False):`` else ``False``.
"""
bases_arguments = self._get_bases_arguments()
if bases_arguments.argument_node.type != "arglist":
# If it is not inheriting from the base model and having
# extra parameters, then init behavior is not changed.
return False
for arg in bases_arguments.argument_node.children:
if (
arg.type == "argument"
and arg.children[0].value == "init"
and arg.children[2].value == "False"
):
return True
return False
@plugin_manager.decorate() @plugin_manager.decorate()
def get_metaclass_signatures(self, metaclasses): def get_metaclass_signatures(self, metaclasses):
return [] return []

View File

@@ -625,9 +625,17 @@ def _dataclass(value, arguments, callback):
] ]
) )
elif c.is_function(): elif c.is_function():
# dataclass_transform on a decorator equivalent of @dataclass # @dataclass_transform
# def create_model(): pass
return ValueSet([value]) return ValueSet([value])
elif value.name.string_name != "dataclass_transform": elif (
# @dataclass(...)
value.name.string_name != "dataclass_transform"
# @dataclass_transform
# def create_model(): pass
# @create_model(...)
or isinstance(value, Decoratee)
):
# dataclass (or like) decorator customization # dataclass (or like) decorator customization
return ValueSet( return ValueSet(
[ [

View File

@@ -482,6 +482,30 @@ dataclass_transform_cases = [
def __init__(self, toto: str): def __init__(self, toto: str):
pass pass
'''), ["toto"], False], '''), ["toto"], False],
# Class based init=false
[dedent('''
@dataclass_transform
class Y():
y: int
z = 5
class X(Y, init=False):'''), [], False],
# Decorator based init=false
[dedent('''
@dataclass_transform
def create_model():
pass
@create_model(init=False)
class X:'''), [], False],
# Metaclass based init=false
[dedent('''
@dataclass_transform
class ModelMeta():
y: int
z = 5
class ModelBase(metaclass=ModelMeta):
t: int
p = 5
class X(ModelBase, init=False):'''), [], False],
] ]
ids = [ ids = [
@@ -493,6 +517,9 @@ ids = [
"decorator_transformed", "decorator_transformed",
"metaclass_transformed", "metaclass_transformed",
"custom_init", "custom_init",
"base_transformed_init_false",
"decorator_transformed_init_false",
"metaclass_transformed_init_false",
] ]