Skip to content

Accessing @attr.s() decorator parameter values #602

Closed

Description

@energizah

In #python today someone wanted to find out if their class was frozen. Cls.__dataclass_params__ keeps the @dataclasses.dataclass() arguments.

_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=True)

Is there a way to get that data in attrs?

Activity

  1. omry commented on Dec 2, 2019

    @omry

    That was me.
    looking at source or attr make, it seems like this metadata is not currently maintained.

    The reason I want this is because I am using attr (or dataclasses) as a template to generate an object that - among other things - performs runtime checks (type validation, recursive frozen check etc).
    This has some more context on what I am shooting for.

    I was able to detect at runtime if a dataclass is frozen but was not able to do the same for attr classes.

  2. omry commented on Dec 2, 2019

    @omry

    This seems to work, but it's very fragile:

    def is_attr_frozen(type_):
        import attr
    
        return type_.__setattr__ == attr._make._frozen_setattrs

    It works if I import the class normally (from foo.bar import FrozenClass), but does not work when I import using import_module.

    FrozenClass = import_module("foo.bar").FrozenClass

    It would be great if there was a supported API to determine that (and possibly attr parameters).

  3. wsanchez commented on Dec 2, 2019

    @wsanchez

    FWIW, I find exposing more attrs-specific stuff onto classes to be problematic. That I use attrs is, to me, an implementation detail, and I don't intend "this is an attrs-built class" to be part of the interface to my classes.

    The more attrs-specific introspection we add, the more locked-in to attrs classes become.

  4. omry commented on Dec 2, 2019

    @omry

    @wsanchez, I agree with the sentiment, but it should still be possible for someone who wants to do this introspection to do it reliably if they choose.

    attrs and dataclasses have a pretty good feature parity already, so the any lock-in is minimal.
    I am planning to support both in my library.
    this specific thing is one of the things I feel more uncomfortable with right now.

    def is_dataclass_frozen(type_):
        return type_.__dataclass_params__.frozen
    
    
    def is_attr_frozen(type_):
        import attr
    
        # This is very hacky and probably fragile as well.
        # Unfortunately currently there isn't an official API in attr that can detect that.
        return type_.__setattr__ == attr._make._frozen_setattrs
  5. hynek commented on Dec 5, 2019

    @hynek
    Member

    Hmmm. So the thing is that I was kinda planning to expose class settings as a class internally anyway, because the amount of arguments is getting out of control.

    However I plan too many internal changes soon-ish that I don't want to lo ourselves in rn.

    Good to know about __dataclass_params__ – we should follow that naming convention if/once we implement it.


    Wilfredo's argument is true but we always insisted on being extensible and allow introspection into attributes. It seems like a glaring omission to not allow introspection into the class itself.


    I think I'll just pinky promise to not break your use case until we have an official API. ;)

  6. omry commented on Dec 5, 2019

    @omry

    Thanks @hynek.
    Glad to hear you are planning on adding an official API for this.
    I totally understand the desire to keep things as is until you have had some time to think and figure out what the best API is, especially with a major internal change in the horizon.

    Thanks for pinky promising not to break my implementation until then! :)

  7. added this to the 21.3.0 milestone on Jul 24, 2021
  8. removed this from the 21.3.0 milestone on Dec 14, 2021
  9. added this to the 22.1.0 milestone on Dec 28, 2021
  10. modified the milestones: 22.2.0, 23.1.0 on Nov 30, 2022
  11. 3 remaining items

  12. added a commit that references this issue on Aug 30, 2025
  13. hynek commented on Sep 30, 2025

    @hynek
    Member

    This has now been fixed by #1454! 😮‍💨

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions