-
-
Notifications
You must be signed in to change notification settings - Fork 374
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
subclass with mandatory attribute cannot be created when the base class has a factory based one #38
Comments
This has been reported before and I’m not sure what to do about it. putting mandatory always before optionals? iow reordering? |
they can always be given as keyword the order should stay the same it should be possible to give them as keyword instead of a positional argument once inheritance is involved it seems sensible to go towards keywords in any case basically all mandatory arguments after a optional one can be primary keyword based |
btw, i do in fact use them as keywords, but putting in a default of None seems the wrong way |
I kind of agree, but what’s better? having a sentinel and explode on it? |
not quite sure what you mean by the sentinel for the code in the example i posted i think that |
what you sketched it results in def __init__(self, attr=False, needed):
pass which is a syntax error. So we need some default value for needed here. |
i see what you mean, in python3 its |
I accidentally opened up a duplicate of this. My personal opinion™ is that we should just allow users to mark attributes as Full example:
Also, in the case of the error we have now, a helpful error message can direct users to use |
I ran into this problem as well and I have a slightly different take on it that I wanted to submit. A more natural solution to me would be to write something like:
At the cost of a very minor repetition of code, this lets the programmer explicitly control the order in which the attributes should appear for representation purposes or when converting to a tuple. However what I wrote obviously doesn't work in the current version of attr: because of the way inheritance is implemented, Sub receives two 'attr' attributes, which happens to break the __init__ method among other things. I do have a bit of beef with that and was both curious about why attributes don't get overridden in subclasses, and willing to do something about it -then I saw this issue and thought that would be a good starting point for my comment. |
how about this:
|
since this is starting to turn into a mirad of dozens and dozens of options i believe this should either not be supported for the sake of simplicity or be supported only by disabling positional constructor arguments in the complete inheritance tree |
I tend to agree. I’m thinking about an option to |
Yea I run into this issue a lot when I have some common optional attributes that I want to share across many classes. e.g.
I'm kinda inspired by go's embedded struct types:
with some getattr generated functionality. There would be a SmallOptions instance embedded within Main instance that would be proxied, and can be accessed directly by Main().options as well. |
or like this
|
closes python-attrs#38 (Rebases python-attrs#281) Co-authored-by: Alex Ford <fordas@uw.edu>
* Added support for keyword-only attributes. Closes #106, and closes #38 (Rebases #281) Co-authored-by: Alex Ford <fordas@uw.edu> * Add `attr.s`-level `kw_only` flag. Add `kw_only` flag to `attr.s` decorator, indicating that all class attributes should be keyword-only in __init__. Minor updates to internal interface of `Attribute` to support evolution of attributes to `kw_only` in class factory. Expand examples with `attr.s` level kw_only. * Add `kw_only` to type stubs. * Update changelog for rebased PR. Hear ye, hear ye. A duplicate PR is born. * Tidy docs from review. * Tidy code from review. * Add explicit tests of PY2 kw_only SyntaxError behavior. * Add `PythonToOldError`, raise for kw_only on PY2. * `Attribute._evolve` to `Attribute._assoc`.
This is a closed issue, and I'm definitely out of my depth as I wade into this discussion, but I'm working (with @asford, fwiw) on a project using attrs, and am getting the "No mandatory attributes after..." error message. I'm at the moment stumped as to what the order of attributes is for my class and which ones have and which lack defaults/factory methods. It would be super useful if the exception printed more about the offending attributes. In my case, I want to know: what is the first attribute that has a default that appears ahead of an attribute which lacks one right now, the error message only tells me what attribute lacks a default. |
Could you open a feature request please? Comments on closed bugs get inevitably lost. |
For anyone stumbling on this issue and still unclear on how to implement a keyword-only attribute, here's the syntax: @attr.s
class MyClass:
x = attr.ib(kw_only=True) |
Because we didn't find a good way to implement it in Python 2 without introducing a forbidding amount of complexity. While we're committed to maintain Python 2-compatibility as long as it's feasible, we reserve to not implement new features for it if they are either impossible or too painful to implement/maintain. |
@hynek while I completely agree, I also think it would be a good idea to state exactly that in the documentation, and/or the error it is very misleading as the ticket is closed, everything is "fixed", py2 is alive... it makes people think they can get away with a workaround in py2, yet this is not true |
Can anyone tell me what is the recommended way now? |
Either make the subclass kw_only=True or overwrite the attribute with the default in the subclass: import attr
def test_example():
@attr.s
class Base(object):
a = attr.ib(default=False)
@attr.s
class Sub(Base):
a = attr.ib()
needed = attr.ib() |
I think this should be working code: @attr.s
class Base():
optional = attr.ib( default = False, kw_only = True )
_internal = attr.ib( default = None, init = False )
@attr.s
class Subclass( Base ):
required = attr.ib() It isn't though, currently, because:
@attr.s( group_kw_only_last_in_init = True )
class Subclass:
required = attr.ib() (Obviously with a better option name than that. 😉) |
My Python-2-Compatible solution is just
|
failing example
The text was updated successfully, but these errors were encountered: