Skip to content

Commit

Permalink
Make the C extension optional; test PURE_PYTHON and PyPy3 on Travis. F…
Browse files Browse the repository at this point in the history
…ixes #26
  • Loading branch information
jamadden committed Nov 8, 2017
1 parent 2602ed6 commit bbb6c7d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 22 deletions.
17 changes: 11 additions & 6 deletions .travis.yml
@@ -1,11 +1,16 @@
language: python
sudo: false
python:
- 2.7
- 3.4
- 3.5
- 3.6
- pypy-5.6.0
matrix:
include:
- python: 2.7
- python: 3.4
- python: 3.5
- python: 3.6
- python: pypy
- python: pypy3
- python: 2.7
env:
- PURE_PYTHON=1
install:
- pip install -U pip
- pip install -U setuptools
Expand Down
6 changes: 5 additions & 1 deletion CHANGES.rst
Expand Up @@ -6,7 +6,11 @@ Changes

- Simplify the internal C handling of attribute names in
``__getattribute__`` and ``__setattr__``.

- Make building the C extension optional. We still attempt to build it
on supported platforms, but we allow it to fail in case of a missing
compiler or headers. See `issue 26
<https://github.com/zopefoundation/zope.proxy/issues/26>`_.
- Test the PURE_PYTHON environment and PyPy3 on Travis CI.

4.3.0 (2017-09-13)
------------------
Expand Down
61 changes: 48 additions & 13 deletions setup.py
Expand Up @@ -21,29 +21,61 @@
import os
import platform

from setuptools import setup, Extension, Feature

from distutils.errors import CCompilerError
from distutils.errors import DistutilsExecError
from distutils.errors import DistutilsPlatformError

from setuptools import Extension
from setuptools.command.build_ext import build_ext
from setuptools import setup
from setuptools import Feature

class optional_build_ext(build_ext):
"""This class subclasses build_ext and allows
the building of C extensions to fail.
"""
def run(self):
try:
build_ext.run(self)
except DistutilsPlatformError as e:
self._unavailable(e)

def build_extension(self, ext):
try:
build_ext.build_extension(self, ext)
except (CCompilerError, DistutilsExecError, OSError) as e:
self._unavailable(e)

def _unavailable(self, e):
print('*' * 80)
print("""WARNING:
An optional code optimization (C extension) could not be compiled.
Optimizations for this package will not be available!""")
print()
print(e)
print('*' * 80)


def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()

Cwrapper = Feature(
"C wrapper",
standard = True,
standard=True,
headers=[os.path.join('src', 'zope', 'proxy', 'proxy.h')],
ext_modules=[Extension("zope.proxy._zope_proxy_proxy",
[os.path.join('src', 'zope', 'proxy',
"_zope_proxy_proxy.c")
],
extra_compile_args=['-g']),
],
ext_modules=[
Extension(
"zope.proxy._zope_proxy_proxy",
[os.path.join('src', 'zope', 'proxy', "_zope_proxy_proxy.c")],
),
],
)

# PyPy won't build the extension.
py_impl = getattr(platform, 'python_implementation', lambda: None)
is_pypy = py_impl() == 'PyPy'
is_pure = os.environ.get('PURE_PYTHON')
if is_pypy or is_pure:
is_pypy = platform.python_implementation() == 'PyPy'
if is_pypy:
features = {}
else:
features = {'Cwrapper': Cwrapper}
Expand All @@ -60,7 +92,7 @@ def read(*rnames):
),
url='http://github.com/zopefoundation/zope.proxy',
license='ZPL 2.1',
classifiers = [
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
Expand All @@ -81,6 +113,9 @@ def read(*rnames):
packages=['zope', 'zope.proxy'],
package_dir={'': 'src'},
namespace_packages=['zope',],
cmdclass={
'build_ext': optional_build_ext,
},
features=features,
install_requires=[
'zope.interface',
Expand Down
2 changes: 0 additions & 2 deletions tox.ini
Expand Up @@ -35,11 +35,9 @@ basepython =
python2.7
setenv =
PURE_PYTHON = 1
PIP_CACHE_DIR = {envdir}/.cache

[testenv:py36-pure]
basepython =
python3.6
setenv =
PURE_PYTHON = 1
PIP_CACHE_DIR = {envdir}/.cache

0 comments on commit bbb6c7d

Please sign in to comment.