/usr/lib/python3/dist-packages/stsci/distutils/command/build_optional_ext.py is in python3-stsci.distutils 0.3.7-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | from distutils import log
from distutils.command.build_ext import build_ext
from distutils.errors import DistutilsError, CCompilerError, CompileError
from distutils.util import strtobool
from configparser import ConfigParser
class build_optional_ext(build_ext):
"""This is a version of the build_ext command that allows specific
extensions to be marked as 'optional'. If an optional extension fails to
build, a warning message is displayed but the build does not cancel.
It should be noted that this functionality already exists in the Python3
versions of distutils and packaging, but we must provide backwards
compatibility for it.
"""
command_name = 'build_ext'
def _find_optional_extensions(self, extensions):
"""Reads the setup.cfg to determine which extensions were set as
'optional'. Optionally, developers may also provide a warning message
to display (otherwise a default message is used). This is one way in
which this command improves on the existing functionality on Python 3.
"""
# TODO: However, support for the 'optional' extension attribute should
# be included in d2to1, since it's a legitimate backwards compatibility
# issue. But until I do another release it will have to be supported
# here.
cfg = ConfigParser()
try:
cfg.read('setup.cfg')
except Exception as e:
log.warn('Failed to read setup.cfg: %s; proceeding as though '
'there are no optional extensions' % e)
return
# Map extension names to extension objects
extensions = dict((ext.name, ext) for ext in extensions)
for section in cfg.sections():
if not section.startswith('extension='):
continue
# The extension name can be specified with the 'name' option, but
# if that's missing the name is taken from the section header for
# now
if cfg.has_option(section, 'name'):
name = cfg.get(section, 'name')
else:
_, name = section.split('=', 1)
if name not in extensions:
# Could happen, for example, if a setup_hook disabled some
# extensions
continue
ext = extensions[name]
if cfg.has_option(section, 'optional'):
ext._optional = strtobool(cfg.get(section, 'optional'))
else:
ext._optional = False
if cfg.has_option(section, 'fail_message'):
ext._fail_message = cfg.get(section, 'fail_message')
def check_extensions_list(self, extensions):
build_ext.check_extensions_list(self, extensions)
self._find_optional_extensions(extensions)
def build_extension(self, ext):
try:
build_ext.build_extension(self, ext)
except (CCompilerError, DistutilsError, CompileError) as e:
if not hasattr(ext, '_optional') or not ext._optional:
raise
log.warn('building optional extension "%s" failed: %s' %
(ext.name, e))
if hasattr(ext, '_fail_message'):
log.warn(ext._fail_message)
|