Skip to content

Caught by surprise using field() without a type annotation #1161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kjohnsen opened this issue Jul 7, 2023 · 1 comment
Closed

Caught by surprise using field() without a type annotation #1161

kjohnsen opened this issue Jul 7, 2023 · 1 comment

Comments

@kjohnsen
Copy link

kjohnsen commented Jul 7, 2023

I know, I know you...recommend against subclassing...but I was doing it in the hopes of reducing boilerplate. And I was really caught off guard by what happened when I mixed type annotations (which I now see the docs say you shouldn't do).

Specifically, I couldn't figure out why my child classes were using parent class default attributes. It took me a while to track it down: when I thought I was redefining the default value for an attribute for a child class, it was being ignored since I also had a field()-defined attribute without a type annotation.

MRE code
#%%
from attrs import define, field
# %%
@define
class Parent:
    x: int = 0
    y: int = 0

@define
class ChildNoAnnotNoField(Parent):
    x: int = 1
    y = 1


@define
class ChildMixedAnnot(Parent):
    # this x Attribute definition is ignored because
    # there is a field without a type annotation
    x: int = 1
    y = field(default=1)

@define
class ChildAnnotField(Parent):
    x: int = 1
    y: int = field(default=1)


print(Parent())               # x=0, y=0
print(ChildNoAnnotNoField())  # x=1, y=0
print(ChildMixedAnnot())      # x=0, y=1
print(ChildAnnotField())      # x=1, y=1

What I suggest is potentially raising a warning for cases like this to spare users from headaches. I had even read most of the docs in some detail, if not super closely, and this threw me for a loop.

Honestly, it wasn't until running into this that I realized you needed type annotations to define an Attribute either. The only place I see is on the Overview page: "Simply assign attrs.field() to the attributes instead of annotating them with types" which could be easily missed. So I'd also suggest making it a little more obvious (maybe on the 'By example' page?) that attributes are defined either by type annotations or by field.

@hynek
Copy link
Member

hynek commented Dec 29, 2023

I've added two warnings; one as suggested to examples, the other to the types chapter. I hope that suffices, thank you for reporting!

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

No branches or pull requests

2 participants