setup.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. NAME = 'PyYAML'
  2. VERSION = '3.09'
  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 persistance."""
  14. AUTHOR = "Kirill Simonov"
  15. AUTHOR_EMAIL = 'xi@resolvent.net'
  16. LICENSE = "MIT"
  17. PLATFORMS = "Any"
  18. URL = "http://pyyaml.org/wiki/PyYAML"
  19. DOWNLOAD_URL = "http://pyyaml.org/download/pyyaml/%s-%s.tar.gz" % (NAME, VERSION)
  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 :: Python",
  26. "Programming Language :: Python :: 2",
  27. "Programming Language :: Python :: 2.3",
  28. "Programming Language :: Python :: 2.4",
  29. "Programming Language :: Python :: 2.5",
  30. "Programming Language :: Python :: 2.6",
  31. "Programming Language :: Python :: 3",
  32. "Programming Language :: Python :: 3.0",
  33. "Programming Language :: Python :: 3.1",
  34. "Topic :: Software Development :: Libraries :: Python Modules",
  35. "Topic :: Text Processing :: Markup",
  36. ]
  37. LIBYAML_CHECK = """
  38. #include <yaml.h>
  39. int main(void) {
  40. yaml_parser_t parser;
  41. yaml_emitter_t emitter;
  42. yaml_parser_initialize(&parser);
  43. yaml_parser_delete(&parser);
  44. yaml_emitter_initialize(&emitter);
  45. yaml_emitter_delete(&emitter);
  46. return 0;
  47. }
  48. """
  49. import sys, os.path
  50. from distutils import log
  51. from distutils.core import setup, Command
  52. from distutils.core import Distribution as _Distribution
  53. from distutils.core import Extension as _Extension
  54. from distutils.dir_util import mkpath
  55. from distutils.command.build_ext import build_ext as _build_ext
  56. from distutils.command.bdist_rpm import bdist_rpm as _bdist_rpm
  57. from distutils.errors import CompileError, LinkError, DistutilsPlatformError
  58. if 'setuptools.extension' in sys.modules:
  59. _Extension = sys.modules['setuptools.extension']._Extension
  60. sys.modules['distutils.core'].Extension = _Extension
  61. sys.modules['distutils.extension'].Extension = _Extension
  62. sys.modules['distutils.command.build_ext'].Extension = _Extension
  63. with_pyrex = None
  64. if sys.version_info[0] < 3:
  65. try:
  66. from Cython.Distutils.extension import Extension as _Extension
  67. from Cython.Distutils import build_ext as _build_ext
  68. with_pyrex = 'cython'
  69. except ImportError:
  70. try:
  71. # Pyrex cannot build _yaml.c at the moment,
  72. # but it may get fixed eventually.
  73. from Pyrex.Distutils import Extension as _Extension
  74. from Pyrex.Distutils import build_ext as _build_ext
  75. with_pyrex = 'pyrex'
  76. except ImportError:
  77. pass
  78. class Distribution(_Distribution):
  79. def __init__(self, attrs=None):
  80. _Distribution.__init__(self, attrs)
  81. if not self.ext_modules:
  82. return
  83. for idx in range(len(self.ext_modules)-1, -1, -1):
  84. ext = self.ext_modules[idx]
  85. if not isinstance(ext, Extension):
  86. continue
  87. setattr(self, ext.attr_name, None)
  88. self.global_options = [
  89. (ext.option_name, None,
  90. "include %s (default if %s is available)"
  91. % (ext.feature_description, ext.feature_name)),
  92. (ext.neg_option_name, None,
  93. "exclude %s" % ext.feature_description),
  94. ] + self.global_options
  95. self.negative_opt = self.negative_opt.copy()
  96. self.negative_opt[ext.neg_option_name] = ext.option_name
  97. def has_ext_modules(self):
  98. if not self.ext_modules:
  99. return False
  100. for ext in self.ext_modules:
  101. with_ext = self.ext_status(ext)
  102. if with_ext is None or with_ext:
  103. return True
  104. return False
  105. def ext_status(self, ext):
  106. if isinstance(ext, Extension):
  107. with_ext = getattr(self, ext.attr_name)
  108. return with_ext
  109. else:
  110. return True
  111. class Extension(_Extension):
  112. def __init__(self, name, sources, feature_name, feature_description,
  113. feature_check, **kwds):
  114. if not with_pyrex:
  115. for filename in sources[:]:
  116. base, ext = os.path.splitext(filename)
  117. if ext == '.pyx':
  118. sources.remove(filename)
  119. sources.append('%s.c' % base)
  120. _Extension.__init__(self, name, sources, **kwds)
  121. self.feature_name = feature_name
  122. self.feature_description = feature_description
  123. self.feature_check = feature_check
  124. self.attr_name = 'with_' + feature_name.replace('-', '_')
  125. self.option_name = 'with-' + feature_name
  126. self.neg_option_name = 'without-' + feature_name
  127. class build_ext(_build_ext):
  128. def run(self):
  129. optional = True
  130. disabled = True
  131. for ext in self.extensions:
  132. with_ext = self.distribution.ext_status(ext)
  133. if with_ext is None:
  134. disabled = False
  135. elif with_ext:
  136. optional = False
  137. disabled = False
  138. break
  139. if disabled:
  140. return
  141. try:
  142. _build_ext.run(self)
  143. except DistutilsPlatformError:
  144. exc = sys.exc_info()[1]
  145. if optional:
  146. log.warn(str(exc))
  147. log.warn("skipping build_ext")
  148. else:
  149. raise
  150. def get_source_files(self):
  151. self.check_extensions_list(self.extensions)
  152. filenames = []
  153. for ext in self.extensions:
  154. if with_pyrex == 'pyrex':
  155. self.pyrex_sources(ext.sources, ext)
  156. elif with_pyrex == 'cython':
  157. self.cython_sources(ext.sources, ext)
  158. for filename in ext.sources:
  159. filenames.append(filename)
  160. base = os.path.splitext(filename)[0]
  161. for ext in ['c', 'h', 'pyx', 'pxd']:
  162. filename = '%s.%s' % (base, ext)
  163. if filename not in filenames and os.path.isfile(filename):
  164. filenames.append(filename)
  165. return filenames
  166. def get_outputs(self):
  167. self.check_extensions_list(self.extensions)
  168. outputs = []
  169. for ext in self.extensions:
  170. fullname = self.get_ext_fullname(ext.name)
  171. filename = os.path.join(self.build_lib,
  172. self.get_ext_filename(fullname))
  173. if os.path.isfile(filename):
  174. outputs.append(filename)
  175. return outputs
  176. def build_extensions(self):
  177. self.check_extensions_list(self.extensions)
  178. for ext in self.extensions:
  179. with_ext = self.distribution.ext_status(ext)
  180. if with_ext is None:
  181. with_ext = self.check_extension_availability(ext)
  182. if not with_ext:
  183. continue
  184. if with_pyrex == 'pyrex':
  185. ext.sources = self.pyrex_sources(ext.sources, ext)
  186. elif with_pyrex == 'cython':
  187. ext.sources = self.cython_sources(ext.sources, ext)
  188. self.build_extension(ext)
  189. def check_extension_availability(self, ext):
  190. cache = os.path.join(self.build_temp, 'check_%s.out' % ext.feature_name)
  191. if not self.force and os.path.isfile(cache):
  192. data = open(cache).read().strip()
  193. if data == '1':
  194. return True
  195. elif data == '0':
  196. return False
  197. mkpath(self.build_temp)
  198. src = os.path.join(self.build_temp, 'check_%s.c' % ext.feature_name)
  199. open(src, 'w').write(ext.feature_check)
  200. log.info("checking if %s is compilable" % ext.feature_name)
  201. try:
  202. [obj] = self.compiler.compile([src],
  203. macros=ext.define_macros+[(undef,) for undef in ext.undef_macros],
  204. include_dirs=ext.include_dirs,
  205. extra_postargs=(ext.extra_compile_args or []),
  206. depends=ext.depends)
  207. except CompileError:
  208. log.warn("")
  209. log.warn("%s is not found or a compiler error: forcing --%s"
  210. % (ext.feature_name, ext.neg_option_name))
  211. log.warn("(if %s is installed correctly, you may need to"
  212. % ext.feature_name)
  213. log.warn(" specify the option --include-dirs or uncomment and")
  214. log.warn(" modify the parameter include_dirs in setup.cfg)")
  215. open(cache, 'w').write('0\n')
  216. return False
  217. prog = 'check_%s' % ext.feature_name
  218. log.info("checking if %s is linkable" % ext.feature_name)
  219. try:
  220. self.compiler.link_executable([obj], prog,
  221. output_dir=self.build_temp,
  222. libraries=ext.libraries,
  223. library_dirs=ext.library_dirs,
  224. runtime_library_dirs=ext.runtime_library_dirs,
  225. extra_postargs=(ext.extra_link_args or []))
  226. except LinkError:
  227. log.warn("")
  228. log.warn("%s is not found or a linker error: forcing --%s"
  229. % (ext.feature_name, ext.neg_option_name))
  230. log.warn("(if %s is installed correctly, you may need to"
  231. % ext.feature_name)
  232. log.warn(" specify the option --library-dirs or uncomment and")
  233. log.warn(" modify the parameter library_dirs in setup.cfg)")
  234. open(cache, 'w').write('0\n')
  235. return False
  236. open(cache, 'w').write('1\n')
  237. return True
  238. class bdist_rpm(_bdist_rpm):
  239. def _make_spec_file(self):
  240. argv0 = sys.argv[0]
  241. features = []
  242. for ext in self.distribution.ext_modules:
  243. if not isinstance(ext, Extension):
  244. continue
  245. with_ext = getattr(self.distribution, ext.attr_name)
  246. if with_ext is None:
  247. continue
  248. if with_ext:
  249. features.append('--'+ext.option_name)
  250. else:
  251. features.append('--'+ext.neg_option_name)
  252. sys.argv[0] = ' '.join([argv0]+features)
  253. spec_file = _bdist_rpm._make_spec_file(self)
  254. sys.argv[0] = argv0
  255. return spec_file
  256. class test(Command):
  257. user_options = []
  258. def initialize_options(self):
  259. pass
  260. def finalize_options(self):
  261. pass
  262. def run(self):
  263. build_cmd = self.get_finalized_command('build')
  264. build_cmd.run()
  265. sys.path.insert(0, build_cmd.build_lib)
  266. if sys.version_info[0] < 3:
  267. sys.path.insert(0, 'tests/lib')
  268. else:
  269. sys.path.insert(0, 'tests/lib3')
  270. import test_all
  271. test_all.main([])
  272. if __name__ == '__main__':
  273. setup(
  274. name=NAME,
  275. version=VERSION,
  276. description=DESCRIPTION,
  277. long_description=LONG_DESCRIPTION,
  278. author=AUTHOR,
  279. author_email=AUTHOR_EMAIL,
  280. license=LICENSE,
  281. platforms=PLATFORMS,
  282. url=URL,
  283. download_url=DOWNLOAD_URL,
  284. classifiers=CLASSIFIERS,
  285. package_dir={'': {2: 'lib', 3: 'lib3'}[sys.version_info[0]]},
  286. packages=['yaml'],
  287. ext_modules=[
  288. Extension('_yaml', ['ext/_yaml.pyx'],
  289. 'libyaml', "LibYAML bindings", LIBYAML_CHECK,
  290. libraries=['yaml']),
  291. ],
  292. distclass=Distribution,
  293. cmdclass={
  294. 'build_ext': build_ext,
  295. 'bdist_rpm': bdist_rpm,
  296. 'test': test,
  297. },
  298. )