Skip to content

Find better name for attr.dataclass #408

Closed

Description

@hynek

So attr.dataclass was meant more or less as a joke, but I just caught myself using it too but the name is bad, because it’s confusing. It implies some kind of symmetry or compatibility to DCs which it doesn’t.

So here’s a nice bike shed, please help me finding a short, memorable, and meaningful color for it!

Activity

  1. added this to the 18.2 milestone on Jul 13, 2018
  2. euresti commented on Jul 13, 2018

    @euresti
    Contributor

    attr.auto?

  3. hynek commented on Jul 14, 2018

    @hynek
    MemberAuthor

    attr.auto?

    That’s kinda my favorite too. It’s just sad that it doesn’t work with the attr prefix but that ship has somewhat sailed. I think I’ll have to re-visit the introduction of an attrs namespace.

  4. hynek commented on Jul 14, 2018

    @hynek
    MemberAuthor

    Which opens the question: if the namespace becomes attrs and you can do from attrs import X, what would be the best name for it? auto seems too short…OTOH @attrs.auto looks perfect. I wonder if in a perfect world, we could come up with something nice and symmetric to it – like @attrs.explicit?

    The world around attrs has changed considerably since the invention of it's original names. It outgrew it’s scope more than I could ever predict when I was scheming with @glyph on IRC and the introduction of static types opened it up to new interesting use cases.

    While I realize that introducing new APIs brings some confusion, there’s always the cautionary tale of why Makefiles use tab characters.


    After using it a bit, I believe that if Python has a future, static typing is unequivocally part of it and I want attrs to embrace it fully and not to feel like we’re dragging our heels. Obviously I do not intend to break backward compatibility but unless someone can talk me out of it, I’m very close to add a new, more forward-looking API and make it the primary one.

    I for one, am very annoyed whenever I use the attr package name with names that don’t make any sense (like attr.validators) and the last time I got annoyed on each import, I abandoned the project in favor of attrs. ;)

  5. hynek commented on Jul 14, 2018

    @hynek
    MemberAuthor

    So I’ve been playing and I’m absolutely in love with this being the future canonical API for attrs:

    >>> import attrs
    >>> import typing
    
    >>> @attrs.auto
    ... class SomeClass:
    ...     a_number: int = 42
    ...     list_of_numbers: typing.List[int] = attrs.Factory(list)
    ...     a_number = attrs.attrib(converter=int)
    
    >>> attrs.fields(SomeClass).a_number.type
    <class 'int'>

    Which kind of means that the question is reversed – should there be another name for attr.s? We will have a conflict with the serious business crowd anyways since they tend to write from attr import attrs, attrib.

    That’s the only thing that annoys me but I don’t think we can fix it: it’s impossible to both from attrs import attrs and import attrs. However it’s not solvable and naming the main function after the project name is not that special…so…attrs.attrs/attr.s it is I guess? (or import everything).

    Which gives us:

    >>> from attrs import attrs, attrib, Factory
    
    >>> @attrs
    ... class SomeClass(object):
    ...     a_number = attrib(default=42)
    ...     list_of_numbers = attrib(default=Factory(list))
    
    >>> sc = SomeClass(1, [1, 2, 3])
    
    >>> attrs.asdict(sc)
    {'a_number': 1, 'list_of_numbers': [1, 2, 3]}
    
    >>> C = attrs.make_class("C", ["a", "b"])
    >>> C("foo", "bar")
    C(a='foo', b='bar')

    Which I think I can live with? At least I don’t have a better idea.


    One thing that’s notable tho and that makes me feel quite good about attr.s/attr.ib is how much easier they’re to distinguish. So there’s definitely gonna be a from attrs import attr and I’m gonna use it.

  6. glyph commented on Jul 14, 2018

    @glyph
    Contributor

    I think it would be helpful to begin by enumerating the problems that this renaming is attempting to solve.

    • PyPI name ≠ import name
      This is certainly a pet peeve of many people and perhaps rightly so.

    • We a more "forward-looking" API.
      My interpretation of this vague sentiment is that in the past, @attr.s was the only way to do things, and as a result @attr.s is now the default way to do things, whereas the lengthier attr.dataclass and attr.s(auto_attribs=True) feel like tack-ons. So, to be specific: being "forward-looking" means organizing the library around type annotations rather than attrib objects.

    • Maybe it's time for srs bsns.
      The popularity of the project has perhaps expanded to a scale where attr.ib and attr.s look too cutesy. I don't really buy this, but, ok, fine.

    • The attr name is insufficiently mellifluous.
      I am not quite sure I understand why from attrs import validators is so much better than from attr import validators. Can you say more about why you feel this is the case?

    • If we're going to do this, we should do it all at once so we have only one transition to manage rather than N.
      While normally conflating issues is a bad thing, I do agree that this sort of reorganization should be done either zero or one times, not 2+ :).

    Am I missing anything?

  7. glyph commented on Jul 14, 2018

    @glyph
    Contributor

    My own feeling on attr.auto is that it may be a manifestation of a local maximum, and if @hynek is talking about a Grand Reorganizing here then it might not be a good name.

    attr.auto is better than attr.dataclass because it articulates the salient difference between it and attr.s more succinctly: auto_attribs is a big distinction and worthy of being reflected in the name.

    But, it's worse as the new default thing that attrs does. My feeling is that if we want the API to be centered around type annotations, then attrs.attrs should simply have auto_attribs default to True, and that's one of the differences between the old and the new API.

  8. glyph commented on Jul 14, 2018

    @glyph
    Contributor

    Alternately, thinking from the perspective of someone approaching attrs for the first time, why does one use this decorator? Because one is defining a type. So perhaps something like this would make more sense:

    • @attrs.type
    • @attrs.cls
    • @attrs.Class

    Or, resurrecting one of my own personal bugaboos from long ago:

    • @attrs.mutable
    • @attrs.immutable
    • @attrs.value
    • @attrs.const

    Or, for ultimate style points:

    • @attrib.utes
    • @attrib.uted
  9. glyph commented on Jul 14, 2018

    @glyph
    Contributor

    OK, last thought for the moment: please don't land this without having a typeshed / mypy update ready and waiting :)

  10. wsanchez commented on Jul 14, 2018

    @wsanchez

    Which kind of means that the question is reversed – should there be another name for attr.s? We will have a conflict with the serious business crowd anyways since they tend to write from attr import attrs, attrib.

    I'm in the serious business camp (can't help myself, sorry) and I don't have a problem with the above. If I port a file, I'll have clean that up. This doesn't sound like a big deal to me.

  11. wsanchez commented on Jul 14, 2018

    @wsanchez

    Mmmm… @attrs.mutable and… I'd say @attrs.frozen, just based on following typing's lead, eg: typing.MutableSet and typing.FrozenSet.

  12. hynek commented on Jul 15, 2018

    @hynek
    MemberAuthor

    @attrs.mutable & @attrs.frozen are definitely hot contenders right now.

  13. euresti commented on Jul 15, 2018

    @euresti
    Contributor

    Another suggestion if we're pushing type annotations. typed=True as the default? or type_annotated=True

  14. hynek commented on Jul 16, 2018

    @hynek
    MemberAuthor

    typed=True as the default?

    What would that mean?

  15. euresti commented on Jul 16, 2018

    @euresti
    Contributor

    Oh I'm sorry. I meant the typed=True -> foo: int, vs typed=False -> foo = attrs.attrib()

    Unless you're really partial to auto_attrib

  16. 28 remaining items

  17. chadrik commented on Nov 28, 2018

    @chadrik
    Contributor
  18. energizah commented on May 21, 2019

    @energizah

    I like @chadrik's points in favor of make over define, that
    you always have to @make class or make_class().

    @hynek

    It’s just sad that it doesn’t work with the attr prefix

    A new idea then:

    @attr.active
    class Foo:
        x = attr.actor()
       

    :-)

  19. hynek commented on May 21, 2019

    @hynek
    MemberAuthor

    Heh I think this topic is settled at this point. FWIW, you can always alias our API. There even seem to be at least two ways to make it work with mypy: python/mypy#5406 (comment)

  20. tigrus commented on Jun 19, 2019

    @tigrus

    Finally, how we can avoid confusing @attrs.dataclass in our code?

    I don't want to confuse colleagues by constructions like this:

    @final
    @attr.dataclass(frozen=True, slots=True)
    class FetchProfiles(object):
        pass
    

    So, is there way to use @attr.auto / @attr.active instead?

  21. hynek commented on Jun 22, 2019

    @hynek
    MemberAuthor

    Funny you'd ask! So as it's very much obvious, I've been procrastinating on these changes for a while, because I'm afraid to get it wrong.

    Now I've been thinking, that maybe I should make a step in between and add attr.auto with the defaults I've been considering so far.


    As for the dataclass method itself, I've noticed that for a former easter egg it's hilariously popular so I may be convinced to add it into the attrs namespace too, once it lands.

  22. micimize commented on Jul 23, 2019

    @micimize

    what about @attrs.driven, or @attrs.expand? Something that implies more explicitly that the macro will generate methods, etc from the attributes.

    On the other side of this, what about making a namespace that actually is intentionally similar to PEP 557 dataclasses and fields, and just has a thin adapter layer between field and attr.ib, etc? How much incompatibility is there beyond the names? Isn't attrs mostly a superset?

  23. tigrus commented on Jul 24, 2019

    @tigrus

    Guys, my team is asking "Why we are using dataclass here?" ...

    While I want less boilerplate code with attrs. And I don't want to have dataclasses with methods.

    We use python dataclasses, when need kind of interface between functions.

    That's why attrs.auto, attrs.driven and attrs.expand will work in my case. attrs.dataclass looks like joke.

  24. hynek commented on Aug 10, 2019

    @hynek
    MemberAuthor

    attrs.dataclass looks like joke.

    To be fair, it was a joke…it was an easter egg (note the comment in __init__.py) that people found out about. ¯\_(ツ)_/¯

  25. hynek commented on Aug 14, 2020

    @hynek
    MemberAuthor

    Please check out #666 y'all.

  26. jbowen7 commented on Sep 3, 2020

    @jbowen7

    This is the kind of stuff that keeps me from doing any real work.

    @hynek, I realize that you've already packaged v20.0.1 with some of the proposed changes from #408 and #487, but I wanted to suggest a completely different solution.

    The new namespace attrs just doesn't smell right. Not for the proposed usage anyway.
    It'll be quite confusing for many users, and it being so damn similar only makes it doubly so.
    I do, however, agree with @glyph that from attrs import validators sounds really good.

    Here it goes:

    1. make attrs an alias to attr for the sake of melody.
    2. create a meaningful submodule in attr for all of the most commonly used structure-esque things.
      How about
    from attr.models import Model, Field
    
    @Model
    class Dataclass:
       init = Field(default=True)
       repr = Field(default=True)
    

    Firstly, it works.
    Secondly, it would be immediately obvious and could capture the attention of a very large audience (Django, if the plagiarism wasn't obvious)

    Capturing that audience could lead to fields that have built in validation.
    Imagine a attrs package with models like:

    from attrs.models import FrozenModel, EnumField, StringField
    
    @Model
    class MagicWand:
       wishes = EnumField(choices=list(range(1,7)))
    
    @FrozenModel
    class Engraving:
       word = StringField(default='Elbereth')
    
    
  27. micimize commented on Sep 3, 2020

    @micimize

    I'm perfectly happy with the new API. I extracted my PEP compatibility proposal into #686

  28. glyph commented on Oct 20, 2020

    @glyph
    Contributor

    Is attr.define it? Should this be closed?

  29. hynek commented on Oct 20, 2020

    @hynek
    MemberAuthor

    Yes, I think this chapter can be closed after more than 2 years.

    attr.define, attr.mutable, attr.frozen, and attr.field it is!

    Thanks everyone for playing!

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