8000 Merge pull request #9645 from xoviat/appveyor · numpy/numpy@d05fd30 · GitHub
[go: up one dir, main page]

Skip to content

Commit d05fd30

Browse files
authored
Merge pull request #9645 from xoviat/appveyor
ENH: enable OpenBLAS on windows.
2 parents 697609c + 448bb82 commit d05fd30

File tree

9 files changed

+220
-36
lines changed

9 files changed

+220
-36
lines changed

appveyor.yml

Lines changed: 184 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,195 @@
1-
skip_tags: true
2-
clone_depth: 1
1+
# As config was originally based on an example by Olivier Grisel. Thanks!
2+
# https://github.com/ogrisel/python-appveyor-demo/blob/master/appveyor.yml
3+
clone_depth: 50
34

4-
os: Visual Studio 2015
5+
# No reason for us to restrict the number concurrent jobs
6+
max_jobs: 100
7+
8+
cache:
9+
- '%LOCALAPPDATA%\pip\Cache'
510

611
environment:
12+
global:
13+
MINGW_32: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin
14+
MINGW_64: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin
15+
OPENBLAS_32: https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com/openblas-5f998ef_gcc7_1_0_win32.zip
16+
OPENBLAS_64: https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com/openblas-5f998ef_gcc7_1_0_win64.zip
17+
APPVEYOR_SAVE_CACHE_ON_ERROR: true
18+
APPVEYOR_SKIP_FINALIZE_ON_EXIT: true
19+
TEST_TIMEOUT: 1000
20+
721
matrix:
8-
- PY_MAJOR_VER: 2
9-
PYTHON_ARCH: "x86"
10-
- PY_MAJOR_VER: 3
11-
PYTHON_ARCH: "x86_64"
12-
- PY_MAJOR_VER: 3
13-
PYTHON_ARCH: "x86"
22+
- PYTHON: C:\Python36
23+
PYTHON_VERSION: 3.6
24+
PYTHON_ARCH: 32
25+
TEST_MODE: fast
1426

