Alex Mendes da Costa | 13 Aug 11:25

[Cython] cython-generated class doesn't work when used as an iterator

Hi,

I'm using cython to wrap DJB's primegen library (http://cr.yp.to/primegen.html).

Here's my pyx file:

cdef extern from "primegen.h":
    ctypedef unsigned long uint32
    ctypedef unsigned long long uint64

    ctypedef struct primegen:
        uint32 buf[16][2048]
        uint64 p[512]
        int num
        int pos
        uint64 base
        uint64 L

    void primegen_init(primegen* pg)
    uint64 primegen_next(primegen* pg)
    uint64 primegen_peek(primegen* pg)
    uint64 primegen_count(primegen* pg, uint64 to)
    void primegen_skipto(primegen* pg, uint64 to)

cdef class PrimeGen:
    cdef primegen pg

    def __new__(self):
        primegen_init(&self.pg)

    def next(self):
        return primegen_next(&self.pg)

    def peek(self):
        return primegen_peek(&self.pg)

    def count(self, uint64 to):
        return primegen_count(&self.pg, to)

    def skipto(self, uint64 to):
        primegen_skipto(&self.pg, to)

Notice that the class has a method called "next".  This means that it should be usable as an iterator.  Here's what happens if I try to do that:

Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from primegen import PrimeGen
>>> class C:
...   def __iter__(self):
...     return PrimeGen()
...
>>> for i in C():
...   print i
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __iter__ returned non-iterator of type 'primegen.PrimeGen'

How come this doesn't work?  The generated class definitely has the "next" method required by the iterator protocol.

>>> p = PrimeGen()
>>> dir(p)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'count', 'next', 'peek', 'skipto']

