intellimath / recordclass

Mutable variant of namedtuple -- recordclass, which support assignments, compact dataclasses and other memory saving variants.
Other
14 stars 3 forks source link

PEP 681. Add `dataclass_transform` decorator for `as_dataclass` #5

Open SaelKimberly opened 4 months ago

SaelKimberly commented 4 months ago

Hello!

There is a feature, that, I think, may greatly improve autocomplete when using recordclass: PEP 681 (dataclass_transform).

I know, this is a feature from python 3.11, but it also available in typing_extensions>=4.1.0, so it works for me on python 3.8 :)

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    try:
        try:
            from typing import dataclass_transform
        except ImportError:
            from typing_extensions import dataclass_transform
    except ImportError:
        from recordclass import as_dataclass
    else:
        from typing import Callable, TypeVar

        from recordclass import as_dataclass as _as_dataclass

        T = TypeVar("T")

        @dataclass_transform()
        def as_dataclass(
            cls: type[T] | None = None,
            *,
            use_dict: bool = False,
            use_weakref: bool = False,
            hashable: bool = False,
            sequence: bool = False,
            mapping: bool = False,
            iterable: bool = False,
            readonly: bool = False,
            fast_new: bool = True,
            rename: bool = False,
            gc: bool = False,
        ) -> Callable[[type[T]], type[T]]:
            if cls is not None:
                return _as_dataclass(
                    use_dict=use_dict,
                    use_weakref=use_weakref,
                    hashable=hashable,
                    sequence=sequence,
                    mapping=mapping,
                    iterable=iterable,
                    readonly=readonly,
                    fast_new=fast_new,
                    rename=rename,
                    gc=gc,
                )(cls)  # type: ignore

            def wrapper(cls: type[T]) -> type[T]:
                return _as_dataclass(
                    use_dict=use_dict,
                    use_weakref=use_weakref,
                    hashable=hashable,
                    sequence=sequence,
                    mapping=mapping,
                    iterable=iterable,
                    readonly=readonly,
                    fast_new=fast_new,
                    rename=rename,
                    gc=gc,
                )(cls)  # type: ignore

            return wrapper
else:
    from recordclass import as_dataclass

Then, when use constructor of recordclass datatypes, or on access on fields, there is no type-checker related issues:

@as_dataclass(readonly=True, fast_new=True)
class simple_model:
    a: int
    b: str = 'a'

This is patched version screenshots:

Type hints for arguments with patch

Type hints for attributes with patch

And without patch:

No type hints for arguments

Invisible dataclass attributes

I really appreciate your work, and hope, it will be helpful :smile_cat:

SaelKimberly commented 4 months ago

P.S: Note, that in patched version, signature of as_dataclass decorator may be without parenthesis...

intellimath commented 4 months ago

Which IDE show such results. For example, in simple IDLE in 3.11: idle_recordclass

SaelKimberly commented 4 months ago

VS Code. Maybe, this is a case of decorator using 🤔