-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Infer attributes from __new__ #1021
Comments
This is follow-up to #982. |
Decreased priority since this doesn't seem like users often struggle with this -- it's easy enough to work around by inserting type annotations. |
One use case is NamedTuple. It's turning mypy into a noise generator for me. |
@toolforger how are you using NamedTuple? I don't think the example from the original post in this issue is applicable to NamedTuple. |
Use instead: class Foo(NamedTuple):
x: int
y: int = 0
Foo(1) # OK, same as Foo(1, 0)
Foo(1, 2) # OK works on Python 3.6+. If you are on Python 2, then wait for this issue to be solved. |
@ilevkivskyi your advice works for direct subclasses. My use case is for an indirect subclass. (I already had to move all fields up into the root class because NamedTuples don't properly support subclassing, but I cannot use frozen dataclasses until 3.7 comes out for my distro. I'm on the verge of ripping out mypy again, or switching from Python to Kotlin.) |
@toolforger I hear your frustration, but please don't take it out on us. We have a lot on our plate and we're only a small team (half of us are volunteers). This will eventually get fixed. (If you want to help by submitting a PR that might speed it up of course.) |
Heh. Getting advice that's inapplicable because the person didn't really understand the situation, after spending weeks of my free time on a dozen or so approaches - well what can I say, it was just the last straw. Won't work on Python, sorry:
|
Can we raise the priority here? I encountered several cases of this in S (links provided at request). What's worse, I also get an error on the super
The workaround is redundant class-level attribute declarations. |
The super error is unrelated, it is just typeshed problem, |
The super error is unrelated, it is just typeshed problem, str doesn't
have __new__ there.
Okay, but the main problem is the need for duplication for every attribute.
|
Updated priority to high. |
How would this work with an E.g.: from enum import Enum
class Colours(Enum):
# letter, ANSI base color, reverse flag
black = "k", "white", True
blue = "b", "blue"
orange = "o", "yellow"
red = "r", "red"
def __new__(cls, value: str, colour: str, reverse: bool = False):
member = object.__new__(cls)
member._value_ = value
member.ansi_colour = colour
member.reverse = reverse
return member The above causes several issues for MyPy; for the above example the I can work around these issues by giving default values any arguments beyond from enum import Enum
from typing import TYPE_CHECKING
class Colours(Enum):
# letter, ANSI base color, reverse flag
black = "k", "white", True
blue = "b", "blue"
orange = "o", "yellow"
red = "r", "red"
if TYPE_CHECKING:
value: str
ansi_colour: str
reverse: bool
def __new__(cls, value: str, colour: str = "white", reverse: bool = False):
member = object.__new__(cls)
member._value_ = value
member.ansi_colour = colour
member.reverse = reverse
return member or, and that's a heavier hammer, put the |
This comment was marked as outdated.
This comment was marked as outdated.
@tpvasconcelos I worked around the issue by using class MyEnum(Enum):
ONE = 1
TWO = 2
THREE = 3
def __new__(cls, value, is_cool_number):
member = object.__new__(cls)
member._value_ = value
# member.is_cool = is_cool_number # Not this
setattr(member, "is_cool", is_cool_number) # This
return member Note that this will make Mypy happy inside And just as a reminder, remember that if your enum inherits from a different type (e.g. It would still be nice to see this fixed upstream one day, since the issue is seven years old at this point. At the moment I don't have the time to learn mypy's codebase and contribute myself, unfortunately. |
The above doesn't work for me (mypy 1.4.1 on Python 3.11.3): from enum import Enum
class Num(Enum):
WOM = (1, True)
TOO = (2, False)
TEE = (3, True)
FOR = (4, False)
def __new__(cls, value, is_cool_number):
obj = object.__new__(cls)
obj._value_ = value
obj.is_not_cool = not is_cool_number
setattr(obj, "is_cool", is_cool_number)
return obj
Num(1) # Missing positional argument "is_cool_number" in call to "Num" [call-arg]
Num["TOO"]
Num.TEE.is_not_cool # "Num" has no attribute "is_not_cool" [attr-defined]
Num.FOR.is_cool # "Num" has no attribute "is_cool" [attr-defined] The "Missing positional argument "is_cool_number" in call to "Num" [call-arg]" is a different beast, though... Later edit: it looks like I missed an important bit in the above comment:
|
if I work around this by manually annotating the member attributes, it breaks exhaustiveness checking because mypy thinks the attributes are enum elements:
results in:
am I missing something? is there a way to avoid this? This is on python 3.11.9 and mypy 1.10.1 |
Off-topic, but closest issue i got from google to my problem. Someone could find it helpful. class Popik:
def __init__(self, *args, **kwargs):
# __init__() would be called after __new__()
# should have same arguments as __new__()
# or use (*args, **kwargs) stub
self.booty: str
def __new__(cls):
# in reality i hijack and extend object from extrenal factory
obj: Popik = cast(Any, type("stub", (object,), {})())
obj.__class__ = cls
obj.booty = "mignon"
return obj
p = Popik()
print(p.booty) |
In this example (from #982) we define an attribute via assignment in
__new__
:Currently mypy doesn't recognize attribute
foo
and complains aboutx.foo
. To implement this, we could do these things:obj
is something similar toself
because of the way is created viaobject.__new__
. This should happen during semantic analysis so that this will work in unannotated method as well.obj
because it is classified as similar toself
.object.__new__
calls viasuper(...)
.The text was updated successfully, but these errors were encountered: