Skip to content
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

error: 'Union[Any, Tuple[Any, Any]]' object is not iterable #1855

Closed
gvanrossum opened this issue Jul 13, 2016 · 10 comments · Fixed by #4067
Closed

error: 'Union[Any, Tuple[Any, Any]]' object is not iterable #1855

gvanrossum opened this issue Jul 13, 2016 · 10 comments · Fixed by #4067
Assignees
Labels

Comments

@gvanrossum
Copy link
Member

gvanrossum commented Jul 13, 2016

Code:

from typing import *
Pair = Tuple[Any, Any]
def f(a: Union[Any, Pair]):
    x, y = a  # E: 'Union[Any, Tuple[Any, Any]]' object is not iterable

If the type of argument is either just Any or just Pair the code passes. But with the union it gives the error.

UPDATE: I don't think the unreduced union is at fault -- an example with two different Tuple types of length 2 also fails. It's more that the unpack operation isn't tried for each variant of the union.

@JukkaL JukkaL added the bug mypy got something wrong label Jul 13, 2016
@gnprice
Copy link
Collaborator

gnprice commented Jul 14, 2016

We've seen this a couple of times internally.

@gvanrossum gvanrossum added this to the 0.4.x milestone Jul 14, 2016
@elazarg
Copy link
Contributor

elazarg commented Sep 18, 2016

Could be related to #2128 ?

@gvanrossum
Copy link
Member Author

gvanrossum commented Sep 18, 2016 via email

@elazarg
Copy link
Contributor

elazarg commented Sep 18, 2016

Turns out it's not directly the same cause: the union case was not handled and not tested.

I believe it's the same root cause but in a deeper sense: the matching of multi-assignment and function calls define is typechecking and should be handled through the subtype module. Many subtype-related decisions are scattered through the checker (such as itemwise matching, and the iteration over union elements that I just added).

But even if it's not moved to subtype.py, I think it'll help to have a single matcher, common to function calls, multi assignment, multi-iteration (what's the terminology for that?) etc. If it was the case, my fix would have probably fixed #2128 too (I did not study it yet, though; It's just a guess).

@nickpresta
Copy link

nickpresta commented May 23, 2017

EDIT: I'm running mypy 0.511 -- I'm trying with the latest master now.

We're seeing this problem manifest itself with our code like this (no OSS code to link):

class User(NamedTuple):
    id: UUID
    # more attributes
    

class UserService:
    def get_or_create(self, user_id: UUID, user_data: Optional[dict] = None) -> Tuple[User, bool]:
        return User(id=uuid4()), False


class Authentication:
    def authenticate(self, request: Request) -> Tuple[User, None]:
        user, _ = UserService().get_or_create(user_id=uuid4())  # ERROR HERE
        return user, None

The error I get is:

error: 'Union[Any, Tuple[Tuple[uuid.UUID, datetime.datetime, datetime.datetime, datetime.datetime, builtins.bool, builtins.str, builtins.str, builtins.str, fallback=users.domain.User], builtins.bool]]' object is not iterable

The Tuple[uuid.UUID, datetime.datetime, ...] bit is our User namedtuple.

As soon as I do something like:

class Authentication:
    def authenticate(self, request: Request) -> Tuple[User, None]:
        some_id = uuid4()
        user = UserService().get_or_create(user_id=some_id)[0]  # explicitly unpack first element
        return user, None

The error then goes away.

Right now we're working around it with the explicit index but any other insight would be much appreciated.

Thanks

@gvanrossum
Copy link
Member Author

Does it repro with the latest master?

@nickpresta
Copy link

@gvanrossum I checked out master and tried to reproduce with mypy 0.520-dev and I don't get the error anymore.

Thanks.

We will wait for 0.520 to be published to PyPI.

@gvanrossum
Copy link
Member Author

OK, then per our policy I will close this issue. (We close issues when they are fixed in master.)

@ilevkivskyi
Copy link
Member

But the original issue is not fixed, I just checked and I still see the same error:
'Union[Any, Tuple[Any, Any]]' object is not iterable

@gvanrossum
Copy link
Member Author

Whoops, sorry.

@gvanrossum gvanrossum reopened this May 23, 2017
OddBloke pushed a commit to OddBloke/typeshed that referenced this issue Aug 7, 2017
TL;DR, we're hitting python/mypy#3805 when
implemented correctly as an override, and
python/mypy#1855 when we try to work around
that with a union.
OddBloke pushed a commit to OddBloke/typeshed that referenced this issue Aug 9, 2017
TL;DR, we're hitting python/mypy#3805 when
implemented correctly as an override, and
python/mypy#1855 when we try to work around
that with a union.
OddBloke pushed a commit to OddBloke/typeshed that referenced this issue Aug 21, 2017
TL;DR, we're hitting python/mypy#3805 when
implemented correctly as an override, and
python/mypy#1855 when we try to work around
that with a union.
OddBloke pushed a commit to OddBloke/typeshed that referenced this issue Aug 21, 2017
TL;DR, we're hitting python/mypy#3805 when
implemented correctly as an override, and
python/mypy#1855 when we try to work around
that with a union.
ambv pushed a commit to python/typeshed that referenced this issue Aug 21, 2017
…1527)

* Make configparser.RawConfigParser.__getitem__ return a SectionProxy

This reflects the code in the cpython tree and makes the following
(valid) code type-check correctly:

```
from configparser import ConfigParser

config = ConfigParser()
config.read_dict({'section': {'key': 'false'}})
assert config['section'].getboolean('key') is False
```

* RawConfigParser.items() returns SectionProxys not mappings

Because .items() uses __getitem__ to produce second item in each tuple.

* section argument to RawConfigParser.items is Optional

* Add comment explaining the status of RawConfigParser.items

TL;DR, we're hitting python/mypy#3805 when
implemented correctly as an override, and
python/mypy#1855 when we try to work around
that with a union.

* Correctly implement RawConfigParser.items overloading

* RawConfigParser.items(str) returns a List not an Iterable
JukkaL pushed a commit that referenced this issue Oct 11, 2017
Fixes #3859
Fixes #3240
Fixes #1855
Fixes #1575

This is a simple fix of various bugs and a crash based on the idea
originally proposed in #2219. The idea is to check assignment for 
every item in a union. However, in contrast to #2219, I think it will 
be more expected/consistent to construct a union of the resulting 
types instead of a join, for example:

```
x: Union[int, str]
x1 = x
reveal_type(x1) # Revealed type is 'Union[int, str]'

y: Union[Tuple[int], Tuple[str]]
(y1,) = y
reveal_type(y1) # Revealed type is 'Union[int, str]'
```

@elazarg did the initial work on this.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment