From 81c8b9e215f727ea0e2123c500e43e827cbc3059 Mon Sep 17 00:00:00 2001 From: Matthew Brett Date: Tue, 23 Aug 2016 13:53:43 -0700 Subject: [PATCH 01/16] CI: add appveyor script and files for wheels When we release, we will want to build the Windows wheels as well. --- appveyor.yml | 182 +++++++++++++++++++++++++++++ ci/appveyor/vcvars64.bat | 1 + ci/conda_recipe/README.md | 3 + ci/conda_recipe/bld.bat | 16 +++ ci/conda_recipe/build.sh | 37 ++++++ ci/conda_recipe/cfg_qt4agg.patch | 13 +++ ci/conda_recipe/condaversion.patch | 15 +++ ci/conda_recipe/meta.yaml | 74 ++++++++++++ ci/conda_recipe/osx-tk.patch | 60 ++++++++++ ci/conda_recipe/rctmp_pyside.patch | 19 +++ ci/conda_recipe/run_test.py | 29 +++++ ci/travis/setup.cfg | 2 + 12 files changed, 451 insertions(+) create mode 100644 appveyor.yml create mode 100644 ci/appveyor/vcvars64.bat create mode 100644 ci/conda_recipe/README.md create mode 100644 ci/conda_recipe/bld.bat create mode 100644 ci/conda_recipe/build.sh create mode 100644 ci/conda_recipe/cfg_qt4agg.patch create mode 100644 ci/conda_recipe/condaversion.patch create mode 100644 ci/conda_recipe/meta.yaml create mode 100644 ci/conda_recipe/osx-tk.patch create mode 100644 ci/conda_recipe/rctmp_pyside.patch create mode 100644 ci/conda_recipe/run_test.py create mode 100644 ci/travis/setup.cfg diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000000..a2c6b3f3b6db --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,182 @@ +# With infos from +# http://tjelvarolsson.com/blog/how-to-continuously-test-your-python-code-on-windows-using-appveyor/ +# https://packaging.python.org/en/latest/appveyor/ +# https://github.com/rmcgibbo/python-appveyor-conda-example + +# Backslashes in quotes need to be escaped: \ -> "\\" + +environment: + + global: + # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the + # /E:ON and /V:ON options are not enabled in the batch script intepreter + # See: http://stackoverflow.com/a/13751649/163740 + CMD_IN_ENV: "cmd /E:ON /V:ON /C obvci_appveyor_python_build_env.cmd" + # Workaround for https://github.com/conda/conda-build/issues/636 + PYTHONIOENCODING: "UTF-8" + TEST_ARGS: --no-pep8 + PYTEST_ARGS: -ra --timeout=300 --durations=25 #--cov-report= --cov=lib #-n %NUMBER_OF_PROCESSORS% + USE_PYTEST: no + #PYTHONHASHSEED: 0 # Workaround for pytest-xdist flaky colletion order + # # https://github.com/pytest-dev/pytest/issues/920 + # # https://github.com/pytest-dev/pytest/issues/1075 + + matrix: + # for testing purpose: numpy 1.8 on py2.7, for the rest use 1.10/latest + # theoretically the CONDA_INSTALL_LOCN could be only two: one for 32bit, + # one for 64bit because we construct envs anyway. But using one for the + # right python version is hopefully making it fast due to package caching. + - TARGET_ARCH: "x64" + CONDA_PY: "27" + CONDA_NPY: "18" + PYTHON_VERSION: "2.7" + TEST_ALL: "no" + CONDA_INSTALL_LOCN: "C:\\Miniconda-x64" + - TARGET_ARCH: "x64" + CONDA_PY: "34" + CONDA_NPY: "110" + PYTHON_VERSION: "3.4" + TEST_ALL: "no" + CONDA_INSTALL_LOCN: "C:\\Miniconda3-x64" + - TARGET_ARCH: "x64" + CONDA_PY: "35" + CONDA_NPY: "110" + PYTHON_VERSION: "3.5" + TEST_ALL: "no" + CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64" + - TARGET_ARCH: "x86" + CONDA_PY: "27" + CONDA_NPY: "18" + PYTHON_VERSION: "2.7" + # this variable influence pdf/svg and most importantly the latex related tests + # which triples the runtime of the tests (7-8min vs 30min). + # pick the one which seems to make the most problems and run it last, so that + # the rest of the tests can give feedback earlier + TEST_ALL: "yes" + CONDA_INSTALL_LOCN: "C:\\Miniconda" + +# We always use a 64-bit machine, but can build x86 distributions +# with the PYTHON_ARCH variable (which is used by CMD_IN_ENV). +platform: + - x64 + +# all our python builds have to happen in tests_script... +build: false + +init: + - cmd: "ECHO %PYTHON_VERSION% PYTEST=%USE_PYTEST% %CONDA_INSTALL_LOCN%" + +install: + - cmd: set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%; + - cmd: set PYTHONUNBUFFERED=1 + # for obvci_appveyor_python_build_env.cmd + - cmd: conda install -c pelson/channel/development --yes --quiet obvious-ci + # for msinttypes and newer stuff + - cmd: conda config --add channels conda-forge + - cmd: conda config --set show_channel_urls yes + - cmd: conda config --set always_yes true + # For building conda packages + - cmd: conda install --yes conda-build jinja2 anaconda-client + # this is now the downloaded conda... + - conda info -a + + # Fix the appveyor build environment to work with conda build + # workaround for missing vcvars64.bat in py34 64bit + - cmd: copy ci\appveyor\vcvars64.bat "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64" + + # For building, use a new environment which only includes the requirements for mpl + # same things as the requirements in ci/conda_recipe/meta.yaml + # if conda-forge gets a new pyqt, it might be nice to install it as well to have more backends + # https://github.com/conda-forge/conda-forge.github.io/issues/157#issuecomment-223536381 + - conda create -q -n test-environment python=%PYTHON_VERSION% + pip setuptools numpy python-dateutil freetype=2.6 msinttypes "tk=8.5" + pyparsing pytz tornado "libpng>=1.6.21,<1.7" "zlib=1.2" "cycler>=0.10" + nose mock sphinx + - activate test-environment + - cmd: echo %PYTHON_VERSION% %TARGET_ARCH% + - cmd: IF %PYTHON_VERSION% == 2.7 conda install -q functools32 + # pytest-cov>=2.3.1 due to https://github.com/pytest-dev/pytest-cov/issues/124 + - if x%USE_PYTEST% == xyes conda install -q pytest "pytest-cov>=2.3.1" pytest-timeout #pytest-xdist + + # Let the install prefer the static builds of the libs + - set LIBRARY_LIB=%CONDA_PREFIX%\Library\lib + - cmd: 'mkdir lib || cmd /c "exit /b 0"' + - copy /Y %LIBRARY_LIB%\zlibstatic.lib lib\z.lib + - copy /Y %LIBRARY_LIB%\libpng_static.lib lib\png.lib + # These z.lib / png.lib are not static versions but files which end up as + # dependencies to the dll file. This is fine for the conda build, but not here + # and for the wheels + - del %LIBRARY_LIB%\png.lib + - del %LIBRARY_LIB%\z.lib + - set MPLBASEDIRLIST=%CONDA_PREFIX%\Library\;. + # enables the local freetype build + - copy ci\travis\setup.cfg . + # Show the installed packages + versions + - conda list + +test_script: + # Now build the thing.. + - '%CMD_IN_ENV% python setup.py develop' + # these should show no z, png, or freetype dll... + - set "DUMPBIN=%VS140COMNTOOLS%\..\..\VC\bin\dumpbin.exe" + #- cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\_png*.pyd' + #- cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd' + - cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd | findstr freetype.*.dll && exit /b 1 || exit /b 0' + - cmd: '"%DUMPBIN%" /DEPENDENTS lib\\matplotlib\\_png*.pyd | findstr z.*.dll && exit /b 1 || exit /b 0' + - cmd: '"%DUMPBIN%" /DEPENDENTS lib\\matplotlib\\_png*.pyd | findstr png.*.dll && exit /b 1 || exit /b 0' + + # this are optional dependencies so that we don't skip so many tests... + - cmd: if x%TEST_ALL% == xyes; conda install -q pillow miktex inkscape + # missing packages on conda-forge for ffmpeg avconv mencoder imagemagick + - cmd: if x%TEST_ALL% == xyes; conda install -q -c menpo ffmpeg # a repackaged version + # This install sometimes failed randomly :-( + #- cmd: choco install imagemagick + + # Test import of tkagg backend + - python -c "import matplotlib as m; m.use('tkagg'); import matplotlib.pyplot as plt; print(plt.get_backend())" + # tests + - if x%USE_PYTEST% == xyes echo The following args are passed to pytest %PYTEST_ARGS% + - if x%USE_PYTEST% == xyes py.test %PYTEST_ARGS% %TEST_ARGS% + - if x%USE_PYTEST% == xno python tests.py %TEST_ARGS% + # Generate a html for visual tests + - python visual_tests.py + +after_test: + # After the tests were a success, build packages (wheels and conda) + + # Build the wheel with the static libs + # Hide the output, the copied files really clutter the build log... + - cmd: '%CMD_IN_ENV% python setup.py bdist_wheel > NUL:' + + # And now the conda build after a cleanup... + # cleanup build files so that they don't pollute the conda build but keep the wheel in dist... + - cmd: git clean -d -x -f -e dist/ + # cleanup the environment so that the test-environment does not leak into the conda build... + - cmd: set MPLBASEDIRLIST= + - cmd: set LIBRARY_LIB= + - cmd: deactivate + - cmd: path + - cmd: where python + - cmd: '%CMD_IN_ENV% conda config --get channels' + - cmd: '%CMD_IN_ENV% conda build -q .\ci\conda_recipe' + + # Move the conda package into the dist directory, to register it + # as an "artifact" for Appveyor. + - cmd: 'copy /Y %CONDA_INSTALL_LOCN%\conda-bld\win-32\*.bz2 dist || cmd /c "exit /b 0"' + - cmd: 'copy /Y %CONDA_INSTALL_LOCN%\conda-bld\win-64\*.bz2 dist || cmd /c "exit /b 0"' + - cmd: dir dist\ + - cmd: echo finished... + +artifacts: + - path: dist\* + name: packages + + - path: result_images\* + name: result_images + type: zip + +on_failure: + - python visual_tests.py + - echo zipping images after a failure... + - 7z a result_images.zip result_images\ |grep -v "Compressing" + - appveyor PushArtifact result_images.zip diff --git a/ci/appveyor/vcvars64.bat b/ci/appveyor/vcvars64.bat new file mode 100644 index 000000000000..c4659becc3ae --- /dev/null +++ b/ci/appveyor/vcvars64.bat @@ -0,0 +1 @@ +CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 \ No newline at end of file diff --git a/ci/conda_recipe/README.md b/ci/conda_recipe/README.md new file mode 100644 index 000000000000..7819c9f0c766 --- /dev/null +++ b/ci/conda_recipe/README.md @@ -0,0 +1,3 @@ +# conda package + +Up to now, this is mainly used to build a test conda package on windows on appveyor. \ No newline at end of file diff --git a/ci/conda_recipe/bld.bat b/ci/conda_recipe/bld.bat new file mode 100644 index 000000000000..a7810d418d2f --- /dev/null +++ b/ci/conda_recipe/bld.bat @@ -0,0 +1,16 @@ +set LIBPATH=%LIBRARY_LIB%; +set INCLUDE=%INCLUDE%;%PREFIX%\Library\include\freetype2 + +ECHO [directories] > setup.cfg +ECHO basedirlist = %LIBRARY_PREFIX% >> setup.cfg +ECHO [packages] >> setup.cfg +ECHO tests = False >> setup.cfg +ECHO sample_data = False >> setup.cfg +ECHO toolkits_tests = False >> setup.cfg + +@rem workaround for https://github.com/matplotlib/matplotlib/issues/6460 +@rem see also https://github.com/conda-forge/libpng-feedstock/pull/4 +copy /y %LIBRARY_LIB%\libpng16.lib %LIBRARY_LIB%\png.lib + +%PYTHON% setup.py install --single-version-externally-managed --record=record.txt +if errorlevel 1 exit 1 diff --git a/ci/conda_recipe/build.sh b/ci/conda_recipe/build.sh new file mode 100644 index 000000000000..c2967acb98cf --- /dev/null +++ b/ci/conda_recipe/build.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +if [ `uname` == Linux ]; then + pushd $PREFIX/lib + ln -s libtcl8.5.so libtcl.so + ln -s libtk8.5.so libtk.so + popd +fi + +cat < setup.cfg +[directories] +basedirlist = $PREFIX + +[packages] +tests = False +toolkit_tests = False +sample_data = False + +EOF + +# The macosx backend isn't building with conda at this stage. +if [ `uname` == Darwin ]; then +cat << EOF >> setup.cfg + +[gui_support] +tkagg = true +macosx = false + +EOF +fi + +cat setup.cfg +sed -i.bak "s|/usr/local|$PREFIX|" setupext.py + + +$PYTHON setup.py install --single-version-externally-managed --record=record.txt + diff --git a/ci/conda_recipe/cfg_qt4agg.patch b/ci/conda_recipe/cfg_qt4agg.patch new file mode 100644 index 000000000000..16e6fc6c3934 --- /dev/null +++ b/ci/conda_recipe/cfg_qt4agg.patch @@ -0,0 +1,13 @@ +diff --git setup.cfg.template setup.cfg.template +index cae6f67..fd11c79 100644 +--- setup.cfg.template ++++ setup.cfg.template +@@ -88,7 +88,7 @@ + # if you have disabled the relevent extension modules. Agg will be used + # by default. + # +-#backend = Agg ++backend = Qt4Agg + # + + [package_data] diff --git a/ci/conda_recipe/condaversion.patch b/ci/conda_recipe/condaversion.patch new file mode 100644 index 000000000000..915fda3bcc23 --- /dev/null +++ b/ci/conda_recipe/condaversion.patch @@ -0,0 +1,15 @@ +diff --git setup.py setup.py +index 8af8b6d..4e4f9d2 100644 +--- setup.py ++++ setup.py +@@ -57,6 +57,9 @@ + import versioneer + __version__ = versioneer.get_version() + ++# For conda builds... ++with open("__conda_version__.txt", "w") as f: ++ f.write(__version__) + + # These are the packages in the order we want to display them. This + # list may contain strings to create section headers for the display. + \ No newline at end of file diff --git a/ci/conda_recipe/meta.yaml b/ci/conda_recipe/meta.yaml new file mode 100644 index 000000000000..5f992efff571 --- /dev/null +++ b/ci/conda_recipe/meta.yaml @@ -0,0 +1,74 @@ +# Full credit goes to https://github.com/conda/conda-recipes for providing this recipe. +# It has been subsequently adapted for automated building with conda-forge and matplotlib. + +package: + name: matplotlib + version: 1.9.9 + +source: + path: ../../ + + patches: + # A patch to make Qt4Agg the default backend. + - cfg_qt4agg.patch # [linux] + # Patches the matplotlibrc template to default to Qt4. + - rctmp_pyside.patch # [not osx] + # dynamic version from git + # we can't use condas usual dynamic versions as setup.py uses + # multiprocessing during the configure stage and this seems to confuse conda-build. + # https://github.com/conda/conda-build/issues/1061 + - condaversion.patch + + +requirements: + build: + - python + - setuptools + - pkg-config # [not win] + - numpy x.x + - python-dateutil + - freetype 2.6* + - msinttypes # [win] + - cycler >=0.10 + - nose + - pyparsing + - pytz +# - py2cairo # [linux and py2k] + - tornado + - libpng >=1.6.21,<1.7 + - zlib 1.2* # [win] + - pyqt # [not osx] + - tk 8.5* # [linux] + - functools32 # [py2k] + + run: + - python + - numpy x.x + - cycler >=0.10 + - python-dateutil + - freetype 2.6* + - pytz + - pyparsing +# - py2cairo # [linux and py2k] + - libpng >=1.6.21,<1.7 + - pyqt # [not osx] + - tk 8.5* # [linux and win] + - functools32 # [py2k] + +test: + imports: + - matplotlib + - matplotlib.pyplot + +about: + home: http://matplotlib.org/ + license: PSF-based (http://matplotlib.org/users/license.html) + summary: Publication quality figures in Python + +extra: + recipe-maintainers: + - janschulz # only in the mpl repository + - mdboom # rest form conda-forge + - ocefpaf + - pelson + - tacaswell diff --git a/ci/conda_recipe/osx-tk.patch b/ci/conda_recipe/osx-tk.patch new file mode 100644 index 000000000000..1411225550e9 --- /dev/null +++ b/ci/conda_recipe/osx-tk.patch @@ -0,0 +1,60 @@ +diff --git setupext.py setupext.py +index ddf2ca1..b9e0729 100755 +--- setupext.py ++++ setupext.py +@@ -1659,52 +1659,11 @@ class BackendTkAgg(OptionalBackendPackage): + ext.library_dirs.extend([os.path.join(sys.prefix, 'dlls')]) + + elif sys.platform == 'darwin': +- # this config section lifted directly from Imaging - thanks to +- # the effbot! +- +- # First test for a MacOSX/darwin framework install + from os.path import join, exists +- framework_dirs = [ +- join(os.getenv('HOME'), '/Library/Frameworks'), +- '/Library/Frameworks', +- '/System/Library/Frameworks/', +- ] + +- # Find the directory that contains the Tcl.framework and +- # Tk.framework bundles. +- tk_framework_found = 0 +- for F in framework_dirs: +- # both Tcl.framework and Tk.framework should be present +- for fw in 'Tcl', 'Tk': +- if not exists(join(F, fw + '.framework')): +- break +- else: +- # ok, F is now directory with both frameworks. Continure +- # building +- tk_framework_found = 1 +- break +- if tk_framework_found: +- # For 8.4a2, we must add -I options that point inside +- # the Tcl and Tk frameworks. In later release we +- # should hopefully be able to pass the -F option to +- # gcc, which specifies a framework lookup path. +- +- tk_include_dirs = [ +- join(F, fw + '.framework', H) +- for fw in ('Tcl', 'Tk') +- for H in ('Headers', 'Versions/Current/PrivateHeaders') +- ] +- +- # For 8.4a2, the X11 headers are not included. Rather +- # than include a complicated search, this is a +- # hard-coded path. It could bail out if X11 libs are +- # not found... +- +- # tk_include_dirs.append('/usr/X11R6/include') +- frameworks = ['-framework', 'Tcl', '-framework', 'Tk'] +- ext.include_dirs.extend(tk_include_dirs) +- ext.extra_link_args.extend(frameworks) +- ext.extra_compile_args.extend(frameworks) ++ ext.include_dirs.append(join(sys.prefix, 'include')) ++ ext.libraries.extend(['tk8.5', 'tcl8.5']) ++ ext.library_dirs.append(join(sys.prefix, 'lib')) + + # you're still here? ok we'll try it this way... + else: diff --git a/ci/conda_recipe/rctmp_pyside.patch b/ci/conda_recipe/rctmp_pyside.patch new file mode 100644 index 000000000000..906803575a90 --- /dev/null +++ b/ci/conda_recipe/rctmp_pyside.patch @@ -0,0 +1,19 @@ +diff --git matplotlibrc.template matplotlibrc.template +index fdbbf26..6902fe9 100644 +--- matplotlibrc.template ++++ matplotlibrc.template +@@ -35,12 +35,12 @@ + # You can also deploy your own backend outside of matplotlib by + # referring to the module name (which must be in the PYTHONPATH) as + # 'module://my_backend'. +-backend : $TEMPLATE_BACKEND ++backend : Qt4Agg + + # If you are using the Qt4Agg backend, you can choose here + # to use the PyQt4 bindings or the newer PySide bindings to + # the underlying Qt4 toolkit. +-#backend.qt4 : PyQt4 # PyQt4 | PySide ++backend.qt4 : PyQt4 # PyQt4 | PySide + + # Note that this can be overridden by the environment variable + # QT_API used by Enthought Tool Suite (ETS); valid values are diff --git a/ci/conda_recipe/run_test.py b/ci/conda_recipe/run_test.py new file mode 100644 index 000000000000..fba57d981e5d --- /dev/null +++ b/ci/conda_recipe/run_test.py @@ -0,0 +1,29 @@ +import os +import platform +import sys + +import matplotlib +import matplotlib.pyplot +import matplotlib._cntr +import matplotlib._delaunay +import matplotlib._image +import matplotlib._path +import matplotlib._png +import matplotlib._tri +import matplotlib.backends._backend_agg +import matplotlib.ft2font +import matplotlib.ttconv +if platform.system() not in ['Windows']: + import matplotlib.backends._tkagg + +import pylab +import mpl_toolkits + +if int(os.getenv('GUI_TEST', 0)): + assert matplotlib.rcParams['backend.qt4'] == 'PyQt4' + + import matplotlib.pyplot as plt + plt.ioff() + plt.title('If this window displays, success: CLOSE TO CONTINUE TESTS') + plt.plot([1,2,5,9]) + plt.show() diff --git a/ci/travis/setup.cfg b/ci/travis/setup.cfg new file mode 100644 index 000000000000..61cdc102a0f8 --- /dev/null +++ b/ci/travis/setup.cfg @@ -0,0 +1,2 @@ +[test] +local_freetype=True \ No newline at end of file From 6f9f62df74135860ebc60c79d723867a14088391 Mon Sep 17 00:00:00 2001 From: Matthew Brett Date: Tue, 23 Aug 2016 16:01:05 -0700 Subject: [PATCH 02/16] BF: backport visual_tests.py file --- visual_tests.py | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 visual_tests.py diff --git a/visual_tests.py b/visual_tests.py new file mode 100644 index 000000000000..f395b9d21d0b --- /dev/null +++ b/visual_tests.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# This builds a html page of all images from the image comparison tests +# and opens that page in the browser. +# +# $ python visual_tests.py +# + +import os +import time +import six + +from collections import defaultdict + +def run(): + # Build a website for visual comparison + image_dir = "result_images" + # build the website + _html = "" + _html += """ + \n""" + _subdirs = [name for name in os.listdir(image_dir) if os.path.isdir(os.path.join(image_dir, name))] + # loop over all pictures + _row = '{0} {1}{2}{4}\n' + _failed = "" + _failed += "

