| # Copyright (c) The PyAMF Project. |
| # See LICENSE.txt for details. |
| |
| """ |
| Meta data and helper functions for setup |
| """ |
| |
| import sys |
| import os.path |
| import fnmatch |
| |
| try: |
| from Cython.Distutils import build_ext |
| |
| have_cython = True |
| except ImportError: |
| from setuptools.command.build_ext import build_ext |
| |
| have_cython = False |
| |
| |
| if have_cython: |
| # may need to work around setuptools bug by providing a fake Pyrex |
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), "fake_pyrex")) |
| |
| |
| from setuptools.command import test, sdist |
| from setuptools import Extension |
| from distutils.core import Distribution |
| |
| |
| _version = None |
| |
| |
| |
| class MyDistribution(Distribution): |
| """ |
| This seems to be is the only obvious way to add a global option to |
| distutils. |
| |
| Provide the ability to disable building the extensions for any called |
| command. |
| """ |
| |
| global_options = Distribution.global_options + [ |
| ('disable-ext', None, 'Disable building extensions.') |
| ] |
| |
| def finalize_options(self): |
| Distribution.finalize_options(self) |
| |
| try: |
| i = self.script_args.index('--disable-ext') |
| except ValueError: |
| self.disable_ext = False |
| else: |
| self.disable_ext = True |
| self.script_args.pop(i) |
| |
| |
| class MyBuildExt(build_ext): |
| """ |
| The companion to L{MyDistribution} that checks to see if building the |
| extensions are disabled. |
| """ |
| |
| def build_extension(self, ext): |
| if self.distribution.disable_ext: |
| return |
| |
| return build_ext.build_extension(self, ext) |
| |
| def build_extensions(self): |
| if self.distribution.disable_ext: |
| return |
| |
| return build_ext.build_extensions(self) |
| |
| |
| class MySDist(sdist.sdist): |
| """ |
| We generate the Cython code for a source distribution |
| """ |
| |
| def cythonise(self): |
| ext = MyBuildExt(self.distribution) |
| ext.initialize_options() |
| ext.finalize_options() |
| |
| ext.check_extensions_list(ext.extensions) |
| |
| for e in ext.extensions: |
| e.sources = ext.cython_sources(e.sources, e) |
| |
| |
| def run(self): |
| if not have_cython: |
| print('ERROR - Cython is required to build source distributions') |
| |
| raise SystemExit(1) |
| |
| self.cythonise() |
| |
| return sdist.sdist.run(self) |
| |
| |
| class TestCommand(test.test): |
| """ |
| Ensures that unittest2 is imported if required and replaces the old |
| unittest module. |
| """ |
| |
| def run_tests(self): |
| try: |
| import unittest2 |
| |
| sys.modules['unittest'] = unittest2 |
| except ImportError: |
| pass |
| |
| return test.test.run_tests(self) |
| |
| |
| def set_version(version): |
| global _version |
| |
| _version = version |
| |
| |
| def get_version(): |
| v = '' |
| prev = None |
| |
| for x in _version: |
| if prev is not None: |
| if isinstance(x, int): |
| v += '.' |
| |
| prev = x |
| v += str(x) |
| |
| return v.strip('.') |
| |
| |
| def get_extras_require(): |
| return { |
| 'wsgi': ['wsgiref'], |
| 'twisted': ['Twisted>=2.5.0'], |
| 'django': ['Django>=0.96'], |
| 'sqlalchemy': ['SQLAlchemy>=0.4'], |
| 'elixir': ['Elixir>=0.7.1'], |
| 'lxml': ['lxml>=2.2'], |
| } |
| |
| |
| def get_package_data(): |
| return { |
| 'cpyamf': ['*.pxd'], |
| } |
| |
| |
| def extra_setup_args(): |
| """ |
| Extra kwargs to supply in the call to C{setup}. |
| |
| This is used to supply custom commands, not metadata - that should live in |
| setup.py itself. |
| """ |
| return { |
| 'distclass': MyDistribution, |
| 'cmdclass': { |
| 'test': TestCommand, |
| 'build_ext': MyBuildExt, |
| 'sdist': MySDist |
| }, |
| 'package_data': get_package_data(), |
| } |
| |
| |
| def get_install_requirements(): |
| """ |
| Returns a list of dependencies for PyAMF to function correctly on the |
| target platform. |
| """ |
| install_requires = [] |
| |
| if sys.version_info < (2, 5): |
| install_requires.extend(["elementtree>=1.2.6", "uuid>=1.30"]) |
| |
| if 'dev' in get_version(): |
| install_requires.extend(['Cython>=0.13']) |
| |
| return install_requires |
| |
| |
| def get_test_requirements(): |
| """ |
| Returns a list of required packages to run the test suite. |
| """ |
| tests_require = [] |
| |
| if sys.version_info < (2, 7): |
| tests_require.extend(['unittest2', 'pysqlite']) |
| |
| return tests_require |
| |
| |
| def write_version_py(filename='pyamf/_version.py'): |
| """ |
| """ |
| if os.path.exists(filename): |
| os.remove(filename) |
| |
| content = """\ |
| # THIS FILE IS GENERATED BY PYAMF SETUP.PY |
| from pyamf.versions import Version |
| |
| version = Version(*%(version)r) |
| """ |
| a = open(filename, 'wt') |
| |
| try: |
| a.write(content % {'version': _version}) |
| finally: |
| a.close() |
| |
| |
| def make_extension(mod_name, **extra_options): |
| """ |
| Tries is best to return an Extension instance based on the mod_name |
| """ |
| base_name = os.path.join(mod_name.replace('.', os.path.sep)) |
| |
| if have_cython: |
| for ext in ['.pyx', '.py']: |
| source = base_name + ext |
| |
| if os.path.exists(source): |
| return Extension(mod_name, [source], **extra_options) |
| |
| print('WARNING: Could not find Cython source for %r' % (mod_name,)) |
| else: |
| source = base_name + '.c' |
| |
| if os.path.exists(source): |
| return Extension(mod_name, [source], **extra_options) |
| |
| print('WARNING: Could not build extension for %r, no source found' % ( |
| mod_name,)) |
| |
| |
| def read(fname): |
| return open(os.path.join(os.path.dirname(__file__), fname)).read() |
| |
| |
| def get_extensions(): |
| """ |
| Return a list of Extension instances that can be compiled. |
| """ |
| if sys.platform.startswith('java'): |
| print(80 * '*') |
| print('WARNING:') |
| print('\tAn optional code optimization (C extension) could not be compiled.\n\n') |
| print('\tOptimizations for this package will not be available!\n\n') |
| print('Compiling extensions is not supported on Jython') |
| print(80 * '*') |
| |
| return [] |
| |
| extensions = [] |
| |
| for p in recursive_glob('.', '*.pyx'): |
| mod_name = os.path.splitext(p)[0].replace(os.path.sep, '.') |
| |
| e = make_extension(mod_name) |
| |
| if e: |
| extensions.append(e) |
| |
| return extensions |
| |
| |
| def get_trove_classifiers(): |
| """ |
| Return a list of trove classifiers that are setup dependent. |
| """ |
| classifiers = [] |
| |
| def dev_status(): |
| version = get_version() |
| |
| if 'dev' in version: |
| return 'Development Status :: 2 - Pre-Alpha' |
| elif 'alpha' in version: |
| return 'Development Status :: 3 - Alpha' |
| elif 'beta' in version: |
| return 'Development Status :: 4 - Beta' |
| else: |
| return 'Development Status :: 5 - Production/Stable' |
| |
| return classifiers + [dev_status()] |
| |
| |
| def recursive_glob(path, pattern): |
| matches = [] |
| |
| for root, dirnames, filenames in os.walk(path): |
| for filename in fnmatch.filter(filenames, pattern): |
| matches.append(os.path.normpath(os.path.join(root, filename))) |
| |
| return matches |