From b2e36f1df7cbc06134464bfcc1e48936e80e91fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarek=20Ziad=C3=A9?= Date: Tue, 31 Mar 2009 22:37:55 +0000 Subject: [PATCH] Merged revisions 70910 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r70910 | tarek.ziade | 2009-03-31 17:27:23 -0500 (Tue, 31 Mar 2009) | 1 line #5583 Added optional Extensions in Distutils ........ --- Doc/distutils/setupscript.rst | 4 ++++ Lib/distutils/command/build_ext.py | 8 +++++++- Lib/distutils/extension.py | 5 +++++ Lib/distutils/tests/test_build_ext.py | 23 ++++++++++++++++++++++- Misc/NEWS | 3 +++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst index 2e5d8c17a73..85089d092dd 100644 --- a/Doc/distutils/setupscript.rst +++ b/Doc/distutils/setupscript.rst @@ -334,6 +334,10 @@ Other options There are still some other options which can be used to handle special cases. +The :option:`optional` option is a boolean; if it is true, that specifies that +a build failure in the extension should not abort the build process, but simply +not install the failing extension. + The :option:`extra_objects` option is a list of object files to be passed to the linker. These files must not have extensions, as the default extension for the compiler is used. diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 1ed69f33c04..229590664c9 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -455,7 +455,13 @@ class build_ext(Command): self.check_extensions_list(self.extensions) for ext in self.extensions: - self.build_extension(ext) + try: + self.build_extension(ext) + except (CCompilerError, DistutilsError) as e: + if not ext.optional: + raise + self.warn('building extension "%s" failed: %s' % + (ext.name, e)) def build_extension(self, ext): sources = ext.sources diff --git a/Lib/distutils/extension.py b/Lib/distutils/extension.py index b271816844d..f7e7b4edc91 100644 --- a/Lib/distutils/extension.py +++ b/Lib/distutils/extension.py @@ -82,6 +82,9 @@ class Extension: language : string extension language (i.e. "c", "c++", "objc"). Will be detected from the source extensions if not provided. + optional : boolean + specifies that a build failure in the extension should not abort the + build process, but simply not install the failing extension. """ # When adding arguments to this constructor, be sure to update @@ -100,6 +103,7 @@ class Extension: swig_opts = None, depends=None, language=None, + optional=None, **kw # To catch unknown keywords ): assert isinstance(name, str), "'name' must be a string" @@ -122,6 +126,7 @@ class Extension: self.swig_opts = swig_opts or [] self.depends = depends or [] self.language = language + self.optional = optional # If there are unknown keyword options, warn about them if len(kw): diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py index 2e47953ee31..094f4b6644c 100644 --- a/Lib/distutils/tests/test_build_ext.py +++ b/Lib/distutils/tests/test_build_ext.py @@ -8,6 +8,9 @@ from distutils.core import Extension, Distribution from distutils.command.build_ext import build_ext from distutils import sysconfig from distutils.tests.support import TempdirManager +from distutils.tests.support import LoggingSilencer +from distutils.extension import Extension +from distutils.errors import UnknownFileError import unittest from test import support @@ -20,7 +23,9 @@ def _get_source_filename(): srcdir = sysconfig.get_config_var('srcdir') return os.path.join(srcdir, 'Modules', 'xxmodule.c') -class BuildExtTestCase(TempdirManager, unittest.TestCase): +class BuildExtTestCase(TempdirManager, + LoggingSilencer, + unittest.TestCase): def setUp(self): # Create a simple test environment # Note that we're making changes to sys.path @@ -141,6 +146,22 @@ class BuildExtTestCase(TempdirManager, unittest.TestCase): self.assert_(lib in cmd.library_dirs) self.assert_(incl in cmd.include_dirs) + def test_optional_extension(self): + + # this extension will fail, but let's ignore this failure + # with the optional argument. + modules = [Extension('foo', ['xxx'], optional=False)] + dist = Distribution({'name': 'xx', 'ext_modules': modules}) + cmd = build_ext(dist) + cmd.ensure_finalized() + self.assertRaises(UnknownFileError, cmd.run) # should raise an error + + modules = [Extension('foo', ['xxx'], optional=True)] + dist = Distribution({'name': 'xx', 'ext_modules': modules}) + cmd = build_ext(dist) + cmd.ensure_finalized() + cmd.run() # should pass + def test_suite(): src = _get_source_filename() if not os.path.exists(src): diff --git a/Misc/NEWS b/Misc/NEWS index 916a2c9926c..78adb643225 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -282,6 +282,9 @@ Core and Builtins Library ------- +- Issue #5583: Added optional Extensions in Distutils. Initial patch by Georg + Brandl. + - Issue #1222: locale.format() bug when the thousands separator is a space character.