summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/distutils/command/build_ext.py23
-rw-r--r--Lib/distutils/tests/test_build_ext.py128
-rw-r--r--Misc/NEWS3
3 files changed, 140 insertions, 14 deletions
diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py
index ade95be..d3668e9 100644
--- a/Lib/distutils/command/build_ext.py
+++ b/Lib/distutils/command/build_ext.py
@@ -329,7 +329,7 @@ class build_ext(Command):
self.compiler.set_include_dirs(self.include_dirs)
if self.define is not None:
# 'define' option is a list of (name,value) tuples
- for (name,value) in self.define:
+ for (name, value) in self.define:
self.compiler.define_macro(name, value)
if self.undef is not None:
for macro in self.undef:
@@ -365,22 +365,24 @@ class build_ext(Command):
continue # OK! (assume type-checking done
# by Extension constructor)
- (ext_name, build_info) = ext
- log.warn("old-style (ext_name, build_info) tuple found in "
- "ext_modules for extension '%s'"
- "-- please convert to Extension instance" % ext_name)
- if not isinstance(ext, tuple) and len(ext) != 2:
+ if not isinstance(ext, tuple) or len(ext) != 2:
raise DistutilsSetupError(
"each element of 'ext_modules' option must be an "
"Extension instance or 2-tuple")
+ ext_name, build_info = ext
+
+ log.warn(("old-style (ext_name, build_info) tuple found in "
+ "ext_modules for extension '%s'"
+ "-- please convert to Extension instance" % ext_name))
+
if not (isinstance(ext_name, str) and
extension_name_re.match(ext_name)):
raise DistutilsSetupError(
"first element of each tuple in 'ext_modules' "
"must be the extension name (a string)")
- if not instance(build_info, DictionaryType):
+ if not isinstance(build_info, dict):
raise DistutilsSetupError(
"second element of each tuple in 'ext_modules' "
"must be a dictionary (build info)")
@@ -391,11 +393,8 @@ class build_ext(Command):
# Easy stuff: one-to-one mapping from dict elements to
# instance attributes.
- for key in ('include_dirs',
- 'library_dirs',
- 'libraries',
- 'extra_objects',
- 'extra_compile_args',
+ for key in ('include_dirs', 'library_dirs', 'libraries',
+ 'extra_objects', 'extra_compile_args',
'extra_link_args'):
val = build_info.get(key)
if val is not None:
diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
index e4a0239..c22be2a 100644
--- a/Lib/distutils/tests/test_build_ext.py
+++ b/Lib/distutils/tests/test_build_ext.py
@@ -10,8 +10,8 @@ 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
-from distutils.errors import CompileError
+from distutils.errors import (UnknownFileError, DistutilsSetupError,
+ CompileError)
import unittest
from test import support
@@ -165,6 +165,130 @@ class BuildExtTestCase(TempdirManager,
cmd.ensure_finalized()
cmd.run() # should pass
+ def test_finalize_options(self):
+ # Make sure Python's include directories (for Python.h, pyconfig.h,
+ # etc.) are in the include search path.
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = build_ext(dist)
+ cmd.finalize_options()
+
+ from distutils import sysconfig
+ py_include = sysconfig.get_python_inc()
+ self.assert_(py_include in cmd.include_dirs)
+
+ plat_py_include = sysconfig.get_python_inc(plat_specific=1)
+ self.assert_(plat_py_include in cmd.include_dirs)
+
+ # make sure cmd.libraries is turned into a list
+ # if it's a string
+ cmd = build_ext(dist)
+ cmd.libraries = 'my_lib'
+ cmd.finalize_options()
+ self.assertEquals(cmd.libraries, ['my_lib'])
+
+ # make sure cmd.library_dirs is turned into a list
+ # if it's a string
+ cmd = build_ext(dist)
+ cmd.library_dirs = 'my_lib_dir'
+ cmd.finalize_options()
+ self.assertEquals(cmd.library_dirs, ['my_lib_dir'])
+
+ # make sure rpath is turned into a list
+ # if it's a list of os.pathsep's paths
+ cmd = build_ext(dist)
+ cmd.rpath = os.pathsep.join(['one', 'two'])
+ cmd.finalize_options()
+ self.assertEquals(cmd.rpath, ['one', 'two'])
+
+ # XXX more tests to perform for win32
+
+ # make sure define is turned into 2-tuples
+ # strings if they are ','-separated strings
+ cmd = build_ext(dist)
+ cmd.define = 'one,two'
+ cmd.finalize_options()
+ self.assertEquals(cmd.define, [('one', '1'), ('two', '1')])
+
+ # make sure undef is turned into a list of
+ # strings if they are ','-separated strings
+ cmd = build_ext(dist)
+ cmd.undef = 'one,two'
+ cmd.finalize_options()
+ self.assertEquals(cmd.undef, ['one', 'two'])
+
+ # make sure swig_opts is turned into a list
+ cmd = build_ext(dist)
+ cmd.swig_opts = None
+ cmd.finalize_options()
+ self.assertEquals(cmd.swig_opts, [])
+
+ cmd = build_ext(dist)
+ cmd.swig_opts = '1 2'
+ cmd.finalize_options()
+ self.assertEquals(cmd.swig_opts, ['1', '2'])
+
+ def test_check_extensions_list(self):
+ dist = Distribution()
+ cmd = build_ext(dist)
+ cmd.finalize_options()
+
+ #'extensions' option must be a list of Extension instances
+ self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, 'foo')
+
+ # each element of 'ext_modules' option must be an
+ # Extension instance or 2-tuple
+ exts = [('bar', 'foo', 'bar'), 'foo']
+ self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
+
+ # first element of each tuple in 'ext_modules'
+ # must be the extension name (a string) and match
+ # a python dotted-separated name
+ exts = [('foo-bar', '')]
+ self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
+
+ # second element of each tuple in 'ext_modules'
+ # must be a ary (build info)
+ exts = [('foo.bar', '')]
+ self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
+
+ # ok this one should pass
+ exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
+ 'some': 'bar'})]
+ cmd.check_extensions_list(exts)
+ ext = exts[0]
+ self.assert_(isinstance(ext, Extension))
+
+ # check_extensions_list adds in ext the values passed
+ # when they are in ('include_dirs', 'library_dirs', 'libraries'
+ # 'extra_objects', 'extra_compile_args', 'extra_link_args')
+ self.assertEquals(ext.libraries, 'foo')
+ self.assert_(not hasattr(ext, 'some'))
+
+ # 'macros' element of build info dict must be 1- or 2-tuple
+ exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
+ 'some': 'bar', 'macros': [('1', '2', '3'), 'foo']})]
+ self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
+
+ exts[0][1]['macros'] = [('1', '2'), ('3',)]
+ cmd.check_extensions_list(exts)
+ self.assertEquals(exts[0].undef_macros, ['3'])
+ self.assertEquals(exts[0].define_macros, [('1', '2')])
+
+ def test_get_source_files(self):
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = build_ext(dist)
+ cmd.ensure_finalized()
+ self.assertEquals(cmd.get_source_files(), ['xxx'])
+
+ def test_get_outputs(self):
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = build_ext(dist)
+ cmd.ensure_finalized()
+ self.assertEquals(len(cmd.get_outputs()), 1)
+
def test_suite():
src = _get_source_filename()
if not os.path.exists(src):
diff --git a/Misc/NEWS b/Misc/NEWS
index 7d5fc15..537434b 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -581,6 +581,9 @@ Core and Builtins
Library
-------
+- Issue #5984: distutils.command.build_ext.check_extensions_list checks were broken
+ for old-style extensions.
+
- Issue #5976: Fixed Distutils test_check_environ.
- Issue #5941: Distutils build_clib command was not working anymore because