setup.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import os
  2. import platform
  3. import re
  4. import sys
  5. from distutils.command.build_ext import build_ext
  6. from distutils.errors import CCompilerError
  7. from distutils.errors import DistutilsExecError
  8. from distutils.errors import DistutilsPlatformError
  9. from setuptools import Distribution as _Distribution, Extension
  10. from setuptools import setup
  11. from setuptools import find_packages
  12. from setuptools.command.test import test as TestCommand
  13. cmdclass = {}
  14. if sys.version_info < (2, 7):
  15. raise Exception("SQLAlchemy requires Python 2.7 or higher.")
  16. cpython = platform.python_implementation() == 'CPython'
  17. ext_modules = [
  18. Extension('sqlalchemy.cprocessors',
  19. sources=['lib/sqlalchemy/cextension/processors.c']),
  20. Extension('sqlalchemy.cresultproxy',
  21. sources=['lib/sqlalchemy/cextension/resultproxy.c']),
  22. Extension('sqlalchemy.cutils',
  23. sources=['lib/sqlalchemy/cextension/utils.c'])
  24. ]
  25. ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
  26. if sys.platform == 'win32':
  27. # 2.6's distutils.msvc9compiler can raise an IOError when failing to
  28. # find the compiler
  29. ext_errors += (IOError,)
  30. class BuildFailed(Exception):
  31. def __init__(self):
  32. self.cause = sys.exc_info()[1] # work around py 2/3 different syntax
  33. class ve_build_ext(build_ext):
  34. # This class allows C extension building to fail.
  35. def run(self):
  36. try:
  37. build_ext.run(self)
  38. except DistutilsPlatformError:
  39. raise BuildFailed()
  40. def build_extension(self, ext):
  41. try:
  42. build_ext.build_extension(self, ext)
  43. except ext_errors:
  44. raise BuildFailed()
  45. except ValueError:
  46. # this can happen on Windows 64 bit, see Python issue 7511
  47. if "'path'" in str(sys.exc_info()[1]): # works with both py 2/3
  48. raise BuildFailed()
  49. raise
  50. cmdclass['build_ext'] = ve_build_ext
  51. class Distribution(_Distribution):
  52. def has_ext_modules(self):
  53. # We want to always claim that we have ext_modules. This will be fine
  54. # if we don't actually have them (such as on PyPy) because nothing
  55. # will get built, however we don't want to provide an overally broad
  56. # Wheel package when building a wheel without C support. This will
  57. # ensure that Wheel knows to treat us as if the build output is
  58. # platform specific.
  59. return True
  60. class PyTest(TestCommand):
  61. # from http://pytest.org/latest/goodpractices.html\
  62. # #integrating-with-setuptools-python-setup-py-test-pytest-runner
  63. # TODO: prefer pytest-runner package at some point, however it was
  64. # not working at the time of this comment.
  65. user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")]
  66. default_options = ["-n", "4", "-q", "--nomemory"]
  67. def initialize_options(self):
  68. TestCommand.initialize_options(self)
  69. self.pytest_args = ""
  70. def finalize_options(self):
  71. TestCommand.finalize_options(self)
  72. self.test_args = []
  73. self.test_suite = True
  74. def run_tests(self):
  75. import shlex
  76. # import here, cause outside the eggs aren't loaded
  77. import pytest
  78. errno = pytest.main(self.default_options + shlex.split(self.pytest_args))
  79. sys.exit(errno)
  80. cmdclass['test'] = PyTest
  81. def status_msgs(*msgs):
  82. print('*' * 75)
  83. for msg in msgs:
  84. print(msg)
  85. print('*' * 75)
  86. with open(
  87. os.path.join(
  88. os.path.dirname(__file__),
  89. 'lib', 'sqlalchemy', '__init__.py')) as v_file:
  90. VERSION = re.compile(
  91. r".*__version__ = '(.*?)'",
  92. re.S).match(v_file.read()).group(1)
  93. with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as r_file:
  94. readme = r_file.read()
  95. def run_setup(with_cext):
  96. kwargs = {}
  97. if with_cext:
  98. kwargs['ext_modules'] = ext_modules
  99. else:
  100. kwargs['ext_modules'] = []
  101. setup(
  102. name="SQLAlchemy",
  103. version=VERSION,
  104. description="Database Abstraction Library",
  105. author="Mike Bayer",
  106. author_email="mike_mp@zzzcomputing.com",
  107. url="http://www.sqlalchemy.org",
  108. packages=find_packages('lib'),
  109. package_dir={'': 'lib'},
  110. license="MIT License",
  111. cmdclass=cmdclass,
  112. tests_require=['pytest >= 2.5.2', 'mock', 'pytest-xdist'],
  113. long_description=readme,
  114. classifiers=[
  115. "Development Status :: 5 - Production/Stable",
  116. "Intended Audience :: Developers",
  117. "License :: OSI Approved :: MIT License",
  118. "Programming Language :: Python",
  119. "Programming Language :: Python :: 3",
  120. "Programming Language :: Python :: Implementation :: CPython",
  121. "Programming Language :: Python :: Implementation :: PyPy",
  122. "Topic :: Database :: Front-Ends",
  123. "Operating System :: OS Independent",
  124. ],
  125. distclass=Distribution,
  126. extras_require={
  127. 'mysql': ['mysqlclient'],
  128. 'pymysql': ['pymysql'],
  129. 'postgresql': ['psycopg2'],
  130. 'postgresql_pg8000': ['pg8000'],
  131. 'postgresql_psycopg2cffi': ['psycopg2cffi'],
  132. 'oracle': ['cx_oracle'],
  133. 'mssql_pyodbc': ['pyodbc'],
  134. 'mssql_pymssql': ['pymssql']
  135. },
  136. **kwargs
  137. )
  138. if not cpython:
  139. run_setup(False)
  140. status_msgs(
  141. "WARNING: C extensions are not supported on " +
  142. "this Python platform, speedups are not enabled.",
  143. "Plain-Python build succeeded."
  144. )
  145. elif os.environ.get('DISABLE_SQLALCHEMY_CEXT'):
  146. run_setup(False)
  147. status_msgs(
  148. "DISABLE_SQLALCHEMY_CEXT is set; " +
  149. "not attempting to build C extensions.",
  150. "Plain-Python build succeeded."
  151. )
  152. else:
  153. try:
  154. run_setup(True)
  155. except BuildFailed as exc:
  156. status_msgs(
  157. exc.cause,
  158. "WARNING: The C extension could not be compiled, " +
  159. "speedups are not enabled.",
  160. "Failure information, if any, is above.",
  161. "Retrying the build without the C extension now."
  162. )
  163. run_setup(False)
  164. status_msgs(
  165. "WARNING: The C extension could not be compiled, " +
  166. "speedups are not enabled.",
  167. "Plain-Python build succeeded."
  168. )