Skip to content

Conversation

@vfdev-5
Copy link
Collaborator

@vfdev-5 vfdev-5 commented Nov 13, 2025

Fixes #5027

  • Removed content of linen/kw_only_dataclasses.py and kept methods and attributes for BC with field and dataclass linked to python built-in dataclasses
  • Removed usage of kw_only_dataclasses in linen module.py
  • Adapted certain failing tests

# limitations under the License.

"""Support for keyword-only fields in dataclasses for Python versions <3.10.
"""This module is kept for backward compatibility.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

praxis is using flax/linen/kw_only_dataclasses.py module here: https://github.com/google/praxis/blob/main/praxis/base_hyperparams.py#L36

v2 = Child(4, a=5) # pylint: disable=too-many-function-args
self.assertDictEqual(dataclasses.asdict(v2), dict(a=5, b=4))

@absltest.expectedFailureIf(True, "non-default argument 'size' follows default argument")
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This test is failing with built-in python dataclasses:
class B inherits from A where a default kwarg is defined, thus B can't define non-default size attribute.

self.assertEqual(
list(Test2.__dataclass_fields__.keys()),
['bar', 'baz', 'parent', 'name'],
set(Test2.__dataclass_fields__.keys()),
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Test adaptation is needed with built-in python dataclasses vs linen.kw_only_dataclasses

@vfdev-5 vfdev-5 force-pushed the fix-py314-kw-only-dataclasses branch from aa49caa to 5fd3b57 Compare November 13, 2025 11:29
# Ignore uv.lock and always upgrade the package to the latest
upgrade-package = ["jax", "jaxlib", "orbax-checkpoint"]

[tool.uv.sources]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is from #5086 and can be removed if that PR wont land

@vfdev-5 vfdev-5 force-pushed the fix-py314-kw-only-dataclasses branch 2 times, most recently from 4be43de to 3eeb377 Compare November 13, 2025 13:26
@hawkinsp
Copy link
Member

Here is a repro for the problem we see with this internally. It's kind of wild and I don't know what's going on here:

import abc
from collections.abc import Iterator, Iterable
import io
from typing import Protocol, TypeVar

T = TypeVar("T")

class CheckpointableIterator(Iterator[T], Protocol[T]):
  pass

isinstance(io.TextIOBase, Iterable)

from flax import linen as nn

class Steppable(metaclass=abc.ABCMeta):
  path: str

class SequenceLayer(nn.Module, Steppable):
  pass

I ran this under Python 3.12.

With the changes in this CL, I get:

Traceback (most recent call last):
  File "/usr/local/google/home/phawkins/p/flax/t.py", line 21, in <module>
    class SequenceLayer(nn.Module, Steppable):
  File "<frozen abc>", line 106, in __new__
  File "/usr/local/google/home/phawkins/p/flax/flax/linen/module.py", line 1040, in __init_subclass__
    cls._customized_dataclass_transform(kw_only)
  File "/usr/local/google/home/phawkins/p/flax/flax/linen/module.py", line 1100, in _customized_dataclass_transform
    dataclasses.dataclass(  # type: ignore[call-overload]
  File "/usr/local/google/home/phawkins/.local/share/uv/python/cpython-3.12.10-linux-x86_64-gnu/lib/python3.12/dataclasses.py", line 1265, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/google/home/phawkins/.local/share/uv/python/cpython-3.12.10-linux-x86_64-gnu/lib/python3.12/dataclasses.py", line 1018, in _process_class
    raise TypeError(f'{name!r} is a field but has no type annotation')
TypeError: 'parent' is a field but has no type annotation

@hawkinsp
Copy link
Member

I still don't know why this works, but adding:

    setattr(cls, '__annotations__', cls.__annotations__)

right before the:

    dataclasses.dataclass(  # type: ignore[call-overload]
      unsafe_hash='__hash__' not in cls.__dict__,
      repr=False,
      kw_only=kw_only,
    )(cls)

call seems to work around the problem.

For some reason, __annotations__ isn't in the class dict, and that makes inspect.get_annotations fail.

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 15, 2025

@hawkinsp thanks a lot for investigations!
I agree it's very wild, every line in the reproducer matters.
I see that it fails with 3.12 and 3.13 but passes with 3.11 and 3.14...

@hawkinsp
Copy link
Member

Another note: for praxis I found that adding from __future__ import annotations was necessary to get the same behavior with Python 3.14 as with previous versions.

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 17, 2025

Reported the bug on cpython: python/cpython#141681

@vfdev-5 vfdev-5 force-pushed the fix-py314-kw-only-dataclasses branch 3 times, most recently from 917ca90 to 1014b25 Compare November 18, 2025 10:42
@cgarciae cgarciae marked this pull request as ready for review November 18, 2025 21:54
@cgarciae cgarciae force-pushed the fix-py314-kw-only-dataclasses branch from 1014b25 to 964f503 Compare November 18, 2025 22:00
@vfdev-5 vfdev-5 force-pushed the fix-py314-kw-only-dataclasses branch from 964f503 to b43ade8 Compare November 19, 2025 11:14
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.

Python 3.14 compatibility issue

3 participants