15-
build_script:
16-
# If there's a newer build queued for the same PR, cancel this one
27+
- PYTHON: C:\Python27-x64
28+
PYTHON_VERSION: 2.7
29+
PYTHON_ARCH: 64
30+
TEST_MODE: fast
31+
32+
- PYTHON: C:\Python34-x64
33+
PYTHON_VERSION: 3.4
34+
PYTHON_ARCH: 64
35+
TEST_MODE: fast
36+
37+
- PYTHON: C:\Python36-x64
38+
PYTHON_VERSION: 3.6
39+
PYTHON_ARCH: 64
40+
TEST_MODE: full
41+
42+
- PYTHON: C:\Python27
43+
PYTHON_VERSION: 2.7
44+
PYTHON_ARCH: 32
45+
SKIP_NOTAG: true
46+
TEST_MODE: full
47+
48+
- PYTHON: C:\Python34
49+
PYTHON_VERSION: 3.4
50+
PYTHON_ARCH: 32
51+
SKIP_NOTAG: true
52+
TEST_MODE: full
53+
54+
- PYTHON: C:\Python35-x64
55+
PYTHON_VERSION: 3.5
56+
PYTHON_ARCH: 64
57+
SKIP_NOTAG: true
58+
TEST_MODE: full
59+
60+
- PYTHON: C:\Python35
61+
PYTHON_VERSION: 3.5
62+
PYTHON_ARCH: 32
63+
SKIP_NOTAG: true
64+
TEST_MODE: full
65+
66+
init:
67+
- "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
68+
- "ECHO \"%APPVEYOR_SCHEDULED_BUILD%\""
69+
# If there is a newer build queued for the same PR, cancel this one.
70+
# The AppVeyor 'rollout builds' option is supposed to serve the same
71+
# purpose but it is problematic because it tends to cancel builds pushed
72+
# directly to master instead of just PR builds (or the converse).
73+
# credits: JuliaLang developers.
1774
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
1875
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
1976
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
20-
throw "There are newer queued builds for this pull request, failing early." }
21-
- ps: Start-FileDownload "https://repo.continuum.io/miniconda/Miniconda$env:PY_MAJOR_VER-latest-Windows-$env:PYTHON_ARCH.exe" C:\Miniconda.exe; echo "Finished downloading miniconda"
22-
- cmd: C:\Miniconda.exe /S /D=C:\Py
23-
- SET PATH=C:\Py;C:\Py\Scripts;C:\Py\Library\bin;%PATH%
24-
- conda config --set always_yes yes
25-
- conda update conda
26-
- conda install cython nose pytz
27-
- pip install . -vvv
77+
Write-Host "There are newer queued builds for this pull request, skipping build."
78+
Exit-AppveyorBuild
79+
}
80+
- ps: |
81+
If (($env:SKIP_NOTAG -eq "true") -and ($env:APPVEYOR_REPO_TAG -ne "true")) {
82+
Write-Host "Skipping build, not at a tag."
83+
Exit-AppveyorBuild
84+
}
85+
86+
install:
87+
# Show size of cache
88+
- C:\cygwin\bin\du -hs "%LOCALAPPDATA%\pip\Cache"
89+
# Prepend newly installed Python to the PATH of this build (this cannot be
90+
# done from inside the powershell script as it would require to restart
91+
# the parent CMD process).
92+
- SET PATH=%PYTHON%;%PYTHON%\Scripts;%PATH%
93+
94+
# Check that we have the expected version and architecture for Python
95+
- python --version
96+
- >-
97+
%CMD_IN_ENV%
98+
python -c "import sys,platform,struct;
99+
print(sys.platform, platform.machine(), struct.calcsize('P') * 8, )"
100+
101+
# Install "openblas.a" to PYTHON\lib
102+
# Library provided by Matthew Brett at https://github.com/matthew-brett/build-openblas
103+
- ps: |
104+
$PYTHON_ARCH = $env:PYTHON_ARCH
105+
$PYTHON = $env:PYTHON
106+
If ($PYTHON_ARCH -eq 32) {
107+
$OPENBLAS = $env:OPENBLAS_32
108+
} Else {
109+
$OPENBLAS = $env:OPENBLAS_64
110+
}
111+
$clnt = new-object System.Net.WebClient
112+
$file = "$(New-TemporaryFile).zip"
113+
$tmpdir = New-TemporaryFile | %{ rm $_; mkdir $_ }
114+
$destination = "$PYTHON\lib\openblas.a"
115+
116+
echo $file
117+
echo $tmpdir
118+
echo $OPENBLAS
119+
120+
$clnt.DownloadFile($OPENBLAS,$file)
121+
Get-FileHash $file | Format-List
122+
123+
Expand-Archive $file $tmpdir
124+
125+
rm $tmpdir\$PYTHON_ARCH\lib\*.dll.a
126+
$lib = ls $tmpdir\$PYTHON_ARCH\lib\*.a | ForEach { ls $_ } | Select-Object -first 1
127+
echo $lib
128+
129+
cp $lib $destination
130+
ls $destination
131+
132+
# Upgrade to the latest pip.
133+
- '%CMD_IN_ENV% python -m pip install -U pip setuptools wheel'
134+
135+
# Install the numpy test dependencies.
136+
- '%CMD_IN_ENV% pip install -U --timeout 5 --retries 2 -r tools/ci/appveyor/requirements.txt'
137+
138+
build_script:
139+
# Here, we add MinGW to the path to be able to link an OpenBLAS.dll
140+
# We then use the import library from the DLL to compile with MSVC
141+
- ps: |
142+
$PYTHON_ARCH = $env:PYTHON_ARCH
143+
If ($PYTHON_ARCH -eq 32) {
144+
$MINGW = $env:MINGW_32
145+
} Else {
146+
$MINGW = $env:MINGW_64
147+
}
148+
$env:Path += ";$MINGW"
149+
$env:NPY_NUM_BUILD_JOBS = "4"
150+
mkdir dist
151+
pip wheel -v -v -v --wheel-dir=dist .
152+
153+
# For each wheel that pip has placed in the "dist" directory
154+
# First, upload the wheel to the "artifacts" tab and then
155+
# install the wheel. If we have only built numpy (as is the case here),
156+
# then there will be one wheel to install.
157+
158+
# This method is more representative of what will be distributed,
159+
# because it actually tests what the built wheels will be rather than
160+
# what 'setup.py install' will do and at it uploads the wheels so that
161+
# they can be inspected.
162+
163+
ls dist -r | Foreach-Object {
164+
appveyor PushArtifact $_.FullName
165+
pip install $_.FullName
166+
}
28167
29168
test_script:
30169
- python runtests.py -v -n
170+
171+
after_build:
172+
# Remove old or huge cache files to hopefully not exceed the 1GB cache limit.
173+
#
174+
# If the cache limit is reached, the cache will not be updated (of not even
175+
# created in the first run). So this is a trade of between keeping the cache
176+
# current and having a cache at all.
177+
# NB: This is done only `on_success` since the cache in uploaded only on
178+
# success anyway.
179+
- C:\cygwin\bin\find "%LOCALAPPDATA%\pip" -type f -mtime +360 -delete
180+
- C:\cygwin\bin\find "%LOCALAPPDATA%\pip" -type f -size +10M -delete
181+
- C:\cygwin\bin\find "%LOCALAPPDATA%\pip" -empty -delete
182+
# Show size of cache
183+
- C:\cygwin\bin\du -hs "%LOCALAPPDATA%\pip\Cache"
184+
185+
on_finish:
186+
# We can get a nice display of test results in the "test" tab with py.test
187+
# For now, this does nothing.
188+
- ps: |
189+
If (Test-Path .\junit-results.xml) {
190+
(new-object net.webclient).UploadFile(
191+
"https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)",
192+
(Resolve-Path .\junit-results.xml)
193+
)
194+
}
195+
$LastExitCode = 0

numpy/distutils/tests/test_system_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def have_compiler():
6868
try:
6969
if not compiler.initialized:
7070
compiler.initialize() # MSVC is different
71-
except DistutilsError:
71+
except (DistutilsError, ValueError):
7272
return False
7373
cmd = [compiler.cc]
7474
try:

numpy/f2py/tests/test_block_docstring.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from __future__ import division, absolute_import, print_function
22

33
import textwrap
4+
import sys
45
from . import util
56

6-
from numpy.testing import run_module_suite, assert_equal
7+
from numpy.testing import run_module_suite, assert_equal, dec
78

89
class TestBlockDocString(util.F2PyTest):
910
code = """
@@ -15,6 +16,7 @@ class TestBlockDocString(util.F2PyTest):
1516
END
1617
"""
1718

19+
@dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)')
1820
def test_block_docstring(self):
1921
expected = "'i'-array(2,3)\n"
2022
assert_equal(self.module.block.__doc__, expected)

numpy/f2py/tests/test_callback.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import math
44
import textwrap
5+
import sys
56

67
from numpy import array
78
from numpy.testing import run_module_suite, assert_, assert_equal, dec
@@ -119,6 +120,7 @@ def mth(self):
119120
r = t(a.mth)
120121
assert_(r == 9, repr(r))
121122

123+
@dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)')
122124
def test_string_callback(self):
123125

124126
def callback(code):

numpy/f2py/tests/test_common.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
from __future__ import division, absolute_import, print_function
22

33
import os
4-
5-
from numpy.testing import run_module_suite, assert_array_equal, dec
4+
import sys
65
import numpy as np
76
from . import util
87

8+
from numpy.testing import run_module_suite, assert_array_equal, dec
99

1010
def _path(*a):
1111
return os.path.join(*((os.path.dirname(__file__),) + a))
1212

1313
class TestCommonBlock(util.F2PyTest):
1414
sources = [_path('src', 'common', 'block.f')]
1515

16+
@dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)')
1617
def test_common_block(self):
1718
self.module.initcb()
1819
assert_array_equal(self.module.block.long_bn,

numpy/f2py/tests/util.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
import textwrap
1717
import re
1818
import random
19+
import numpy.f2py
1920

2021
from numpy.compat import asbytes, asstr
21-
import numpy.f2py
22-
from numpy.testing import SkipTest, temppath
22+
from numpy.testing import SkipTest, temppath, dec
23+
from importlib import import_module
2324

2425
try:
2526
from hashlib import md5
@@ -146,8 +147,7 @@ def build_module(source_files, options=[], skip=[], only=[], module_name=None):
146147
os.unlink(fn)
147148

148149
# Import
149-
__import__(module_name)
150-
return sys.modules[module_name]
150+
return import_module(module_name)
151151

152152

153153
@_memoize
@@ -319,6 +319,7 @@ class F2PyTest(object):
319319
module = None
320320
module_name = None
321321

322+
@dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)')
322323
def setup(self):
323324
if self.module is not None:
324325
return

numpy/ma/tests/test_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import pickle
1414
import operator
1515
import itertools
16+
import sys
1617
from functools import reduce
1718

1819

@@ -47,6 +48,7 @@
4748
ravel, repeat, reshape, resize, shape, sin, sinh, sometrue, sort, sqrt,
4849
subtract, sum, take, tan, tanh, transpose, where, zeros,
4950
)
51+
from numpy.testing import dec
5052

5153
pi = np.pi
5254

@@ -3632,6 +3634,8 @@ def test_varstd(self):
36323634
assert_almost_equal(np.sqrt(mXvar0[k]),
36333635
mX[:, k].compressed().std())
36343636

3637+
@dec.knownfailureif(sys.platform=='win32' and sys.version_info < (3, 6),
3638+
msg='Fails on Python < 3.6 (Issue #9671)')
36353639
@suppress_copy_mask_on_assignment
36363640
def test_varstd_specialcases(self):
36373641
# Test a special case for var

numpy/testing/tests/test_utils.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,15 +267,18 @@ def test_error_message(self):
267267
try:
268268
self._assert_func(np.array([1, 2]), np.matrix([1, 2]))
269269
except AssertionError as e:
270-
self.assertEqual(
271-
str(e),
272-
"\nArrays are not equal\n\n"
273-
"(shapes (2,), (1, 2) mismatch)\n"
274-
" x: array([1, 2])\n"
275-
" y: [repr failed for <matrix>: The truth value of an array "
276-
"with more than one element is ambiguous. Use a.any() or "
277-
"a.all()]")
278-
270+
msg = str(e)
271+
msg2 = msg.replace("shapes (2L,), (1L, 2L)", "shapes (2,), (1, 2)")
272+
msg_reference = "\nArrays are not equal\n\n" \
273+
"(shapes (2,), (1, 2) mismatch)\n" \
274+
" x: array([1, 2])\n" \
275+
" y: [repr failed for <matrix>: The truth value of an array " \
276+
"with more than one element is ambiguous. Use a.any() or " \
277+
"a.all()]"
278+
try:
279+
self.assertEqual(msg, msg_reference)
280+
except AssertionError:
281+
self.assertEqual(msg2, msg_reference)
279282

280283
class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
281284

tools/ci/appveyor/requirements.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cython
2+
nose
3+
pytest-timeout
4+
pytest-xdist
5+
pytest-env
6+
pytest-faulthandler

0 commit comments

Comments
 (0)
0