summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2014-03-05 14:31:49 -0700
committerCharles Harris <charlesr.harris@gmail.com>2014-03-05 14:31:49 -0700
commit94a1c20e8153a92ae51f5915468fcff266ab497b (patch)
tree49579f4f93a6cb20f3dfc2f024a90fd12a04a7e3 /numpy
parent2e2bd93641aa505da8206d16d87271e606bb5192 (diff)
parent50bf6df95bdb5e4254719b0a6061cd1cdece2b7c (diff)
downloadnumpy-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__.py10
-rw-r--r--numpy/distutils/misc_util.py8
-rw-r--r--numpy/distutils/npy_pkg_config.py14
-rw-r--r--numpy/distutils/tests/test_npy_pkg_config.py75
-rw-r--r--numpy/distutils/unixccompiler.py5
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