1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
import sys
from setuptools import setup as _setup
py3_args = ['use_2to3', 'convert_2to3_doctests', 'use_2to3_fixers', 'test_dirs', 'test_build_dir', 'doctest_exts', 'pyversion_patching']
if sys.version_info < (3,):
# Remove any Python-3.x-only arguments (so they don't generate complaints
# from 2.x setuptools) and then just pass through to the regular setup
# routine.
def setup(*args, **kwargs):
for a in py3_args:
if a in kwargs:
del kwargs[a]
return _setup(*args, **kwargs)
else:
import os
import re
import logging
from setuptools import Distribution as _Distribution
from distutils.core import Command
from setuptools.command.build_py import Mixin2to3
from distutils import dir_util, file_util, log
import setuptools.command.test
from pkg_resources import normalize_path
try:
import patch
patch.logger.setLevel(logging.WARN)
except ImportError:
patch = None
patchfile_re = re.compile(r'(.*)\.py([0-9.]+)\.patch$')
def pyversion_patch(filename):
'''Find the best pyversion-fixup patch for a given filename and apply
it.
'''
dir, file = os.path.split(filename)
best_ver = (0,)
patchfile = None
for dirfile in os.listdir(dir):
m = patchfile_re.match(dirfile)
if not m:
continue
base, ver = m.groups()
if base != file:
continue
ver = tuple([int(v) for v in ver.split('.')])
if sys.version_info >= ver and ver > best_ver:
best_ver = ver
patchfile = dirfile
if not patchfile:
return False
log.info("Applying %s to %s..." % (patchfile, filename))
cwd = os.getcwd()
os.chdir(dir)
try:
p = patch.fromfile(patchfile)
p.apply()
finally:
os.chdir(cwd)
return True
class Distribution (_Distribution):
def __init__(self, attrs=None):
self.test_dirs = []
self.test_build_dir = None
self.doctest_exts = ['.py', '.rst']
self.pyversion_patching = False
_Distribution.__init__(self, attrs)
class BuildTestsCommand (Command, Mixin2to3):
# Create mirror copy of tests, convert all .py files using 2to3
user_options = []
def initialize_options(self):
self.test_base = None
def finalize_options(self):
test_base = self.distribution.test_build_dir
if not test_base:
bcmd = self.get_finalized_command('build')
test_base = bcmd.build_base
self.test_base = test_base
def run(self):
use_2to3 = getattr(self.distribution, 'use_2to3', False)
test_dirs = getattr(self.distribution, 'test_dirs', [])
test_base = self.test_base
bpy_cmd = self.get_finalized_command("build_py")
lib_base = normalize_path(bpy_cmd.build_lib)
modified = []
py_modified = []
doc_modified = []
dir_util.mkpath(test_base)
for testdir in test_dirs:
for srcdir, dirnames, filenames in os.walk(testdir):
destdir = os.path.join(test_base, srcdir)
dir_util.mkpath(destdir)
for fn in filenames:
if fn.startswith("."):
# Skip .svn folders and such
continue
dstfile, copied = file_util.copy_file(
os.path.join(srcdir, fn),
os.path.join(destdir, fn),
update=True)
if copied:
modified.append(dstfile)
if fn.endswith('.py'):
py_modified.append(dstfile)
for ext in self.distribution.doctest_exts:
if fn.endswith(ext):
doc_modified.append(dstfile)
break
if use_2to3:
self.run_2to3(py_modified)
self.run_2to3(doc_modified, True)
if self.distribution.pyversion_patching:
if patch is not None:
for file in modified:
pyversion_patch(file)
else:
log.warn("Warning: pyversion_patching specified in setup config but patch module not found. Patching will not be performed.")
dir_util.mkpath(lib_base)
self.reinitialize_command('egg_info', egg_base=lib_base)
self.run_command('egg_info')
class TestCommand (setuptools.command.test.test):
# Override 'test' command to make sure 'build_tests' gets run first.
def run(self):
self.run_command('build_tests')
setuptools.command.test.test.run(self)
def setup(*args, **kwargs):
kwargs.setdefault('distclass', Distribution)
cmdclass = kwargs.setdefault('cmdclass', {})
cmdclass.setdefault('build_tests', BuildTestsCommand)
cmdclass.setdefault('test', TestCommand)
return _setup(*args, **kwargs)
|