Skip to content

Dict constructor: Generator has incompatible item type "object"; expected "Tuple[Any, Any]" #5287

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

Closed
beamerblvd opened this issue Jun 27, 2018 · 4 comments

Comments

@beamerblvd
Copy link

I filed an issue about improving the dict constructor signature on typeshed, but I think there's also a related bug in the way MyPy is generating this error.

I have the following code:

parameters = dict(
    map(str.strip, p.split('=', 1)) if '=' in p else (p.strip(), None)
    for p in encoded_parameters.split(';')
) if encoded_parameters else {}  # type: Dict

On the second line of this, I get the following error:

error: Generator has incompatible item type "object"; expected "Tuple[Any, Any]"

I get that the error is due to my above-reported problem with the dict constructor signature; however, I also don't believe the error is right. First, the object is too generic. But second, if I improve it slightly (improved for type-checking purposes; the code isn't actually any better/worse):

parameters = dict(
    tuple(map(str.strip, p.split('=', 1))) if '=' in p else (p.strip(), None)
    for p in encoded_parameters.split(';')
) if encoded_parameters else {}  # type: Dict

This yields the exact same error, and it shouldn't. I now have a generator of tuples, and it should recognize that. There should be no error with this second approach.

@ilevkivskyi
Copy link
Member

In the second case (with a tuple call) the iterable item is essentially a join of Tuple[str, ...] and Tuple[str, None]. I think potentially we can say it is Tuple[object, ...] (but still not a subtype of Tuple[Any, Any]). The point here is that mypy is not able (and most likely will never be) to prove that p.split('=', 1) if '=' in p has length exactly two.

The rest is a duplicate of #4975

@beamerblvd
Copy link
Author

But it seems like you could infer the two-tuple from the presence of the two-tuple in that join. For that matter, it seems just as easy (easier) to infer the exact number of elements from the second argument to split. Even if not, why can't I # type: Tuple[str, str] on that line (misplaced type annotation) to clear things up? As it stands, I'm currently # type: ignore-ing that line.

@ilevkivskyi
Copy link
Member

But it seems like you could infer the two-tuple from the presence of the two-tuple in that join.

No, this would be too unsafe.

Even if not, why can't I # type: Tuple[str, str] on that line

This is for variable definitions, what you need is typing.cast, so you write cast(Tuple[str, str], p.split())

@beamerblvd
Copy link
Author

This is for variable definitions, what you need is typing.cast, so you write cast(Tuple[str, str], p.split())

Indeed, this worked for me. Thanks for the help, and sorry for the unnecessary bug report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants