#! /usr/bin/env python # coding: utf-8 from __future__ import print_function import sys import os import platform from textwrap import dedent name_space = 'ruamel' package_name = 'yaml' full_package_name = name_space + '.' + package_name exclude_files = [ 'setup.py', ] def get_version(): v_i = 'version_info = ' for line in open('py/__init__.py'): if not line.startswith(v_i): continue s_e = line[len(v_i):].strip()[1:-1].split(', ') els = [x.strip()[1:-1] if x[0] in '\'"' else int(x) for x in s_e] return els def _check_convert_version(tup): """create a PEP 386 pseudo-format conformant string from tuple tup""" ret_val = str(tup[0]) # first is always digit next_sep = "." # separator for next extension, can be "" or "." nr_digits = 0 # nr of adjacent digits in rest, to verify post_dev = False # are we processig post/dev for x in tup[1:]: if isinstance(x, int): nr_digits += 1 if nr_digits > 2: raise ValueError("too many consecutive digits " + ret_val) ret_val += next_sep + str(x) next_sep = '.' continue first_letter = x[0].lower() next_sep = '' if first_letter in 'abcr': if post_dev: raise ValueError("release level specified after " "post/dev:" + x) nr_digits = 0 ret_val += 'rc' if first_letter == 'r' else first_letter elif first_letter in 'pd': nr_digits = 1 # only one can follow post_dev = True ret_val += '.post' if first_letter == 'p' else '.dev' else: raise ValueError('First letter of "' + x + '" not recognised') return ret_val version_info = get_version() version_str = _check_convert_version(version_info) if __name__ == '__main__': # put here so setup.py can be imported more easily from setuptools import setup, find_packages, Extension, Distribution from setuptools.command import install_lib # windows things this is pure, that way you would get pure python # whl files that take precedence on Linux over source with compilable C if '--universal' in sys.argv: Distribution.is_pure = lambda *args: True Distribution.is_pure = lambda *args: False class MyInstallLib(install_lib.install_lib): "create __init__.py on the fly" def run(self): install_lib.install_lib.run(self) def install(self): fpp = full_package_name.split('.') # full package path full_exclude_files = [os.path.join(*(fpp + [x])) for x in exclude_files] alt_files = [] outfiles = install_lib.install_lib.install(self) for x in outfiles: for full_exclude_file in full_exclude_files: if full_exclude_file in x: os.remove(x) break else: alt_files.append(x) return alt_files def check_extensions(): """check if the C module can be build by trying to compile a small program against the libyaml development library""" if sys.platform == "win32": return None import tempfile import shutil import distutils.sysconfig import distutils.ccompiler from distutils.errors import CompileError, LinkError libraries = ['yaml'] # write a temporary .c file to compile c_code = dedent(""" #include int main(int argc, char* argv[]) { yaml_parser_t parser; parser = parser; /* prevent warning */ return 0; } """) tmp_dir = tempfile.mkdtemp(prefix='tmp_ruamel_yaml_') ret_val = None try: bin_file_name = os.path.join(tmp_dir, 'test_yaml') file_name = bin_file_name + '.c' with open(file_name, 'w') as fp: fp.write(c_code) # and try to compile it compiler = distutils.ccompiler.new_compiler() assert isinstance(compiler, distutils.ccompiler.CCompiler) distutils.sysconfig.customize_compiler(compiler) try: compiler.link_executable( compiler.compile([file_name]), bin_file_name, libraries=libraries, ) except CompileError: print('libyaml compile error') except LinkError: print('libyaml link error') else: ret_val = [ Extension( '_yaml', sources=['ext/_yaml.c'], libraries=libraries, ), ] except: pass finally: shutil.rmtree(tmp_dir) return ret_val def main(): install_requires = [ "ruamel.base", "ruamel.std.argparse>=0.5.1", ] # use fast ordereddict for !!omap if sys.version_info[0] == 2 and \ platform.python_implementation() == "CPython": install_requires.extend(['ruamel.ordereddict']) # if sys.version_info < (3, 4): # install_requires.append("") packages = [full_package_name] + [ (full_package_name + '.' + x) for x in find_packages('py', exclude=['test'])] setup( name=full_package_name, version=version_str, description=full_package_name + " is a YAML parser/emitter that " "supports roundtrip preservation of comments, seq/map flow style, and " "map key order", install_requires=install_requires, long_description=open('README.rst').read(), url='https://bitbucket.org/ruamel/' + package_name, author='Anthon van der Neut', author_email='a.van.der.neut@ruamel.eu', license="MIT license", package_dir={full_package_name: 'py'}, namespace_packages=[name_space], packages=packages, ext_modules=check_extensions(), entry_points=mk_entry_points(full_package_name), cmdclass={'install_lib': MyInstallLib}, classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup", ] ) def mk_entry_points(full_package_name): script_name = full_package_name.rsplit('.', 1)[-1] return {'console_scripts': [ '{0} = {1}:main'.format(script_name, full_package_name), ]} if __name__ == '__main__': if 'yamlctest' in sys.argv: print(check_extensions()) sys.exit(1) main()