Only Failed

" + _failed += "\n\n" + _has_failure = False + _body = "" + for subdir in _subdirs: + if subdir == "test_compare_images": + # these are the image which test the image comparison functions... + continue + pictures = defaultdict(dict) + for file in os.listdir(os.path.join(image_dir, subdir)): + if os.path.isdir(os.path.join(image_dir, subdir, file)): + continue + fn, fext = os.path.splitext(file) + if fext != ".png": + continue + # Always use / for URLs. + if "-failed-diff" in fn: + pictures[fn[:-12]]["f"] = "/".join((subdir, file)) + elif "-expected" in fn: + pictures[fn[:-9]]["e"] = "/".join((subdir, file)) + else: + pictures[fn]["c"] = "/".join((subdir, file)) + + _body += "

{0}

".format(subdir) + _body += "
nameactualexpecteddiff
\n\n" + for name, test in six.iteritems(pictures): + if test.get("f", None): + # a real failure in the image generation, resulting in different images + _has_failure = True + s = "(failed)" + failed = 'diff'.format(test.get("f", "")) + current = ''.format(test.get("c", "")) + _failed += _row.format(name, "", current, test.get("e", ""), failed) + elif test.get("c", None) is None: + # A failure in the test, resulting in no current image + _has_failure = True + s = "(failed)" + failed = '--' + current = '(Failure in test, no image produced)' + _failed += _row.format(name, "", current, test.get("e", ""), failed) + else: + s = "(passed)" + failed = '--' + current = ''.format(test.get("c", "")) + _body += _row.format(name, "", current, test.get("e", ""), failed) + _body += "
nameactualexpecteddiff
\n" + _failed += "\n" + if _has_failure: + _html += _failed + _html += _body + _html += "\n" + index = os.path.join(image_dir, "index.html") + with open(index, "w") as f: + f.write(_html) + try: + import webbrowser + webbrowser.open(index) + except: + print("Open {0} in a browser for a visual comparison.".format(str(index))) + +if __name__ == '__main__': + run() From 5cc1faa90de3dca784e5702bf4e638bed15d3477 Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Wed, 2 Dec 2015 23:19:38 +0100 Subject: [PATCH 03/16] BLD: Include conda dirs in basedir conda installs includes/libs in \Library, so adding this dir makes installing under conda much easier. --- setupext.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/setupext.py b/setupext.py index 5b84c0a4f121..b9c2bf8860e4 100755 --- a/setupext.py +++ b/setupext.py @@ -171,9 +171,15 @@ def get_base_dirs(): """ if options['basedirlist']: return options['basedirlist'] - + + win_bases = ['win32_static', ] + # on windows, we also add the \Library of the local interperter, as + # conda installs libs/includes there + if os.getenv('CONDA_DEFAULT_ENV'): + win_bases.append(os.path.join(os.getenv('CONDA_DEFAULT_ENV'), "Library")) + basedir_map = { - 'win32': ['win32_static', ], + 'win32': win_bases, 'darwin': ['/usr/local/', '/usr', '/usr/X11', '/opt/X11', '/opt/local'], 'sunos5': [os.getenv('MPLIB_BASE') or '/usr/local', ], From bdb7196b0ddcb99ad13c73e04b1a8a8151753d52 Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Wed, 2 Dec 2015 23:39:48 +0100 Subject: [PATCH 04/16] BLD: Add a way to influence basedirs with env vars --- setupext.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/setupext.py b/setupext.py index b9c2bf8860e4..a59be00c85ab 100755 --- a/setupext.py +++ b/setupext.py @@ -172,9 +172,12 @@ def get_base_dirs(): if options['basedirlist']: return options['basedirlist'] + if os.environ.get('MPLBASEDIRLIST'): + return os.environ.get('MPLBASEDIRLIST').split(os.pathsep) + win_bases = ['win32_static', ] - # on windows, we also add the \Library of the local interperter, as - # conda installs libs/includes there + # on conda windows, we also add the \Library of the local interperter, + # as conda installs libs/includes there if os.getenv('CONDA_DEFAULT_ENV'): win_bases.append(os.path.join(os.getenv('CONDA_DEFAULT_ENV'), "Library")) @@ -194,8 +197,11 @@ def get_include_dirs(): Returns a list of standard include directories on this platform. """ include_dirs = [os.path.join(d, 'include') for d in get_base_dirs()] - include_dirs.extend( - os.environ.get('CPLUS_INCLUDE_PATH', '').split(os.pathsep)) + if sys.platform != 'win32': + # gcc includes this dir automatically, so also look for headers in + # these dirs + include_dirs.extend( + os.environ.get('CPLUS_INCLUDE_PATH', '').split(os.pathsep)) return include_dirs From be582488514c794eb59f53343d9d0e67f4da7f62 Mon Sep 17 00:00:00 2001 From: Matthew Brett Date: Wed, 24 Aug 2016 10:24:24 -0700 Subject: [PATCH 05/16] CI: enable extra checks of Windows DLLs From suggestion by Jan Schulz. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a2c6b3f3b6db..bf16836d932e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -119,8 +119,8 @@ test_script: - '%CMD_IN_ENV% python setup.py develop' # these should show no z, png, or freetype dll... - set "DUMPBIN=%VS140COMNTOOLS%\..\..\VC\bin\dumpbin.exe" - #- cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\_png*.pyd' - #- cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd' + - cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\_png*.pyd' + - cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd' - cmd: '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd | findstr freetype.*.dll && exit /b 1 || exit /b 0' - cmd: '"%DUMPBIN%" /DEPENDENTS lib\\matplotlib\\_png*.pyd | findstr z.*.dll && exit /b 1 || exit /b 0' - cmd: '"%DUMPBIN%" /DEPENDENTS lib\\matplotlib\\_png*.pyd | findstr png.*.dll && exit /b 1 || exit /b 0' From 04c24cdd71a8d0f56b03cc4e4dda79ad01bf4742 Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Thu, 3 Dec 2015 15:11:24 +0100 Subject: [PATCH 06/16] BLD: also find newer freetype --- setupext.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setupext.py b/setupext.py index a59be00c85ab..a95aa248a347 100755 --- a/setupext.py +++ b/setupext.py @@ -957,7 +957,10 @@ def check(self): return "Using local version for testing" if sys.platform == 'win32': - check_include_file(get_include_dirs(), 'ft2build.h', 'freetype') + try: + check_include_file(get_include_dirs(), 'ft2build.h', 'freetype') + except CheckFailed: + check_include_file(get_include_dirs(), 'freetype2\\ft2build.h', 'freetype') return 'Using unknown version found on system.' status, output = getstatusoutput("freetype-config --ftversion") From affc50e369e1b99568f00cf8076fca857ff47ef0 Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Sat, 23 Jan 2016 21:16:29 +0100 Subject: [PATCH 07/16] Win: build with a local freetype Makes it possible to use the local freetype config option in setup.cfg. Parts of this commit are from https://github.com/jbmohler/matplotlib-winbuild --- build_alllocal.cmd | 32 ++++++ setup_external_compile.py | 228 ++++++++++++++++++++++++++++++++++++++ setupext.py | 75 ++++++++++--- 3 files changed, 318 insertions(+), 17 deletions(-) create mode 100644 build_alllocal.cmd create mode 100644 setup_external_compile.py diff --git a/build_alllocal.cmd b/build_alllocal.cmd new file mode 100644 index 000000000000..e7d2a00670ab --- /dev/null +++ b/build_alllocal.cmd @@ -0,0 +1,32 @@ +:: This assumes you have installed all the dependencies via conda packages: +:: # create a new environment with the required packages +:: conda create -n "matplotlib_build" python=3.4 numpy python-dateutil pyparsing pytz tornado pyqt cycler tk libpng zlib freetype +:: activate matplotlib_build +:: # this package is only available in the conda-forge channel +:: conda install -c conda-forge msinttypes + +set TARGET=bdist_wheel +IF [%1]==[] ( + echo Using default target: %TARGET% +) else ( + set TARGET=%1 + echo Using user supplied target: %TARGET% +) + +IF NOT DEFINED CONDA_DEFAULT_ENV ( + echo No Conda env activated: you need to create a conda env with the right packages and activate it! + GOTO:eof +) + +:: copy the libs which have "wrong" names +set LIBRARY_LIB=%CONDA_DEFAULT_ENV%\Library\lib +mkdir lib || cmd /c "exit /b 0" +copy %LIBRARY_LIB%\zlibstatic.lib lib\z.lib +copy %LIBRARY_LIB%\libpng_static.lib lib\png.lib + +:: Make the header files and the rest of the static libs available during the build +:: CONDA_DEFAULT_ENV is a env variable which is set to the currently active environment path +set MPLBASEDIRLIST=%CONDA_DEFAULT_ENV%\Library\;. + +:: build the target +python setup.py %TARGET% diff --git a/setup_external_compile.py b/setup_external_compile.py new file mode 100644 index 000000000000..25b7dcfb5325 --- /dev/null +++ b/setup_external_compile.py @@ -0,0 +1,228 @@ +""" +This file extracts and builds library dependencies libpng, zlib, & freetype2 on +MS Windows. It also extract tcl/tk for the header files. + +There are four possible build targets -- one for each permutation of VS 2008, +2010 and 32/64 bit. This builds the configuration that matches the Python +install that is executing. + +For Python 2.6, 2.7, 3.2: + +- VS 2008, 32 bit -- Windows SDK v7.0 +- VS 2008, 64 bit -- Windows SDK v7.0 + +For Python 3.3, 3.4: + +- VS 2010, 32 bit -- Windows SDK v7.1 +- VS 2010, 64 bit -- Windows SDK v7.1 +""" + +from __future__ import print_function, absolute_import +import sys +import platform +import os +import glob +import shutil +import zipfile +import tarfile +import distutils.msvc9compiler as msvc + +def fixproj(project_file, bit_target): + """ + :param bit_target: one of 'Win32' or 'x64' + """ + with open(project_file, 'r') as fd: + content = '\n'.join(line.strip() for line in fd if line.strip()) + content = content.replace('Win32', bit_target).replace('x64', bit_target) + with open(project_file, 'w') as fd: + fd.write(content) + +def tar_extract(tar_file, target): + with tarfile.open(tar_file, 'r:gz') as tgz: + tgz.extractall(target) + +def zip_extract(zip_file, target): + with zipfile.ZipFile(zip_file) as zf: + zf.extractall(target) + +# Configuration selection & declaration: +DEPSSRC = os.path.join(os.path.dirname(os.path.normpath(__file__)), 'deps_source') +DEPSBUILD = os.path.join(os.path.dirname(os.path.normpath(__file__)), 'build') +X64 = platform.architecture()[0] == '64bit' +PYVER = sys.version_info[:2] +VS2010 = PYVER >= (3, 3) +# If not VS2010, then use VS2008 + +VCVARSALL = None + +def prepare_build_cmd(build_cmd, **kwargs): + global VCVARSALL + if VCVARSALL == None: + candidate = msvc.find_vcvarsall(10.0 if VS2010 else 9.0) + if candidate == None: + raise RuntimeError('Microsoft VS {} required'.format('2010' if VS2010 else '2008')) + else: + VCVARSALL = candidate + + return build_cmd.format(vcvarsall=VCVARSALL, xXX='x64' if X64 else 'x86', **kwargs) + +def config_dir(): + segment = 'msvcr{}-x{}'.format('100' if VS2010 else '90', '64' if X64 else '32') + return os.path.join(DEPSBUILD, segment) + +def tcl_config_dir(): + return os.path.join(config_dir(), 'tcl85', 'include') + +def build_tcl(): + inclib = config_dir() + tcl_inclib = tcl_config_dir() + if not os.path.exists(tcl_inclib): + os.makedirs(tcl_inclib) + tcl_inclib_x11 = os.path.join(tcl_inclib, 'X11') + if not os.path.exists(tcl_inclib_x11): + os.makedirs(tcl_inclib_x11) + + distfile = os.path.join(DEPSSRC, 'tcl8513-src.zip') + compfile = os.path.join(tcl_inclib, 'tcl.h') + if not os.path.exists(compfile) or os.path.getmtime(distfile) > os.path.getmtime(compfile): + zip_extract(distfile, DEPSBUILD) + targetdir = os.path.join(DEPSBUILD, 'tcl8.5.13') + headers = glob.glob(os.path.join(targetdir, 'generic', '*.h')) + for filename in headers: + shutil.copy(filename, tcl_inclib) + + distfile = os.path.join(DEPSSRC, 'tk8513-src.zip') + compfile = os.path.join(tcl_inclib, 'tk.h') + if not os.path.exists(compfile) or os.path.getmtime(distfile) > os.path.getmtime(compfile): + zip_extract(distfile, DEPSBUILD) + targetdir = os.path.join(DEPSBUILD, 'tk8.5.13') + headers = glob.glob(os.path.join(targetdir, 'generic', '*.h')) + for filename in headers: + shutil.copy(filename, tcl_inclib) + headers = glob.glob(os.path.join(targetdir, 'xlib', 'X11', '*.*')) + for filename in headers: + shutil.copy(filename, tcl_inclib_x11) + +ZLIB_BUILD_CMD = """\ +@ECHO OFF +REM call "%ProgramFiles%\\Microsoft SDKs\\Windows\\v7.0\\Bin\\SetEnv.Cmd" /Release /{xXX} /xp +call "{vcvarsall}" {xXX} + +cd /D %ZLIB% +nmake -f win32\\Makefile.msc clean +nmake -f win32\\Makefile.msc +copy /Y /B *.dll %INCLIB% +copy /Y /B *.lib %INCLIB% +copy /Y /B zlib.lib %INCLIB%\\z.lib +copy /Y /B zlib.h %INCLIB% +copy /Y /B zconf.h %INCLIB% +""" + +def build_zlib(): + inclib = config_dir() + if not os.path.exists(inclib): + os.makedirs(inclib) + + distfile = os.path.join(DEPSSRC, 'zlib128.zip') + compfile = os.path.join(inclib, 'z.lib') + if os.path.exists(compfile) and os.path.getmtime(distfile) < os.path.getmtime(compfile): + # already built + return + + zip_extract(distfile, DEPSBUILD) + + cmdfile = os.path.join(DEPSBUILD, 'build_zlib.cmd') + with open(cmdfile, 'w') as cmd: + cmd.write(prepare_build_cmd(ZLIB_BUILD_CMD)) + + os.environ['INCLIB'] = inclib + os.environ['ZLIB'] = os.path.join(DEPSBUILD, 'zlib-1.2.8') + os.system(cmdfile) + +LIBPNG_BUILD_CMD = """\ +@ECHO OFF +REM call "%ProgramFiles%\\Microsoft SDKs\\Windows\\v7.0\\Bin\\SetEnv.Cmd" /Release /{xXX} /xp +call "{vcvarsall}" {xXX} +set CMAKE="cmake.exe" + +set BUILDDIR=%LIBPNG%-build +rd /S /Q %BUILDDIR% +%CMAKE% -G"NMake Makefiles" -H%LIBPNG% -B%BUILDDIR% ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DZLIB_INCLUDE_DIR=%INCLIB% ^ + -DZLIB_LIBRARY:FILEPATH=%INCLIB%\\zlib.lib ^ + -DPNG_STATIC=ON ^ + -DPNG_SHARED=OFF +copy /Y /B %BUILDDIR%\\pnglibconf.h %INCLIB% +copy /Y /B %LIBPNG%\\png.h %INCLIB% +copy /Y /B %LIBPNG%\\pngconf.h %INCLIB% +cd %BUILDDIR% +nmake -f Makefile +REM It's a static lib -- no *.dll in sight! +REM copy /Y /B *.dll %INCLIB% +copy /Y /B *.lib %INCLIB% +copy /Y /B libpng16_static.lib %INCLIB%\\png.lib +""" + +def build_libpng(): + inclib = config_dir() + if not os.path.exists(inclib): + os.mkdir(inclib) + + distfile = os.path.join(DEPSSRC, 'libpng-1.6.7.tar.gz') + compfile = os.path.join(inclib, 'png.lib') + if os.path.exists(compfile) and os.path.getmtime(distfile) < os.path.getmtime(compfile): + # already built + return + + tar_extract(distfile, DEPSBUILD) + + cmdfile = os.path.join(DEPSBUILD, 'build_libpng.cmd') + with open(cmdfile, 'w') as cmd: + cmd.write(prepare_build_cmd(LIBPNG_BUILD_CMD)) + + os.environ['INCLIB'] = inclib + os.environ['LIBPNG'] = os.path.join(DEPSBUILD, 'libpng-1.6.7') + os.system(cmdfile) + +FREETYPE_VERSION = '2.4.11' + +FREETYPE_BUILD_CMD = """\ +@ECHO OFF +REM call "%ProgramFiles%\\Microsoft SDKs\\Windows\\v7.0\\Bin\\SetEnv.Cmd" /Release /{xXX} /xp +call "{vcvarsall}" {xXX} +set MSBUILD=C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe + +rd /S /Q %FREETYPE%\\objs +%MSBUILD% %FREETYPE%\\builds\\win32\\{vc20xx}\\freetype.sln /t:Clean;Build /p:Configuration="{config}";Platform={WinXX} +xcopy /Y /E /Q %FREETYPE%\\include %INCLIB% +xcopy /Y /E /Q %FREETYPE%\\objs\\win32\\{vc20xx} %INCLIB% +copy /Y /B %FREETYPE%\\objs\\win32\\{vc20xx}\\*.lib %INCLIB%\\freetype.lib +""" + +def build_freetype(): + inclib = config_dir() + if not os.path.exists(inclib): + os.mkdir(inclib) + + distfile = os.path.join(DEPSSRC, 'ft2411.zip') + compfile = os.path.join(inclib, 'freetype.lib') + if os.path.exists(compfile) and os.path.getmtime(distfile) < os.path.getmtime(compfile): + # already built + return + + vc = 'vc2010' if VS2010 else 'vc2008' + WinXX = 'x64' if X64 else 'Win32' + + zip_extract(distfile, DEPSBUILD) + ft_dir = os.path.join(DEPSBUILD, 'freetype-2.4.11') + fixproj(os.path.join(ft_dir, 'builds', 'win32', vc, 'freetype.sln'), WinXX) + fixproj(os.path.join(ft_dir, 'builds', 'win32', vc, 'freetype.{}'.format('vcxproj' if VS2010 else 'vcproj')), WinXX) + + cmdfile = os.path.join(DEPSBUILD, 'build_freetype.cmd') + with open(cmdfile, 'w') as cmd: + cmd.write(prepare_build_cmd(FREETYPE_BUILD_CMD, vc20xx=vc, WinXX=WinXX, config='Release' if VS2010 else 'LIB Release')) + + os.environ['INCLIB'] = inclib + os.environ['FREETYPE'] = ft_dir + os.system(cmdfile) \ No newline at end of file diff --git a/setupext.py b/setupext.py index a95aa248a347..f8a891492695 100755 --- a/setupext.py +++ b/setupext.py @@ -61,7 +61,8 @@ def _get_xdg_cache_dir(): # This is the version of FreeType to use when building a local # version. It must match the value in -# lib/matplotlib.__init__.py +# lib/matplotlib.__init__.py and also needs to be changed below in the +# embedded windows build script (grep for "REMINDER" in this file) LOCAL_FREETYPE_VERSION = '2.6.1' # md5 hash of the freetype tarball LOCAL_FREETYPE_HASH = '348e667d728c597360e4a87c16556597' @@ -171,16 +172,16 @@ def get_base_dirs(): """ if options['basedirlist']: return options['basedirlist'] - + if os.environ.get('MPLBASEDIRLIST'): return os.environ.get('MPLBASEDIRLIST').split(os.pathsep) win_bases = ['win32_static', ] - # on conda windows, we also add the \Library of the local interperter, + # on conda windows, we also add the \Library of the local interperter, # as conda installs libs/includes there if os.getenv('CONDA_DEFAULT_ENV'): win_bases.append(os.path.join(os.getenv('CONDA_DEFAULT_ENV'), "Library")) - + basedir_map = { 'win32': win_bases, 'darwin': ['/usr/local/', '/usr', '/usr/X11', @@ -198,7 +199,7 @@ def get_include_dirs(): """ include_dirs = [os.path.join(d, 'include') for d in get_base_dirs()] if sys.platform != 'win32': - # gcc includes this dir automatically, so also look for headers in + # gcc includes this dir automatically, so also look for headers in # these dirs include_dirs.extend( os.environ.get('CPLUS_INCLUDE_PATH', '').split(os.pathsep)) @@ -1010,8 +1011,12 @@ def add_flags(self, ext): # Statically link to the locally-built freetype. # This is certainly broken on Windows. ext.include_dirs.insert(0, os.path.join(src_path, 'include')) + if sys.platform == 'win32': + libfreetype = 'libfreetype.lib' + else: + libfreetype = 'libfreetype.a' ext.extra_objects.insert( - 0, os.path.join(src_path, 'objs', '.libs', 'libfreetype.a')) + 0, os.path.join(src_path, 'objs', '.libs', libfreetype)) ext.define_macros.append(('FREETYPE_BUILD_TYPE', 'local')) else: pkg_config.setup_extension( @@ -1034,8 +1039,12 @@ def do_custom_build(self): 'build', 'freetype-{0}'.format(LOCAL_FREETYPE_VERSION)) # We've already built freetype - if os.path.isfile( - os.path.join(src_path, 'objs', '.libs', 'libfreetype.a')): + if sys.platform == 'win32': + libfreetype = 'libfreetype.lib' + else: + libfreetype = 'libfreetype.a' + + if os.path.isfile(os.path.join(src_path, 'objs', '.libs', libfreetype)): return tarball = 'freetype-{0}.tar.gz'.format(LOCAL_FREETYPE_VERSION) @@ -1107,15 +1116,47 @@ def do_custom_build(self): "{0} does not match expected hash.".format(tarball)) print("Building {0}".format(tarball)) - cflags = 'CFLAGS="{0} -fPIC" '.format(os.environ.get('CFLAGS', '')) - - subprocess.check_call( - ['tar', 'zxf', tarball], cwd='build') - subprocess.check_call( - [cflags + './configure --with-zlib=no --with-bzip2=no ' - '--with-png=no --with-harfbuzz=no'], shell=True, cwd=src_path) - subprocess.check_call( - [cflags + 'make'], shell=True, cwd=src_path) + if sys.platform != 'win32': + # compilation on all other platforms than windows + cflags = 'CFLAGS="{0} -fPIC" '.format(os.environ.get('CFLAGS', '')) + + subprocess.check_call( + ['tar', 'zxf', tarball], cwd='build') + subprocess.check_call( + [cflags + './configure --with-zlib=no --with-bzip2=no ' + '--with-png=no --with-harfbuzz=no'], shell=True, cwd=src_path) + subprocess.check_call( + [cflags + 'make'], shell=True, cwd=src_path) + else: + # compilation on windows + FREETYPE_BUILD_CMD = """\ +call "%ProgramFiles%\\Microsoft SDKs\\Windows\\v7.0\\Bin\\SetEnv.Cmd" /Release /{xXX} /xp +call "{vcvarsall}" {xXX} +set MSBUILD=C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe +rd /S /Q %FREETYPE%\\objs +%MSBUILD% %FREETYPE%\\builds\\windows\\{vc20xx}\\freetype.sln /t:Clean;Build /p:Configuration="{config}";Platform={WinXX} +:: move to the "normal" path for the unix builds... +mkdir %FREETYPE%\\objs\\.libs +:: REMINDER: fix when changing the version +copy %FREETYPE%\\objs\\{vc20xx}\\{xXX}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib +""" + from setup_external_compile import fixproj, prepare_build_cmd, VS2010, X64, tar_extract + vc = 'vc2010' if VS2010 else 'vc2008' + vc = 'vc2010' if VS2010 else 'vc2008' + WinXX = 'x64' if X64 else 'Win32' + tar_extract(tarball_path, "build") + + #fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.sln'), WinXX) + #fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.{}'.format( + # 'vcxproj' if VS2010 else 'vcproj')), WinXX) + + cmdfile = os.path.join("build", 'build_freetype.cmd') + with open(cmdfile, 'w') as cmd: + cmd.write(prepare_build_cmd(FREETYPE_BUILD_CMD, vc20xx=vc, WinXX=WinXX, + config='Release' if VS2010 else 'LIB Release')) + + os.environ['FREETYPE'] = src_path + subprocess.check_call([cmdfile], shell=True) class FT2Font(SetupPackage): From 696f215a5d1fb182bd8a1644164425f9f2eee94f Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Sat, 23 Jan 2016 21:57:01 +0100 Subject: [PATCH 08/16] CI: enable local freetype and use conda forge functools on py27 --- build_alllocal.cmd | 2 ++ ci/conda_recipe/meta.yaml | 1 - setupext.py | 7 ++++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/build_alllocal.cmd b/build_alllocal.cmd index e7d2a00670ab..37560d1830de 100644 --- a/build_alllocal.cmd +++ b/build_alllocal.cmd @@ -4,6 +4,8 @@ :: activate matplotlib_build :: # this package is only available in the conda-forge channel :: conda install -c conda-forge msinttypes +:: if you build on py2.7: +:: conda install -c conda-forge functools32 set TARGET=bdist_wheel IF [%1]==[] ( diff --git a/ci/conda_recipe/meta.yaml b/ci/conda_recipe/meta.yaml index 5f992efff571..88cf1cfd6fd1 100644 --- a/ci/conda_recipe/meta.yaml +++ b/ci/conda_recipe/meta.yaml @@ -19,7 +19,6 @@ source: # https://github.com/conda/conda-build/issues/1061 - condaversion.patch - requirements: build: - python diff --git a/setupext.py b/setupext.py index f8a891492695..42084096a91d 100755 --- a/setupext.py +++ b/setupext.py @@ -1135,10 +1135,15 @@ def do_custom_build(self): set MSBUILD=C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe rd /S /Q %FREETYPE%\\objs %MSBUILD% %FREETYPE%\\builds\\windows\\{vc20xx}\\freetype.sln /t:Clean;Build /p:Configuration="{config}";Platform={WinXX} +echo Build completed, moving result" :: move to the "normal" path for the unix builds... mkdir %FREETYPE%\\objs\\.libs :: REMINDER: fix when changing the version -copy %FREETYPE%\\objs\\{vc20xx}\\{xXX}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib +copy %FREETYPE%\\objs\\{vc20xx}\\{xXX}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib +if errorlevel 1 ( + rem This is a py27 version, which has a different location for the lib file :-/ + copy %FREETYPE%\\objs\\{WinXX}\\{vc20xx}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib +) """ from setup_external_compile import fixproj, prepare_build_cmd, VS2010, X64, tar_extract vc = 'vc2010' if VS2010 else 'vc2008' From e2a4e0bbb92d8559e32c967f103e31718dd982b1 Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Mon, 25 Jan 2016 19:51:12 +0100 Subject: [PATCH 09/16] CI/Win: also build a local freetype on py27 64bit --- setupext.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setupext.py b/setupext.py index 42084096a91d..dbc398bd518e 100755 --- a/setupext.py +++ b/setupext.py @@ -1142,18 +1142,18 @@ def do_custom_build(self): copy %FREETYPE%\\objs\\{vc20xx}\\{xXX}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib if errorlevel 1 ( rem This is a py27 version, which has a different location for the lib file :-/ - copy %FREETYPE%\\objs\\{WinXX}\\{vc20xx}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib + copy %FREETYPE%\\objs\\win32\\{vc20xx}\\freetype261.lib %FREETYPE%\\objs\\.libs\\libfreetype.lib ) """ from setup_external_compile import fixproj, prepare_build_cmd, VS2010, X64, tar_extract - vc = 'vc2010' if VS2010 else 'vc2008' + # Note: freetype has no build profile for 2014, so we don't bother... vc = 'vc2010' if VS2010 else 'vc2008' WinXX = 'x64' if X64 else 'Win32' tar_extract(tarball_path, "build") - - #fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.sln'), WinXX) - #fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.{}'.format( - # 'vcxproj' if VS2010 else 'vcproj')), WinXX) + # This is only false for py2.7, even on py3.5... + if not VS2010: + fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.sln'), WinXX) + fixproj(os.path.join(src_path, 'builds', 'windows', vc, 'freetype.vcproj'), WinXX) cmdfile = os.path.join("build", 'build_freetype.cmd') with open(cmdfile, 'w') as cmd: From 22fb8ac113ae2d0237b889b46faddae15da76c6b Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Wed, 27 Jan 2016 20:35:16 +0100 Subject: [PATCH 10/16] TST: up tolerance for test_wedge_range affected: matplotlib.tests.test_patches.test_wedge_range.test (RMS 0.059) (x64,27) matplotlib.tests.test_patches.test_wedge_range.test (RMS 0.059) (x64,34) matplotlib.tests.test_patches.test_wedge_range.test (RMS 0.059) (x86,27) it seems that only the middle figure in the last row is different. Up the tolerance on windows to let the tests pass. --- lib/matplotlib/tests/test_patches.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 44856642b282..f844431d58d1 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -20,6 +20,9 @@ from matplotlib import path as mpath from matplotlib import transforms as mtrans +import sys +on_win = (sys.platform == 'win32') + def test_Polygon_close(): #: Github issue #1018 identified a bug in the Polygon handling @@ -250,7 +253,7 @@ def test_wedge_movement(): @image_comparison(baseline_images=['wedge_range'], - remove_text=True) + remove_text=True, tol=0.06 if on_win else 0) def test_wedge_range(): ax = plt.axes() From fdf35a09fb35393307265dc4033dfa36710a19fb Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Thu, 9 Jun 2016 15:04:43 +0200 Subject: [PATCH 11/16] TST: increase tolerance for test_patches.test_wedge_range --- lib/matplotlib/tests/test_patches.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index f844431d58d1..3cd550bd5ea8 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -252,8 +252,9 @@ def test_wedge_movement(): assert_equal(getattr(w, attr), new_v) +# png needs tol>=0.06, pdf tol>=1.617 @image_comparison(baseline_images=['wedge_range'], - remove_text=True, tol=0.06 if on_win else 0) + remove_text=True, tol=1.65 if on_win else 0) def test_wedge_range(): ax = plt.axes() From d4687c911a100b98fdc10c0e9a0fff7acd774eee Mon Sep 17 00:00:00 2001 From: Matthew Brett Date: Wed, 24 Aug 2016 17:02:38 -0700 Subject: [PATCH 12/16] MAINT: remove baseline images from Windows wheel Add and use script to remove baseline test images from Windows wheel. --- appveyor.yml | 3 +++ tools/rm_test_images.py | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tools/rm_test_images.py diff --git a/appveyor.yml b/appveyor.yml index bf16836d932e..be26f17ae2d4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -147,6 +147,9 @@ after_test: # Build the wheel with the static libs # Hide the output, the copied files really clutter the build log... - cmd: '%CMD_IN_ENV% python setup.py bdist_wheel > NUL:' + # Delete the result images from the wheel + - pip install delocate + - python tools\rm_test_images.py dist\*.whl # And now the conda build after a cleanup... # cleanup build files so that they don't pollute the conda build but keep the wheel in dist... diff --git a/tools/rm_test_images.py b/tools/rm_test_images.py new file mode 100644 index 000000000000..f53c1b12ff95 --- /dev/null +++ b/tools/rm_test_images.py @@ -0,0 +1,47 @@ +#!/usr/bin/env +""" Remove test images from matplotlib wheel(s) +""" +from __future__ import print_function + +from os.path import join as pjoin, basename, abspath, isdir +from shutil import rmtree +from argparse import ArgumentParser + +IMAGE_PATH = pjoin('matplotlib', 'tests', 'baseline_images') + +from delocate.wheeltools import InWheelCtx + + +def rm_images(whl_fname, out_fname, verbose=False): + whl_fname = abspath(whl_fname) + out_fname = abspath(out_fname) + with InWheelCtx(whl_fname) as ctx: + if not isdir(IMAGE_PATH): + if verbose: + print('No {} in {}'.format(IMAGE_PATH, whl_fname)) + return + rmtree(IMAGE_PATH) + # Write the wheel + ctx.out_wheel = out_fname + + +def get_parser(): + parser = ArgumentParser() + parser.add_argument('whl_fnames', nargs='+') + parser.add_argument('--verbose', action='store_true') + parser.add_argument('--out-path') + return parser + + +def main(): + args = get_parser().parse_args() + for whl_fname in args.whl_fnames: + out_fname = (pjoin(args.out_path, basename(whl_fname)) if args.out_path + else whl_fname) + if args.verbose: + print('Removing test images from {}'.format(whl_fname)) + rm_images(whl_fname, out_fname, verbose=args.verbose) + + +if __name__ == "__main__": + main() From bd10463514fda1dc215461b9f8b6d112eac907ee Mon Sep 17 00:00:00 2001 From: Matthew Brett Date: Wed, 24 Aug 2016 18:56:37 -0700 Subject: [PATCH 13/16] BF: fix finding of wheel with wildcard cmd shell does not do wildcard expansion. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index be26f17ae2d4..372d4812dab6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -149,7 +149,7 @@ after_test: - cmd: '%CMD_IN_ENV% python setup.py bdist_wheel > NUL:' # Delete the result images from the wheel - pip install delocate - - python tools\rm_test_images.py dist\*.whl + - cmd: for %%w in ("dist\*.whl") do python tools\rm_test_images.py %%w # And now the conda build after a cleanup... # cleanup build files so that they don't pollute the conda build but keep the wheel in dist... From 95f1e72f8552bfd27d079ae026f71e2f8fea53cf Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Wed, 27 Jan 2016 20:40:17 +0100 Subject: [PATCH 14/16] TST: up tolerance for test_tri_smooth_gradient affected: * matplotlib.tests.test_triangulation.test_tri_smooth_gradient.test (RMS 0.014) (x64,35) The diff looks pitch black to me... -> up the tolerance... --- lib/matplotlib/tests/test_triangulation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_triangulation.py b/lib/matplotlib/tests/test_triangulation.py index 06e56a3c6230..49a7d40baffb 100644 --- a/lib/matplotlib/tests/test_triangulation.py +++ b/lib/matplotlib/tests/test_triangulation.py @@ -14,6 +14,8 @@ import matplotlib.cm as cm from matplotlib.path import Path +import sys +on_win = (sys.platform == 'win32') def test_delaunay(): # No duplicate points, regular grid. @@ -770,7 +772,8 @@ def z(x, y): @image_comparison(baseline_images=['tri_smooth_gradient'], - extensions=['png'], remove_text=True) + extensions=['png'], remove_text=True, + tol=0.015 if on_win else 0) def test_tri_smooth_gradient(): # Image comparison based on example trigradient_demo. From 71372e710401c503306e99015cad048b99754b1c Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Tue, 26 Jan 2016 23:39:38 +0100 Subject: [PATCH 15/16] TST: some tex tests also need to guard against missing gs Also fixed a problem in an error message when bytes were appended to a string (fails on py3.x) by using %. One of the errors before: ====================================================================== ERROR: matplotlib.tests.test_backend_ps.test_savefig_to_stringio_with_usetex ---------------------------------------------------------------------- Traceback (most recent call last): File "lib\site-packages\nose\case.py", line 198, in runTest self.test(*self.arg) File "lib\matplotlib\testing\decorators.py", line 152, in wrapped_callable func(*args, **kwargs) File "lib\matplotlib\testing\decorators.py", line 55, in failer result = f(*args, **kwargs) File "lib\matplotlib\tests\test_backend_ps.py", line 77, in test_savefig_to_stringio_with_usetex _test_savefig_to_stringio() File "lib\matplotlib\tests\test_backend_ps.py", line 40, in _test_savefig_to_stringio fig.savefig(buffer, format=format) File "lib\matplotlib\figure.py", line 1698, in savefig self.canvas.print_figure(*args, **kwargs) File "lib\matplotlib\backend_bases.py", line 2232, in print_figure **kwargs) File "lib\matplotlib\backends\backend_ps.py", line 985, in print_ps return self._print_ps(outfile, 'ps', *args, **kwargs) File "lib\matplotlib\backends\backend_ps.py", line 1012, in _print_ps **kwargs) File "lib\matplotlib\backends\backend_ps.py", line 1376, in _print_figure_tex rotated=psfrag_rotated) File "lib\matplotlib\backends\backend_ps.py", line 1539, in gs_distill raise RuntimeError(m % output) RuntimeError: ghostscript was not able to process your image. Here is the full report generated by ghostscript: b'' --- lib/matplotlib/backends/backend_ps.py | 9 +++++++-- lib/matplotlib/tests/test_backend_ps.py | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index 7a0b983acaa6..b5d284cfffbd 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -1503,8 +1503,13 @@ def gs_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False): with io.open(outfile, 'rb') as fh: if exit_status: - raise RuntimeError('ghostscript was not able to process \ - your image.\nHere is the full report generated by ghostscript:\n\n' + fh.read()) + output = fh.read() + m = "\n".join(["ghostscript was not able to process your image.", + "Here is the full report generated by ghostscript:", + "", + "%s"]) + # use % to prevent problems with bytes + raise RuntimeError(m % output) else: verbose.report(fh.read(), 'debug') os.remove(outfile) diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index ae12c501ba14..f017164ff7bb 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -71,6 +71,7 @@ def test_savefig_to_stringio_with_distiller(): @cleanup @needs_tex +@needs_ghostscript def test_savefig_to_stringio_with_usetex(): matplotlib.rcParams['text.latex.unicode'] = True matplotlib.rcParams['text.usetex'] = True @@ -90,6 +91,7 @@ def test_savefig_to_stringio_eps_afm(): @cleanup @needs_tex +@needs_ghostscript def test_savefig_to_stringio_with_usetex_eps(): matplotlib.rcParams['text.latex.unicode'] = True matplotlib.rcParams['text.usetex'] = True From 83b840778a49f8d0b3bf33d963ae3cb2fafd5b4b Mon Sep 17 00:00:00 2001 From: Jan Schulz Date: Tue, 26 Jan 2016 22:02:32 +0100 Subject: [PATCH 16/16] TST: if no converter is found, skip the test --- lib/matplotlib/testing/compare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/testing/compare.py b/lib/matplotlib/testing/compare.py index 1d476d40e975..d5a41a611f7c 100644 --- a/lib/matplotlib/testing/compare.py +++ b/lib/matplotlib/testing/compare.py @@ -174,8 +174,8 @@ def convert(filename, cache): """ base, extension = filename.rsplit('.', 1) if extension not in converter: - raise ImageComparisonFailure( - "Don't know how to convert %s files to png" % extension) + from nose import SkipTest + raise SkipTest("Don't know how to convert %s files to png" % extension) newname = base + '_' + extension + '.png' if not os.path.exists(filename): raise IOError("'%s' does not exist" % filename) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy