core.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import sys
  2. from distutils.core import Distribution
  3. if 'setuptools' in sys.modules:
  4. have_setuptools = True
  5. from setuptools import setup as old_setup
  6. # easy_install imports math, it may be picked up from cwd
  7. from setuptools.command import easy_install
  8. try:
  9. # very old versions of setuptools don't have this
  10. from setuptools.command import bdist_egg
  11. except ImportError:
  12. have_setuptools = False
  13. else:
  14. from distutils.core import setup as old_setup
  15. have_setuptools = False
  16. import warnings
  17. import distutils.core
  18. import distutils.dist
  19. from numpy.distutils.extension import Extension # noqa: F401
  20. from numpy.distutils.numpy_distribution import NumpyDistribution
  21. from numpy.distutils.command import config, config_compiler, \
  22. build, build_py, build_ext, build_clib, build_src, build_scripts, \
  23. sdist, install_data, install_headers, install, bdist_rpm, \
  24. install_clib
  25. from numpy.distutils.misc_util import is_sequence, is_string
  26. numpy_cmdclass = {'build': build.build,
  27. 'build_src': build_src.build_src,
  28. 'build_scripts': build_scripts.build_scripts,
  29. 'config_cc': config_compiler.config_cc,
  30. 'config_fc': config_compiler.config_fc,
  31. 'config': config.config,
  32. 'build_ext': build_ext.build_ext,
  33. 'build_py': build_py.build_py,
  34. 'build_clib': build_clib.build_clib,
  35. 'sdist': sdist.sdist,
  36. 'install_data': install_data.install_data,
  37. 'install_headers': install_headers.install_headers,
  38. 'install_clib': install_clib.install_clib,
  39. 'install': install.install,
  40. 'bdist_rpm': bdist_rpm.bdist_rpm,
  41. }
  42. if have_setuptools:
  43. # Use our own versions of develop and egg_info to ensure that build_src is
  44. # handled appropriately.
  45. from numpy.distutils.command import develop, egg_info
  46. numpy_cmdclass['bdist_egg'] = bdist_egg.bdist_egg
  47. numpy_cmdclass['develop'] = develop.develop
  48. numpy_cmdclass['easy_install'] = easy_install.easy_install
  49. numpy_cmdclass['egg_info'] = egg_info.egg_info
  50. def _dict_append(d, **kws):
  51. for k, v in kws.items():
  52. if k not in d:
  53. d[k] = v
  54. continue
  55. dv = d[k]
  56. if isinstance(dv, tuple):
  57. d[k] = dv + tuple(v)
  58. elif isinstance(dv, list):
  59. d[k] = dv + list(v)
  60. elif isinstance(dv, dict):
  61. _dict_append(dv, **v)
  62. elif is_string(dv):
  63. d[k] = dv + v
  64. else:
  65. raise TypeError(repr(type(dv)))
  66. def _command_line_ok(_cache=None):
  67. """ Return True if command line does not contain any
  68. help or display requests.
  69. """
  70. if _cache:
  71. return _cache[0]
  72. elif _cache is None:
  73. _cache = []
  74. ok = True
  75. display_opts = ['--'+n for n in Distribution.display_option_names]
  76. for o in Distribution.display_options:
  77. if o[1]:
  78. display_opts.append('-'+o[1])
  79. for arg in sys.argv:
  80. if arg.startswith('--help') or arg=='-h' or arg in display_opts:
  81. ok = False
  82. break
  83. _cache.append(ok)
  84. return ok
  85. def get_distribution(always=False):
  86. dist = distutils.core._setup_distribution
  87. # XXX Hack to get numpy installable with easy_install.
  88. # The problem is easy_install runs it's own setup(), which
  89. # sets up distutils.core._setup_distribution. However,
  90. # when our setup() runs, that gets overwritten and lost.
  91. # We can't use isinstance, as the DistributionWithoutHelpCommands
  92. # class is local to a function in setuptools.command.easy_install
  93. if dist is not None and \
  94. 'DistributionWithoutHelpCommands' in repr(dist):
  95. dist = None
  96. if always and dist is None:
  97. dist = NumpyDistribution()
  98. return dist
  99. def setup(**attr):
  100. cmdclass = numpy_cmdclass.copy()
  101. new_attr = attr.copy()
  102. if 'cmdclass' in new_attr:
  103. cmdclass.update(new_attr['cmdclass'])
  104. new_attr['cmdclass'] = cmdclass
  105. if 'configuration' in new_attr:
  106. # To avoid calling configuration if there are any errors
  107. # or help request in command in the line.
  108. configuration = new_attr.pop('configuration')
  109. old_dist = distutils.core._setup_distribution
  110. old_stop = distutils.core._setup_stop_after
  111. distutils.core._setup_distribution = None
  112. distutils.core._setup_stop_after = "commandline"
  113. try:
  114. dist = setup(**new_attr)
  115. finally:
  116. distutils.core._setup_distribution = old_dist
  117. distutils.core._setup_stop_after = old_stop
  118. if dist.help or not _command_line_ok():
  119. # probably displayed help, skip running any commands
  120. return dist
  121. # create setup dictionary and append to new_attr
  122. config = configuration()
  123. if hasattr(config, 'todict'):
  124. config = config.todict()
  125. _dict_append(new_attr, **config)
  126. # Move extension source libraries to libraries
  127. libraries = []
  128. for ext in new_attr.get('ext_modules', []):
  129. new_libraries = []
  130. for item in ext.libraries:
  131. if is_sequence(item):
  132. lib_name, build_info = item
  133. _check_append_ext_library(libraries, lib_name, build_info)
  134. new_libraries.append(lib_name)
  135. elif is_string(item):
  136. new_libraries.append(item)
  137. else:
  138. raise TypeError("invalid description of extension module "
  139. "library %r" % (item,))
  140. ext.libraries = new_libraries
  141. if libraries:
  142. if 'libraries' not in new_attr:
  143. new_attr['libraries'] = []
  144. for item in libraries:
  145. _check_append_library(new_attr['libraries'], item)
  146. # sources in ext_modules or libraries may contain header files
  147. if ('ext_modules' in new_attr or 'libraries' in new_attr) \
  148. and 'headers' not in new_attr:
  149. new_attr['headers'] = []
  150. # Use our custom NumpyDistribution class instead of distutils' one
  151. new_attr['distclass'] = NumpyDistribution
  152. return old_setup(**new_attr)
  153. def _check_append_library(libraries, item):
  154. for libitem in libraries:
  155. if is_sequence(libitem):
  156. if is_sequence(item):
  157. if item[0]==libitem[0]:
  158. if item[1] is libitem[1]:
  159. return
  160. warnings.warn("[0] libraries list contains %r with"
  161. " different build_info" % (item[0],),
  162. stacklevel=2)
  163. break
  164. else:
  165. if item==libitem[0]:
  166. warnings.warn("[1] libraries list contains %r with"
  167. " no build_info" % (item[0],),
  168. stacklevel=2)
  169. break
  170. else:
  171. if is_sequence(item):
  172. if item[0]==libitem:
  173. warnings.warn("[2] libraries list contains %r with"
  174. " no build_info" % (item[0],),
  175. stacklevel=2)
  176. break
  177. else:
  178. if item==libitem:
  179. return
  180. libraries.append(item)
  181. def _check_append_ext_library(libraries, lib_name, build_info):
  182. for item in libraries:
  183. if is_sequence(item):
  184. if item[0]==lib_name:
  185. if item[1] is build_info:
  186. return
  187. warnings.warn("[3] libraries list contains %r with"
  188. " different build_info" % (lib_name,),
  189. stacklevel=2)
  190. break
  191. elif item==lib_name:
  192. warnings.warn("[4] libraries list contains %r with"
  193. " no build_info" % (lib_name,),
  194. stacklevel=2)
  195. break
  196. libraries.append((lib_name, build_info))