Bug 369363

Summary: Type not inferred when iterating objects with __next__
Product: [Developer tools] kdev-python Reporter: Nicolás Alvarez <nalvarez>
Component: Language supportAssignee: Sven Brauch <mail>
Status: RESOLVED FIXED    
Severity: normal CC: mail
Priority: NOR    
Version First Reported In: 5.0.1   
Target Milestone: 1.7.3   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed/Implemented In: 5.1.0
Sentry Crash Report:

Description Nicolás Alvarez 2016-09-25 23:02:30 UTC
If I have a generator implemented as a function, iterating over it with a for loop (or list comprehension) correctly deduces the type of the item variable:

def gen1():
    yield "blah"

for item1 in gen1():
    print(item1)

Here, KDevelop knows item1 is a str, because that is what gen1 yields.

However, if I do the same with a class that has a custom __next__ method, the type is not deduced:

class Gen2:
    def __iter__(self):
        return self
    def __next__(self):
        return "blah"

gen2 = Gen2()
for item2 in gen2:
    print(item2)

The tooltip shows item2 as 'mixed', its attributes are not highlighted or completed, etc.

This affects a few built-in types, such as I/O classes that yield strings (lines) when iterated. (In many cases the definitions in documentation_files don't have a __next__ and they should, but the point of this bug is that adding the missing __next__ makes no difference)
Comment 1 Nicolás Alvarez 2016-09-25 23:12:36 UTC
By the way, as another example for the unit tests:

class Foo:
    def __iter__(self):
        return Bar()
    def __next__(self):
        return "blah"

class Bar:
    def __next__(self):
        return {}

for x in Foo():
    pass

Here 'x' should be of type 'dict', not 'str'!
Comment 2 Sven Brauch 2016-10-03 21:30:16 UTC
Valid issue but probably hard to fix given how it's implemented currently. :/
Comment 3 Francis Herne 2016-11-29 23:05:56 UTC
Git commit e0a92aac7d716bf706205a913d92246716e8727e by Francis Herne.
Committed on 29/11/2016 at 23:05.
Pushed by flherne into branch 'master'.

Get iterable content using __iter__() and __next__().
Supports unpacking and iterating over custom sequence types.
See tests for examples (by Nicolás Alvarez).

Returning `iter(builtin_container)` isn't handled usefully
 because they use docstring cheats with no real return values.

Differential Revision: https://phabricator.kde.org/D3540

M  +4    -6    duchain/declarationbuilder.cpp
M  +3    -0    duchain/declarationbuilder.h
M  +1    -1    duchain/expressionvisitor.cpp
M  +31   -25   duchain/helpers.cpp
M  +1    -1    duchain/helpers.h
M  +21   -0    duchain/tests/pyduchaintest.cpp

https://commits.kde.org/kdev-python/e0a92aac7d716bf706205a913d92246716e8727e