You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unconstrained type variable combined with isinstance() doesn't seem to work #1539
I'm guessing that s might be of a non-str, non-bytes type, and mypy doesn't recognize "else: raise" as a type guard. I'm currently in day-job avoidance, so I'd better not go find out by replacing the "raise" with "return s".
The reason the example doesn't work is that after the isinstance() the type of s is str (or bytes), but nothing else changes -- in particular, the return type is still S. str is not a subtype of S, so mypy rejects the return statement.
To make the example work, mypy could perhaps somehow keep track of the fact that S must be a supertype of str after the first isinstance() check, and use this information when checking the return statement.
Oh dang. I totally missed that the errors were about the return type, not about the + operators. Oh well. Since I blogged about this and linked to this issue from the blog, you can expect some more drive-by comments.
Actually this particular program really is invalid because S might be a subtype of str; then isinstance(s, str) will be true but '(' + s + ')' is still only a str and not an S.
If you change both return statements to return s, though, the program is valid but mypy still rejects it, because it doesn't know how to use both pieces of information simultaneously: that s is of type str and also of type S.
Hi ... I realize this is necromancy, but I'm running into this trying to type some existing code:
def localize(v: T) -> T:
if isinstance(v, str):
return loctable.localize(v, default='')
return v
The intent is that this function will translate anything it's capable of translating -- a string -- and return everything else untouched. Mypy doesn't like this very much:
export.py:60: error: Incompatible return value type (got "str", expected "T")
... But, of course, T is a str in this case -- but mypy doesn't seem to be able to dynamically constrain typevars.
That's a good point -- but in this case, localize is typed to always return string because it's performing a lookup and constructing a new object and it doesn't take care to use the type constructor of the type it was given. The annotation here should be correct: localize inflexibly returns a string.
I think using isinstance checks, while unpythonic, is necessary on boundaries between Python and JSON in particular.
Since I arrived here via google, I think a workaround for this lack of type constraining is likely to use something like @overload; I have since used something like the following:
Activity
yaseppochi commentedon May 17, 2016
I'm guessing that s might be of a non-str, non-bytes type, and mypy doesn't recognize "else: raise" as a type guard. I'm currently in day-job avoidance, so I'd better not go find out by replacing the "raise" with "return s".
JukkaL commentedon May 17, 2016
The reason the example doesn't work is that after the
isinstance()the type ofsisstr(orbytes), but nothing else changes -- in particular, the return type is stillS.stris not a subtype ofS, so mypy rejects the return statement.To make the example work, mypy could perhaps somehow keep track of the fact that
Smust be a supertype ofstrafter the firstisinstance()check, and use this information when checking the return statement.gvanrossum commentedon May 17, 2016
Oh dang. I totally missed that the errors were about the return type, not about the + operators. Oh well. Since I blogged about this and linked to this issue from the blog, you can expect some more drive-by comments.
rwbarton commentedon May 18, 2016
Actually this particular program really is invalid because
Smight be a subtype ofstr; thenisinstance(s, str)will be true but'(' + s + ')'is still only astrand not anS.If you change both return statements to
return s, though, the program is valid but mypy still rejects it, because it doesn't know how to use both pieces of information simultaneously: thatsis of typestrand also of typeS.JukkaL commentedon May 18, 2016
@rwbarton True, I got it wrong. In any case, this is a pretty subtle issue and doesn't look like a high-priority one.
jnsnow commentedon Feb 15, 2020
Hi ... I realize this is necromancy, but I'm running into this trying to type some existing code:
The intent is that this function will translate anything it's capable of translating -- a string -- and return everything else untouched. Mypy doesn't like this very much:
export.py:60: error: Incompatible return value type (got "str", expected "T")
... But, of course, T is a str in this case -- but mypy doesn't seem to be able to dynamically constrain typevars.
JelleZijlstra commentedon Feb 16, 2020
Or
vcould be a subtype of str, but yourloctable.localizewould presumably still return astr.jnsnow commentedon Feb 22, 2020
That's a good point -- but in this case,
localizeis typed to always return string because it's performing a lookup and constructing a new object and it doesn't take care to use the type constructor of the type it was given. The annotation here should be correct: localize inflexibly returns a string.I think using
isinstancechecks, while unpythonic, is necessary on boundaries between Python and JSON in particular.Since I arrived here via google, I think a workaround for this lack of type constraining is likely to use something like @overload; I have since used something like the following: