Iterator in conjunction with Python properties fail

Are you running the latest graph-tool version?

2.35

Do you observe the problem with the current git version?

I will give a minimal example. It would be nice, if you test it yourself, since compiling graph-tool costs me several hours.

Are you using Macports or Homebrew? If yes, please submit an issue there instead:

No

Did you compile graph-tool manually?

Part of, I use Gentoo with the distribution package.

If you answered yes above, did you use the exact same compiler to build graph-tool, boost-python and Python?

Yes

A minimal and self-contained example that shows the problem.

This code should print the same in all 3 for loops but does not.

#!/usr/bin/env python3

import graph_tool

class Foo:
    def __init__(self):
        self.g = graph_tool.Graph()
        self.g.vp["foo"] = self.g.new_vp("bool")
        for i in range(10):
            v = self.g.add_vertex()
            if i % 2 == 0:
                self.g.vp.foo[v] = True

    @property
    def a(self):
        return graph_tool.GraphView(self.g, vfilt=self.g.vp.foo)

foo = Foo()

t1 = foo.a
for i in t1.vertices():
    print("1.", i)

for i in foo.a.vertices():
    print("2.", i)

t2 = foo.a.vertices()
for i in t2:
    print("3.", i)

This prints only

1. 0
1. 2
1. 4
1. 6
1. 8

So basically it ignores the next 2 for loops.

Your operating system.

Gentoo

The Python version you are using.

Gentoo allows multiple. I tested with 3.6, 3.7 and 3.8 (always the same bug).

If you compiled graph-tool manually: Your compiler version, as well as the version of Boost being used.

GCC 9.2.0, Boost 1.72.0

If you are reporting a compilation error, please provide the entire ./configure output, as well as the entire contents of the config.log file and the entire compilation output.

No.

Additional information

see this minimal example for a pure Python working example that mimics the above script:

#!/usr/bin/env python3

class Iterator:
    def __init__(self):
        self.x = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.x > 3:
            raise StopIteration
        self.x += 1
        return self.x

class Sub:
    def it(self):
        return Iterator()

class Foo:
    @property
    def a(self):
        return Sub()

foo = Foo()

t1 = foo.a
for i in t1.it():
    print("1:", i)

for i in foo.a.it():
    print("2:", i)

t2 = foo.a.it()
for i in t2:
    print("3:", i)