Thanks,
Alex
<div><div dir="ltr">Hi,<br><div class="gmail_quote">
<div dir="ltr">
<br>I'm using cython to wrap DJB's primegen library (<a href="http://cr.yp.to/primegen.html" target="_blank">http://cr.yp.to/primegen.html</a>).<br><br>
Here's my pyx file:<br><br><div>
cdef extern from "primegen.h":<br>&nbsp;&nbsp;&nbsp; ctypedef unsigned long uint32<br>&nbsp;&nbsp;&nbsp; ctypedef unsigned long long uint64<br><br>&nbsp;&nbsp;&nbsp; ctypedef struct primegen:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint32 buf[16][2048]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64 p[512]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int num<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int pos<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64 base<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64 L<br><br>&nbsp;&nbsp;&nbsp; void primegen_init(primegen* pg)<br>&nbsp;&nbsp;&nbsp; uint64 primegen_next(primegen* pg)<br>&nbsp;&nbsp;&nbsp; uint64 primegen_peek(primegen* pg)<br>&nbsp;&nbsp;&nbsp; uint64 primegen_count(primegen* pg, uint64 to)<br>

&nbsp;&nbsp;&nbsp; void primegen_skipto(primegen* pg, uint64 to)<br><br>cdef class PrimeGen:<br>&nbsp;&nbsp;&nbsp; cdef primegen pg<br><br>&nbsp;&nbsp;&nbsp; def __new__(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; primegen_init(&amp;<a href="http://self.pg" target="_blank">self.pg</a>)<br><br>
&nbsp;&nbsp;&nbsp; def next(self):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return primegen_next(&amp;<a href="http://self.pg" target="_blank">self.pg</a>)<br><br>&nbsp;&nbsp;&nbsp; def peek(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return primegen_peek(&amp;<a href="http://self.pg" target="_blank">self.pg</a>)<br><br>&nbsp;&nbsp;&nbsp; def count(self, uint64 to):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return primegen_count(&amp;<a href="http://self.pg" target="_blank">self.pg</a>, to)<br><br>&nbsp;&nbsp;&nbsp; def skipto(self, uint64 to):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; primegen_skipto(&amp;<a href="http://self.pg" target="_blank">self.pg</a>, to)<br>
</div>
<br>Notice that the class has a method called "next".&nbsp; This means that it should be usable as an iterator.&nbsp; Here's what happens if I try to do that:<br><br><div>
<span>Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) <br>[GCC 4.0.1 (Apple Inc. build 5465)] on darwin<br>

Type "help", "copyright", "credits" or "license" for more information.<br></span><span>&gt;&gt;&gt; from primegen import PrimeGen</span><br><span>&gt;&gt;&gt; class C:</span><br><span>...&nbsp;&nbsp; def __iter__(self):</span><br><span>...&nbsp;&nbsp;&nbsp;&nbsp; return PrimeGen()</span><br><span>... </span><br><span>&gt;&gt;&gt; for i in C():</span><br><span>...&nbsp;&nbsp; print i</span><br><span>... </span><br><span>Traceback (most recent call last):</span><br><span>&nbsp; File "&lt;stdin&gt;", line 1, in &lt;module&gt;</span><br><span>TypeError: __iter__ returned non-iterator of type 'primegen.PrimeGen'<br><br></span>
</div>How come this doesn't work?&nbsp; The generated class definitely has the "next" method required by the iterator protocol.<br><br><div>

<span>&gt;&gt;&gt; p = PrimeGen()</span><br><span>
&gt;&gt;&gt; dir(p)</span><br><span>
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__str__', 'count', 'next', 'peek', 'skipto']</span><br>
</div>
<br>Thanks,<br>Alex</div>
</div>
</div></div>
Robert Bradshaw | 13 Aug 11:31

Re: [Cython] cython-generated class doesn't work when used as an iterator

You actually need to provide a __next__ method. See

http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/ 
Manual/special_methods.html

- Robert

On Aug 13, 2008, at 2:25 AM, Alex Mendes da Costa wrote:

> Hi,
>
> I'm using cython to wrap DJB's primegen library (http://cr.yp.to/ 
> primegen.html).
>
> Here's my pyx file:
>
> cdef extern from "primegen.h":
>     ctypedef unsigned long uint32
>     ctypedef unsigned long long uint64
>
>     ctypedef struct primegen:
>         uint32 buf[16][2048]
>         uint64 p[512]
>         int num
>         int pos
>         uint64 base
>         uint64 L
>
>     void primegen_init(primegen* pg)
>     uint64 primegen_next(primegen* pg)
>     uint64 primegen_peek(primegen* pg)
>     uint64 primegen_count(primegen* pg, uint64 to)
>     void primegen_skipto(primegen* pg, uint64 to)
>
> cdef class PrimeGen:
>     cdef primegen pg
>
>     def __new__(self):
>         primegen_init(&self.pg)
>
>     def next(self):
>         return primegen_next(&self.pg)
>
>     def peek(self):
>         return primegen_peek(&self.pg)
>
>     def count(self, uint64 to):
>         return primegen_count(&self.pg, to)
>
>     def skipto(self, uint64 to):
>         primegen_skipto(&self.pg, to)
>
> Notice that the class has a method called "next".  This means that  
> it should be usable as an iterator.  Here's what happens if I try  
> to do that:
>
> Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
> [GCC 4.0.1 (Apple Inc. build 5465)] on darwin
> Type "help", "copyright", "credits" or "license" for more information.
> >>> from primegen import PrimeGen
> >>> class C:
> ...   def __iter__(self):
> ...     return PrimeGen()
> ...
> >>> for i in C():
> ...   print i
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: __iter__ returned non-iterator of type 'primegen.PrimeGen'
>
> How come this doesn't work?  The generated class definitely has the  
> "next" method required by the iterator protocol.
>
> >>> p = PrimeGen()
> >>> dir(p)
> ['__class__', '__delattr__', '__doc__', '__getattribute__',  
> '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',  
> '__repr__', '__setattr__', '__str__', 'count', 'next', 'peek',  
> 'skipto']
>
> Thanks,
> Alex
> _______________________________________________
> Cython-dev mailing list
> Cython-dev@...
> http://codespeak.net/mailman/listinfo/cython-dev

William Stein | 13 Aug 11:44

Re: [Cython] cython-generated class doesn't work when used as an iterator

On Wed, Aug 13, 2008 at 2:25 AM, Alex Mendes da Costa
<alexmdac@...> wrote:
> Hi,
>
> I'm using cython to wrap DJB's primegen library
> (http://cr.yp.to/primegen.html).

Are you going to contribute this code and the wrapper
to Sage (http://sagemath.org)?  I've wanted to add
primegen to Sage for a long time -- in fact, I asked
DJB about its license on a panel discussion and
in his response he released primegen under a public
domain license.

 -- William

>
> Here's my pyx file:
>
> cdef extern from "primegen.h":
>     ctypedef unsigned long uint32
>     ctypedef unsigned long long uint64
>
>     ctypedef struct primegen:
>         uint32 buf[16][2048]
>         uint64 p[512]
>         int num
>         int pos
>         uint64 base
>         uint64 L
>
>     void primegen_init(primegen* pg)
>     uint64 primegen_next(primegen* pg)
>     uint64 primegen_peek(primegen* pg)
>     uint64 primegen_count(primegen* pg, uint64 to)
>     void primegen_skipto(primegen* pg, uint64 to)
>
> cdef class PrimeGen:
>     cdef primegen pg
>
>     def __new__(self):
>         primegen_init(&self.pg)
>
>     def next(self):
>         return primegen_next(&self.pg)
>
>     def peek(self):
>         return primegen_peek(&self.pg)
>
>     def count(self, uint64 to):
>         return primegen_count(&self.pg, to)
>
>     def skipto(self, uint64 to):
>         primegen_skipto(&self.pg, to)
>
> Notice that the class has a method called "next".  This means that it should
> be usable as an iterator.  Here's what happens if I try to do that:
>
> Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
> [GCC 4.0.1 (Apple Inc. build 5465)] on darwin
> Type "help", "copyright", "credits" or "license" for more information.
>>>> from primegen import PrimeGen
>>>> class C:
> ...   def __iter__(self):
> ...     return PrimeGen()
> ...
>>>> for i in C():
> ...   print i
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: __iter__ returned non-iterator of type 'primegen.PrimeGen'
>
> How come this doesn't work?  The generated class definitely has the "next"
> method required by the iterator protocol.
>
>>>> p = PrimeGen()
>>>> dir(p)
> ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
> '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
> '__setattr__', '__str__', 'count', 'next', 'peek', 'skipto']
>
> Thanks,
> Alex
> _______________________________________________
> Cython-dev mailing list
> Cython-dev@...
> http://codespeak.net/mailman/listinfo/cython-dev
>
>

--

-- 
William Stein
Associate Professor of Mathematics
University of Washington
http://wstein.org
Alex Mendes da Costa | 13 Aug 12:03

Re: [Cython] cython-generated class doesn't work when used as an iterator

Yes, you can incorporate this code into Sage if you like.

Alex

On Wed, Aug 13, 2008 at 2:44 AM, William Stein <wstein-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
On Wed, Aug 13, 2008 at 2:25 AM, Alex Mendes da Costa
<alexmdac-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Hi,
>
> I'm using cython to wrap DJB's primegen library
> (http://cr.yp.to/primegen.html).

Are you going to contribute this code and the wrapper
to Sage (http://sagemath.org)?  I've wanted to add
primegen to Sage for a long time -- in fact, I asked
DJB about its license on a panel discussion and
in his response he released primegen under a public
domain license.

 -- William

>
> Here's my pyx file:
>
> cdef extern from "primegen.h":
>     ctypedef unsigned long uint32
>     ctypedef unsigned long long uint64
>
>     ctypedef struct primegen:
>         uint32 buf[16][2048]
>         uint64 p[512]
>         int num
>         int pos
>         uint64 base
>         uint64 L
>
>     void primegen_init(primegen* pg)
>     uint64 primegen_next(primegen* pg)
>     uint64 primegen_peek(primegen* pg)
>     uint64 primegen_count(primegen* pg, uint64 to)
>     void primegen_skipto(primegen* pg, uint64 to)
>
> cdef class PrimeGen:
>     cdef primegen pg
>
>     def __new__(self):
>         primegen_init(&self.pg)
>
>     def next(self):
>         return primegen_next(&self.pg)
>
>     def peek(self):
>         return primegen_peek(&self.pg)
>
>     def count(self, uint64 to):
>         return primegen_count(&self.pg, to)
>
>     def skipto(self, uint64 to):
>         primegen_skipto(&self.pg, to)
>
> Notice that the class has a method called "next".  This means that it should
> be usable as an iterator.  Here's what happens if I try to do that:
>
> Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
> [GCC 4.0.1 (Apple Inc. build 5465)] on darwin
> Type "help", "copyright", "credits" or "license" for more information.
>>>> from primegen import PrimeGen
>>>> class C:
> ...   def __iter__(self):
> ...     return PrimeGen()
> ...
>>>> for i in C():
> ...   print i
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: __iter__ returned non-iterator of type 'primegen.PrimeGen'
>
> How come this doesn't work?  The generated class definitely has the "next"
> method required by the iterator protocol.
>
>>>> p = PrimeGen()
>>>> dir(p)
> ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
> '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
> '__setattr__', '__str__', 'count', 'next', 'peek', 'skipto']
>
> Thanks,
> Alex
> _______________________________________________
> Cython-dev mailing list
> Cython-dev-F/1GfIIGwJtbRRN4PJnoQQ@public.gmane.org
> http://codespeak.net/mailman/listinfo/cython-dev
>
>



--
William Stein
Associate Professor of Mathematics
University of Washington
http://wstein.org
_______________________________________________
Cython-dev mailing list
Cython-dev-F/1GfIIGwJtbRRN4PJnoQQ@public.gmane.org
http://codespeak.net/mailman/listinfo/cython-dev

<div><div dir="ltr">Yes, you can incorporate this code into Sage if you like.<br><br>Alex<br><br><div class="gmail_quote">On Wed, Aug 13, 2008 at 2:44 AM, William Stein <span dir="ltr">&lt;<a href="mailto:wstein@...">wstein@...</a>&gt;</span> wrote:<br><blockquote class="gmail_quote">
<div class="Ih2E3d">On Wed, Aug 13, 2008 at 2:25 AM, Alex Mendes da Costa<br>
&lt;<a href="mailto:alexmdac@...">alexmdac@...</a>&gt; wrote:<br>
&gt; Hi,<br>
&gt;<br>
&gt; I'm using cython to wrap DJB's primegen library<br>
&gt; (<a href="http://cr.yp.to/primegen.html" target="_blank">http://cr.yp.to/primegen.html</a>).<br><br>
</div>Are you going to contribute this code and the wrapper<br>
to Sage (<a href="http://sagemath.org" target="_blank">http://sagemath.org</a>)? &nbsp;I've wanted to add<br>
primegen to Sage for a long time -- in fact, I asked<br>
DJB about its license on a panel discussion and<br>
in his response he released primegen under a public<br>
domain license.<br><br>
&nbsp;-- William<br><div>
<div></div>
<div class="Wj3C7c">
<br>
&gt;<br>
&gt; Here's my pyx file:<br>
&gt;<br>
&gt; cdef extern from "primegen.h":<br>
&gt; &nbsp; &nbsp; ctypedef unsigned long uint32<br>
&gt; &nbsp; &nbsp; ctypedef unsigned long long uint64<br>
&gt;<br>
&gt; &nbsp; &nbsp; ctypedef struct primegen:<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; uint32 buf[16][2048]<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; uint64 p[512]<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; int num<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; int pos<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; uint64 base<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; uint64 L<br>
&gt;<br>
&gt; &nbsp; &nbsp; void primegen_init(primegen* pg)<br>
&gt; &nbsp; &nbsp; uint64 primegen_next(primegen* pg)<br>
&gt; &nbsp; &nbsp; uint64 primegen_peek(primegen* pg)<br>
&gt; &nbsp; &nbsp; uint64 primegen_count(primegen* pg, uint64 to)<br>
&gt; &nbsp; &nbsp; void primegen_skipto(primegen* pg, uint64 to)<br>
&gt;<br>
&gt; cdef class PrimeGen:<br>
&gt; &nbsp; &nbsp; cdef primegen pg<br>
&gt;<br>
&gt; &nbsp; &nbsp; def __new__(self):<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; primegen_init(&amp;<a href="http://self.pg" target="_blank">self.pg</a>)<br>
&gt;<br>
&gt; &nbsp; &nbsp; def next(self):<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; return primegen_next(&amp;<a href="http://self.pg" target="_blank">self.pg</a>)<br>
&gt;<br>
&gt; &nbsp; &nbsp; def peek(self):<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; return primegen_peek(&amp;<a href="http://self.pg" target="_blank">self.pg</a>)<br>
&gt;<br>
&gt; &nbsp; &nbsp; def count(self, uint64 to):<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; return primegen_count(&amp;<a href="http://self.pg" target="_blank">self.pg</a>, to)<br>
&gt;<br>
&gt; &nbsp; &nbsp; def skipto(self, uint64 to):<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; primegen_skipto(&amp;<a href="http://self.pg" target="_blank">self.pg</a>, to)<br>
&gt;<br>
&gt; Notice that the class has a method called "next". &nbsp;This means that it should<br>
&gt; be usable as an iterator. &nbsp;Here's what happens if I try to do that:<br>
&gt;<br>
&gt; Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)<br>
&gt; [GCC 4.0.1 (Apple Inc. build 5465)] on darwin<br>
&gt; Type "help", "copyright", "credits" or "license" for more information.<br>
&gt;&gt;&gt;&gt; from primegen import PrimeGen<br>
&gt;&gt;&gt;&gt; class C:<br>
&gt; ... &nbsp; def __iter__(self):<br>
&gt; ... &nbsp; &nbsp; return PrimeGen()<br>
&gt; ...<br>
&gt;&gt;&gt;&gt; for i in C():<br>
&gt; ... &nbsp; print i<br>
&gt; ...<br>
&gt; Traceback (most recent call last):<br>
&gt; &nbsp; File "&lt;stdin&gt;", line 1, in &lt;module&gt;<br>
&gt; TypeError: __iter__ returned non-iterator of type 'primegen.PrimeGen'<br>
&gt;<br>
&gt; How come this doesn't work? &nbsp;The generated class definitely has the "next"<br>
&gt; method required by the iterator protocol.<br>
&gt;<br>
&gt;&gt;&gt;&gt; p = PrimeGen()<br>
&gt;&gt;&gt;&gt; dir(p)<br>
&gt; ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',<br>
&gt; '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',<br>
&gt; '__setattr__', '__str__', 'count', 'next', 'peek', 'skipto']<br>
&gt;<br>
&gt; Thanks,<br>
&gt; Alex<br>
</div>
</div>
<div class="Ih2E3d">&gt; _______________________________________________<br>
&gt; Cython-dev mailing list<br>
&gt; <a href="mailto:Cython-dev@...">Cython-dev@...</a><br>
&gt; <a href="http://codespeak.net/mailman/listinfo/cython-dev" target="_blank">http://codespeak.net/mailman/listinfo/cython-dev</a><br>
&gt;<br>
&gt;<br><br><br><br>
</div>--<br>
William Stein<br>
Associate Professor of Mathematics<br>
University of Washington<br><a href="http://wstein.org" target="_blank">http://wstein.org</a><br><div>
<div></div>
<div class="Wj3C7c">_______________________________________________<br>
Cython-dev mailing list<br><a href="mailto:Cython-dev@...">Cython-dev@...</a><br><a href="http://codespeak.net/mailman/listinfo/cython-dev" target="_blank">http://codespeak.net/mailman/listinfo/cython-dev</a><br>
</div>
</div>
</blockquote>
</div>
<br>
</div></div>

Gmane