Commit dc71622b authored by Tarek Ziadé's avatar Tarek Ziadé

Merged revisions 72531 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r72531 | tarek.ziade | 2009-05-10 12:12:08 +0200 (Sun, 10 May 2009) | 1 line

  fixed #5984 and improved test coverage
........
parent 3967ecc4
...@@ -128,7 +128,7 @@ class build_ext (Command): ...@@ -128,7 +128,7 @@ class build_ext (Command):
self.swig_opts = None self.swig_opts = None
self.user = None self.user = None
def finalize_options (self): def finalize_options(self):
from distutils import sysconfig from distutils import sysconfig
self.set_undefined_options('build', self.set_undefined_options('build',
...@@ -145,15 +145,14 @@ class build_ext (Command): ...@@ -145,15 +145,14 @@ class build_ext (Command):
self.extensions = self.distribution.ext_modules self.extensions = self.distribution.ext_modules
# Make sure Python's include directories (for Python.h, pyconfig.h, # Make sure Python's include directories (for Python.h, pyconfig.h,
# etc.) are in the include search path. # etc.) are in the include search path.
py_include = sysconfig.get_python_inc() py_include = sysconfig.get_python_inc()
plat_py_include = sysconfig.get_python_inc(plat_specific=1) plat_py_include = sysconfig.get_python_inc(plat_specific=1)
if self.include_dirs is None: if self.include_dirs is None:
self.include_dirs = self.distribution.include_dirs or [] self.include_dirs = self.distribution.include_dirs or []
if type(self.include_dirs) is StringType: if isinstance(self.include_dirs, str):
self.include_dirs = string.split(self.include_dirs, os.pathsep) self.include_dirs = self.include_dirs.split(os.pathsep)
# Put the Python "system" include dir at the end, so that # Put the Python "system" include dir at the end, so that
# any local include dirs take precedence. # any local include dirs take precedence.
...@@ -161,7 +160,7 @@ class build_ext (Command): ...@@ -161,7 +160,7 @@ class build_ext (Command):
if plat_py_include != py_include: if plat_py_include != py_include:
self.include_dirs.append(plat_py_include) self.include_dirs.append(plat_py_include)
if type(self.libraries) is StringType: if isinstance(self.libraries, str):
self.libraries = [self.libraries] self.libraries = [self.libraries]
# Life is easier if we're not forever checking for None, so # Life is easier if we're not forever checking for None, so
...@@ -252,14 +251,14 @@ class build_ext (Command): ...@@ -252,14 +251,14 @@ class build_ext (Command):
# symbols can be separated with commas. # symbols can be separated with commas.
if self.define: if self.define:
defines = string.split(self.define, ',') defines = self.define.split(',')
self.define = map(lambda symbol: (symbol, '1'), defines) self.define = map(lambda symbol: (symbol, '1'), defines)
# The option for macros to undefine is also a string from the # The option for macros to undefine is also a string from the
# option parsing, but has to be a list. Multiple symbols can also # option parsing, but has to be a list. Multiple symbols can also
# be separated with commas here. # be separated with commas here.
if self.undef: if self.undef:
self.undef = string.split(self.undef, ',') self.undef = self.undef.split(',')
if self.swig_opts is None: if self.swig_opts is None:
self.swig_opts = [] self.swig_opts = []
...@@ -276,11 +275,7 @@ class build_ext (Command): ...@@ -276,11 +275,7 @@ class build_ext (Command):
self.library_dirs.append(user_lib) self.library_dirs.append(user_lib)
self.rpath.append(user_lib) self.rpath.append(user_lib)
# finalize_options () def run(self):
def run (self):
from distutils.ccompiler import new_compiler from distutils.ccompiler import new_compiler
# 'self.extensions', as supplied by setup.py, is a list of # 'self.extensions', as supplied by setup.py, is a list of
...@@ -327,7 +322,7 @@ class build_ext (Command): ...@@ -327,7 +322,7 @@ class build_ext (Command):
self.compiler.set_include_dirs(self.include_dirs) self.compiler.set_include_dirs(self.include_dirs)
if self.define is not None: if self.define is not None:
# 'define' option is a list of (name,value) tuples # '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) self.compiler.define_macro(name, value)
if self.undef is not None: if self.undef is not None:
for macro in self.undef: for macro in self.undef:
...@@ -344,10 +339,7 @@ class build_ext (Command): ...@@ -344,10 +339,7 @@ class build_ext (Command):
# Now actually compile and link everything. # Now actually compile and link everything.
self.build_extensions() self.build_extensions()
# run () def check_extensions_list(self, extensions):
def check_extensions_list (self, extensions):
"""Ensure that the list of extensions (presumably provided as a """Ensure that the list of extensions (presumably provided as a
command option 'extensions') is valid, i.e. it is a list of command option 'extensions') is valid, i.e. it is a list of
Extension objects. We also support the old-style list of 2-tuples, Extension objects. We also support the old-style list of 2-tuples,
...@@ -357,32 +349,33 @@ class build_ext (Command): ...@@ -357,32 +349,33 @@ class build_ext (Command):
Raise DistutilsSetupError if the structure is invalid anywhere; Raise DistutilsSetupError if the structure is invalid anywhere;
just returns otherwise. just returns otherwise.
""" """
if type(extensions) is not ListType: if not isinstance(extensions, list):
raise DistutilsSetupError, \ raise DistutilsSetupError, \
"'ext_modules' option must be a list of Extension instances" "'ext_modules' option must be a list of Extension instances"
for i in range(len(extensions)): for i, ext in enumerate(extensions):
ext = extensions[i]
if isinstance(ext, Extension): if isinstance(ext, Extension):
continue # OK! (assume type-checking done continue # OK! (assume type-checking done
# by Extension constructor) # by Extension constructor)
(ext_name, build_info) = ext if not isinstance(ext, tuple) or len(ext) != 2:
log.warn(("old-style (ext_name, build_info) tuple found in "
"ext_modules for extension '%s'"
"-- please convert to Extension instance" % ext_name))
if type(ext) is not TupleType and len(ext) != 2:
raise DistutilsSetupError, \ raise DistutilsSetupError, \
("each element of 'ext_modules' option must be an " ("each element of 'ext_modules' option must be an "
"Extension instance or 2-tuple") "Extension instance or 2-tuple")
if not (type(ext_name) is StringType and 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)): extension_name_re.match(ext_name)):
raise DistutilsSetupError, \ raise DistutilsSetupError, \
("first element of each tuple in 'ext_modules' " ("first element of each tuple in 'ext_modules' "
"must be the extension name (a string)") "must be the extension name (a string)")
if type(build_info) is not DictionaryType: if not isinstance(build_info, dict):
raise DistutilsSetupError, \ raise DistutilsSetupError, \
("second element of each tuple in 'ext_modules' " ("second element of each tuple in 'ext_modules' "
"must be a dictionary (build info)") "must be a dictionary (build info)")
...@@ -393,11 +386,8 @@ class build_ext (Command): ...@@ -393,11 +386,8 @@ class build_ext (Command):
# Easy stuff: one-to-one mapping from dict elements to # Easy stuff: one-to-one mapping from dict elements to
# instance attributes. # instance attributes.
for key in ('include_dirs', for key in ('include_dirs', 'library_dirs', 'libraries',
'library_dirs', 'extra_objects', 'extra_compile_args',
'libraries',
'extra_objects',
'extra_compile_args',
'extra_link_args'): 'extra_link_args'):
val = build_info.get(key) val = build_info.get(key)
if val is not None: if val is not None:
...@@ -416,8 +406,7 @@ class build_ext (Command): ...@@ -416,8 +406,7 @@ class build_ext (Command):
ext.define_macros = [] ext.define_macros = []
ext.undef_macros = [] ext.undef_macros = []
for macro in macros: for macro in macros:
if not (type(macro) is TupleType and if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
1 <= len(macro) <= 2):
raise DistutilsSetupError, \ raise DistutilsSetupError, \
("'macros' element of build info dict " ("'macros' element of build info dict "
"must be 1- or 2-tuple") "must be 1- or 2-tuple")
...@@ -428,12 +417,7 @@ class build_ext (Command): ...@@ -428,12 +417,7 @@ class build_ext (Command):
extensions[i] = ext extensions[i] = ext
# for extensions def get_source_files(self):
# check_extensions_list ()
def get_source_files (self):
self.check_extensions_list(self.extensions) self.check_extensions_list(self.extensions)
filenames = [] filenames = []
...@@ -443,9 +427,7 @@ class build_ext (Command): ...@@ -443,9 +427,7 @@ class build_ext (Command):
return filenames return filenames
def get_outputs(self):
def get_outputs (self):
# Sanity check the 'extensions' list -- can't assume this is being # Sanity check the 'extensions' list -- can't assume this is being
# done in the same run as a 'build_extensions()' call (in fact, we # done in the same run as a 'build_extensions()' call (in fact, we
# can probably assume that it *isn't*!). # can probably assume that it *isn't*!).
...@@ -461,8 +443,6 @@ class build_ext (Command): ...@@ -461,8 +443,6 @@ class build_ext (Command):
self.get_ext_filename(fullname))) self.get_ext_filename(fullname)))
return outputs return outputs
# get_outputs ()
def build_extensions(self): def build_extensions(self):
# First, sanity-check the 'extensions' list # First, sanity-check the 'extensions' list
self.check_extensions_list(self.extensions) self.check_extensions_list(self.extensions)
......
...@@ -7,6 +7,8 @@ from StringIO import StringIO ...@@ -7,6 +7,8 @@ from StringIO import StringIO
from distutils.core import Extension, Distribution from distutils.core import Extension, Distribution
from distutils.command.build_ext import build_ext from distutils.command.build_ext import build_ext
from distutils import sysconfig from distutils import sysconfig
from distutils.tests import support
from distutils.errors import DistutilsSetupError
import unittest import unittest
from test import test_support from test import test_support
...@@ -15,10 +17,13 @@ from test import test_support ...@@ -15,10 +17,13 @@ from test import test_support
# Don't load the xx module more than once. # Don't load the xx module more than once.
ALREADY_TESTED = False ALREADY_TESTED = False
class BuildExtTestCase(unittest.TestCase): class BuildExtTestCase(support.TempdirManager,
support.LoggingSilencer,
unittest.TestCase):
def setUp(self): def setUp(self):
# Create a simple test environment # Create a simple test environment
# Note that we're making changes to sys.path # Note that we're making changes to sys.path
super(BuildExtTestCase, self).setUp()
self.tmp_dir = tempfile.mkdtemp(prefix="pythontest_") self.tmp_dir = tempfile.mkdtemp(prefix="pythontest_")
self.sys_path = sys.path[:] self.sys_path = sys.path[:]
sys.path.append(self.tmp_dir) sys.path.append(self.tmp_dir)
...@@ -74,6 +79,7 @@ class BuildExtTestCase(unittest.TestCase): ...@@ -74,6 +79,7 @@ class BuildExtTestCase(unittest.TestCase):
sys.path = self.sys_path sys.path = self.sys_path
# XXX on Windows the test leaves a directory with xx module in TEMP # XXX on Windows the test leaves a directory with xx module in TEMP
shutil.rmtree(self.tmp_dir, os.name == 'nt' or sys.platform == 'cygwin') shutil.rmtree(self.tmp_dir, os.name == 'nt' or sys.platform == 'cygwin')
super(BuildExtTestCase, self).tearDown()
def test_solaris_enable_shared(self): def test_solaris_enable_shared(self):
dist = Distribution({'name': 'xx'}) dist = Distribution({'name': 'xx'})
...@@ -96,6 +102,130 @@ class BuildExtTestCase(unittest.TestCase): ...@@ -96,6 +102,130 @@ class BuildExtTestCase(unittest.TestCase):
# make sur we get some lobrary dirs under solaris # make sur we get some lobrary dirs under solaris
self.assert_(len(cmd.library_dirs) > 0) self.assert_(len(cmd.library_dirs) > 0)
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'])]
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'])]
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'])]
dist = Distribution({'name': 'xx', 'ext_modules': modules})
cmd = build_ext(dist)
cmd.ensure_finalized()
self.assertEquals(len(cmd.get_outputs()), 1)
def test_suite(): def test_suite():
if not sysconfig.python_build: if not sysconfig.python_build:
if test_support.verbose: if test_support.verbose:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment