question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

cythonize fails when given `setuptools.extension.Extension`

See original GitHub issue

Calling cythonize with an instance of setuptools.extension.Extension raises an AttributeError. The cause is that setuptools.extension.Extension subclasses distutils.extension.Extension, which is defined as an old-style class. These types can be confirmed with:

import distutils.core.Extension
import types
import setuptools.extension.Extension

assert type(distutils.core.Extension) != types.TypeType
assert type(setuptools.extension.Extension) != types.TypeType

This behavior arises with:

  • setuptools == 28.7.0
  • cython == 0.25.1

This issue did not exist with earlier cython versions. Closer examination of the docstring of function cythonize reveals that one should pass a list of Extension objects:

As module list, pass either a glob pattern, a list of glob patterns or a list of
    Extension objects.  The latter allows you to configure the extensions separately
    through the normal distutils options.

So, my usage was wrong. Indeed, passing a list of Extension objects avoids the error. Since this error did not exist in the past, and because I believe that I followed some example when I initially wrote the code to pass an extension itself, I wonder whether this case is supposed to be supported, or if not, whether it should be emphasized in the docstring. Tracing the cause took a long time, especially because I assumed that cythonize was already properly called.

One workaround is to create a new-style subclass:

class Extension(setuptools.extension.Extension,object):
    pass

This works fine. Traceback from dd/download.py when object is removed from the above subclass definition:

dd:python setup.py install --cudd --linetrace
compile Cython extensions with line tracing
Traceback (most recent call last):
  File "setup.py", line 136, in <module>
    run_setup()
  File "setup.py", line 93, in run_setup
    extensions = download.extensions(directives)
  File "/path/dd/download.py", line 119, in extensions
    v, compiler_directives=directives)
  File "~/.virtualenvs/dev/lib/python2.7/site-packages/Cython/Build/Dependencies.py", line 809, in cythonize
    aliases=aliases)
  File "~/.virtualenvs/dev/lib/python2.7/site-packages/Cython/Build/Dependencies.py", line 648, in create_extension_list
    elif isinstance(patterns, basestring) or not isinstance(patterns, collections.Iterable):
  File "~/.virtualenvs/dev/lib/python2.7/abc.py", line 144, in __instancecheck__
    return cls.__subclasscheck__(subtype)
  File "~/.virtualenvs/dev/lib/python2.7/abc.py", line 180, in __subclasscheck__
    if issubclass(subclass, scls):
  File "~/.virtualenvs/dev/lib/python2.7/abc.py", line 180, in __subclasscheck__
    if issubclass(subclass, scls):
  File "/home/ioannis/.virtualenvs/dev/lib/python2.7/abc.py", line 161, in __subclasscheck__
    ok = cls.__subclasshook__(subclass)
  File "~/.virtualenvs/dev/lib/python2.7/site-packages/backports_abc.py", line 66, in __subclasshook__
    mro = C.__mro__
AttributeError: class Extension has no attribute '__mro__'

The failure is due to the isinstance(patterns, collections.Iterable). It can be reproduced as follows:

import collections

from Cython.Build import cythonize
from setuptools.extension import Extension

a = Extension('foo', sources=['foo.pyx'])

isinstance([a], collections.Iterable)  # works fine
isinstance(a, collections.Iterable)  # raises `AttributeError`

I will report this issue also to setuptools, though it seems to me that defining an old-style class is intentional there.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
johnyfcommented, Nov 5, 2016

This was happening in one virtualenv of mine, but not a fresh one (nor the global one). The answer is in the traceback (see OP):

mkvirtualenv test
pip install cython backports_abc
pip freeze
backports-abc==0.4
Cython==0.25.1

The error can then be reproduced. I do not know whether this classifies as a bug of backports_abc.

0reactions
johnyfcommented, Nov 16, 2016

Thanks for fixing this issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Unable to build libraries using cython? - python - Stack Overflow
I can confirm that the cython code works fine in the native python form. This led me to guess that the error is...
Read more >
Source Files and Compilation - Cython's Documentation
The setuptools extension provided with Cython allows you to pass .pyx ... In the case that Cython fails to compile a Python module,...
Read more >
Building Extension Modules - Setuptools
Setuptools can build C/C++ extension modules. The keyword argument ext_modules of setup() should be a list of instances of the setuptools.Extension class.
Read more >
Error in compiling cython extension on Python 3.6.4 on ...
I compile this cython extension on a Windows host using below command python setup.py build_ext --inplace. Whether I use distutils or ...
Read more >
Extending Python with Complied Code
cythonize is a utility that sets up extension module builds for you in a cython-aware way. Building a module¶. For testing, it's helpful...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found