setup.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. from __future__ import print_function
  2. import os
  3. import sys
  4. import glob
  5. import setuptools
  6. import setuptools.command.test
  7. from distutils import sysconfig
  8. from distutils.errors import (
  9. CCompilerError,
  10. DistutilsExecError,
  11. DistutilsPlatformError
  12. )
  13. HERE = os.path.dirname(os.path.abspath(__file__))
  14. ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
  15. if sys.platform == 'win32' and sys.version_info >= (2, 6):
  16. # distutils.msvc9compiler can raise IOError if the compiler is missing
  17. ext_errors += (IOError, )
  18. is_jython = sys.platform.startswith('java')
  19. is_pypy = hasattr(sys, 'pypy_version_info')
  20. is_py3k = sys.version_info[0] == 3
  21. BUILD_WARNING = """
  22. -----------------------------------------------------------------------
  23. WARNING: The C extensions could not be compiled
  24. -----------------------------------------------------------------------
  25. Maybe you do not have a C compiler installed on this system?
  26. The reason was:
  27. %s
  28. This is just a warning as most of the functionality will work even
  29. without the updated C extension. It will simply fallback to the
  30. built-in _multiprocessing module. Most notably you will not be able to use
  31. FORCE_EXECV on POSIX systems. If this is a problem for you then please
  32. install a C compiler or fix the error(s) above.
  33. -----------------------------------------------------------------------
  34. """
  35. # -*- py3k -*-
  36. extras = {}
  37. # -*- Distribution Meta -*-
  38. import re
  39. re_meta = re.compile(r'__(\w+?)__\s*=\s*(.*)')
  40. re_vers = re.compile(r'VERSION\s*=\s*\((.*?)\)')
  41. re_doc = re.compile(r'^"""(.+?)"""')
  42. rq = lambda s: s.strip("\"'")
  43. def add_default(m):
  44. attr_name, attr_value = m.groups()
  45. return ((attr_name, rq(attr_value)), )
  46. def add_version(m):
  47. v = list(map(rq, m.groups()[0].split(', ')))
  48. return (('VERSION', '.'.join(v[0:4]) + ''.join(v[4:])), )
  49. def add_doc(m):
  50. return (('doc', m.groups()[0]), )
  51. pats = {re_meta: add_default,
  52. re_vers: add_version,
  53. re_doc: add_doc}
  54. here = os.path.abspath(os.path.dirname(__file__))
  55. meta_fh = open(os.path.join(here, 'billiard/__init__.py'))
  56. try:
  57. meta = {}
  58. for line in meta_fh:
  59. if line.strip() == '# -eof meta-':
  60. break
  61. for pattern, handler in pats.items():
  62. m = pattern.match(line.strip())
  63. if m:
  64. meta.update(handler(m))
  65. finally:
  66. meta_fh.close()
  67. if sys.version_info < (2, 7):
  68. raise ValueError('Versions of Python before 2.7 are not supported')
  69. if sys.platform == 'win32': # Windows
  70. macros = dict()
  71. libraries = ['ws2_32']
  72. elif sys.platform.startswith('darwin'): # macOS
  73. macros = dict(
  74. HAVE_SEM_OPEN=1,
  75. HAVE_SEM_TIMEDWAIT=0,
  76. HAVE_FD_TRANSFER=1,
  77. HAVE_BROKEN_SEM_GETVALUE=1
  78. )
  79. libraries = []
  80. elif sys.platform.startswith('cygwin'): # Cygwin
  81. macros = dict(
  82. HAVE_SEM_OPEN=1,
  83. HAVE_SEM_TIMEDWAIT=1,
  84. HAVE_FD_TRANSFER=0,
  85. HAVE_BROKEN_SEM_UNLINK=1
  86. )
  87. libraries = []
  88. elif sys.platform in ('freebsd4', 'freebsd5', 'freebsd6'):
  89. # FreeBSD's P1003.1b semaphore support is very experimental
  90. # and has many known problems. (as of June 2008)
  91. macros = dict( # FreeBSD 4-6
  92. HAVE_SEM_OPEN=0,
  93. HAVE_SEM_TIMEDWAIT=0,
  94. HAVE_FD_TRANSFER=1,
  95. )
  96. libraries = []
  97. elif re.match('^(gnukfreebsd(8|9|10|11)|freebsd(7|8|9|0))', sys.platform):
  98. macros = dict( # FreeBSD 7+ and GNU/kFreeBSD 8+
  99. HAVE_SEM_OPEN=bool(
  100. sysconfig.get_config_var('HAVE_SEM_OPEN') and not
  101. bool(sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED'))
  102. ),
  103. HAVE_SEM_TIMEDWAIT=1,
  104. HAVE_FD_TRANSFER=1,
  105. )
  106. libraries = []
  107. elif sys.platform.startswith('openbsd'):
  108. macros = dict( # OpenBSD
  109. HAVE_SEM_OPEN=0, # Not implemented
  110. HAVE_SEM_TIMEDWAIT=0,
  111. HAVE_FD_TRANSFER=1,
  112. )
  113. libraries = []
  114. else: # Linux and other unices
  115. macros = dict(
  116. HAVE_SEM_OPEN=1,
  117. HAVE_SEM_TIMEDWAIT=1,
  118. HAVE_FD_TRANSFER=1,
  119. )
  120. libraries = ['rt']
  121. if sys.platform == 'win32':
  122. multiprocessing_srcs = [
  123. 'Modules/_billiard/multiprocessing.c',
  124. 'Modules/_billiard/semaphore.c',
  125. 'Modules/_billiard/win32_functions.c',
  126. ]
  127. else:
  128. multiprocessing_srcs = [
  129. 'Modules/_billiard/multiprocessing.c',
  130. ]
  131. if macros.get('HAVE_SEM_OPEN', False):
  132. multiprocessing_srcs.append('Modules/_billiard/semaphore.c')
  133. long_description = open(os.path.join(HERE, 'README.rst')).read()
  134. # -*- Installation Requires -*-
  135. py_version = sys.version_info
  136. is_jython = sys.platform.startswith('java')
  137. is_pypy = hasattr(sys, 'pypy_version_info')
  138. def strip_comments(l):
  139. return l.split('#', 1)[0].strip()
  140. def reqs(f):
  141. return list(filter(None, [strip_comments(l) for l in open(
  142. os.path.join(os.getcwd(), 'requirements', f)).readlines()]))
  143. def _is_build_command(argv=sys.argv, cmds=('install', 'build', 'bdist')):
  144. for arg in argv:
  145. if arg.startswith(cmds):
  146. return arg
  147. class pytest(setuptools.command.test.test):
  148. user_options = [('pytest-args=', 'a', 'Arguments to pass to py.test')]
  149. def initialize_options(self):
  150. setuptools.command.test.test.initialize_options(self)
  151. self.pytest_args = []
  152. def run_tests(self):
  153. import pytest
  154. sys.exit(pytest.main(self.pytest_args))
  155. def run_setup(with_extensions=True):
  156. extensions = []
  157. if with_extensions:
  158. extensions = [
  159. setuptools.Extension(
  160. '_billiard',
  161. sources=multiprocessing_srcs,
  162. define_macros=macros.items(),
  163. libraries=libraries,
  164. include_dirs=['Modules/_billiard'],
  165. depends=glob.glob('Modules/_billiard/*.h') + ['setup.py'],
  166. ),
  167. ]
  168. if sys.platform == 'win32':
  169. extensions.append(
  170. setuptools.Extension(
  171. '_winapi',
  172. sources=multiprocessing_srcs,
  173. define_macros=macros.items(),
  174. libraries=libraries,
  175. include_dirs=['Modules/_billiard'],
  176. depends=glob.glob('Modules/_billiard/*.h') + ['setup.py'],
  177. ),
  178. )
  179. packages = setuptools.find_packages(exclude=['ez_setup', 't', 't.*'])
  180. setuptools.setup(
  181. name='billiard',
  182. version=meta['VERSION'],
  183. description=meta['doc'],
  184. long_description=long_description,
  185. packages=packages,
  186. ext_modules=extensions,
  187. author=meta['author'],
  188. author_email=meta['author_email'],
  189. keywords='multiprocessing pool process',
  190. maintainer=meta['maintainer'],
  191. maintainer_email=meta['contact'],
  192. url=meta['homepage'],
  193. zip_safe=False,
  194. license='BSD',
  195. tests_require=reqs('test.txt'),
  196. cmdclass={'test': pytest},
  197. classifiers=[
  198. 'Development Status :: 5 - Production/Stable',
  199. 'Intended Audience :: Developers',
  200. 'Programming Language :: Python',
  201. 'Programming Language :: C',
  202. 'Programming Language :: Python :: 2',
  203. 'Programming Language :: Python :: 2.7',
  204. 'Programming Language :: Python :: 3',
  205. 'Programming Language :: Python :: 3.4',
  206. 'Programming Language :: Python :: 3.5',
  207. 'Programming Language :: Python :: 3.6',
  208. 'Programming Language :: Python :: Implementation :: CPython',
  209. 'Programming Language :: Python :: Implementation :: Jython',
  210. 'Programming Language :: Python :: Implementation :: PyPy',
  211. 'Operating System :: Microsoft :: Windows',
  212. 'Operating System :: POSIX',
  213. 'License :: OSI Approved :: BSD License',
  214. 'Topic :: Software Development :: Libraries :: Python Modules',
  215. 'Topic :: System :: Distributed Computing',
  216. ],
  217. **extras
  218. )
  219. try:
  220. run_setup(not (is_jython or is_pypy or is_py3k))
  221. except BaseException:
  222. if _is_build_command(sys.argv):
  223. import traceback
  224. print(BUILD_WARNING % '\n'.join(traceback.format_stack()),
  225. file=sys.stderr)
  226. run_setup(False)
  227. else:
  228. raise