173 lines
5.5 KiB
Python
173 lines
5.5 KiB
Python
#!/usr/bin/env python
|
|
import os
|
|
from os import listdir
|
|
import os.path
|
|
from os.path import exists, isdir, isfile, join, splitext
|
|
import sys
|
|
import types
|
|
import glob
|
|
import string
|
|
import traceback
|
|
|
|
from distutils.core import setup
|
|
if not os.getenv('CHEETAH_INSTALL_WITHOUT_SETUPTOOLS'):
|
|
try:
|
|
from setuptools import setup
|
|
except ImportError:
|
|
from distutils.core import setup
|
|
|
|
from distutils.core import Command
|
|
from distutils.command.build_ext import build_ext
|
|
from distutils.command.install_data import install_data
|
|
from distutils.errors import CCompilerError, DistutilsExecError, \
|
|
DistutilsPlatformError
|
|
|
|
#imports from Cheetah ...
|
|
from cheetah.FileUtils import findFiles
|
|
|
|
if sys.platform == 'win32' and sys.version_info > (2, 6):
|
|
# 2.6's distutils.msvc9compiler can raise an IOError when failing to
|
|
# find the compiler
|
|
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError,
|
|
IOError)
|
|
else:
|
|
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
|
|
|
|
##################################################
|
|
## CLASSES ##
|
|
|
|
class BuildFailed(Exception):
|
|
pass
|
|
|
|
class mod_build_ext(build_ext):
|
|
"""A modified version of the distutils build_ext command that raises an
|
|
exception when building of the extension fails.
|
|
"""
|
|
|
|
def run(self):
|
|
try:
|
|
build_ext.run(self)
|
|
except DistutilsPlatformError, x:
|
|
raise BuildFailed(x)
|
|
|
|
def build_extension(self, ext):
|
|
try:
|
|
build_ext.build_extension(self, ext)
|
|
except ext_errors, x:
|
|
raise BuildFailed(x)
|
|
|
|
|
|
class mod_install_data(install_data):
|
|
"""A modified version of the disutils install_data command that allows data
|
|
files to be included directly in the installed Python package tree.
|
|
"""
|
|
|
|
def finalize_options(self):
|
|
|
|
if self.install_dir is None:
|
|
installobj = self.distribution.get_command_obj('install')
|
|
#self.install_dir = installobj.install_platlib
|
|
self.install_dir = installobj.install_lib
|
|
install_data.finalize_options(self)
|
|
|
|
def run (self):
|
|
|
|
if not self.dry_run:
|
|
self.mkpath(self.install_dir)
|
|
data_files = self.get_inputs()
|
|
|
|
for entry in data_files:
|
|
if not isinstance(entry, basestring):
|
|
raise ValueError('The entries in "data_files" must be strings')
|
|
|
|
entry = string.join(string.split(entry, '/'), os.sep)
|
|
# entry is a filename or glob pattern
|
|
if entry.startswith('recursive:'):
|
|
entry = entry[len('recursive:'):]
|
|
dir = entry.split()[0]
|
|
globPatterns = entry.split()[1:]
|
|
filenames = findFiles(dir, globPatterns)
|
|
else:
|
|
filenames = glob.glob(entry)
|
|
|
|
for filename in filenames:
|
|
## generate the dstPath from the filename
|
|
# - deal with 'package_dir' translations
|
|
topDir, subPath = (filename.split(os.sep)[0],
|
|
os.sep.join( filename.split(os.sep)[1:] )
|
|
)
|
|
|
|
package_dirDict = self.distribution.package_dir
|
|
if package_dirDict:
|
|
packageDir = topDir
|
|
for key, val in package_dirDict.items():
|
|
if val == topDir:
|
|
packageDir = key
|
|
break
|
|
else:
|
|
packageDir = topDir
|
|
dstPath = os.path.join(self.install_dir, packageDir, subPath)
|
|
|
|
## add the file to the list of outfiles
|
|
dstdir = os.path.split(dstPath)[0]
|
|
if not self.dry_run:
|
|
self.mkpath(dstdir)
|
|
outfile = self.copy_file(filename, dstPath)[0]
|
|
else:
|
|
outfile = dstPath
|
|
self.outfiles.append(outfile)
|
|
|
|
##################################################
|
|
## FUNCTIONS ##
|
|
|
|
def run_setup(configurations):
|
|
""" Run distutils setup.
|
|
|
|
The parameters passed to setup() are extracted from the list of modules,
|
|
classes or instances given in configurations.
|
|
|
|
Names with leading underscore are removed from the parameters.
|
|
Parameters which are not strings, lists, tuples, or dicts are removed as
|
|
well. Configurations which occur later in the configurations list
|
|
override settings of configurations earlier in the list.
|
|
|
|
"""
|
|
# Build parameter dictionary
|
|
kws = {}
|
|
newkws = {}
|
|
for configuration in configurations:
|
|
kws.update(vars(configuration))
|
|
for name, value in kws.items():
|
|
if name[:1] == '_':
|
|
continue
|
|
if not isinstance(value, (basestring, list, tuple, dict, int)):
|
|
continue
|
|
newkws[name] = value
|
|
kws = newkws
|
|
|
|
# Add setup extensions
|
|
cmdclasses = {
|
|
'build_ext': mod_build_ext,
|
|
'install_data': mod_install_data,
|
|
}
|
|
|
|
kws['cmdclass'] = cmdclasses
|
|
|
|
# Invoke distutils setup
|
|
try:
|
|
setup(**kws)
|
|
except BuildFailed, x:
|
|
print("One or more C extensions failed to build.")
|
|
print("Details: %s" % x)
|
|
if os.environ.get('CHEETAH_C_EXTENSIONS_REQUIRED'):
|
|
raise x
|
|
print("Retrying without C extensions enabled.")
|
|
|
|
del kws['ext_modules']
|
|
setup(**kws)
|
|
|
|
print("One or more C extensions failed to build.")
|
|
print("Performance enhancements will not be available.")
|
|
print("Pure Python installation succeeded.")
|
|
|