diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2014-03-05 14:31:49 -0700 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2014-03-05 14:31:49 -0700 |
commit | 94a1c20e8153a92ae51f5915468fcff266ab497b (patch) | |
tree | 49579f4f93a6cb20f3dfc2f024a90fd12a04a7e3 /numpy | |
parent | 2e2bd93641aa505da8206d16d87271e606bb5192 (diff) | |
parent | 50bf6df95bdb5e4254719b0a6061cd1cdece2b7c (diff) | |
download | numpy-94a1c20e8153a92ae51f5915468fcff266ab497b.tar.gz |
Merge pull request #4421 from meltingwax/meltingwax/4382
BUG: Fix support for builds with directories that contain whitespace
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/distutils/fcompiler/__init__.py | 10 | ||||
-rw-r--r-- | numpy/distutils/misc_util.py | 8 | ||||
-rw-r--r-- | numpy/distutils/npy_pkg_config.py | 14 | ||||
-rw-r--r-- | numpy/distutils/tests/test_npy_pkg_config.py | 75 | ||||
-rw-r--r-- | numpy/distutils/unixccompiler.py | 5 |
5 files changed, 89 insertions, 23 deletions
diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py index 0b1b1ee6d..07d5e506e 100644 --- a/numpy/distutils/fcompiler/__init__.py +++ b/numpy/distutils/fcompiler/__init__.py @@ -38,7 +38,7 @@ from distutils.util import split_quoted, strtobool from numpy.distutils.ccompiler import CCompiler, gen_lib_options from numpy.distutils import log from numpy.distutils.misc_util import is_string, all_strings, is_sequence, \ - make_temp_file, get_shared_lib_extension + make_temp_file, get_shared_lib_extension, quote from numpy.distutils.environment import EnvironmentConfig from numpy.distutils.exec_command import find_executable from numpy.distutils.compat import get_exception @@ -582,12 +582,12 @@ class FCompiler(CCompiler): % (self.__class__.__name__, src)) extra_compile_args = self.extra_f90_compile_args or [] if self.object_switch[-1]==' ': - o_args = [self.object_switch.strip(), obj] + o_args = [self.object_switch.strip(), quote(obj)] else: - o_args = [self.object_switch.strip()+obj] + o_args = [self.object_switch.strip() + quote(obj)] assert self.compile_switch.strip() - s_args = [self.compile_switch, src] + s_args = [self.compile_switch, quote(src)] if extra_compile_args: log.info('extra %s options: %r' \ @@ -659,6 +659,7 @@ class FCompiler(CCompiler): else: ld_args = objects + self.objects ld_args = ld_args + lib_opts + o_args + ld_args = [quote(ld_arg) for ld_arg in ld_args] if debug: ld_args[:0] = ['-g'] if extra_preargs: @@ -987,3 +988,4 @@ def get_f77flags(src): if __name__ == '__main__': show_fcompilers() + diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py index c146178f0..a9ca12832 100644 --- a/numpy/distutils/misc_util.py +++ b/numpy/distutils/misc_util.py @@ -15,6 +15,11 @@ import distutils from distutils.errors import DistutilsError try: + from pipes import quote +except ImportError: + from shlex import quote + +try: set except NameError: from sets import Set as set @@ -31,7 +36,8 @@ __all__ = ['Configuration', 'get_numpy_include_dirs', 'default_config_dict', 'get_script_files', 'get_lib_source_files', 'get_data_files', 'dot_join', 'get_frame', 'minrelpath', 'njoin', 'is_sequence', 'is_string', 'as_list', 'gpaths', 'get_language', - 'quote_args', 'get_build_architecture', 'get_info', 'get_pkg_info'] + 'quote_args', 'quote', 'get_build_architecture', 'get_info', + 'get_pkg_info'] class InstallableLib(object): """ diff --git a/numpy/distutils/npy_pkg_config.py b/numpy/distutils/npy_pkg_config.py index ceab906a4..3192bfa32 100644 --- a/numpy/distutils/npy_pkg_config.py +++ b/numpy/distutils/npy_pkg_config.py @@ -10,6 +10,8 @@ if sys.version_info[0] < 3: else: from configparser import ConfigParser, SafeConfigParser, NoOptionError +from numpy.distutils.misc_util import quote + __all__ = ['FormatError', 'PkgNotFound', 'LibraryInfo', 'VariableSet', 'read_config', 'parse_flags'] @@ -56,7 +58,7 @@ def parse_flags(line): * 'ignored' """ - lexer = shlex.shlex(line) + lexer = shlex.shlex(line, posix=True) lexer.whitespace_split = True d = {'include_dirs': [], 'library_dirs': [], 'libraries': [], @@ -88,8 +90,6 @@ def parse_flags(line): return d -def _escape_backslash(val): - return val.replace('\\', '\\\\') class LibraryInfo(object): """ @@ -147,11 +147,11 @@ class LibraryInfo(object): def cflags(self, section="default"): val = self.vars.interpolate(self._sections[section]['cflags']) - return _escape_backslash(val) + return quote(val) def libs(self, section="default"): val = self.vars.interpolate(self._sections[section]['libs']) - return _escape_backslash(val) + return quote(val) def __str__(self): m = ['Name: %s' % self.name] @@ -289,7 +289,7 @@ def parse_config(filename, dirs=None): vars = {} if config.has_section('variables'): for name, value in config.items("variables"): - vars[name] = _escape_backslash(value) + vars[name] = quote(value) # Parse "normal" sections secs = [s for s in config.sections() if not s in ['meta', 'variables']] @@ -338,7 +338,7 @@ def _read_config_imp(filenames, dirs=None): (pkgname, meta["name"])) mod = sys.modules[pkgname] - vars["pkgdir"] = _escape_backslash(os.path.dirname(mod.__file__)) + vars["pkgdir"] = quote(os.path.dirname(mod.__file__)) return LibraryInfo(name=meta["name"], description=meta["description"], version=meta["version"], sections=sections, vars=VariableSet(vars)) diff --git a/numpy/distutils/tests/test_npy_pkg_config.py b/numpy/distutils/tests/test_npy_pkg_config.py index 5443ece48..e703edbd0 100644 --- a/numpy/distutils/tests/test_npy_pkg_config.py +++ b/numpy/distutils/tests/test_npy_pkg_config.py @@ -1,6 +1,7 @@ from __future__ import division, absolute_import, print_function import os +import shlex from tempfile import mkstemp from numpy.testing import * @@ -38,6 +39,12 @@ simple_variable_d = {'cflags': '-I/foo/bar/include', 'libflags': '-L/foo/bar/lib 'version': '0.1', 'name': 'foo'} class TestLibraryInfo(TestCase): + + def assertLexEqual(self, str1, str2): + # Use shlex.split for comparison because it is above quotes + # eg: shlex.split("'abc'") == shlex.split("abc") + return shlex.split(str1) == shlex.split(str2) + def test_simple(self): fd, filename = mkstemp('foo.ini') try: @@ -48,10 +55,10 @@ class TestLibraryInfo(TestCase): os.close(fd) out = read_config(pkg) - self.assertTrue(out.cflags() == simple_d['cflags']) - self.assertTrue(out.libs() == simple_d['libflags']) - self.assertTrue(out.name == simple_d['name']) - self.assertTrue(out.version == simple_d['version']) + self.assertLexEqual(out.cflags(), simple_d['cflags']) + self.assertLexEqual(out.libs(), simple_d['libflags']) + self.assertEqual(out.name, simple_d['name']) + self.assertEqual(out.version, simple_d['version']) finally: os.remove(filename) @@ -65,13 +72,13 @@ class TestLibraryInfo(TestCase): os.close(fd) out = read_config(pkg) - self.assertTrue(out.cflags() == simple_variable_d['cflags']) - self.assertTrue(out.libs() == simple_variable_d['libflags']) - self.assertTrue(out.name == simple_variable_d['name']) - self.assertTrue(out.version == simple_variable_d['version']) + self.assertLexEqual(out.cflags(), simple_variable_d['cflags']) + self.assertLexEqual(out.libs(), simple_variable_d['libflags']) + self.assertEqual(out.name, simple_variable_d['name']) + self.assertEqual(out.version, simple_variable_d['version']) out.vars['prefix'] = '/Users/david' - self.assertTrue(out.cflags() == '-I/Users/david/include') + self.assertLexEqual(out.cflags(), '-I/Users/david/include') finally: os.remove(filename) @@ -88,6 +95,28 @@ class TestParseFlags(TestCase): self.assertTrue(d['include_dirs'] == ['/usr/include']) self.assertTrue(d['macros'] == ['FOO']) + def test_quotes_cflags(self): + d = parse_flags("-I'/usr/foo bar/include' -DFOO") + self.assertTrue(d['include_dirs'] == ['/usr/foo bar/include']) + self.assertTrue(d['macros'] == ['FOO']) + + d = parse_flags("-I/usr/'foo bar'/include -DFOO") + self.assertTrue(d['include_dirs'] == ['/usr/foo bar/include']) + self.assertTrue(d['macros'] == ['FOO']) + + d = parse_flags("'-I/usr/foo bar'/include -DFOO") + self.assertTrue(d['include_dirs'] == ['/usr/foo bar/include']) + self.assertTrue(d['macros'] == ['FOO']) + + def test_escaping_cflags(self): + d = parse_flags("-I/usr/foo\\ bar/include -DFOO") + self.assertTrue(d['include_dirs'] == ['/usr/foo bar/include']) + self.assertTrue(d['macros'] == ['FOO']) + + d = parse_flags(r"-I/usr/foo\ bar/include -DFOO") + self.assertTrue(d['include_dirs'] == ['/usr/foo bar/include']) + self.assertTrue(d['macros'] == ['FOO']) + def test_simple_lflags(self): d = parse_flags("-L/usr/lib -lfoo -L/usr/lib -lbar") self.assertTrue(d['library_dirs'] == ['/usr/lib', '/usr/lib']) @@ -96,3 +125,31 @@ class TestParseFlags(TestCase): d = parse_flags("-L /usr/lib -lfoo -L/usr/lib -lbar") self.assertTrue(d['library_dirs'] == ['/usr/lib', '/usr/lib']) self.assertTrue(d['libraries'] == ['foo', 'bar']) + + def test_quotes_lflags(self): + d = parse_flags("-L'/usr/foo bar' -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo bar', '/usr/lib']) + + d = parse_flags("-L/usr/'foo bar' -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo bar', '/usr/lib']) + + d = parse_flags("\"-L/usr/foo bar\" -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo bar', '/usr/lib']) + + d = parse_flags("\"-L/usr/foo bar/baz buz\" -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo bar/baz buz', '/usr/lib']) + + def test_escaping_lflags(self): + d = parse_flags("-L/usr/foo\\ bar -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo bar', '/usr/lib']) + + d = parse_flags(r"-L/usr/foo\ bar -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo bar', '/usr/lib']) + + def test_odd_characters_lflags(self): + # tab in directory name + d = parse_flags('-L/usr/"foo\tbar" -lfoo -L/usr/lib -lbar') + self.assertTrue(d['library_dirs'] == ['/usr/foo\tbar', '/usr/lib']) + + d = parse_flags("-L/usr/foo\\\tbar -lfoo -L/usr/lib -lbar") + self.assertTrue(d['library_dirs'] == ['/usr/foo\tbar', '/usr/lib']) diff --git a/numpy/distutils/unixccompiler.py b/numpy/distutils/unixccompiler.py index 955407aa0..a198acb8b 100644 --- a/numpy/distutils/unixccompiler.py +++ b/numpy/distutils/unixccompiler.py @@ -10,6 +10,7 @@ from distutils.errors import DistutilsExecError, CompileError from distutils.unixccompiler import * from numpy.distutils.ccompiler import replace_method from numpy.distutils.compat import get_exception +from numpy.distutils.misc_util import quote_args, quote if sys.version_info[0] < 3: from . import log @@ -88,8 +89,8 @@ def UnixCCompiler_create_static_lib(self, objects, output_libname, display = '%s: adding %d object files to %s' % ( os.path.basename(self.archiver[0]), len(objects), output_filename) - self.spawn(self.archiver + [output_filename] + objects, - display = display) + command = self.archiver + [quote(output_filename)] + quote_args(objects) + self.spawn(command, display = display) # Not many Unices required ranlib anymore -- SunOS 4.x is, I # think the only major Unix that does. Maybe we need some |