blob: a41b166e0a59b918eaa0ce89656b97bf62cfb31e [file] [log] [blame]
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
===================
Command extenders
===================
Command extenders.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
__test__ = False
from distutils import fancy_getopt as _fancy_getopt
from distutils.command import build as _build
from distutils.command import build_ext as _build_ext
from distutils.command import install as _install
from distutils.command import install_data as _install_data
from distutils.command import install_lib as _install_lib
import os as _os
from _setup.util import log
_option_defaults = {}
_option_inherits = {}
_option_finalizers = {}
_command_mapping = {
'install': 'Install',
'install_data': 'InstallData',
'install_lib': 'InstallLib',
'build': 'Build',
'build_ext': 'BuildExt',
}
def add_option(command, long_name, help_text, short_name=None, default=None,
inherit=None):
""" Add an option """
try:
command_class = globals()[_command_mapping[command]]
except KeyError:
raise ValueError("Unknown command %r" % (command,))
for opt in command_class.user_options:
if opt[0] == long_name:
break
else:
opt = (long_name, short_name, help_text)
command_class.user_options.append(opt)
if not long_name.endswith('='):
command_class.boolean_options.append(long_name)
attr_name = _fancy_getopt.translate_longopt(long_name)
else:
attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
if not _option_defaults.has_key(command):
_option_defaults[command] = []
if inherit is not None:
if isinstance(inherit, (str, unicode)):
inherit = [inherit]
for i_inherit in inherit:
add_option(
i_inherit, long_name, help_text, short_name, default
)
default = None
if not _option_inherits.has_key(command):
_option_inherits[command] = []
for i_inherit in inherit:
for i_command, opt_name in _option_inherits[command]:
if i_command == i_inherit and opt_name == attr_name:
break
else:
_option_inherits[command].append((i_inherit, attr_name))
_option_defaults[command].append((attr_name, default))
def add_finalizer(command, key, func):
""" Add finalizer """
if not _option_finalizers.has_key(command):
_option_finalizers[command] = {}
if not _option_finalizers[command].has_key(key):
_option_finalizers[command][key] = func
class Install(_install.install):
""" Extended installer to reflect the additional data options """
user_options = _install.install.user_options + [
('single-version-externally-managed', None,
"Compat option. Does not a thing."),
]
boolean_options = _install.install.boolean_options + [
'single-version-externally-managed'
]
def initialize_options(self):
""" Prepare for new options """
_install.install.initialize_options(self)
self.single_version_externally_managed = None
if _option_defaults.has_key('install'):
for opt_name, default in _option_defaults['install']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install.install.finalize_options(self)
if _option_inherits.has_key('install'):
for parent, opt_name in _option_inherits['install']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('install'):
for func in _option_finalizers['install'].values():
func(self)
class InstallData(_install_data.install_data):
""" Extended data installer """
user_options = _install_data.install_data.user_options + []
boolean_options = _install_data.install_data.boolean_options + []
def initialize_options(self):
""" Prepare for new options """
_install_data.install_data.initialize_options(self)
if _option_defaults.has_key('install_data'):
for opt_name, default in _option_defaults['install_data']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install_data.install_data.finalize_options(self)
if _option_inherits.has_key('install_data'):
for parent, opt_name in _option_inherits['install_data']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('install_data'):
for func in _option_finalizers['install_data'].values():
func(self)
class InstallLib(_install_lib.install_lib):
""" Extended lib installer """
user_options = _install_lib.install_lib.user_options + []
boolean_options = _install_lib.install_lib.boolean_options + []
def initialize_options(self):
""" Prepare for new options """
_install_lib.install_lib.initialize_options(self)
if _option_defaults.has_key('install_lib'):
for opt_name, default in _option_defaults['install_lib']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install_lib.install_lib.finalize_options(self)
if _option_inherits.has_key('install_lib'):
for parent, opt_name in _option_inherits['install_lib']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('install_lib'):
for func in _option_finalizers['install_lib'].values():
func(self)
class BuildExt(_build_ext.build_ext):
"""
Extended extension builder class
This class allows extensions to provide a ``check_prerequisites`` method
which is called before actually building it. The method takes the
`BuildExt` instance and returns whether the extension should be skipped or
not.
"""
def initialize_options(self):
""" Prepare for new options """
_build_ext.build_ext.initialize_options(self)
if _option_defaults.has_key('build_ext'):
for opt_name, default in _option_defaults['build_ext']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_build_ext.build_ext.finalize_options(self)
if _option_inherits.has_key('build_ext'):
for parent, opt_name in _option_inherits['build_ext']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('build_ext'):
for func in _option_finalizers['build_ext'].values():
func(self)
def build_extension(self, ext):
"""
Build C extension - with extended functionality
The following features are added here:
- ``ext.check_prerequisites`` is called before the extension is being
built. See `Extension` for details. If the method does not exist,
simply no check will be run.
- The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
unset) depending on the extensions name, but only if they are not
already defined.
:Parameters:
`ext` : `Extension`
The extension to build. If it's a pure
``distutils.core.Extension``, simply no prequisites check is
applied.
:Return: whatever ``distutils.command.build_ext.build_ext`` returns
:Rtype: any
"""
# handle name macros
macros = dict(ext.define_macros or ())
tup = ext.name.split('.')
if len(tup) == 1:
pkg, mod = None, tup[0]
else:
pkg, mod = '.'.join(tup[:-1]), tup[-1]
if pkg is not None and 'EXT_PACKAGE' not in macros:
ext.define_macros.append(('EXT_PACKAGE', pkg))
if 'EXT_MODULE' not in macros:
ext.define_macros.append(('EXT_MODULE', mod))
if pkg is None:
macros = dict(ext.undef_macros or ())
if 'EXT_PACKAGE' not in macros:
ext.undef_macros.append('EXT_PACKAGE')
# handle prereq checks
try:
checker = ext.check_prerequisites
except AttributeError:
pass
else:
if checker(self):
log.info("Skipping %s extension" % ext.name)
return
return _build_ext.build_ext.build_extension(self, ext)
class Build(_build.build):
def initialize_options(self):
""" Prepare for new options """
_build.build.initialize_options(self)
if _option_defaults.has_key('build'):
for opt_name, default in _option_defaults['build']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_build.build.finalize_options(self)
if _option_inherits.has_key('build'):
for parent, opt_name in _option_inherits['build']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('build'):
for func in _option_finalizers['build'].values():
func(self)