-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Unpacking tuples of variable length #1178
Comments
The error message is incorrect. However, mypy may not be able to type check this properly since it doesn't recognize the
The recommended way to work around the issue is to use casts:
|
Also, mypy could recognize
|
I just ran into this issue and was going to post the following test case, but didn't realise that len(x) wasn't yet a way to distinguish among unions:
|
python/mypy#1178 is about variable-length tuples, while exc_info() always returns a tuple with length 3. Ideally, exc_info() would return Union[Tuple[Type[_E], _E, TracebackType], Tuple[None, None, None]], but that is a different issue.
* Add ExcInfo and OptExcInfo type aliases * Implement StartResponse using a protocol * Mark stub-only types with an underscore * Remove wrong TODO note python/mypy#1178 is about variable-length tuples, while exc_info() always returns a tuple with length 3. Ideally, exc_info() would return Union[Tuple[Type[_E], _E, TracebackType], Tuple[None, None, None]], but that is a different issue.
* Add ExcInfo and OptExcInfo type aliases * Implement StartResponse using a protocol * Mark stub-only types with an underscore * Remove wrong TODO note python/mypy#1178 is about variable-length tuples, while exc_info() always returns a tuple with length 3. Ideally, exc_info() would return Union[Tuple[Type[_E], _E, TracebackType], Tuple[None, None, None]], but that is a different issue.
I'm getting a different error, but I'm guessing this is the same issue:
(I have a mypy.ini specifying check_untyped_defs) |
@pgunn In your particular case you can use |
@ilevkivskyi Will look into that; unfortunate that it's actually necessary, but it's great that it's possible. Thanks. |
@ilevkivskyi I'm trying to follow the docs here:
This is also getting very verbose. Not sure if it's that these are keyword rather than positional arguments that's giving me the problem.
This may be wandering away from the topic of the issue though; if it's wandered too far I'm fine with not getting an answer; don't want to clutter things for devs. |
Yes, this is because they are keyword args, see #6580 Anyway, in your case I would just return a less precise type like |
@ilevkivskyi It does. Thanks! I have some other code not well-covered by this tack, but perhaps by the time we're ready to switch to requiring mypy to pass in CI before merges, this kind of thing will have a more graceful solution. |
There seems to be an issue even with fixed-length tuples: # file: ex.py
from typing import Tuple
points = (1, 2) # type: Tuple[int, int]
x, y, z = *points, 0 This results in incorrect inference about the tuple size: $ mypy ex.py
ex.py:4: error: Need more than 2 values to unpack (3 expected)
Found 1 error in 1 file (checked 1 source file) A workaround is to use x, y, z = cast(Tuple[int, int, int], (*points, 3)) |
@goodmami could you open a new issue for that? It seems like a different (enough) problem. |
I think this is a missing feature rather than a bug (although this does cause a false positive). |
If your list to unpack is never greater than your left side and you know how many variables are on the left side, then you can do this (assuming there are 5 variables on the left side): list_to_unpack = [1, 2, 3]
a, b, c, d, e = list_to_unpack + (5 - len(list_to_unpack)) * [None]
print(a)
print(b)
print(c)
print(d)
print(e)
# output
# 1
# 2
# 3
# None
# None if you also want to catch the cases where the list is bigger than the variables, then you can do as follows: list_to_unpack = [1, 2, 3, 4, 5, 6]
count_variables = 5
a, b, c, d, e = list(list_to_unpack + (count_variables - len(list_to_unpack)) * [None])[:count_variables] |
First of many stabs at eliminating Any and # type: ignore from the codebase. Here we eliminated several different type ignores; the remaining # type: ignore is just a mypy limitation. I also narrowed the typing of RichReprResult from Iterable[Any|...]] to Iterable[object] since after inspection of the code this is what's really required. There's one particularly nasty cast that's needed. It's definitely a mypy bug that it's not throwing an error for us here. See: python/mypy#1178 and I've opened a similar issue for pyright. There's an open PR for mypy that would resolve this, but at least until this is fixed we need to be casting. In order to correctly type the auto_repr function, I introduced a SupportsRichRepr protocol; we could also have made this runtimecheckable and replaced a hasattr check in the code with it, but it seemed unnecessary so I opted not to.
I ran into a similar issue today. Minimal example: transition: tuple[int, int] | tuple[int, int, str] = (1, 1, "a")
if len(transition) == 3:
print(transition[2]) An error is raised by mypy for last line: |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This is getting very off-topic. Let's leave this issue focused on narrowing tuple types with |
Just wondering if this issue has been resolved? I still get a mypy error for the following code snippet: from typing import Tuple
def f0(n: int) -> Tuple[int, ...]:
return tuple(range(n))
def f2() -> Tuple[int, int]:
ret = f0(2)
assert len(ret) == 2
return ret
if __name__ == '__main__':
print(f2()) Save the code in |
It's not resolved, that's why this issue is still open. |
Thanks for quick reply. I’ll use the workaround mentioned in this thread
then.
…On Fri, Aug 25, 2023 at 4:41 PM Jelle Zijlstra ***@***.***> wrote:
It's not resolved, that's why this issue is still open.
—
Reply to this email directly, view it on GitHub
<#1178 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ASLXBGMUAWX5U76IV23HOWTXXEEXNANCNFSM4BZXWZWQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Fixes #1178 Supersedes #10367 This is includes implementation for fixed length tuples, homogeneous tuples, and variadic tuples (and combinations of those). Generally implementation is straightforward. Some notes: * Unfortunately, it is necessary to add a new attribute `min_len` to `TypeVarTupleType`, which is probably fine, as it doesn't have that many attributes so far. * Supporting more general use cases (like `>` comparisons for variadic tuples) can cause quick proliferation of unions. I added two mechanisms to counteract this: not applying the narrowing if the integer literal in comparison is itself large, and collapsing unions of tuples into a single tuple (if possible) after we are done with the narrowing. This looks a bit arbitrary, but I think it is important to have. * Main missing feature here is probably not inferring type information from indirect comparisons like `len(x) > foo() > 1`. Supporting this kind of things in full generality is cumbersome, and we may add cases that turn out to be important later. * Note I am quite careful with indexing "inside" a `TypeVarTuple`, it is not really needed now, but I wanted to make everything future proof, so that it will be easy to add support for upper bounds for `TypeVarTuple`s, like `Nums = TypeVarTuple("Nums", bound=tuple[float, ...])`. * I also fix couple existing inconsistencies with `Any` handling in type narrowing. It looks like they stem from the old incorrect logic that meet of `Any` and `X` should be `X`, while in fact it should be `Any`. These fixes are not strictly necessary, but otherwise there may be new false positives, because I introduce a bunch of additional type narrowing scenarios here. cc @hatal175, thanks for the test cases, and for your nice first attempt to implement this! Co-authored-by: Tal Hayon <talhayon1@gmail.com>
Given the following code:
mypy complains about the following error:
The text was updated successfully, but these errors were encountered: