From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ciao.gmane.io (ciao.gmane.io [116.202.254.214]) by sourceware.org (Postfix) with ESMTPS id 0DF1E386F82B for ; Fri, 27 May 2022 21:26:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0DF1E386F82B Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1nuhTm-0009kY-GX for cygwin@cygwin.com; Fri, 27 May 2022 23:26:42 +0200 X-Injected-Via-Gmane: http://gmane.org/ To: cygwin@cygwin.com From: airplanemath Subject: PyIter_Check false positives Date: Fri, 27 May 2022 17:26:30 -0400 Message-ID: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.1 (cygwin) Cancel-Lock: sha1:DvRLrvcLAD+wPLidBUC98SwkWz0= X-Spam-Status: No, score=-2.2 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_GOODAOL, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: cygwin@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: General Cygwin discussions and problem reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 May 2022 21:26:45 -0000 --=-=-= Content-Type: text/plain I found this problem running the tests for pandas, but can reproduce it more simply. Compile the following cython file to create a thin wrapper around the C-API function: > from cpython.iterator cimport PyIter_Check > > def is_iterator(obj: object) -> bool: > return PyIter_Check(obj) with `cythonize --build --inplace test_iterator.pyx` (probably requires python39-cython), changing the name if needed, then try the following in Python: >>> from collections.abc import Iterator >>> from fractions import Fraction >>> from os import environ >>> from test_iterator import is_iterator >>> isinstance(environ, Iterator) False >>> is_iterator(environ) True >>> next(environ) Traceback (most recent call last): File "", line 1, in TypeError: '_Environ' object is not an iterator >>> isinstance(Fraction(0, 1), Iterator) False >>> is_iterator(Fraction(0, 1)) True >>> next(Fraction(0, 1)) Traceback (most recent call last): File "", line 1, in TypeError: 'Fraction' object is not an iterator >From the Python documentation [1], it appears that `PyIter_Check` is intended to return True only if the `PyIter_Next` will work, and `PyIter_Next` is the C equivalent of the python `next` function. That is, `isinstance(thing, Iterator)` and `is_iterator(thing)` should agree with each other, and should return True only if `next(thing)` works (produces an element or says there aren't any). On Linux, both checks agree with each other, returning False, and the attempts to advance the iterator with `next` still fail. As seen above, on (my) Cygwin, PyIter_Check disagrees with `collections.abc.Iterator` and succeeds in cases where `next` produces a TypeError. I can reproduce this with python3.9 and with python2.7 on Cygwin. Am I missing something in the documentation? Is this a side-effect of working on top of Windows? In case it's relevant, I'm using an unpatched Cython with the distribution Python packages. [1] https://docs.python.org/3/c-api/iter.html#c.PyIter_Check --=-=-= Content-Type: text/x-python3 Content-Disposition: inline; filename=test_iterator.pyx Content-Description: PyIter_Next Cython wrapper module source from cpython.iterator cimport PyIter_Check def is_iterator(obj: object) -> bool: """Check whether obj is an iterator. Should agree with isinstance(obj, collections.abc.Iterator). Parameters ---------- obj : object Returns ------- bool """ return PyIter_Check(obj) --=-=-=--