Skip to content

List comprehensions sometimes call iter(iter(v)) instead of just iter(v) #128211

@DemiMarie

Description

@DemiMarie

Bug report

Bug description:

A development version of the Qubes OS updater gave the following traceback:

Dec 23 21:53:01 dom0 widget-wrapper[25404]: Traceback (most recent call last):
Dec 23 21:53:01 dom0 widget-wrapper[25404]:   File "/usr/lib/python3.13/site-packages/qui/updater/updater.py", line 215, in next_clicked
Dec 23 21:53:01 dom0 widget-wrapper[25404]:     vms_to_update = self.intro_page.get_vms_to_update()
Dec 23 21:53:01 dom0 widget-wrapper[25404]:   File "/usr/lib/python3.13/site-packages/qui/updater/intro_page.py", line 147, in get_vms_to_update
Dec 23 21:53:01 dom0 widget-wrapper[25404]:     return self.list_store.get_selected()
Dec 23 21:53:01 dom0 widget-wrapper[25404]:            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
Dec 23 21:53:01 dom0 widget-wrapper[25404]:   File "/usr/lib/python3.13/site-packages/qui/updater/utils.py", line 306, in get_selected
Dec 23 21:53:01 dom0 widget-wrapper[25404]:     selected_rows = [row for row in self if row.selected]
Dec 23 21:53:01 dom0 widget-wrapper[25404]:                                     ^^^^
Dec 23 21:53:01 dom0 widget-wrapper[25404]: TypeError: 'UpdateListIter' object is not iterable

However, this makes no sense. The code can be found at https://github.com/QubesOS/qubes-desktop-linux-manager/blob/a3e4d177785bbc1b1ee72bd7cd83ef7b8a4e8827/qui/updater/utils.py#L300-L309, where self is an ListWrapper instance. Its __iter__ method returns an UpdateListIter, which is a valid iterator. However, UpdateListIter does not have its own __iter__ method. Adding a method that returns self makes the problem go away.

A small reproducer is below:

class B:
    def __next__(self):
        raise StopIteration
class A:
    def __iter__(self):
         return B()
# works
for i in A():
    print(i)
# BUG: should print [], but instead raises TypeError
print([i for i in A()])

On Python 3.12, this works (and prints []). On Python 3.13, this raises TypeError.

At least some standard library iterators (such as iter([]) have an __iter__(self) that returns self, as shown by the following program printing True on both 3.13 and 3.14:

a = iter([])
print(a is iter(a))

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions