435 lines
15 KiB
Python
Executable File
435 lines
15 KiB
Python
Executable File
#!/usr/bin/env python
|
|
"""gevent build & installation script"""
|
|
from __future__ import print_function
|
|
import sys
|
|
import os
|
|
import os.path
|
|
import sysconfig
|
|
|
|
# setuptools is *required* on Windows
|
|
# (https://bugs.python.org/issue23246) and for PyPy. No reason not to
|
|
# use it everywhere. v24.2.0 is needed for python_requires
|
|
from setuptools import Extension, setup
|
|
from setuptools import find_packages
|
|
|
|
|
|
from _setuputils import read
|
|
from _setuputils import read_version
|
|
from _setuputils import system
|
|
from _setuputils import PYPY, WIN
|
|
from _setuputils import IGNORE_CFFI
|
|
from _setuputils import SKIP_LIBUV
|
|
from _setuputils import ConfiguringBuildExt
|
|
from _setuputils import BuildFailed
|
|
from _setuputils import cythonize1
|
|
|
|
|
|
|
|
if WIN:
|
|
# Make sure the env vars that make.cmd needs are set
|
|
if not os.environ.get('PYTHON_EXE'):
|
|
os.environ['PYTHON_EXE'] = 'pypy' if PYPY else 'python'
|
|
if not os.environ.get('PYEXE'):
|
|
os.environ['PYEXE'] = os.environ['PYTHON_EXE']
|
|
|
|
|
|
if PYPY and sys.pypy_version_info[:3] < (2, 6, 1): # pylint:disable=no-member
|
|
# We have to have CFFI >= 1.3.0, and this platform cannot upgrade
|
|
# it.
|
|
raise Exception("PyPy >= 2.6.1 is required")
|
|
|
|
|
|
|
|
__version__ = read_version()
|
|
|
|
|
|
from _setuplibev import libev_configure_command
|
|
from _setuplibev import LIBEV_EMBED
|
|
from _setuplibev import CORE
|
|
|
|
from _setupares import ARES
|
|
|
|
# Get access to the greenlet header file.
|
|
# The sysconfig dir is not enough if we're in a virtualenv
|
|
# See https://github.com/pypa/pip/issues/4610
|
|
include_dirs = [sysconfig.get_path("include")]
|
|
venv_include_dir = os.path.join(sys.prefix, 'include', 'site',
|
|
'python' + sysconfig.get_python_version())
|
|
venv_include_dir = os.path.abspath(venv_include_dir)
|
|
if os.path.exists(venv_include_dir):
|
|
include_dirs.append(venv_include_dir)
|
|
|
|
# If we're installed via buildout, and buildout also installs
|
|
# greenlet, we have *NO* access to greenlet.h at all. So include
|
|
# our own copy as a fallback.
|
|
include_dirs.append('deps')
|
|
|
|
SEMAPHORE = Extension(name="gevent.__semaphore",
|
|
sources=["src/gevent/_semaphore.py"],
|
|
depends=['src/gevent/__semaphore.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
|
|
LOCAL = Extension(name="gevent._local",
|
|
sources=["src/gevent/local.py"],
|
|
depends=['src/gevent/_local.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
|
|
GREENLET = Extension(name="gevent._greenlet",
|
|
sources=[
|
|
"src/gevent/greenlet.py",
|
|
],
|
|
depends=[
|
|
'src/gevent/_greenlet.pxd',
|
|
'src/gevent/__ident.pxd',
|
|
'src/gevent/_ident.py'
|
|
],
|
|
include_dirs=include_dirs)
|
|
|
|
ABSTRACT_LINKABLE = Extension(name="gevent.__abstract_linkable",
|
|
sources=["src/gevent/_abstract_linkable.py"],
|
|
depends=['src/gevent/__abstract_linkable.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
|
|
IDENT = Extension(name="gevent.__ident",
|
|
sources=["src/gevent/_ident.py"],
|
|
depends=['src/gevent/__ident.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
|
|
IMAP = Extension(name="gevent.__imap",
|
|
sources=["src/gevent/_imap.py"],
|
|
depends=['src/gevent/__imap.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
EVENT = Extension(name="gevent._event",
|
|
sources=["src/gevent/event.py"],
|
|
depends=['src/gevent/_event.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
QUEUE = Extension(name="gevent._queue",
|
|
sources=["src/gevent/queue.py"],
|
|
depends=['src/gevent/_queue.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
HUB_LOCAL = Extension(name="gevent.__hub_local",
|
|
sources=["src/gevent/_hub_local.py"],
|
|
depends=['src/gevent/__hub_local.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
WAITER = Extension(name="gevent.__waiter",
|
|
sources=["src/gevent/_waiter.py"],
|
|
depends=['src/gevent/__waiter.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
HUB_PRIMITIVES = Extension(name="gevent.__hub_primitives",
|
|
sources=["src/gevent/_hub_primitives.py"],
|
|
depends=['src/gevent/__hub_primitives.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
GLT_PRIMITIVES = Extension(name="gevent.__greenlet_primitives",
|
|
sources=["src/gevent/_greenlet_primitives.py"],
|
|
depends=['src/gevent/__greenlet_primitives.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
TRACER = Extension(name="gevent.__tracer",
|
|
sources=["src/gevent/_tracer.py"],
|
|
depends=['src/gevent/__tracer.pxd'],
|
|
include_dirs=include_dirs)
|
|
|
|
|
|
_to_cythonize = [
|
|
GLT_PRIMITIVES,
|
|
HUB_PRIMITIVES,
|
|
HUB_LOCAL,
|
|
WAITER,
|
|
GREENLET,
|
|
TRACER,
|
|
|
|
ABSTRACT_LINKABLE,
|
|
SEMAPHORE,
|
|
LOCAL,
|
|
|
|
IDENT,
|
|
IMAP,
|
|
EVENT,
|
|
QUEUE,
|
|
]
|
|
|
|
EXT_MODULES = [
|
|
CORE,
|
|
ARES,
|
|
ABSTRACT_LINKABLE,
|
|
SEMAPHORE,
|
|
LOCAL,
|
|
GREENLET,
|
|
IDENT,
|
|
IMAP,
|
|
EVENT,
|
|
QUEUE,
|
|
HUB_LOCAL,
|
|
WAITER,
|
|
HUB_PRIMITIVES,
|
|
GLT_PRIMITIVES,
|
|
TRACER,
|
|
]
|
|
|
|
LIBEV_CFFI_MODULE = 'src/gevent/libev/_corecffi_build.py:ffi'
|
|
LIBUV_CFFI_MODULE = 'src/gevent/libuv/_corecffi_build.py:ffi'
|
|
cffi_modules = []
|
|
|
|
if not WIN:
|
|
# We can't properly handle (hah!) file-descriptors and
|
|
# handle mapping on Windows/CFFI with libev, because the file needed,
|
|
# libev_vfd.h, can't be included, linked, and used: it uses
|
|
# Python API functions, and you're not supposed to do that from
|
|
# CFFI code. Plus I could never get the libraries= line to ffi.compile()
|
|
# correct to make linking work.
|
|
cffi_modules.append(
|
|
LIBEV_CFFI_MODULE
|
|
)
|
|
|
|
if not SKIP_LIBUV:
|
|
# libuv can't be built on manylinux1 because it needs glibc >= 2.12
|
|
# but manylinux1 has only 2.5, so we set SKIP_LIBUV in the script make-manylinux
|
|
cffi_modules.append(LIBUV_CFFI_MODULE)
|
|
|
|
greenlet_requires = [
|
|
# We need to watch our greenlet version fairly carefully,
|
|
# since we compile cython code that extends the greenlet object.
|
|
# Binary compatibility would break if the greenlet struct changes.
|
|
# (Which it did in 0.4.14 for Python 3.7)
|
|
'greenlet >= 0.4.14; platform_python_implementation=="CPython"',
|
|
]
|
|
|
|
# Note that we don't add cffi to install_requires, it's
|
|
# optional. We tend to build and distribute wheels with the CFFI
|
|
# modules built and they can be imported if CFFI is installed.
|
|
# We need cffi 1.4.0 for new style callbacks;
|
|
# we need cffi 1.11.3 (on CPython 3) to avoid test errors.
|
|
|
|
# The exception is on Windows, where we want the libuv backend we distribute
|
|
# to be the default, and that requires cffi; but don't try to install it
|
|
# on PyPy or it messes up the build
|
|
cffi_requires = [
|
|
"cffi >= 1.11.5 ; sys_platform == 'win32' and platform_python_implementation == 'CPython'",
|
|
]
|
|
|
|
|
|
install_requires = greenlet_requires + cffi_requires
|
|
|
|
# We use headers from greenlet, so it needs to be installed before we
|
|
# can compile. If it isn't already installed before we start
|
|
# installing, and we say 'pip install gevent', a 'setup_requires'
|
|
# doesn't save us: pip happily downloads greenlet and drops it in a
|
|
# .eggs/ directory in the build directory, but that directory doesn't
|
|
# have includes! So we fail to build a wheel, pip goes ahead and
|
|
# installs greenlet, and builds gevent again, which works.
|
|
|
|
# Since we ship the greenlet header for buildout support (which fails
|
|
# to install the headers at all, AFAICS, we don't need to bother with
|
|
# the buggy setup_requires.)
|
|
|
|
setup_requires = cffi_requires + []
|
|
|
|
if PYPY:
|
|
# These use greenlet/greenlet.h, which doesn't exist on PyPy
|
|
EXT_MODULES.remove(LOCAL)
|
|
EXT_MODULES.remove(GREENLET)
|
|
EXT_MODULES.remove(SEMAPHORE)
|
|
EXT_MODULES.remove(ABSTRACT_LINKABLE)
|
|
|
|
# As of PyPy 5.10, this builds, but won't import (missing _Py_ReprEnter)
|
|
EXT_MODULES.remove(CORE)
|
|
|
|
# This uses PyWeakReference and doesn't compile on PyPy
|
|
EXT_MODULES.remove(IDENT)
|
|
|
|
_to_cythonize.remove(LOCAL)
|
|
_to_cythonize.remove(GREENLET)
|
|
_to_cythonize.remove(SEMAPHORE)
|
|
_to_cythonize.remove(IDENT)
|
|
_to_cythonize.remove(ABSTRACT_LINKABLE)
|
|
|
|
EXT_MODULES.remove(IMAP)
|
|
_to_cythonize.remove(IMAP)
|
|
|
|
EXT_MODULES.remove(EVENT)
|
|
_to_cythonize.remove(EVENT)
|
|
|
|
EXT_MODULES.remove(QUEUE)
|
|
_to_cythonize.remove(QUEUE)
|
|
|
|
EXT_MODULES.remove(HUB_LOCAL)
|
|
_to_cythonize.remove(HUB_LOCAL)
|
|
|
|
EXT_MODULES.remove(WAITER)
|
|
_to_cythonize.remove(WAITER)
|
|
|
|
EXT_MODULES.remove(GLT_PRIMITIVES)
|
|
_to_cythonize.remove(GLT_PRIMITIVES)
|
|
|
|
EXT_MODULES.remove(HUB_PRIMITIVES)
|
|
_to_cythonize.remove(HUB_PRIMITIVES)
|
|
|
|
EXT_MODULES.remove(TRACER)
|
|
_to_cythonize.remove(TRACER)
|
|
|
|
|
|
for mod in _to_cythonize:
|
|
EXT_MODULES.remove(mod)
|
|
EXT_MODULES.append(cythonize1(mod))
|
|
del _to_cythonize
|
|
|
|
|
|
if IGNORE_CFFI and not PYPY:
|
|
# Allow distributors to turn off CFFI builds
|
|
# even if it's available, because CFFI always embeds
|
|
# our copy of libev/libuv and they may not want that.
|
|
del cffi_modules[:]
|
|
|
|
# If we are running info / help commands, or we're being imported by
|
|
# tools like pyroma, we don't need to build anything
|
|
_BUILDING = True
|
|
if ((len(sys.argv) >= 2
|
|
and ('--help' in sys.argv[1:]
|
|
or sys.argv[1] in ('--help-commands',
|
|
'egg_info',
|
|
'--version',
|
|
'clean',
|
|
'--long-description')))
|
|
or __name__ != '__main__'):
|
|
_BUILDING = False
|
|
|
|
def make_long_description():
|
|
readme = read('README.rst')
|
|
about = read('doc', '_about.rst')
|
|
install = read('doc', 'install.rst')
|
|
readme = readme.replace('.. include:: doc/_about.rst',
|
|
about)
|
|
readme = readme.replace('.. include:: doc/install.rst',
|
|
install)
|
|
|
|
return readme
|
|
|
|
|
|
def run_setup(ext_modules, run_make):
|
|
if run_make:
|
|
if (not LIBEV_EMBED and not WIN and cffi_modules) or PYPY:
|
|
# We're not embedding libev but we do want
|
|
# to build the CFFI module. We need to configure libev
|
|
# because the CORE Extension won't.
|
|
# TODO: Generalize this.
|
|
if LIBEV_CFFI_MODULE in cffi_modules and not WIN:
|
|
system(libev_configure_command)
|
|
|
|
setup(
|
|
name='gevent',
|
|
version=__version__,
|
|
description='Coroutine-based network library',
|
|
long_description=make_long_description(),
|
|
license='MIT',
|
|
keywords='greenlet coroutine cooperative multitasking light threads monkey',
|
|
author='Denis Bilenko',
|
|
author_email='denis.bilenko@gmail.com',
|
|
maintainer='Jason Madden',
|
|
maintainer_email='jason@nextthought.com',
|
|
url='http://www.gevent.org/',
|
|
project_urls={
|
|
'Bug Tracker': 'https://github.com/gevent/gevent/issues',
|
|
'Source Code': 'https://github.com/gevent/gevent/',
|
|
'Documentation': 'http://www.gevent.org',
|
|
},
|
|
package_dir={'': 'src'},
|
|
packages=find_packages('src'),
|
|
include_package_data=True,
|
|
ext_modules=ext_modules,
|
|
cmdclass=dict(build_ext=ConfiguringBuildExt),
|
|
install_requires=install_requires,
|
|
setup_requires=setup_requires,
|
|
extras_require={
|
|
'dnspython': [
|
|
'dnspython',
|
|
'idna',
|
|
],
|
|
'events': [
|
|
'zope.event',
|
|
'zope.interface',
|
|
],
|
|
'doc': [
|
|
'repoze.sphinx.autointerface',
|
|
],
|
|
'test': [
|
|
'zope.interface',
|
|
'zope.event',
|
|
|
|
# Makes tests faster
|
|
# Fails to build on PyPy on Windows.
|
|
'psutil ; platform_python_implementation == "CPython" or sys_platform != "win32"',
|
|
# examples, called from tests, use this
|
|
'requests',
|
|
|
|
# We don't run coverage on Windows, and pypy can't build it there
|
|
# anyway (coveralls -> cryptopgraphy -> openssl)
|
|
'coverage>=5.0a3 ; sys_platform != "win32"',
|
|
'coveralls>=1.0 ; sys_platform != "win32"',
|
|
|
|
'futures ; python_version == "2.7"',
|
|
'mock ; python_version == "2.7"',
|
|
|
|
# leak checks. previously we had a hand-rolled version.
|
|
'objgraph',
|
|
]
|
|
},
|
|
# It's always safe to pass the CFFI keyword, even if
|
|
# cffi is not installed: it's just ignored in that case.
|
|
cffi_modules=cffi_modules,
|
|
zip_safe=False,
|
|
test_suite="greentest.testrunner",
|
|
classifiers=[
|
|
"License :: OSI Approved :: MIT License",
|
|
"Programming Language :: Python :: 2.7",
|
|
"Programming Language :: Python :: 3.4",
|
|
"Programming Language :: Python :: 3.5",
|
|
"Programming Language :: Python :: 3.6",
|
|
"Programming Language :: Python :: 3.7",
|
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
"Operating System :: MacOS :: MacOS X",
|
|
"Operating System :: POSIX",
|
|
"Operating System :: Microsoft :: Windows",
|
|
"Topic :: Internet",
|
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
"Intended Audience :: Developers",
|
|
"Development Status :: 4 - Beta"
|
|
],
|
|
python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
|
|
entry_points={
|
|
'gevent.plugins.monkey.will_patch_all': [
|
|
"signal_os_incompat = gevent.monkey:_subscribe_signal_os",
|
|
],
|
|
},
|
|
)
|
|
|
|
# Tools like pyroma expect the actual call to `setup` to be performed
|
|
# at the top-level at import time, so don't stash it away behind 'if
|
|
# __name__ == __main__'
|
|
|
|
if os.getenv('READTHEDOCS'):
|
|
# Sometimes RTD fails to put our virtualenv bin directory
|
|
# on the PATH, meaning we can't run cython. Fix that.
|
|
new_path = os.environ['PATH'] + os.pathsep + os.path.dirname(sys.executable)
|
|
os.environ['PATH'] = new_path
|
|
|
|
try:
|
|
run_setup(EXT_MODULES, run_make=_BUILDING)
|
|
except BuildFailed:
|
|
if ARES not in EXT_MODULES or not ARES.optional:
|
|
raise
|
|
EXT_MODULES.remove(ARES)
|
|
run_setup(EXT_MODULES, run_make=_BUILDING)
|
|
if ARES not in EXT_MODULES and __name__ == '__main__' and _BUILDING:
|
|
sys.stderr.write('\nWARNING: The gevent.ares extension has been disabled.\n')
|