Repository: numpy/numpy

Issue:
cannot configure/build without locale, due to commit 5652b0785
<!-- Please describe the issue in detail here, and fill in the fields below -->

### Reproducing code example:
assume that
```
>>> import locale
>>> locale.getpreferredencoding(False) is None
True
```

Then `python setup.py build_ext` fails with
`TypeError: decode() argument 1 must be string, not None` (see below for the full backtrace). I've tracked this down (by bisecting the numpy master branch) to commit 5652b0785 which introduced the use of locale, and uses it without checking that `locale.getpreferredencoding(False)` may return `None`, as the call to `text.decode()` must have a valid locale.

It's easy to patch, please tell me if this would be acceptable before I spend more time on this --- I'd imagine you might decide not to fix it---on the other hand it may be argued that a broken/missing locale should not stop numpy from being built, and it is a problem now. 

### Error message:
Full traceback:
```
Running from numpy source directory.
Cythonizing sources
numpy/random/mtrand/randint_helpers.pxi.in has not changed
numpy/random/mtrand/mtrand.pyx has not changed
blas_opt_info:
blas_mkl_info:
customize UnixCCompiler
C compiler: cc -fno-strict-aliasing -OPT:Olimit=0 -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wno-unused -fPIC

creating /tmp/tmpDJvQAg/tmp
creating /tmp/tmpDJvQAg/tmp/tmpDJvQAg
compile options: '-MMD -MF /tmp/tmpDJvQAg/file.c.d -c'
cc: /tmp/tmpDJvQAg/file.c
Traceback (most recent call last):
  File "setup.py", line 394, in <module>
    setup_package()
  File "setup.py", line 386, in setup_package
    setup(**metadata)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/core.py", line 135, in setup
    config = configuration()
  File "setup.py", line 166, in configuration
    config.add_subpackage('numpy')
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/misc_util.py", line 1029, in add_subpackage
    caller_level = 2)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/misc_util.py", line 998, in get_subpackage
    caller_level = caller_level + 1)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/misc_util.py", line 935, in _get_configuration_from_setup_py
    config = setup_module.configuration(*args)
  File "numpy/setup.py", line 10, in configuration
    config.add_subpackage('core')
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/misc_util.py", line 1029, in add_subpackage
    caller_level = 2)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/misc_util.py", line 998, in get_subpackage
    caller_level = caller_level + 1)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/misc_util.py", line 935, in _get_configuration_from_setup_py
    config = setup_module.configuration(*args)
  File "numpy/core/setup.py", line 839, in configuration
    blas_info = get_info('blas_opt', 0)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 432, in get_info
    return cl().get_info(notfound_action)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 624, in get_info
    self.calc_info()
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 1635, in calc_info
    blas_mkl_info = get_info('blas_mkl')
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 432, in get_info
    return cl().get_info(notfound_action)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 624, in get_info
    self.calc_info()
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 1071, in calc_info
    info = self.check_libs2(lib_dirs, mkl_libs)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 780, in check_libs2
    exts = self.library_extensions()
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/system_info.py", line 739, in library_extensions
    c = customized_ccompiler()
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/__init__.py", line 34, in customized_ccompiler
    c.customize('')
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/ccompiler.py", line 522, in CCompiler_customize
    extra_preargs=['-MMD', '-MF', fn + '.d'])
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/ccompiler.py", line 343, in CCompiler_compile
    single_compile(o)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/ccompiler.py", line 303, in single_compile
    self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/unixccompiler.py", line 58, in UnixCCompiler__compile
    extra_postargs, display = display)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/ccompiler.py", line 139, in CCompiler_spawn
    s, o = exec_command(cmd)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/exec_command.py", line 214, in exec_command
    **env)
  File "/usr/home/dimpase/Sage/sagemath/upstream/numpy/numpy/distutils/exec_command.py", line 264, in _exec_command
    errors='replace')
TypeError: decode() argument 1 must be string, not None

```

<!-- A short code example that reproduces the problem/missing feature. It should be
self-contained, i.e., possible to run as-is via 'python myproblem.py' -->

<!-- Remove these sections for a feature request -->



<!-- If you are reporting a segfault please include a GDB traceback, which you
can generate by following
https://github.com/numpy/numpy/blob/master/doc/source/dev/development_environment.rst#debugging -->

<!-- Full error message, if any (starting from line Traceback: ...) -->

### Numpy/Python version information:

CPython 2.7.15 built from source:
``` 
Python 2.7.15 (default, Nov 15 2018, 12:10:04) 
[GCC 4.2.1 Compatible FreeBSD Clang 6.0.1 (tags/RELEASE_601/final 335540)] on freebsd12
```

Problem shows itself on the master branch, all the way to 5652b0785, as well as on releases 1.14 and 1.15.



Discussion:
What if you replace `False` by `True` in `locale.getpreferredencoding(False)`? Can you think of a good replacement. I note that we use `getpreferredencoding` in a few other places, but `exec_command.py` is the only place with `False`.
No, replacing `False` by `True` does  not help. For the current master (a4b96ad764) to build I need to apply
```
diff --git a/numpy/distutils/exec_command.py b/numpy/distutils/exec_command.py
index af7810d75..aaba3b077 100644
--- a/numpy/distutils/exec_command.py
+++ b/numpy/distutils/exec_command.py
@@ -67,8 +67,9 @@ def filepath_from_subprocess_output(output):
 
     Inherited from `exec_command`, and possibly incorrect.
     """
-    output = output.decode(locale.getpreferredencoding(False),
-                           errors='replace')
+    mylocale = locale.getpreferredencoding(False)
+    if mylocale is not None:
+        output = output.decode(mylocale, errors='replace')
     output = output.replace('\r\n', '\n')
     # Another historical oddity
     if output[-1:] == '\n':
@@ -278,9 +279,9 @@ def _exec_command(command, use_shell=None, use_tee = None, **env):
         return 127, ''
 
     text, err = proc.communicate()
-    text = text.decode(locale.getpreferredencoding(False),
-                       errors='replace')
-
+    mylocale = locale.getpreferredencoding(False)
+    if mylocale is not None:
+        text = text.decode(mylocale, errors='replace')
     text = text.replace('\r\n', '\n')
     # Another historical oddity
     if text[-1:] == '\n':
```

Note that few tests fail, due to absent locale, but it's another story 

Resolving patch:
diff --git a/numpy/distutils/exec_command.py b/numpy/distutils/exec_command.py
--- a/numpy/distutils/exec_command.py
+++ b/numpy/distutils/exec_command.py
@@ -67,8 +67,10 @@ def filepath_from_subprocess_output(output):
 
     Inherited from `exec_command`, and possibly incorrect.
     """
-    output = output.decode(locale.getpreferredencoding(False),
-                           errors='replace')
+    mylocale = locale.getpreferredencoding(False)
+    if mylocale is None:
+        mylocale = 'ascii'
+    output = output.decode(mylocale, errors='replace')
     output = output.replace('\r\n', '\n')
     # Another historical oddity
     if output[-1:] == '\n':
@@ -278,9 +280,10 @@ def _exec_command(command, use_shell=None, use_tee = None, **env):
         return 127, ''
 
     text, err = proc.communicate()
-    text = text.decode(locale.getpreferredencoding(False),
-                       errors='replace')
-
+    mylocale = locale.getpreferredencoding(False)
+    if mylocale is None:
+        mylocale = 'ascii'
+    text = text.decode(mylocale, errors='replace')
     text = text.replace('\r\n', '\n')
     # Another historical oddity
     if text[-1:] == '\n':


Test patch: