Skip to content

gh-148941: Skip generating __init__ when class already defines it#151184

Open
nahcmon wants to merge 2 commits into
python:mainfrom
nahcmon:gh-148941-dataclass-init-not-generated-when-user-defined
Open

gh-148941: Skip generating __init__ when class already defines it#151184
nahcmon wants to merge 2 commits into
python:mainfrom
nahcmon:gh-148941-dataclass-init-not-generated-when-user-defined

Conversation

@nahcmon

@nahcmon nahcmon commented Jun 9, 2026

Copy link
Copy Markdown

Bug

When @dataclass(init=True) (the default) is applied to a class that already defines __init__ in its own __dict__, the generated __init__ is always discarded by _set_new_attribute. However, _init_fn was still called unconditionally, and its field-ordering validation raised TypeError when inherited fields with defaults were followed by fields without defaults:

from dataclasses import dataclass

@dataclass
class Base:
    x: int = 0  # has a default

@dataclass
class Child(Base):
    y: int          # no default — would produce invalid generated signature
    def __init__(self, y):
        self.y = y
# TypeError: non-default argument 'y' follows default argument 'x'

The docs state: "If the class already defines __init__(), this parameter is ignored." The design table in dataclasses.py itself also documents this as the intended behaviour (the init=True / class-has-__init__ cell is intentionally blank/no-op).

Fix

Add and '__init__' not in cls.__dict__ to the guard before calling _init_fn in _process_class. This skips the generation (and its validation) entirely when the class's own __init__ would have been preserved anyway.

Tests

test_overwriting_init_with_field_ordering_conflict is added to TestInit in Lib/test/test_dataclasses/__init__.py:

  • Fails before the fix: TypeError: non-default argument 'y' follows default argument 'x'
  • Passes after the fix: Child(5).y == 5, class's own __init__ is used

All 282 dataclasses tests pass.

NEWS

Misc/NEWS.d/next/Library/2026-06-09-16-41-45.gh-issue-148941.aB3kLm.rst added.

CLA

⚠️ The GitHub account nahcmon may not have a signed PSF CLA on file. If the CLA bot flags this PR, the contributor will need to sign at https://www.python.org/psf/contrib/contrib-form/ before it can be merged.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Comment thread Lib/dataclasses.py Outdated
(f' if {condition}:',
' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
f' super(__class__, self).__setattr__(name, value)'),
' super(__class__, self).__setattr__(name, value)'),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all unrelated changes.

nahcmon added 2 commits June 9, 2026 20:47
…it (pythonGH-148941)

When @DataClass(init=True) is applied to a class that already defines
__init__ in its own __dict__, the generated __init__ is always discarded
by _set_new_attribute.  However, _init_fn was still called unconditionally,
and its field-ordering validation raised TypeError for inherited fields
with defaults followed by fields without.  The docs state "If the class
already defines __init__(), this parameter is ignored."  Align the
implementation with that documented behaviour by checking
'__init__' not in cls.__dict__ before calling _init_fn.
@nahcmon nahcmon force-pushed the gh-148941-dataclass-init-not-generated-when-user-defined branch from 01401bd to 8429874 Compare June 9, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants