-
-
Notifications
You must be signed in to change notification settings - Fork 383
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
Ability to have kw_only
attributes defined anywhere, as an optional feature
#559
Conversation
I haven’t looked at that code in a while, so based on your patch, we already sort kw_only at the end anyways and all you have to do is to disable an artificial sanity check to leave it through? 🤔 |
@hynek kind of, but at least on |
As far as I can see it, the idea is solid. The name not so much. :) I think it should reflect what the user gets, not how it's implemented. I think even Also: is there a scenario where leaving the check off by default could be considered a regression? 🤔 |
I've updated the param name to the suggested I will start working on the docs! |
Hmm, some checks are failing with stuff that seems to be unrelated to the change: |
They pass now but for some reason one of the checks doesn’t run. I even think that’s because AP changed something between you opening this PR and now (it used to be only one check). Could you rebase on master please? Maybe it’ll fix itself... |
What I'm saying is: just remove the check, keep the test and add a newsfragment that announces it. No option. Can you do that anytime soon or should I just do it quickly for you? |
@hynek great! Ok, I can do the change today :) |
I decided to implement
A couple of days passed, and I want to refactor my code back to using the base class. Now I have to change all constructor invocations everywhere, again, from the positional argument to the keyword one. May I ask, why you can't mark P.S. of course, I am not a member of |
I don't disagree with you, but this sounds like a preference, not a technical necessity? Moreover, it seems like you could add a your own decorator/validator that catches this issue? Again, I personally don't disagree, but this seems a bit too opinionated. If I'd be like that with everything, there wouldn't be any subclassing in |
To me, it is a technical necessity from the point that pure python doesn't work like that, you cannot magically change a keyword-only argument of a base class constructor to be positional in a subclass without overriding the whole signature. |
I'm not sure I understand? That's not what we are trying to do here and it's something you can do now anyway: In [1]: import attr
In [2]: @attr.s
...: class C1:
...: x = attr.ib(kw_only=True)
...: @attr.s
...: class C2(C1):
...: x = attr.ib()
...:
In [3]: C2(1)
Out[3]: C2(x=1)
In [4]: C1(1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-a55995036880> in <module>
----> 1 C1(1)
TypeError: __init__() takes 1 positional argument but 2 were given This PR is about this use case: In [4]: @attr.s
...: class C1:
...: always_kw = attr.ib(kw_only=True)
...: @attr.s
...: class C2(C1):
...: pos = attr.ib()
...:
In [5]: C2(1, always_kw=2)
Out[5]: C2(always_kw=2, pos=1) Which I kinda can see the value of. Maybe there are use-cases where it makes sense to carry around a kw-only attribute –especially if it has a default value – and leave the rest pos-only? Am I missing something? |
Ah, right, I should've looked to the test case, sorry. So, all keyword-only attributes will jump to the end of the list of arguments. What if there are multiple base classes, settings multiple keyword-only arguments?
What would be the order of arguments of What if we throw in multiple inheritance?
|
They already do jump at the end of the arguments – behind a
The changes don't modify any behavior at all, they just remove a restriction. |
Well, I did not expect that :) Honestly, I've never tried to do so. |
Great, thanks for taking the time to talk it through! |
Ok, change done: now we can specify kw_only attrs anywhere and they won't be checked for ordering. No more flag to enable or disable the check. It won't even check if mandatory kw_only attrs are before or after non-mandatory kw_only args, which I think is the right thing to do, because they don't actually have any order when calling init (they can't be positional because they are kw_only). This allowed me to simplify a lot of the code that checked for ordering of mandatory vs non-mandatory attrs. |
You skipped the newsfragment again but I'll do it myself real quick to avoid further cycles. Thanks! |
@hynek ouch, sorry. And thanks for merging it! :) |
Ability to have
kw_only
attributes defined anywhere, as an optional feature (when enabled,don't raise errors if a non keyword-only attribute is defined after a keyword-only one).
I'm really interested in allowing
kw_only
attrs anywhere, because it would fix the problem ofnot being able to add mandatory attrs to classes if the base class already has optional
attrs.
By making the optional attrs keyword-only, and allowing keyword-only attrs anywhere, the
child classes will can add their own mandatory attrs after the otional keyword-only ones from
the base class.
This would be super useful for me in several projects in which I hit that wall. And I suspect
there are many facing the same problem (#38, questions in stack overflow, etc).
In #448 concerns were raised regarding the obvious ordering of attributes getting less obvious
because of this. So to avoid unexpected ordering changes, I decided to make this behaviour
optional and disabled by default, using a new parameter in
attr.s
.I know, terrible name for the parameter, can't think of a better one right now. Suggestions?
But the behaviour is this:
kw_only_order_check=True
(Default): don't allow non keyword-only attrs after keyword-onlyattrs.
kw_only_order_check=False
: allow keyword-only attrs anywhere.Is there anything else I should check or add tests to?
And I'm not sure where should I document this.
Also, I would like the change itself to be validated before I continue working on tests and docs, if possible, so I don't spend too much time on this if you don't think the feature should be added :)
Pull Request Check List
.pyi
).tests/typing_example.py
.docs/api.rst
by hand.@attr.s()
have to be added by hand too.versionadded
,versionchanged
, ordeprecated
directives..rst
files is written using semantic newlines.changelog.d
.If you have any questions to any of the points above, just submit and ask! This checklist is here to help you, not to deter you from contributing!