8th day of python challenges 111-117
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
from tempfile import TemporaryFile
|
||||
|
||||
from numpy.distutils import exec_command
|
||||
from numpy.distutils.exec_command import get_pythonexe
|
||||
from numpy.testing import tempdir, assert_, assert_warns
|
||||
|
||||
# In python 3 stdout, stderr are text (unicode compliant) devices, so to
|
||||
# emulate them import StringIO from the io module.
|
||||
if sys.version_info[0] >= 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from StringIO import StringIO
|
||||
|
||||
class redirect_stdout(object):
|
||||
"""Context manager to redirect stdout for exec_command test."""
|
||||
def __init__(self, stdout=None):
|
||||
self._stdout = stdout or sys.stdout
|
||||
|
||||
def __enter__(self):
|
||||
self.old_stdout = sys.stdout
|
||||
sys.stdout = self._stdout
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self._stdout.flush()
|
||||
sys.stdout = self.old_stdout
|
||||
# note: closing sys.stdout won't close it.
|
||||
self._stdout.close()
|
||||
|
||||
class redirect_stderr(object):
|
||||
"""Context manager to redirect stderr for exec_command test."""
|
||||
def __init__(self, stderr=None):
|
||||
self._stderr = stderr or sys.stderr
|
||||
|
||||
def __enter__(self):
|
||||
self.old_stderr = sys.stderr
|
||||
sys.stderr = self._stderr
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self._stderr.flush()
|
||||
sys.stderr = self.old_stderr
|
||||
# note: closing sys.stderr won't close it.
|
||||
self._stderr.close()
|
||||
|
||||
class emulate_nonposix(object):
|
||||
"""Context manager to emulate os.name != 'posix' """
|
||||
def __init__(self, osname='non-posix'):
|
||||
self._new_name = osname
|
||||
|
||||
def __enter__(self):
|
||||
self._old_name = os.name
|
||||
os.name = self._new_name
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
os.name = self._old_name
|
||||
|
||||
|
||||
def test_exec_command_stdout():
|
||||
# Regression test for gh-2999 and gh-2915.
|
||||
# There are several packages (nose, scipy.weave.inline, Sage inline
|
||||
# Fortran) that replace stdout, in which case it doesn't have a fileno
|
||||
# method. This is tested here, with a do-nothing command that fails if the
|
||||
# presence of fileno() is assumed in exec_command.
|
||||
|
||||
# The code has a special case for posix systems, so if we are on posix test
|
||||
# both that the special case works and that the generic code works.
|
||||
|
||||
# Test posix version:
|
||||
with redirect_stdout(StringIO()):
|
||||
with redirect_stderr(TemporaryFile()):
|
||||
with assert_warns(DeprecationWarning):
|
||||
exec_command.exec_command("cd '.'")
|
||||
|
||||
if os.name == 'posix':
|
||||
# Test general (non-posix) version:
|
||||
with emulate_nonposix():
|
||||
with redirect_stdout(StringIO()):
|
||||
with redirect_stderr(TemporaryFile()):
|
||||
with assert_warns(DeprecationWarning):
|
||||
exec_command.exec_command("cd '.'")
|
||||
|
||||
def test_exec_command_stderr():
|
||||
# Test posix version:
|
||||
with redirect_stdout(TemporaryFile(mode='w+')):
|
||||
with redirect_stderr(StringIO()):
|
||||
with assert_warns(DeprecationWarning):
|
||||
exec_command.exec_command("cd '.'")
|
||||
|
||||
if os.name == 'posix':
|
||||
# Test general (non-posix) version:
|
||||
with emulate_nonposix():
|
||||
with redirect_stdout(TemporaryFile()):
|
||||
with redirect_stderr(StringIO()):
|
||||
with assert_warns(DeprecationWarning):
|
||||
exec_command.exec_command("cd '.'")
|
||||
|
||||
|
||||
class TestExecCommand(object):
|
||||
def setup(self):
|
||||
self.pyexe = get_pythonexe()
|
||||
|
||||
def check_nt(self, **kws):
|
||||
s, o = exec_command.exec_command('cmd /C echo path=%path%')
|
||||
assert_(s == 0)
|
||||
assert_(o != '')
|
||||
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "import sys;sys.stderr.write(sys.platform)"' % self.pyexe)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'win32')
|
||||
|
||||
def check_posix(self, **kws):
|
||||
s, o = exec_command.exec_command("echo Hello", **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Hello')
|
||||
|
||||
s, o = exec_command.exec_command('echo $AAA', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == '')
|
||||
|
||||
s, o = exec_command.exec_command('echo "$AAA"', AAA='Tere', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Tere')
|
||||
|
||||
s, o = exec_command.exec_command('echo "$AAA"', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == '')
|
||||
|
||||
if 'BBB' not in os.environ:
|
||||
os.environ['BBB'] = 'Hi'
|
||||
s, o = exec_command.exec_command('echo "$BBB"', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Hi')
|
||||
|
||||
s, o = exec_command.exec_command('echo "$BBB"', BBB='Hey', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Hey')
|
||||
|
||||
s, o = exec_command.exec_command('echo "$BBB"', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Hi')
|
||||
|
||||
del os.environ['BBB']
|
||||
|
||||
s, o = exec_command.exec_command('echo "$BBB"', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == '')
|
||||
|
||||
|
||||
s, o = exec_command.exec_command('this_is_not_a_command', **kws)
|
||||
assert_(s != 0)
|
||||
assert_(o != '')
|
||||
|
||||
s, o = exec_command.exec_command('echo path=$PATH', **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o != '')
|
||||
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "import sys,os;sys.stderr.write(os.name)"' %
|
||||
self.pyexe, **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'posix')
|
||||
|
||||
def check_basic(self, *kws):
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "raise \'Ignore me.\'"' % self.pyexe, **kws)
|
||||
assert_(s != 0)
|
||||
assert_(o != '')
|
||||
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "import sys;sys.stderr.write(\'0\');'
|
||||
'sys.stderr.write(\'1\');sys.stderr.write(\'2\')"' %
|
||||
self.pyexe, **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == '012')
|
||||
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "import sys;sys.exit(15)"' % self.pyexe, **kws)
|
||||
assert_(s == 15)
|
||||
assert_(o == '')
|
||||
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "print(\'Heipa\'")' % self.pyexe, **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Heipa')
|
||||
|
||||
def check_execute_in(self, **kws):
|
||||
with tempdir() as tmpdir:
|
||||
fn = "file"
|
||||
tmpfile = os.path.join(tmpdir, fn)
|
||||
f = open(tmpfile, 'w')
|
||||
f.write('Hello')
|
||||
f.close()
|
||||
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "f = open(\'%s\', \'r\'); f.close()"' %
|
||||
(self.pyexe, fn), **kws)
|
||||
assert_(s != 0)
|
||||
assert_(o != '')
|
||||
s, o = exec_command.exec_command(
|
||||
'"%s" -c "f = open(\'%s\', \'r\'); print(f.read()); '
|
||||
'f.close()"' % (self.pyexe, fn), execute_in=tmpdir, **kws)
|
||||
assert_(s == 0)
|
||||
assert_(o == 'Hello')
|
||||
|
||||
def test_basic(self):
|
||||
with redirect_stdout(StringIO()):
|
||||
with redirect_stderr(StringIO()):
|
||||
with assert_warns(DeprecationWarning):
|
||||
if os.name == "posix":
|
||||
self.check_posix(use_tee=0)
|
||||
self.check_posix(use_tee=1)
|
||||
elif os.name == "nt":
|
||||
self.check_nt(use_tee=0)
|
||||
self.check_nt(use_tee=1)
|
||||
self.check_execute_in(use_tee=0)
|
||||
self.check_execute_in(use_tee=1)
|
@@ -0,0 +1,81 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
|
||||
from numpy.testing import assert_, suppress_warnings
|
||||
import numpy.distutils.fcompiler
|
||||
|
||||
customizable_flags = [
|
||||
('f77', 'F77FLAGS'),
|
||||
('f90', 'F90FLAGS'),
|
||||
('free', 'FREEFLAGS'),
|
||||
('arch', 'FARCH'),
|
||||
('debug', 'FDEBUG'),
|
||||
('flags', 'FFLAGS'),
|
||||
('linker_so', 'LDFLAGS'),
|
||||
]
|
||||
|
||||
|
||||
def test_fcompiler_flags(monkeypatch):
|
||||
monkeypatch.setenv('NPY_DISTUTILS_APPEND_FLAGS', '0')
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='none')
|
||||
flag_vars = fc.flag_vars.clone(lambda *args, **kwargs: None)
|
||||
|
||||
for opt, envvar in customizable_flags:
|
||||
new_flag = '-dummy-{}-flag'.format(opt)
|
||||
prev_flags = getattr(flag_vars, opt)
|
||||
|
||||
monkeypatch.setenv(envvar, new_flag)
|
||||
new_flags = getattr(flag_vars, opt)
|
||||
|
||||
monkeypatch.delenv(envvar)
|
||||
assert_(new_flags == [new_flag])
|
||||
|
||||
monkeypatch.setenv('NPY_DISTUTILS_APPEND_FLAGS', '1')
|
||||
|
||||
for opt, envvar in customizable_flags:
|
||||
new_flag = '-dummy-{}-flag'.format(opt)
|
||||
prev_flags = getattr(flag_vars, opt)
|
||||
monkeypatch.setenv(envvar, new_flag)
|
||||
new_flags = getattr(flag_vars, opt)
|
||||
|
||||
monkeypatch.delenv(envvar)
|
||||
if prev_flags is None:
|
||||
assert_(new_flags == [new_flag])
|
||||
else:
|
||||
assert_(new_flags == prev_flags + [new_flag])
|
||||
|
||||
|
||||
def test_fcompiler_flags_append_warning(monkeypatch):
|
||||
# Test to check that the warning for append behavior changing in future
|
||||
# is triggered. Need to use a real compiler instance so that we have
|
||||
# non-empty flags to start with (otherwise the "if var and append" check
|
||||
# will always be false).
|
||||
try:
|
||||
with suppress_warnings() as sup:
|
||||
sup.record()
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95')
|
||||
fc.customize()
|
||||
except numpy.distutils.fcompiler.CompilerNotFound:
|
||||
pytest.skip("gfortran not found, so can't execute this test")
|
||||
|
||||
# Ensure NPY_DISTUTILS_APPEND_FLAGS not defined
|
||||
monkeypatch.delenv('NPY_DISTUTILS_APPEND_FLAGS', raising=False)
|
||||
|
||||
for opt, envvar in customizable_flags:
|
||||
new_flag = '-dummy-{}-flag'.format(opt)
|
||||
with suppress_warnings() as sup:
|
||||
sup.record()
|
||||
prev_flags = getattr(fc.flag_vars, opt)
|
||||
|
||||
monkeypatch.setenv(envvar, new_flag)
|
||||
with suppress_warnings() as sup:
|
||||
sup.record()
|
||||
new_flags = getattr(fc.flag_vars, opt)
|
||||
if prev_flags:
|
||||
# Check that warning was issued
|
||||
assert len(sup.log) == 1
|
||||
|
||||
monkeypatch.delenv(envvar)
|
||||
assert_(new_flags == [new_flag])
|
||||
|
@@ -0,0 +1,57 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
from numpy.testing import assert_
|
||||
|
||||
import numpy.distutils.fcompiler
|
||||
|
||||
g77_version_strings = [
|
||||
('GNU Fortran 0.5.25 20010319 (prerelease)', '0.5.25'),
|
||||
('GNU Fortran (GCC 3.2) 3.2 20020814 (release)', '3.2'),
|
||||
('GNU Fortran (GCC) 3.3.3 20040110 (prerelease) (Debian)', '3.3.3'),
|
||||
('GNU Fortran (GCC) 3.3.3 (Debian 20040401)', '3.3.3'),
|
||||
('GNU Fortran (GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) 3.2.2'
|
||||
' 20030222 (Red Hat Linux 3.2.2-5)', '3.2.2'),
|
||||
]
|
||||
|
||||
gfortran_version_strings = [
|
||||
('GNU Fortran 95 (GCC 4.0.3 20051023 (prerelease) (Debian 4.0.2-3))',
|
||||
'4.0.3'),
|
||||
('GNU Fortran 95 (GCC) 4.1.0', '4.1.0'),
|
||||
('GNU Fortran 95 (GCC) 4.2.0 20060218 (experimental)', '4.2.0'),
|
||||
('GNU Fortran (GCC) 4.3.0 20070316 (experimental)', '4.3.0'),
|
||||
('GNU Fortran (rubenvb-4.8.0) 4.8.0', '4.8.0'),
|
||||
('4.8.0', '4.8.0'),
|
||||
('4.0.3-7', '4.0.3'),
|
||||
("gfortran: warning: couldn't understand kern.osversion '14.1.0\n4.9.1",
|
||||
'4.9.1'),
|
||||
("gfortran: warning: couldn't understand kern.osversion '14.1.0\n"
|
||||
"gfortran: warning: yet another warning\n4.9.1",
|
||||
'4.9.1'),
|
||||
('GNU Fortran (crosstool-NG 8a21ab48) 7.2.0', '7.2.0')
|
||||
]
|
||||
|
||||
class TestG77Versions(object):
|
||||
def test_g77_version(self):
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu')
|
||||
for vs, version in g77_version_strings:
|
||||
v = fc.version_match(vs)
|
||||
assert_(v == version, (vs, v))
|
||||
|
||||
def test_not_g77(self):
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu')
|
||||
for vs, _ in gfortran_version_strings:
|
||||
v = fc.version_match(vs)
|
||||
assert_(v is None, (vs, v))
|
||||
|
||||
class TestGFortranVersions(object):
|
||||
def test_gfortran_version(self):
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95')
|
||||
for vs, version in gfortran_version_strings:
|
||||
v = fc.version_match(vs)
|
||||
assert_(v == version, (vs, v))
|
||||
|
||||
def test_not_gfortran(self):
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95')
|
||||
for vs, _ in g77_version_strings:
|
||||
v = fc.version_match(vs)
|
||||
assert_(v is None, (vs, v))
|
@@ -0,0 +1,32 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import numpy.distutils.fcompiler
|
||||
from numpy.testing import assert_
|
||||
|
||||
|
||||
intel_32bit_version_strings = [
|
||||
("Intel(R) Fortran Intel(R) 32-bit Compiler Professional for applications"
|
||||
"running on Intel(R) 32, Version 11.1", '11.1'),
|
||||
]
|
||||
|
||||
intel_64bit_version_strings = [
|
||||
("Intel(R) Fortran IA-64 Compiler Professional for applications"
|
||||
"running on IA-64, Version 11.0", '11.0'),
|
||||
("Intel(R) Fortran Intel(R) 64 Compiler Professional for applications"
|
||||
"running on Intel(R) 64, Version 11.1", '11.1')
|
||||
]
|
||||
|
||||
class TestIntelFCompilerVersions(object):
|
||||
def test_32bit_version(self):
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='intel')
|
||||
for vs, version in intel_32bit_version_strings:
|
||||
v = fc.version_match(vs)
|
||||
assert_(v == version)
|
||||
|
||||
|
||||
class TestIntelEM64TFCompilerVersions(object):
|
||||
def test_64bit_version(self):
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler='intelem')
|
||||
for vs, version in intel_64bit_version_strings:
|
||||
v = fc.version_match(vs)
|
||||
assert_(v == version)
|
@@ -0,0 +1,24 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
from numpy.testing import assert_
|
||||
import numpy.distutils.fcompiler
|
||||
|
||||
nag_version_strings = [('nagfor', 'NAG Fortran Compiler Release '
|
||||
'6.2(Chiyoda) Build 6200', '6.2'),
|
||||
('nagfor', 'NAG Fortran Compiler Release '
|
||||
'6.1(Tozai) Build 6136', '6.1'),
|
||||
('nagfor', 'NAG Fortran Compiler Release '
|
||||
'6.0(Hibiya) Build 1021', '6.0'),
|
||||
('nagfor', 'NAG Fortran Compiler Release '
|
||||
'5.3.2(971)', '5.3.2'),
|
||||
('nag', 'NAGWare Fortran 95 compiler Release 5.1'
|
||||
'(347,355-367,375,380-383,389,394,399,401-402,407,'
|
||||
'431,435,437,446,459-460,463,472,494,496,503,508,'
|
||||
'511,517,529,555,557,565)', '5.1')]
|
||||
|
||||
class TestNagFCompilerVersions(object):
|
||||
def test_version_match(self):
|
||||
for comp, vs, version in nag_version_strings:
|
||||
fc = numpy.distutils.fcompiler.new_fcompiler(compiler=comp)
|
||||
v = fc.version_match(vs)
|
||||
assert_(v == version)
|
@@ -0,0 +1,44 @@
|
||||
|
||||
from numpy.distutils.from_template import process_str
|
||||
from numpy.testing import assert_equal
|
||||
|
||||
|
||||
pyf_src = """
|
||||
python module foo
|
||||
<_rd=real,double precision>
|
||||
interface
|
||||
subroutine <s,d>foosub(tol)
|
||||
<_rd>, intent(in,out) :: tol
|
||||
end subroutine <s,d>foosub
|
||||
end interface
|
||||
end python module foo
|
||||
"""
|
||||
|
||||
expected_pyf = """
|
||||
python module foo
|
||||
interface
|
||||
subroutine sfoosub(tol)
|
||||
real, intent(in,out) :: tol
|
||||
end subroutine sfoosub
|
||||
subroutine dfoosub(tol)
|
||||
double precision, intent(in,out) :: tol
|
||||
end subroutine dfoosub
|
||||
end interface
|
||||
end python module foo
|
||||
"""
|
||||
|
||||
|
||||
def normalize_whitespace(s):
|
||||
"""
|
||||
Remove leading and trailing whitespace, and convert internal
|
||||
stretches of whitespace to a single space.
|
||||
"""
|
||||
return ' '.join(s.split())
|
||||
|
||||
|
||||
def test_from_template():
|
||||
"""Regression test for gh-10712."""
|
||||
pyf = process_str(pyf_src)
|
||||
normalized_pyf = normalize_whitespace(pyf)
|
||||
normalized_expected_pyf = normalize_whitespace(expected_pyf)
|
||||
assert_equal(normalized_pyf, normalized_expected_pyf)
|
@@ -0,0 +1,84 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
from os.path import join, sep, dirname
|
||||
|
||||
from numpy.distutils.misc_util import (
|
||||
appendpath, minrelpath, gpaths, get_shared_lib_extension, get_info
|
||||
)
|
||||
from numpy.testing import (
|
||||
assert_, assert_equal
|
||||
)
|
||||
|
||||
ajoin = lambda *paths: join(*((sep,)+paths))
|
||||
|
||||
class TestAppendpath(object):
|
||||
|
||||
def test_1(self):
|
||||
assert_equal(appendpath('prefix', 'name'), join('prefix', 'name'))
|
||||
assert_equal(appendpath('/prefix', 'name'), ajoin('prefix', 'name'))
|
||||
assert_equal(appendpath('/prefix', '/name'), ajoin('prefix', 'name'))
|
||||
assert_equal(appendpath('prefix', '/name'), join('prefix', 'name'))
|
||||
|
||||
def test_2(self):
|
||||
assert_equal(appendpath('prefix/sub', 'name'),
|
||||
join('prefix', 'sub', 'name'))
|
||||
assert_equal(appendpath('prefix/sub', 'sup/name'),
|
||||
join('prefix', 'sub', 'sup', 'name'))
|
||||
assert_equal(appendpath('/prefix/sub', '/prefix/name'),
|
||||
ajoin('prefix', 'sub', 'name'))
|
||||
|
||||
def test_3(self):
|
||||
assert_equal(appendpath('/prefix/sub', '/prefix/sup/name'),
|
||||
ajoin('prefix', 'sub', 'sup', 'name'))
|
||||
assert_equal(appendpath('/prefix/sub/sub2', '/prefix/sup/sup2/name'),
|
||||
ajoin('prefix', 'sub', 'sub2', 'sup', 'sup2', 'name'))
|
||||
assert_equal(appendpath('/prefix/sub/sub2', '/prefix/sub/sup/name'),
|
||||
ajoin('prefix', 'sub', 'sub2', 'sup', 'name'))
|
||||
|
||||
class TestMinrelpath(object):
|
||||
|
||||
def test_1(self):
|
||||
n = lambda path: path.replace('/', sep)
|
||||
assert_equal(minrelpath(n('aa/bb')), n('aa/bb'))
|
||||
assert_equal(minrelpath('..'), '..')
|
||||
assert_equal(minrelpath(n('aa/..')), '')
|
||||
assert_equal(minrelpath(n('aa/../bb')), 'bb')
|
||||
assert_equal(minrelpath(n('aa/bb/..')), 'aa')
|
||||
assert_equal(minrelpath(n('aa/bb/../..')), '')
|
||||
assert_equal(minrelpath(n('aa/bb/../cc/../dd')), n('aa/dd'))
|
||||
assert_equal(minrelpath(n('.././..')), n('../..'))
|
||||
assert_equal(minrelpath(n('aa/bb/.././../dd')), n('dd'))
|
||||
|
||||
class TestGpaths(object):
|
||||
|
||||
def test_gpaths(self):
|
||||
local_path = minrelpath(join(dirname(__file__), '..'))
|
||||
ls = gpaths('command/*.py', local_path)
|
||||
assert_(join(local_path, 'command', 'build_src.py') in ls, repr(ls))
|
||||
f = gpaths('system_info.py', local_path)
|
||||
assert_(join(local_path, 'system_info.py') == f[0], repr(f))
|
||||
|
||||
class TestSharedExtension(object):
|
||||
|
||||
def test_get_shared_lib_extension(self):
|
||||
import sys
|
||||
ext = get_shared_lib_extension(is_python_ext=False)
|
||||
if sys.platform.startswith('linux'):
|
||||
assert_equal(ext, '.so')
|
||||
elif sys.platform.startswith('gnukfreebsd'):
|
||||
assert_equal(ext, '.so')
|
||||
elif sys.platform.startswith('darwin'):
|
||||
assert_equal(ext, '.dylib')
|
||||
elif sys.platform.startswith('win'):
|
||||
assert_equal(ext, '.dll')
|
||||
# just check for no crash
|
||||
assert_(get_shared_lib_extension(is_python_ext=True))
|
||||
|
||||
|
||||
def test_installed_npymath_ini():
|
||||
# Regression test for gh-7707. If npymath.ini wasn't installed, then this
|
||||
# will give an error.
|
||||
info = get_info('npymath')
|
||||
|
||||
assert isinstance(info, dict)
|
||||
assert "define_macros" in info
|
@@ -0,0 +1,86 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import os
|
||||
|
||||
from numpy.distutils.npy_pkg_config import read_config, parse_flags
|
||||
from numpy.testing import temppath, assert_
|
||||
|
||||
simple = """\
|
||||
[meta]
|
||||
Name = foo
|
||||
Description = foo lib
|
||||
Version = 0.1
|
||||
|
||||
[default]
|
||||
cflags = -I/usr/include
|
||||
libs = -L/usr/lib
|
||||
"""
|
||||
simple_d = {'cflags': '-I/usr/include', 'libflags': '-L/usr/lib',
|
||||
'version': '0.1', 'name': 'foo'}
|
||||
|
||||
simple_variable = """\
|
||||
[meta]
|
||||
Name = foo
|
||||
Description = foo lib
|
||||
Version = 0.1
|
||||
|
||||
[variables]
|
||||
prefix = /foo/bar
|
||||
libdir = ${prefix}/lib
|
||||
includedir = ${prefix}/include
|
||||
|
||||
[default]
|
||||
cflags = -I${includedir}
|
||||
libs = -L${libdir}
|
||||
"""
|
||||
simple_variable_d = {'cflags': '-I/foo/bar/include', 'libflags': '-L/foo/bar/lib',
|
||||
'version': '0.1', 'name': 'foo'}
|
||||
|
||||
class TestLibraryInfo(object):
|
||||
def test_simple(self):
|
||||
with temppath('foo.ini') as path:
|
||||
with open(path, 'w') as f:
|
||||
f.write(simple)
|
||||
pkg = os.path.splitext(path)[0]
|
||||
out = read_config(pkg)
|
||||
|
||||
assert_(out.cflags() == simple_d['cflags'])
|
||||
assert_(out.libs() == simple_d['libflags'])
|
||||
assert_(out.name == simple_d['name'])
|
||||
assert_(out.version == simple_d['version'])
|
||||
|
||||
def test_simple_variable(self):
|
||||
with temppath('foo.ini') as path:
|
||||
with open(path, 'w') as f:
|
||||
f.write(simple_variable)
|
||||
pkg = os.path.splitext(path)[0]
|
||||
out = read_config(pkg)
|
||||
|
||||
assert_(out.cflags() == simple_variable_d['cflags'])
|
||||
assert_(out.libs() == simple_variable_d['libflags'])
|
||||
assert_(out.name == simple_variable_d['name'])
|
||||
assert_(out.version == simple_variable_d['version'])
|
||||
out.vars['prefix'] = '/Users/david'
|
||||
assert_(out.cflags() == '-I/Users/david/include')
|
||||
|
||||
class TestParseFlags(object):
|
||||
def test_simple_cflags(self):
|
||||
d = parse_flags("-I/usr/include")
|
||||
assert_(d['include_dirs'] == ['/usr/include'])
|
||||
|
||||
d = parse_flags("-I/usr/include -DFOO")
|
||||
assert_(d['include_dirs'] == ['/usr/include'])
|
||||
assert_(d['macros'] == ['FOO'])
|
||||
|
||||
d = parse_flags("-I /usr/include -DFOO")
|
||||
assert_(d['include_dirs'] == ['/usr/include'])
|
||||
assert_(d['macros'] == ['FOO'])
|
||||
|
||||
def test_simple_lflags(self):
|
||||
d = parse_flags("-L/usr/lib -lfoo -L/usr/lib -lbar")
|
||||
assert_(d['library_dirs'] == ['/usr/lib', '/usr/lib'])
|
||||
assert_(d['libraries'] == ['foo', 'bar'])
|
||||
|
||||
d = parse_flags("-L /usr/lib -lfoo -L/usr/lib -lbar")
|
||||
assert_(d['library_dirs'] == ['/usr/lib', '/usr/lib'])
|
||||
assert_(d['libraries'] == ['foo', 'bar'])
|
@@ -0,0 +1,79 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
import subprocess
|
||||
import os
|
||||
import json
|
||||
import sys
|
||||
|
||||
from numpy.distutils import _shell_utils
|
||||
|
||||
argv_cases = [
|
||||
[r'exe'],
|
||||
[r'path/exe'],
|
||||
[r'path\exe'],
|
||||
[r'\\server\path\exe'],
|
||||
[r'path to/exe'],
|
||||
[r'path to\exe'],
|
||||
|
||||
[r'exe', '--flag'],
|
||||
[r'path/exe', '--flag'],
|
||||
[r'path\exe', '--flag'],
|
||||
[r'path to/exe', '--flag'],
|
||||
[r'path to\exe', '--flag'],
|
||||
|
||||
# flags containing literal quotes in their name
|
||||
[r'path to/exe', '--flag-"quoted"'],
|
||||
[r'path to\exe', '--flag-"quoted"'],
|
||||
[r'path to/exe', '"--flag-quoted"'],
|
||||
[r'path to\exe', '"--flag-quoted"'],
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(params=[
|
||||
_shell_utils.WindowsParser,
|
||||
_shell_utils.PosixParser
|
||||
])
|
||||
def Parser(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def runner(Parser):
|
||||
if Parser != _shell_utils.NativeParser:
|
||||
pytest.skip('Unable to run with non-native parser')
|
||||
|
||||
if Parser == _shell_utils.WindowsParser:
|
||||
return lambda cmd: subprocess.check_output(cmd)
|
||||
elif Parser == _shell_utils.PosixParser:
|
||||
# posix has no non-shell string parsing
|
||||
return lambda cmd: subprocess.check_output(cmd, shell=True)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@pytest.mark.parametrize('argv', argv_cases)
|
||||
def test_join_matches_subprocess(Parser, runner, argv):
|
||||
"""
|
||||
Test that join produces strings understood by subprocess
|
||||
"""
|
||||
# invoke python to return its arguments as json
|
||||
cmd = [
|
||||
sys.executable, '-c',
|
||||
'import json, sys; print(json.dumps(sys.argv[1:]))'
|
||||
]
|
||||
joined = Parser.join(cmd + argv)
|
||||
json_out = runner(joined).decode()
|
||||
assert json.loads(json_out) == argv
|
||||
|
||||
|
||||
@pytest.mark.parametrize('argv', argv_cases)
|
||||
def test_roundtrip(Parser, argv):
|
||||
"""
|
||||
Test that split is the inverse operation of join
|
||||
"""
|
||||
try:
|
||||
joined = Parser.join(argv)
|
||||
assert argv == Parser.split(joined)
|
||||
except NotImplementedError:
|
||||
pytest.skip("Not implemented")
|
@@ -0,0 +1,257 @@
|
||||
from __future__ import division, print_function
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import pytest
|
||||
from tempfile import mkstemp, mkdtemp
|
||||
from subprocess import Popen, PIPE
|
||||
from distutils.errors import DistutilsError
|
||||
|
||||
from numpy.testing import assert_, assert_equal, assert_raises
|
||||
from numpy.distutils import ccompiler, customized_ccompiler
|
||||
from numpy.distutils.system_info import system_info, ConfigParser
|
||||
from numpy.distutils.system_info import AliasedOptionError
|
||||
from numpy.distutils.system_info import default_lib_dirs, default_include_dirs
|
||||
from numpy.distutils import _shell_utils
|
||||
|
||||
|
||||
def get_class(name, notfound_action=1):
|
||||
"""
|
||||
notfound_action:
|
||||
0 - do nothing
|
||||
1 - display warning message
|
||||
2 - raise error
|
||||
"""
|
||||
cl = {'temp1': Temp1Info,
|
||||
'temp2': Temp2Info,
|
||||
'duplicate_options': DuplicateOptionInfo,
|
||||
}.get(name.lower(), _system_info)
|
||||
return cl()
|
||||
|
||||
simple_site = """
|
||||
[ALL]
|
||||
library_dirs = {dir1:s}{pathsep:s}{dir2:s}
|
||||
libraries = {lib1:s},{lib2:s}
|
||||
extra_compile_args = -I/fake/directory -I"/path with/spaces" -Os
|
||||
runtime_library_dirs = {dir1:s}
|
||||
|
||||
[temp1]
|
||||
library_dirs = {dir1:s}
|
||||
libraries = {lib1:s}
|
||||
runtime_library_dirs = {dir1:s}
|
||||
|
||||
[temp2]
|
||||
library_dirs = {dir2:s}
|
||||
libraries = {lib2:s}
|
||||
extra_link_args = -Wl,-rpath={lib2_escaped:s}
|
||||
rpath = {dir2:s}
|
||||
|
||||
[duplicate_options]
|
||||
mylib_libs = {lib1:s}
|
||||
libraries = {lib2:s}
|
||||
"""
|
||||
site_cfg = simple_site
|
||||
|
||||
fakelib_c_text = """
|
||||
/* This file is generated from numpy/distutils/testing/test_system_info.py */
|
||||
#include<stdio.h>
|
||||
void foo(void) {
|
||||
printf("Hello foo");
|
||||
}
|
||||
void bar(void) {
|
||||
printf("Hello bar");
|
||||
}
|
||||
"""
|
||||
|
||||
def have_compiler():
|
||||
""" Return True if there appears to be an executable compiler
|
||||
"""
|
||||
compiler = customized_ccompiler()
|
||||
try:
|
||||
cmd = compiler.compiler # Unix compilers
|
||||
except AttributeError:
|
||||
try:
|
||||
if not compiler.initialized:
|
||||
compiler.initialize() # MSVC is different
|
||||
except (DistutilsError, ValueError):
|
||||
return False
|
||||
cmd = [compiler.cc]
|
||||
try:
|
||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
||||
p.stdout.close()
|
||||
p.stderr.close()
|
||||
p.wait()
|
||||
except OSError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
HAVE_COMPILER = have_compiler()
|
||||
|
||||
|
||||
class _system_info(system_info):
|
||||
|
||||
def __init__(self,
|
||||
default_lib_dirs=default_lib_dirs,
|
||||
default_include_dirs=default_include_dirs,
|
||||
verbosity=1,
|
||||
):
|
||||
self.__class__.info = {}
|
||||
self.local_prefixes = []
|
||||
defaults = {'library_dirs': '',
|
||||
'include_dirs': '',
|
||||
'runtime_library_dirs': '',
|
||||
'rpath': '',
|
||||
'src_dirs': '',
|
||||
'search_static_first': "0",
|
||||
'extra_compile_args': '',
|
||||
'extra_link_args': ''}
|
||||
self.cp = ConfigParser(defaults)
|
||||
# We have to parse the config files afterwards
|
||||
# to have a consistent temporary filepath
|
||||
|
||||
def _check_libs(self, lib_dirs, libs, opt_libs, exts):
|
||||
"""Override _check_libs to return with all dirs """
|
||||
info = {'libraries': libs, 'library_dirs': lib_dirs}
|
||||
return info
|
||||
|
||||
|
||||
class Temp1Info(_system_info):
|
||||
"""For testing purposes"""
|
||||
section = 'temp1'
|
||||
|
||||
|
||||
class Temp2Info(_system_info):
|
||||
"""For testing purposes"""
|
||||
section = 'temp2'
|
||||
|
||||
class DuplicateOptionInfo(_system_info):
|
||||
"""For testing purposes"""
|
||||
section = 'duplicate_options'
|
||||
|
||||
|
||||
class TestSystemInfoReading(object):
|
||||
|
||||
def setup(self):
|
||||
""" Create the libraries """
|
||||
# Create 2 sources and 2 libraries
|
||||
self._dir1 = mkdtemp()
|
||||
self._src1 = os.path.join(self._dir1, 'foo.c')
|
||||
self._lib1 = os.path.join(self._dir1, 'libfoo.so')
|
||||
self._dir2 = mkdtemp()
|
||||
self._src2 = os.path.join(self._dir2, 'bar.c')
|
||||
self._lib2 = os.path.join(self._dir2, 'libbar.so')
|
||||
# Update local site.cfg
|
||||
global simple_site, site_cfg
|
||||
site_cfg = simple_site.format(**{
|
||||
'dir1': self._dir1,
|
||||
'lib1': self._lib1,
|
||||
'dir2': self._dir2,
|
||||
'lib2': self._lib2,
|
||||
'pathsep': os.pathsep,
|
||||
'lib2_escaped': _shell_utils.NativeParser.join([self._lib2])
|
||||
})
|
||||
# Write site.cfg
|
||||
fd, self._sitecfg = mkstemp()
|
||||
os.close(fd)
|
||||
with open(self._sitecfg, 'w') as fd:
|
||||
fd.write(site_cfg)
|
||||
# Write the sources
|
||||
with open(self._src1, 'w') as fd:
|
||||
fd.write(fakelib_c_text)
|
||||
with open(self._src2, 'w') as fd:
|
||||
fd.write(fakelib_c_text)
|
||||
# We create all class-instances
|
||||
|
||||
def site_and_parse(c, site_cfg):
|
||||
c.files = [site_cfg]
|
||||
c.parse_config_files()
|
||||
return c
|
||||
self.c_default = site_and_parse(get_class('default'), self._sitecfg)
|
||||
self.c_temp1 = site_and_parse(get_class('temp1'), self._sitecfg)
|
||||
self.c_temp2 = site_and_parse(get_class('temp2'), self._sitecfg)
|
||||
self.c_dup_options = site_and_parse(get_class('duplicate_options'),
|
||||
self._sitecfg)
|
||||
|
||||
|
||||
def teardown(self):
|
||||
# Do each removal separately
|
||||
try:
|
||||
shutil.rmtree(self._dir1)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
shutil.rmtree(self._dir2)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
os.remove(self._sitecfg)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def test_all(self):
|
||||
# Read in all information in the ALL block
|
||||
tsi = self.c_default
|
||||
assert_equal(tsi.get_lib_dirs(), [self._dir1, self._dir2])
|
||||
assert_equal(tsi.get_libraries(), [self._lib1, self._lib2])
|
||||
assert_equal(tsi.get_runtime_lib_dirs(), [self._dir1])
|
||||
extra = tsi.calc_extra_info()
|
||||
assert_equal(extra['extra_compile_args'], ['-I/fake/directory', '-I/path with/spaces', '-Os'])
|
||||
|
||||
def test_temp1(self):
|
||||
# Read in all information in the temp1 block
|
||||
tsi = self.c_temp1
|
||||
assert_equal(tsi.get_lib_dirs(), [self._dir1])
|
||||
assert_equal(tsi.get_libraries(), [self._lib1])
|
||||
assert_equal(tsi.get_runtime_lib_dirs(), [self._dir1])
|
||||
|
||||
def test_temp2(self):
|
||||
# Read in all information in the temp2 block
|
||||
tsi = self.c_temp2
|
||||
assert_equal(tsi.get_lib_dirs(), [self._dir2])
|
||||
assert_equal(tsi.get_libraries(), [self._lib2])
|
||||
# Now from rpath and not runtime_library_dirs
|
||||
assert_equal(tsi.get_runtime_lib_dirs(key='rpath'), [self._dir2])
|
||||
extra = tsi.calc_extra_info()
|
||||
assert_equal(extra['extra_link_args'], ['-Wl,-rpath=' + self._lib2])
|
||||
|
||||
def test_duplicate_options(self):
|
||||
# Ensure that duplicates are raising an AliasedOptionError
|
||||
tsi = self.c_dup_options
|
||||
assert_raises(AliasedOptionError, tsi.get_option_single, "mylib_libs", "libraries")
|
||||
assert_equal(tsi.get_libs("mylib_libs", [self._lib1]), [self._lib1])
|
||||
assert_equal(tsi.get_libs("libraries", [self._lib2]), [self._lib2])
|
||||
|
||||
@pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler")
|
||||
def test_compile1(self):
|
||||
# Compile source and link the first source
|
||||
c = customized_ccompiler()
|
||||
previousDir = os.getcwd()
|
||||
try:
|
||||
# Change directory to not screw up directories
|
||||
os.chdir(self._dir1)
|
||||
c.compile([os.path.basename(self._src1)], output_dir=self._dir1)
|
||||
# Ensure that the object exists
|
||||
assert_(os.path.isfile(self._src1.replace('.c', '.o')) or
|
||||
os.path.isfile(self._src1.replace('.c', '.obj')))
|
||||
finally:
|
||||
os.chdir(previousDir)
|
||||
|
||||
@pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler")
|
||||
@pytest.mark.skipif('msvc' in repr(ccompiler.new_compiler()),
|
||||
reason="Fails with MSVC compiler ")
|
||||
def test_compile2(self):
|
||||
# Compile source and link the second source
|
||||
tsi = self.c_temp2
|
||||
c = customized_ccompiler()
|
||||
extra_link_args = tsi.calc_extra_info()['extra_link_args']
|
||||
previousDir = os.getcwd()
|
||||
try:
|
||||
# Change directory to not screw up directories
|
||||
os.chdir(self._dir2)
|
||||
c.compile([os.path.basename(self._src2)], output_dir=self._dir2,
|
||||
extra_postargs=extra_link_args)
|
||||
# Ensure that the object exists
|
||||
assert_(os.path.isfile(self._src2.replace('.c', '.o')))
|
||||
finally:
|
||||
os.chdir(previousDir)
|
Reference in New Issue
Block a user