-
-
Couldn't load subscription status.
- Fork 406
Description
The problem is simple.
@attr.s class A: a = attr.ib() b = attr.ib(default=1) @attr.s class B(A): c = attr.ib() ValueError: No mandatory attributes allowed after an attribute with a default value or factory. Attribute in question: Attribute(name='c', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None) Since, in the case of inheritance, attrs will order the attributes so:
- a
- b (default=1)
- c
and this is illegal (presumably because it would result in __init__(a, b=1, c), which is illegal Python).
The current approach has the benefit of the order of attributes being very clear, and it fits well with positional parameters (i.e. A(a=1, b=2) === A(1, 2)). This is a neat symmetry.
First of all, I don't see a way to make this work naturally (i.e. to make the example work as is), simply because of Python.
I can see several solutions to this problem (maybe there are more?).
The first solution: leave it as is, say it's unsupported.
The second solution: when processing an inheriting class, group non-default fields together first, then fields with defaults. So the order would instead be:
- a
- c
- b (default=1)
I think this would preserve backward compatibility. It's at odds with the point of the attribute order being significant that I mentioned earlier.
The third solution: this works only on Python 3. Introduce keyword-only parameters (https://www.python.org/dev/peps/pep-3102/) somehow. I would need to think about a nice API but let's pretend it'd just be:
@attr.s class A: a = attr.ib() b = attr.ib(default=1, kwonly=True) @attr.s class B(A): c = attr.ib() Then we'd basically do the same as for the second proposal, only for kwonly parameters, but now it's explicit. The generated __init__s would be:
class A: def __init__(self, a, *, b=1) class B(A): def __init__(self, a, c, *, b=1) I think this is nice since we're basically just exposing existing Python functionality.
If you like any of the proposals, I will put together a PR.