setup.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. NAME = 'PyYAML'
  2. VERSION = '5.3.1'
  3. DESCRIPTION = "YAML parser and emitter for Python"
  4. LONG_DESCRIPTION = """\
  5. YAML is a data serialization format designed for human readability
  6. and interaction with scripting languages. PyYAML is a YAML parser
  7. and emitter for Python.
  8. PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
  9. support, capable extension API, and sensible error messages. PyYAML
  10. supports standard YAML tags and provides Python-specific tags that
  11. allow to represent an arbitrary Python object.
  12. PyYAML is applicable for a broad range of tasks from complex
  13. configuration files to object serialization and persistence."""
  14. AUTHOR = "Kirill Simonov"
  15. AUTHOR_EMAIL = 'xi@resolvent.net'
  16. LICENSE = "MIT"
  17. PLATFORMS = "Any"
  18. URL = "https://github.com/yaml/pyyaml"
  19. DOWNLOAD_URL = "https://pypi.org/project/PyYAML/"
  20. CLASSIFIERS = [
  21. "Development Status :: 5 - Production/Stable",
  22. "Intended Audience :: Developers",
  23. "License :: OSI Approved :: MIT License",
  24. "Operating System :: OS Independent",
  25. "Programming Language :: Cython",
  26. "Programming Language :: Python",
  27. "Programming Language :: Python :: 2",
  28. "Programming Language :: Python :: 2.7",
  29. "Programming Language :: Python :: 3",
  30. "Programming Language :: Python :: 3.5",
  31. "Programming Language :: Python :: 3.6",
  32. "Programming Language :: Python :: 3.7",
  33. "Programming Language :: Python :: 3.8",
  34. "Programming Language :: Python :: Implementation :: CPython",
  35. "Programming Language :: Python :: Implementation :: PyPy",
  36. "Topic :: Software Development :: Libraries :: Python Modules",
  37. "Topic :: Text Processing :: Markup",
  38. ]
  39. LIBYAML_CHECK = """
  40. #include <yaml.h>
  41. int main(void) {
  42. yaml_parser_t parser;
  43. yaml_emitter_t emitter;
  44. yaml_parser_initialize(&parser);
  45. yaml_parser_delete(&parser);
  46. yaml_emitter_initialize(&emitter);
  47. yaml_emitter_delete(&emitter);
  48. return 0;
  49. }
  50. """
  51. import sys, os.path, platform, warnings
  52. from distutils import log
  53. from distutils.core import setup, Command
  54. from distutils.core import Distribution as _Distribution
  55. from distutils.core import Extension as _Extension
  56. from distutils.command.build_ext import build_ext as _build_ext
  57. from distutils.command.bdist_rpm import bdist_rpm as _bdist_rpm
  58. from distutils.errors import DistutilsError, CompileError, LinkError, DistutilsPlatformError
  59. if 'setuptools.extension' in sys.modules:
  60. _Extension = sys.modules['setuptools.extension']._Extension
  61. sys.modules['distutils.core'].Extension = _Extension
  62. sys.modules['distutils.extension'].Extension = _Extension
  63. sys.modules['distutils.command.build_ext'].Extension = _Extension
  64. with_cython = False
  65. if 'sdist' in sys.argv:
  66. # we need cython here
  67. with_cython = True
  68. try:
  69. from Cython.Distutils.extension import Extension as _Extension
  70. from Cython.Distutils import build_ext as _build_ext
  71. with_cython = True
  72. except ImportError:
  73. if with_cython:
  74. raise
  75. try:
  76. from wheel.bdist_wheel import bdist_wheel
  77. except ImportError:
  78. bdist_wheel = None
  79. # on Windows, disable wheel generation warning noise
  80. windows_ignore_warnings = [
  81. "Unknown distribution option: 'python_requires'",
  82. "Config variable 'Py_DEBUG' is unset",
  83. "Config variable 'WITH_PYMALLOC' is unset",
  84. "Config variable 'Py_UNICODE_SIZE' is unset",
  85. "Cython directive 'language_level' not set"
  86. ]
  87. if platform.system() == 'Windows':
  88. for w in windows_ignore_warnings:
  89. warnings.filterwarnings('ignore', w)
  90. class Distribution(_Distribution):
  91. def __init__(self, attrs=None):
  92. _Distribution.__init__(self, attrs)
  93. if not self.ext_modules:
  94. return
  95. for idx in range(len(self.ext_modules)-1, -1, -1):
  96. ext = self.ext_modules[idx]
  97. if not isinstance(ext, Extension):
  98. continue
  99. setattr(self, ext.attr_name, None)
  100. self.global_options = [
  101. (ext.option_name, None,
  102. "include %s (default if %s is available)"
  103. % (ext.feature_description, ext.feature_name)),
  104. (ext.neg_option_name, None,
  105. "exclude %s" % ext.feature_description),
  106. ] + self.global_options
  107. self.negative_opt = self.negative_opt.copy()
  108. self.negative_opt[ext.neg_option_name] = ext.option_name
  109. def has_ext_modules(self):
  110. if not self.ext_modules:
  111. return False
  112. for ext in self.ext_modules:
  113. with_ext = self.ext_status(ext)
  114. if with_ext is None or with_ext:
  115. return True
  116. return False
  117. def ext_status(self, ext):
  118. implementation = platform.python_implementation()
  119. if implementation != 'CPython':
  120. return False
  121. if isinstance(ext, Extension):
  122. with_ext = getattr(self, ext.attr_name)
  123. return with_ext
  124. else:
  125. return True
  126. class Extension(_Extension):
  127. def __init__(self, name, sources, feature_name, feature_description,
  128. feature_check, **kwds):
  129. if not with_cython:
  130. for filename in sources[:]:
  131. base, ext = os.path.splitext(filename)
  132. if ext == '.pyx':
  133. sources.remove(filename)
  134. sources.append('%s.c' % base)
  135. _Extension.__init__(self, name, sources, **kwds)
  136. self.feature_name = feature_name
  137. self.feature_description = feature_description
  138. self.feature_check = feature_check
  139. self.attr_name = 'with_' + feature_name.replace('-', '_')
  140. self.option_name = 'with-' + feature_name
  141. self.neg_option_name = 'without-' + feature_name
  142. class build_ext(_build_ext):
  143. def run(self):
  144. optional = True
  145. disabled = True
  146. for ext in self.extensions:
  147. with_ext = self.distribution.ext_status(ext)
  148. if with_ext is None:
  149. disabled = False
  150. elif with_ext:
  151. optional = False
  152. disabled = False
  153. break
  154. if disabled:
  155. return
  156. try:
  157. _build_ext.run(self)
  158. except DistutilsPlatformError:
  159. exc = sys.exc_info()[1]
  160. if optional:
  161. log.warn(str(exc))
  162. log.warn("skipping build_ext")
  163. else:
  164. raise
  165. def get_source_files(self):
  166. self.check_extensions_list(self.extensions)
  167. filenames = []
  168. for ext in self.extensions:
  169. if with_cython:
  170. self.cython_sources(ext.sources, ext)
  171. for filename in ext.sources:
  172. filenames.append(filename)
  173. base = os.path.splitext(filename)[0]
  174. for ext in ['c', 'h', 'pyx', 'pxd']:
  175. filename = '%s.%s' % (base, ext)
  176. if filename not in filenames and os.path.isfile(filename):
  177. filenames.append(filename)
  178. return filenames
  179. def get_outputs(self):
  180. self.check_extensions_list(self.extensions)
  181. outputs = []
  182. for ext in self.extensions:
  183. fullname = self.get_ext_fullname(ext.name)
  184. filename = os.path.join(self.build_lib,
  185. self.get_ext_filename(fullname))
  186. if os.path.isfile(filename):
  187. outputs.append(filename)
  188. return outputs
  189. def build_extensions(self):
  190. self.check_extensions_list(self.extensions)
  191. for ext in self.extensions:
  192. with_ext = self.distribution.ext_status(ext)
  193. if with_ext is not None and not with_ext:
  194. continue
  195. if with_cython:
  196. ext.sources = self.cython_sources(ext.sources, ext)
  197. try:
  198. self.build_extension(ext)
  199. except (CompileError, LinkError):
  200. if with_ext is not None:
  201. raise
  202. log.warn("Error compiling module, falling back to pure Python")
  203. class bdist_rpm(_bdist_rpm):
  204. def _make_spec_file(self):
  205. argv0 = sys.argv[0]
  206. features = []
  207. for ext in self.distribution.ext_modules:
  208. if not isinstance(ext, Extension):
  209. continue
  210. with_ext = getattr(self.distribution, ext.attr_name)
  211. if with_ext is None:
  212. continue
  213. if with_ext:
  214. features.append('--'+ext.option_name)
  215. else:
  216. features.append('--'+ext.neg_option_name)
  217. sys.argv[0] = ' '.join([argv0]+features)
  218. spec_file = _bdist_rpm._make_spec_file(self)
  219. sys.argv[0] = argv0
  220. return spec_file
  221. class test(Command):
  222. user_options = []
  223. def initialize_options(self):
  224. pass
  225. def finalize_options(self):
  226. pass
  227. def run(self):
  228. build_cmd = self.get_finalized_command('build')
  229. build_cmd.run()
  230. sys.path.insert(0, build_cmd.build_lib)
  231. if sys.version_info[0] < 3:
  232. sys.path.insert(0, 'tests/lib')
  233. else:
  234. sys.path.insert(0, 'tests/lib3')
  235. import test_all
  236. if not test_all.main([]):
  237. raise DistutilsError("Tests failed")
  238. cmdclass = {
  239. 'build_ext': build_ext,
  240. 'bdist_rpm': bdist_rpm,
  241. 'test': test,
  242. }
  243. if bdist_wheel:
  244. cmdclass['bdist_wheel'] = bdist_wheel
  245. if __name__ == '__main__':
  246. setup(
  247. name=NAME,
  248. version=VERSION,
  249. description=DESCRIPTION,
  250. long_description=LONG_DESCRIPTION,
  251. author=AUTHOR,
  252. author_email=AUTHOR_EMAIL,
  253. license=LICENSE,
  254. platforms=PLATFORMS,
  255. url=URL,
  256. download_url=DOWNLOAD_URL,
  257. classifiers=CLASSIFIERS,
  258. package_dir={'': {2: 'lib', 3: 'lib3'}[sys.version_info[0]]},
  259. packages=['yaml'],
  260. ext_modules=[
  261. Extension('_yaml', ['ext/_yaml.pyx'],
  262. 'libyaml', "LibYAML bindings", LIBYAML_CHECK,
  263. libraries=['yaml']),
  264. ],
  265. distclass=Distribution,
  266. cmdclass=cmdclass,
  267. python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
  268. )