aboutsummaryrefslogtreecommitdiff
path: root/libraries/matplotlib
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/matplotlib')
-rw-r--r--libraries/matplotlib/matplotlib.SlackBuild32
-rw-r--r--libraries/matplotlib/matplotlib.info8
-rw-r--r--libraries/matplotlib/setupext.py756
3 files changed, 292 insertions, 504 deletions
diff --git a/libraries/matplotlib/matplotlib.SlackBuild b/libraries/matplotlib/matplotlib.SlackBuild
index d50fcb6e1b5e8..980d4a7256b0a 100644
--- a/libraries/matplotlib/matplotlib.SlackBuild
+++ b/libraries/matplotlib/matplotlib.SlackBuild
@@ -2,17 +2,38 @@
# Slackware build script for matplotlib
+# Copyright 2011-2016 Serban Udrea <s.udrea@gsi.de>
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification,
+# is permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
# Written by Aleksandar Samardzic <asamardzic@gmail.com>
# Updated to 0.99.1.2 by João Felipe Santos <joao.eel@gmail.com>
# Patch for libpng borrowed from Arch Linux
-# Updated up to version 1.4.1 by Serban Udrea <S.Udrea@gsi.de>
+# Updated up to version 1.5.2 by Serban Udrea <S.Udrea@gsi.de>
PRGNAM=matplotlib
-VERSION=${VERSION:-1.4.2}
+VERSION=${VERSION:-1.5.2}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
-TARBALL_VERSION=1.4.2 # Tarball sometimes has a wrong version number
+TARBALL_VERSION=${TARBALL_VERSION:-1.5.2} # Tarball sometimes has a wrong version number
DISABLE_TESTS=${DISABLE_TESTS:-Y}
DISABLE_TK_TESTS=${DISABLE_TK_TESTS:-Y}
@@ -46,6 +67,7 @@ find -L . \
# Use setup.cfg to decide about the optional subpackages tests and
# toolkits_tests
+#
cat setup.cfg.template > setup.cfg
DISABLE_TESTS=$(echo "$DISABLE_TESTS"|cut -b 1|tr a-z A-Z)
@@ -69,10 +91,10 @@ fi
# Use modified setupext.py to make sure that the build process gets
# interrupted if requirements are not fulfilled
-
+#
cat "${CWD}/setupext.py" > setupext.py
-python setup.py install --root $PKG # > ${CWD}/SETUP.OUTPUT 2>&1
+python setup.py install --root $PKG # > ${CWD}/SETUP.OUTPUT 2>&1
find $PKG | xargs file | grep -e "executable" -e "shared object" | grep ELF \
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
diff --git a/libraries/matplotlib/matplotlib.info b/libraries/matplotlib/matplotlib.info
index 5bb124ca18274..cebbaa5b00943 100644
--- a/libraries/matplotlib/matplotlib.info
+++ b/libraries/matplotlib/matplotlib.info
@@ -1,10 +1,10 @@
PRGNAM="matplotlib"
-VERSION="1.4.2"
+VERSION="1.5.2"
HOMEPAGE="http://matplotlib.org/"
-DOWNLOAD="http://downloads.sourceforge.net/matplotlib/matplotlib-1.4.2.tar.gz"
-MD5SUM="7d22efb6cce475025733c50487bd8898"
+DOWNLOAD="https://pypi.python.org/packages/15/89/240b4ebcd63bcdde9aa522fbd2e13f0af3347bea443cb8ad111e3b4c6f3a/matplotlib-1.5.2.tar.gz#md5=66f35e55cc15455eb37b415ae51f1e51"
+MD5SUM="66f35e55cc15455eb37b415ae51f1e51"
DOWNLOAD_x86_64=""
MD5SUM_x86_64=""
-REQUIRES="numpy python-dateutil pytz six tornado pyparsing"
+REQUIRES="numpy python-dateutil pytz tornado pyparsing cycler"
MAINTAINER="Serban Udrea"
EMAIL="S.Udrea@gsi.de"
diff --git a/libraries/matplotlib/setupext.py b/libraries/matplotlib/setupext.py
index 1caadeb66c8f4..5a1939fa125e9 100644
--- a/libraries/matplotlib/setupext.py
+++ b/libraries/matplotlib/setupext.py
@@ -13,8 +13,11 @@ import sys
import warnings
from textwrap import fill
+import versioneer
-PY3 = (sys.version_info[0] >= 3)
+
+PY3min = (sys.version_info[0] >= 3)
+PY32min = (PY3min and sys.version_info[1] >= 2 or sys.version_info[0] > 3)
try:
@@ -44,13 +47,13 @@ except ImportError:
if sys.platform != 'win32':
- if sys.version_info[0] < 3:
+ if not PY3min:
from commands import getstatusoutput
else:
from subprocess import getstatusoutput
-if PY3:
+if PY3min:
import configparser
else:
import ConfigParser as configparser
@@ -67,7 +70,10 @@ options = {
setup_cfg = os.environ.get('MPLSETUPCFG', 'setup.cfg')
if os.path.exists(setup_cfg):
- config = configparser.SafeConfigParser()
+ if PY32min:
+ config = configparser.ConfigParser()
+ else:
+ config = configparser.SafeConfigParser()
config.read(setup_cfg)
try:
@@ -110,7 +116,7 @@ def extract_versions():
"""
with open('lib/matplotlib/__init__.py') as fd:
for line in fd.readlines():
- if (line.startswith('__version__')):
+ if (line.startswith('__version__numpy__')):
exec(line.strip())
return locals()
@@ -161,7 +167,10 @@ def get_include_dirs():
"""
Returns a list of standard include directories on this platform.
"""
- return [os.path.join(d, 'include') for d in get_base_dirs()]
+ 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))
+ return include_dirs
def is_min_version(found, minversion):
@@ -202,6 +211,8 @@ else:
# Remove the -Wstrict-prototypesoption, is it's not valid for C++
customize_compiler = sysconfig.customize_compiler
+
+
def my_customize_compiler(compiler):
retval = customize_compiler(compiler)
try:
@@ -251,8 +262,13 @@ class PkgConfig(object):
if sys.platform == 'win32':
self.has_pkgconfig = False
else:
+ try:
+ self.pkg_config = os.environ['PKG_CONFIG']
+ except KeyError:
+ self.pkg_config = 'pkg-config'
+
self.set_pkgconfig_path()
- status, output = getstatusoutput("pkg-config --help")
+ status, output = getstatusoutput(self.pkg_config + " --help")
self.has_pkgconfig = (status == 0)
if not self.has_pkgconfig:
print("IMPORTANT WARNING:")
@@ -285,7 +301,7 @@ class PkgConfig(object):
executable = alt_exec
if self.has_pkgconfig:
- executable = 'pkg-config {0}'.format(package)
+ executable = (self.pkg_config + ' {0}').format(package)
use_defaults = True
@@ -329,7 +345,7 @@ class PkgConfig(object):
return None
status, output = getstatusoutput(
- "pkg-config %s --modversion" % (package))
+ self.pkg_config + " %s --modversion" % (package))
if status == 0:
return output
return None
@@ -374,7 +390,6 @@ class SetupPackage(object):
"""
return []
-
def get_py_modules(self):
"""
Get a list of top-level modules to add to the configuration.
@@ -428,7 +443,9 @@ class SetupPackage(object):
`min_version` is the minimum version required.
`version` will override the found version if this package
- requires an alternate method for that.
+ requires an alternate method for that. Set version='unknown'
+ if the version is not known but you still want to disabled
+ pkg_config version check.
"""
if version is None:
version = pkg_config.get_version(package)
@@ -442,7 +459,7 @@ class SetupPackage(object):
raise CheckFailed(
"Requires patches that have not been merged upstream.")
- if min_version:
+ if min_version and version != 'unknown':
if (not is_min_version(version, min_version)):
raise CheckFailed(
"Requires %s %s or later. Found %s." %
@@ -453,7 +470,8 @@ class SetupPackage(object):
ext = make_extension('test', [])
pkg_config.setup_extension(ext, package)
- check_include_file(ext.include_dirs, include_file, package)
+ check_include_file(
+ ext.include_dirs + get_include_dirs(), include_file, package)
return 'version %s' % version
@@ -467,13 +485,17 @@ class OptionalPackage(SetupPackage):
def get_config(cls):
"""
Look at `setup.cfg` and return one of ["auto", True, False] indicating
- if the package is at default state ("auto"), forced by the user (True)
- or opted-out (False).
+ if the package is at default state ("auto"), forced by the user (case
+ insensitively defined as 1, true, yes, on for True) or opted-out (case
+ insensitively defined as 0, false, no, off for False).
"""
- try:
- return config.getboolean(cls.config_category, cls.name)
- except:
- return "auto"
+ conf = "auto"
+ if config is not None and config.has_option(cls.config_category, cls.name):
+ try:
+ conf = config.getboolean(cls.config_category, cls.name)
+ except ValueError:
+ conf = config.get(cls.config_category, cls.name)
+ return conf
def check(self):
"""
@@ -553,7 +575,7 @@ class Matplotlib(SetupPackage):
name = "matplotlib"
def check(self):
- return extract_versions()['__version__']
+ return versioneer.get_version()
def get_packages(self):
return [
@@ -588,13 +610,14 @@ class Matplotlib(SetupPackage):
'mpl-data/images/*.xpm',
'mpl-data/images/*.svg',
'mpl-data/images/*.gif',
+ 'mpl-data/images/*.pdf',
'mpl-data/images/*.png',
'mpl-data/images/*.ppm',
'mpl-data/example/*.npy',
'mpl-data/matplotlibrc',
'backends/web_backend/*.*',
- 'backends/web_backend/jquery/js/*',
- 'backends/web_backend/jquery/css/themes/base/*.*',
+ 'backends/web_backend/jquery/js/*.min.js',
+ 'backends/web_backend/jquery/css/themes/base/*.min.css',
'backends/web_backend/jquery/css/themes/base/images/*',
'backends/web_backend/css/*.*',
'backends/Matplotlib.nib/*',
@@ -643,9 +666,8 @@ class Tests(OptionalPackage):
msgs = []
msg_template = ('{package} is required to run the matplotlib test '
- 'suite. pip/easy_install may attempt to install it '
- 'after matplotlib.')
-
+ 'suite. Please install it with pip or your preferred'
+ ' tool to run the test suite')
bad_nose = msg_template.format(
package='nose %s or later' % self.nose_min_version
@@ -659,7 +681,6 @@ class Tests(OptionalPackage):
except ImportError:
msgs += [bad_nose]
-
if sys.version_info >= (3, 3):
msgs += ['using unittest.mock']
else:
@@ -674,6 +695,7 @@ class Tests(OptionalPackage):
def get_packages(self):
return [
'matplotlib.tests',
+ 'matplotlib.sphinxext.tests',
]
def get_package_data(self):
@@ -686,14 +708,13 @@ class Tests(OptionalPackage):
baseline_images +
[
'tests/mpltest.ttf',
- 'tests/test_rcparams.rc'
+ 'tests/test_rcparams.rc',
+ 'tests/test_utf32_be_rcparams.rc',
+ 'sphinxext/tests/tinypages/*.rst',
+ 'sphinxext/tests/tinypages/*.py',
+ 'sphinxext/tests/tinypages/_static/*',
]}
- def get_install_requires(self):
- requires = ['nose>=%s' % self.nose_min_version]
- if not sys.version_info >= (3, 3):
- requires += ['mock']
- return requires
class Toolkits_Tests(Tests):
name = "toolkits_tests"
@@ -815,11 +836,9 @@ class Numpy(SetupPackage):
except ImportError:
raise CheckFailed(
"could not be found" )
- #return 'not found. pip may install it below.'
-
if not is_min_version(numpy.__version__, min_version):
raise CheckFailed(
- "requires numpy %s or later to build; found %s" %
+ "requires numpy %s or later to build. (Found %s)" %
(min_version, numpy.__version__))
return 'version %s' % numpy.__version__
@@ -832,6 +851,9 @@ class Numpy(SetupPackage):
ext.define_macros.append(('PY_ARRAY_UNIQUE_SYMBOL', array_api_name))
ext.add_hook('include_dirs', self.include_dirs_hook)
+ ext.define_macros.append(('NPY_NO_DEPRECATED_API',
+ 'NPY_1_7_API_VERSION'))
+
def get_setup_requires(self):
return ['numpy>=1.6']
@@ -839,76 +861,6 @@ class Numpy(SetupPackage):
return ['numpy>=1.6']
-class CXX(SetupPackage):
- name = 'pycxx'
-
- def check(self):
- if PY3:
- # There is no version of PyCXX in the wild that will work
- # with Python 3.x and matplotlib, since they lack support
- # for the buffer object.
- self.__class__.found_external = False
- return ("Official versions of PyCXX are not compatible "
- "with matplotlib on Python 3.x, since they lack "
- "support for the buffer object. Using local "
- "copy")
-
- self.__class__.found_external = True
- old_stdout = sys.stdout
- if PY3:
- sys.stdout = io.StringIO()
- else:
- sys.stdout = io.BytesIO()
-
- try:
- import CXX
- except ImportError:
- self.__class__.found_external = False
- return "Couldn't import. Using local copy."
- finally:
- sys.stdout = old_stdout
-
- try:
- return self._check_for_pkg_config(
- 'PyCXX', 'CXX/Extensions.hxx', min_version='6.2.4')
- except CheckFailed as e:
- # It's ok to just proceed here, since the `import CXX`
- # worked above, and PyCXX (at least upstream) ensures that
- # its header files are on the default distutils include
- # path (either in a standard C place such as /usr/include,
- # or in /usr/include/pythonX.Y.
- return 'Using system CXX (version unknown, no pkg-config info)'
-
- def add_flags(self, ext):
- if self.found_external and not 'sdist' in sys.argv:
- support_dir = os.path.normpath(
- os.path.join(
- sys.prefix,
- 'share',
- 'python%d.%d' % (
- sys.version_info[0], sys.version_info[1]),
- 'CXX'))
- if not os.path.exists(support_dir):
- # On Fedora 17, these files are installed in /usr/share/CXX
- support_dir = '/usr/src/CXX'
- ext.sources.extend([
- os.path.join(support_dir, x) for x in
- ['cxxsupport.cxx', 'cxx_extensions.cxx',
- 'IndirectPythonInterface.cxx',
- 'cxxextensions.c']])
- pkg_config.setup_extension(ext, 'PyCXX')
- else:
- ext.include_dirs.append('extern')
- ext.sources.extend(glob.glob('extern/CXX/*.cxx'))
- ext.sources.extend(glob.glob('extern/CXX/*.c'))
- ext.define_macros.append(('PYCXX_ISO_CPP_LIB', '1'))
- if PY3:
- ext.define_macros.append(('PYCXX_PYTHON_2TO3', '1'))
- if not (sys.platform == 'win32' and win32_compiler == 'msvc'):
- ext.libraries.append('stdc++')
- ext.libraries.append('m')
-
-
class LibAgg(SetupPackage):
name = 'libagg'
@@ -921,23 +873,24 @@ class LibAgg(SetupPackage):
self.__class__.found_external = False
return str(e) + ' Using local copy.'
- def add_flags(self, ext):
+ def add_flags(self, ext, add_sources=True):
if self.found_external:
pkg_config.setup_extension(ext, 'libagg')
else:
- ext.include_dirs.append('extern/agg24/include')
- agg_sources = [
- 'agg_bezier_arc.cpp',
- 'agg_curves.cpp',
- 'agg_image_filters.cpp',
- 'agg_trans_affine.cpp',
- 'agg_vcgen_contour.cpp',
- 'agg_vcgen_dash.cpp',
- 'agg_vcgen_stroke.cpp',
- 'agg_vpgen_segmentator.cpp'
- ]
- ext.sources.extend(
- os.path.join('extern', 'agg24', 'src', x) for x in agg_sources)
+ ext.include_dirs.append('extern/agg24-svn/include')
+ if add_sources:
+ agg_sources = [
+ 'agg_bezier_arc.cpp',
+ 'agg_curves.cpp',
+ 'agg_image_filters.cpp',
+ 'agg_trans_affine.cpp',
+ 'agg_vcgen_contour.cpp',
+ 'agg_vcgen_dash.cpp',
+ 'agg_vcgen_stroke.cpp',
+ 'agg_vpgen_segmentator.cpp'
+ ]
+ ext.sources.extend(
+ os.path.join('extern', 'agg24-svn', 'src', x) for x in agg_sources)
class FreeType(SetupPackage):
@@ -959,12 +912,15 @@ class FreeType(SetupPackage):
if version is None or 'No such file or directory\ngrep:' in version:
version = self.version_from_header()
+ # pkg_config returns the libtool version rather than the
+ # freetype version so we need to explicitly pass the version
+ # to _check_for_pkg_config
return self._check_for_pkg_config(
'freetype2', 'ft2build.h',
min_version='2.3', version=version)
def version_from_header(self):
- version = 'Failed to identify version.'
+ version = 'unknown'
ext = self.get_extension()
if ext is None:
return version
@@ -997,19 +953,18 @@ class FreeType(SetupPackage):
default_libraries=['freetype', 'z'])
-
class FT2Font(SetupPackage):
name = 'ft2font'
def get_extension(self):
sources = [
'src/ft2font.cpp',
+ 'src/ft2font_wrapper.cpp',
'src/mplutils.cpp'
]
ext = make_extension('matplotlib.ft2font', sources)
FreeType().add_flags(ext)
Numpy().add_flags(ext)
- CXX().add_flags(ext)
return ext
@@ -1038,14 +993,14 @@ class Png(SetupPackage):
def get_extension(self):
sources = [
- 'src/_png.cpp', 'src/mplutils.cpp'
+ 'src/_png.cpp',
+ 'src/mplutils.cpp'
]
ext = make_extension('matplotlib._png', sources)
pkg_config.setup_extension(
ext, 'libpng', default_libraries=['png', 'z'],
alt_exec='libpng-config --ldflags')
Numpy().add_flags(ext)
- CXX().add_flags(ext)
return ext
@@ -1091,7 +1046,6 @@ class TTConv(SetupPackage):
]
ext = make_extension('matplotlib.ttconv', sources)
Numpy().add_flags(ext)
- CXX().add_flags(ext)
ext.include_dirs.append('extern')
return ext
@@ -1101,15 +1055,13 @@ class Path(SetupPackage):
def get_extension(self):
sources = [
- 'src/_path.cpp',
- 'src/path_cleanup.cpp',
- 'src/agg_py_transforms.cpp'
+ 'src/py_converters.cpp',
+ 'src/_path_wrapper.cpp'
]
ext = make_extension('matplotlib._path', sources)
Numpy().add_flags(ext)
LibAgg().add_flags(ext)
- CXX().add_flags(ext)
return ext
@@ -1118,17 +1070,18 @@ class Image(SetupPackage):
def get_extension(self):
sources = [
- 'src/_image.cpp', 'src/mplutils.cpp'
+ 'src/_image.cpp',
+ 'src/mplutils.cpp',
+ 'src/_image_wrapper.cpp'
]
ext = make_extension('matplotlib._image', sources)
Numpy().add_flags(ext)
LibAgg().add_flags(ext)
- CXX().add_flags(ext)
return ext
-class Contour(SetupPackage):
- name = "contour"
+class ContourLegacy(SetupPackage):
+ name = "contour_legacy"
def get_extension(self):
sources = [
@@ -1139,6 +1092,19 @@ class Contour(SetupPackage):
return ext
+class Contour(SetupPackage):
+ name = "contour"
+
+ def get_extension(self):
+ sources = [
+ "src/_contour.cpp",
+ "src/_contour_wrapper.cpp",
+ ]
+ ext = make_extension('matplotlib._contour', sources)
+ Numpy().add_flags(ext)
+ return ext
+
+
class Delaunay(SetupPackage):
name = "delaunay"
@@ -1172,50 +1138,51 @@ class Tri(SetupPackage):
def get_extension(self):
sources = [
"lib/matplotlib/tri/_tri.cpp",
+ "lib/matplotlib/tri/_tri_wrapper.cpp",
"src/mplutils.cpp"
]
ext = make_extension('matplotlib._tri', sources)
Numpy().add_flags(ext)
- CXX().add_flags(ext)
return ext
-class Six(SetupPackage):
- name = "six"
- min_version = "1.4"
+class Externals(SetupPackage):
+ name = "externals"
+
+ def get_packages(self):
+ return ['matplotlib.externals']
+
+
+class Pytz(SetupPackage):
+ name = "pytz"
def check(self):
try:
- import six
+ import pytz
except ImportError:
raise CheckFailed(
- "could not be found")
-
- if not is_min_version(six.__version__, self.min_version):
- raise CheckFailed(
- "requires six %s or later; found %s" %
- (self.min_version, six.__version__))
+ "could not be found")
- return "using six version %s" % six.__version__
+ return "using pytz version %s" % pytz.__version__
def get_install_requires(self):
- return ['six>={0}'.format(self.min_version)]
+ return ['pytz']
-class Pytz(SetupPackage):
- name = "pytz"
+class Cycler(SetupPackage):
+ name = "cycler"
def check(self):
try:
- import pytz
+ import cycler
except ImportError:
- raise CheckFailed (
+ raise CheckFailed(
"could not be found")
- return "using pytz version %s" % pytz.__version__
+ return "using cycler version %s" % cycler.__version__
def get_install_requires(self):
- return ['pytz']
+ return ['cycler']
class Dateutil(SetupPackage):
@@ -1237,12 +1204,13 @@ class Dateutil(SetupPackage):
#self.version = '!=2.1'
raise CheckFailed (
- "could not be found")
+ "could not be found")
+
major, minor1, _, _, _ = sys.version_info
if dateutil.__version__ == '2.1' and (major, minor1) == (3, 3):
raise CheckFailed (
- "dateutil v. 2.1 has a bug that breaks installation"
- "on python 3.3.x, use another dateutil version")
+ "dateutil v. 2.1 has a bug that breaks installation"
+ "on python 3.3.x, use another dateutil version")
return "using dateutil version %s" % dateutil.__version__
def get_install_requires(self):
@@ -1260,14 +1228,15 @@ class Tornado(SetupPackage):
import tornado
except ImportError:
raise CheckFailed (
- "could not be found")
+ "could not be found")
return "using tornado version %s" % tornado.version
class Pyparsing(SetupPackage):
name = "pyparsing"
-
+ # pyparsing 2.0.4 has broken python 3 support.
+ # pyparsing 2.1.2 is broken in python3.4/3.3.
def is_ok(self):
# pyparsing 2.0.0 bug, but it may be patched in distributions
try:
@@ -1282,14 +1251,14 @@ class Pyparsing(SetupPackage):
try:
import pyparsing
except ImportError:
- raise CheckFailed (
+ raise CheckFailed(
"could not be found")
required = [1, 5, 6]
if [int(x) for x in pyparsing.__version__.split('.')] < required:
- raise CheckFailed (
- "matplotlib requires pyparsing >= {0}; yours is ".format(
- '.'.join(str(x) for x in required)) + pyparsing.__version__)
+ raise CheckFailed(
+ "matplotlib requires pyparsing >= {0}".format(
+ '.'.join(str(x) for x in required)))
if not self.is_ok():
return (
@@ -1300,320 +1269,55 @@ class Pyparsing(SetupPackage):
return "using pyparsing version %s" % pyparsing.__version__
def get_install_requires(self):
+ versionstring = 'pyparsing>=1.5.6,!=2.0.4,!=2.1.2'
if self.is_ok():
- return ['pyparsing>=1.5.6']
+ return [versionstring]
else:
- return ['pyparsing>=1.5.6,!=2.0.0']
+ return [versionstring + ',!=2.0.0']
class BackendAgg(OptionalBackendPackage):
name = "agg"
+ force = True
def get_extension(self):
sources = [
"src/mplutils.cpp",
- "src/agg_py_transforms.cpp",
- "src/_backend_agg.cpp"
+ "src/py_converters.cpp",
+ "src/_backend_agg.cpp",
+ "src/_backend_agg_wrapper.cpp"
]
ext = make_extension('matplotlib.backends._backend_agg', sources)
Numpy().add_flags(ext)
LibAgg().add_flags(ext)
FreeType().add_flags(ext)
- CXX().add_flags(ext)
return ext
class BackendTkAgg(OptionalBackendPackage):
name = "tkagg"
+ force = True
- def __init__(self):
- self.tcl_tk_cache = None
-
- def check_requirements(self):
- try:
- if PY3:
- import tkinter as Tkinter
- else:
- import Tkinter
- except ImportError:
- raise CheckFailed('TKAgg requires Tkinter.')
- except RuntimeError:
- raise CheckFailed('Tkinter present but import failed.')
- else:
- if Tkinter.TkVersion < 8.3:
- raise CheckFailed("Tcl/Tk v8.3 or later required.")
-
- ext = self.get_extension()
- check_include_file(ext.include_dirs, "tk.h", "Tk")
-
- try:
- tk_v = Tkinter.__version__.split()[-2]
- except (AttributeError, IndexError):
- # Tkinter.__version__ has been removed in python 3
- tk_v = 'version not identified'
-
- BackendAgg.force = True
-
- return "version %s" % tk_v
+ def check(self):
+ return "installing; run-time loading from Python Tcl / Tk"
def get_extension(self):
sources = [
- 'src/agg_py_transforms.cpp',
+ 'src/py_converters.cpp',
'src/_tkagg.cpp'
]
ext = make_extension('matplotlib.backends._tkagg', sources)
self.add_flags(ext)
Numpy().add_flags(ext)
- LibAgg().add_flags(ext)
- CXX().add_flags(ext)
+ LibAgg().add_flags(ext, add_sources=False)
return ext
- def query_tcltk(self):
- """
- Tries to open a Tk window in order to query the Tk object
- about its library paths. This should never be called more
- than once by the same process, as Tk intricacies may cause the
- Python interpreter to hang. The function also has a workaround
- if no X server is running (useful for autobuild systems).
- """
- # Use cached values if they exist, which ensures this function
- # only executes once
- if self.tcl_tk_cache is not None:
- return self.tcl_tk_cache
-
- # By this point, we already know that Tkinter imports correctly
- if PY3:
- import tkinter as Tkinter
- else:
- import Tkinter
- tcl_lib_dir = ''
- tk_lib_dir = ''
- # First try to open a Tk window (requires a running X server)
- try:
- tk = Tkinter.Tk()
- except Tkinter.TclError:
- # Next, start Tcl interpreter without opening a Tk window
- # (no need for X server) This feature is available in
- # python version 2.4 and up
- try:
- tcl = Tkinter.Tcl()
- except AttributeError: # Python version not high enough
- pass
- except Tkinter.TclError: # Something went wrong while opening Tcl
- pass
- else:
- tcl_lib_dir = str(tcl.getvar('tcl_library'))
- # Guess Tk location based on Tcl location
- (head, tail) = os.path.split(tcl_lib_dir)
- tail = tail.replace('Tcl', 'Tk').replace('tcl', 'tk')
- tk_lib_dir = os.path.join(head, tail)
- if not os.path.exists(tk_lib_dir):
- tk_lib_dir = tcl_lib_dir.replace(
- 'Tcl', 'Tk').replace('tcl', 'tk')
- else:
- # Obtain Tcl and Tk locations from Tk widget
- tk.withdraw()
- tcl_lib_dir = str(tk.getvar('tcl_library'))
- tk_lib_dir = str(tk.getvar('tk_library'))
- tk.destroy()
-
- # Save directories and version string to cache
- self.tcl_tk_cache = tcl_lib_dir, tk_lib_dir, str(Tkinter.TkVersion)[:3]
- return self.tcl_tk_cache
-
- def parse_tcl_config(self, tcl_lib_dir, tk_lib_dir):
- try:
- if PY3:
- import tkinter as Tkinter
- else:
- import Tkinter
- except ImportError:
- return None
-
- tcl_poss = [tcl_lib_dir,
- os.path.normpath(os.path.join(tcl_lib_dir, '..')),
- "/usr/lib/tcl" + str(Tkinter.TclVersion),
- "/usr/lib"]
- tk_poss = [tk_lib_dir,
- os.path.normpath(os.path.join(tk_lib_dir, '..')),
- "/usr/lib/tk" + str(Tkinter.TkVersion),
- "/usr/lib"]
- for ptcl, ptk in zip(tcl_poss, tk_poss):
- tcl_config = os.path.join(ptcl, "tclConfig.sh")
- tk_config = os.path.join(ptk, "tkConfig.sh")
- if (os.path.exists(tcl_config) and os.path.exists(tk_config)):
- break
- if not (os.path.exists(tcl_config) and os.path.exists(tk_config)):
- return None
-
- def get_var(file, varname):
- p = subprocess.Popen(
- '. %s ; eval echo ${%s}' % (file, varname),
- shell=True,
- executable="/bin/sh",
- stdout=subprocess.PIPE)
- result = p.communicate()[0]
- return result.decode('ascii')
-
- tcl_lib_dir = get_var(
- tcl_config, 'TCL_LIB_SPEC').split()[0][2:].strip()
- tcl_inc_dir = get_var(
- tcl_config, 'TCL_INCLUDE_SPEC')[2:].strip()
- tcl_lib = get_var(tcl_config, 'TCL_LIB_FLAG')[2:].strip()
-
- tk_lib_dir = get_var(tk_config, 'TK_LIB_SPEC').split()[0][2:].strip()
- tk_inc_dir = get_var(tk_config, 'TK_INCLUDE_SPEC').strip()
- if tk_inc_dir == '':
- tk_inc_dir = tcl_inc_dir
- else:
- tk_inc_dir = tk_inc_dir[2:]
- tk_lib = get_var(tk_config, 'TK_LIB_FLAG')[2:].strip()
-
- if not os.path.exists(os.path.join(tk_inc_dir, 'tk.h')):
- return None
-
- return (tcl_lib_dir, tcl_inc_dir, tcl_lib,
- tk_lib_dir, tk_inc_dir, tk_lib)
-
- def guess_tcl_config(self, tcl_lib_dir, tk_lib_dir, tk_ver):
- if not (os.path.exists(tcl_lib_dir) and os.path.exists(tk_lib_dir)):
- return None
-
- tcl_lib = os.path.normpath(os.path.join(tcl_lib_dir, '../'))
- tk_lib = os.path.normpath(os.path.join(tk_lib_dir, '../'))
-
- tcl_inc = os.path.normpath(
- os.path.join(tcl_lib_dir,
- '../../include/tcl' + tk_ver))
- if not os.path.exists(tcl_inc):
- tcl_inc = os.path.normpath(
- os.path.join(tcl_lib_dir,
- '../../include'))
-
- tk_inc = os.path.normpath(os.path.join(
- tk_lib_dir,
- '../../include/tk' + tk_ver))
- if not os.path.exists(tk_inc):
- tk_inc = os.path.normpath(os.path.join(
- tk_lib_dir,
- '../../include'))
-
- if not os.path.exists(os.path.join(tk_inc, 'tk.h')):
- tk_inc = tcl_inc
-
- if not os.path.exists(tcl_inc):
- # this is a hack for suse linux, which is broken
- if (sys.platform.startswith('linux') and
- os.path.exists('/usr/include/tcl.h') and
- os.path.exists('/usr/include/tk.h')):
- tcl_inc = '/usr/include'
- tk_inc = '/usr/include'
-
- if not os.path.exists(os.path.join(tk_inc, 'tk.h')):
- return None
-
- return tcl_lib, tcl_inc, 'tcl' + tk_ver, tk_lib, tk_inc, 'tk' + tk_ver
-
- def hardcoded_tcl_config(self):
- tcl_inc = "/usr/local/include"
- tk_inc = "/usr/local/include"
- tcl_lib = "/usr/local/lib"
- tk_lib = "/usr/local/lib"
- return tcl_lib, tcl_inc, 'tcl', tk_lib, tk_inc, 'tk'
-
def add_flags(self, ext):
+ ext.include_dirs.extend(['src'])
if sys.platform == 'win32':
- major, minor1, minor2, s, tmp = sys.version_info
- if sys.version_info[0:2] < (3, 4):
- ext.include_dirs.extend(['win32_static/include/tcl85'])
- ext.libraries.extend(['tk85', 'tcl85'])
- else:
- ext.include_dirs.extend(['win32_static/include/tcl86'])
- ext.libraries.extend(['tk86t', 'tcl86t'])
- 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)
-
- # you're still here? ok we'll try it this way...
- else:
- # There are 3 methods to try, in decreasing order of "smartness"
- #
- # 1. Parse the tclConfig.sh and tkConfig.sh files that have
- # all the information we need
- #
- # 2. Guess the include and lib dirs based on the location of
- # Tkinter's 'tcl_library' and 'tk_library' variables.
- #
- # 3. Use some hardcoded locations that seem to work on a lot
- # of distros.
-
- # Query Tcl/Tk system for library paths and version string
- try:
- tcl_lib_dir, tk_lib_dir, tk_ver = self.query_tcltk()
- except:
- tk_ver = ''
- result = self.hardcoded_tcl_config()
- else:
- result = self.parse_tcl_config(tcl_lib_dir, tk_lib_dir)
- if result is None:
- result = self.guess_tcl_config(
- tcl_lib_dir, tk_lib_dir, tk_ver)
- if result is None:
- result = self.hardcoded_tcl_config()
-
- # Add final versions of directories and libraries to ext lists
- (tcl_lib_dir, tcl_inc_dir, tcl_lib,
- tk_lib_dir, tk_inc_dir, tk_lib) = result
- ext.include_dirs.extend([tcl_inc_dir, tk_inc_dir])
- ext.library_dirs.extend([tcl_lib_dir, tk_lib_dir])
- ext.libraries.extend([tcl_lib, tk_lib])
+ # PSAPI library needed for finding Tcl / Tk at run time
+ ext.libraries.extend(['psapi'])
class BackendGtk(OptionalBackendPackage):
@@ -1727,22 +1431,19 @@ class BackendGtkAgg(BackendGtk):
return super(BackendGtkAgg, self).check()
except:
raise
- else:
- BackendAgg.force = True
def get_package_data(self):
return {'matplotlib': ['mpl-data/*.glade']}
def get_extension(self):
sources = [
- 'src/agg_py_transforms.cpp',
+ 'src/py_converters.cpp',
'src/_gtkagg.cpp',
'src/mplutils.cpp'
]
ext = make_extension('matplotlib.backends._gtkagg', sources)
self.add_flags(ext)
LibAgg().add_flags(ext)
- CXX().add_flags(ext)
Numpy().add_flags(ext)
return ext
@@ -1786,16 +1487,25 @@ class BackendGtk3Agg(OptionalBackendPackage):
except:
return "unknown (can not use multiprocessing to determine)"
try:
- success, msg = p.map(backend_gtk3agg_internal_check, [0])[0]
+ res = p.map_async(backend_gtk3agg_internal_check, [0])
+ success, msg = res.get(timeout=10)[0]
+ except multiprocessing.TimeoutError:
+ p.terminate()
+ # No result returned. Probaly hanging, terminate the process.
+ success = False
+ raise CheckFailed("Check timed out")
except:
+ p.close()
+ # Some other error.
success = False
msg = "Could not determine"
- finally:
+ raise
+ else:
p.close()
+ finally:
p.join()
- if success:
- BackendAgg.force = True
+ if success:
return msg
else:
raise CheckFailed(msg)
@@ -1850,12 +1560,24 @@ class BackendGtk3Cairo(OptionalBackendPackage):
p = multiprocessing.Pool()
except:
return "unknown (can not use multiprocessing to determine)"
- success, msg = p.map(backend_gtk3cairo_internal_check, [0])[0]
- p.close()
- p.join()
- if success:
- BackendAgg.force = True
+ try:
+ res = p.map_async(backend_gtk3cairo_internal_check, [0])
+ success, msg = res.get(timeout=10)[0]
+ except multiprocessing.TimeoutError:
+ p.terminate()
+ # No result returned. Probaly hanging, terminate the process.
+ success = False
+ raise CheckFailed("Check timed out")
+ except:
+ p.close()
+ success = False
+ raise
+ else:
+ p.close()
+ finally:
+ p.join()
+ if success:
return msg
else:
raise CheckFailed(msg)
@@ -1868,20 +1590,22 @@ class BackendWxAgg(OptionalBackendPackage):
name = "wxagg"
def check_requirements(self):
+ wxversioninstalled = True
try:
import wxversion
except ImportError:
- raise CheckFailed("requires wxPython")
+ wxversioninstalled = False
- try:
- _wx_ensure_failed = wxversion.AlreadyImportedError
- except AttributeError:
- _wx_ensure_failed = wxversion.VersionError
+ if wxversioninstalled:
+ try:
+ _wx_ensure_failed = wxversion.AlreadyImportedError
+ except AttributeError:
+ _wx_ensure_failed = wxversion.VersionError
- try:
- wxversion.ensureMinimal('2.8')
- except _wx_ensure_failed:
- pass
+ try:
+ wxversion.ensureMinimal('2.8')
+ except _wx_ensure_failed:
+ pass
try:
import wx
@@ -1897,8 +1621,6 @@ class BackendWxAgg(OptionalBackendPackage):
raise CheckFailed(
"Requires wxPython 2.8, found %s" % backend_version)
- BackendAgg.force = True
-
return "version %s" % backend_version
@@ -1914,14 +1636,13 @@ class BackendMacOSX(OptionalBackendPackage):
def get_extension(self):
sources = [
'src/_macosx.m',
- 'src/agg_py_transforms.cpp',
+ 'src/py_converters.cpp',
'src/path_cleanup.cpp'
]
ext = make_extension('matplotlib.backends._macosx', sources)
Numpy().add_flags(ext)
LibAgg().add_flags(ext)
- CXX().add_flags(ext)
ext.extra_link_args.extend(['-framework', 'Cocoa'])
return ext
@@ -1938,7 +1659,7 @@ class Windowing(OptionalBackendPackage):
config = self.get_config()
if config is False:
raise CheckFailed("skipping due to configuration")
- return "installing"
+ return ""
def get_extension(self):
sources = [
@@ -1986,19 +1707,38 @@ class BackendQtBase(OptionalBackendPackage):
else:
# Multiprocessing OK
try:
- msg = p.map(self.callback, [self])[0]
+ res = p.map_async(self.callback, [self])
+ msg = res.get(timeout=10)[0]
+ except multiprocessing.TimeoutError:
+ p.terminate()
+ # No result returned. Probaly hanging, terminate the process.
+ raise CheckFailed("Check timed out")
except:
- # If we hit an error on multiprocessing raise it
+ # Some other error.
+ p.close()
raise
+ else:
+ # Clean exit
+ p.close()
finally:
# Tidy up multiprocessing
- p.close()
p.join()
return msg
-def backend_qt4_internal_check(self):
+def backend_pyside_internal_check(self):
+ try:
+ from PySide import __version__
+ from PySide import QtCore
+ except ImportError:
+ raise CheckFailed("PySide not found")
+ else:
+ return ("Qt: %s, PySide: %s" %
+ (QtCore.__version__, __version__))
+
+
+def backend_pyqt4_internal_check(self):
try:
from PyQt4 import QtCore
except ImportError:
@@ -2010,10 +1750,27 @@ def backend_qt4_internal_check(self):
except AttributeError:
raise CheckFailed('PyQt4 not correctly imported')
else:
- BackendAgg.force = True
return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str))
+def backend_qt4_internal_check(self):
+ successes = []
+ failures = []
+ try:
+ successes.append(backend_pyside_internal_check(self))
+ except CheckFailed as e:
+ failures.append(str(e))
+
+ try:
+ successes.append(backend_pyqt4_internal_check(self))
+ except CheckFailed as e:
+ failures.append(str(e))
+
+ if len(successes) == 0:
+ raise CheckFailed('; '.join(failures))
+ return '; '.join(successes + failures)
+
+
class BackendQt4(BackendQtBase):
name = "qt4agg"
@@ -2034,7 +1791,6 @@ def backend_qt5_internal_check(self):
except AttributeError:
raise CheckFailed('PyQt5 not correctly imported')
else:
- BackendAgg.force = True
return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str))
@@ -2046,27 +1802,6 @@ class BackendQt5(BackendQtBase):
self.callback = backend_qt5_internal_check
-def backend_pyside_internal_check(self):
- try:
- from PySide import __version__
- from PySide import QtCore
- except ImportError:
- raise CheckFailed("PySide not found")
- else:
- BackendAgg.force = True
- return ("Qt: %s, PySide: %s" %
- (QtCore.__version__, __version__))
-
-
-class BackendPySide(BackendQtBase):
- name = "pyside"
-
- def __init__(self, *args, **kwargs):
- BackendQtBase.__init__(self, *args, **kwargs)
- self.callback = backend_pyside_internal_check
-
-
-
class BackendCairo(OptionalBackendPackage):
name = "cairo"
@@ -2153,3 +1888,34 @@ class PdfToPs(SetupPackage):
pass
raise CheckFailed()
+
+
+class OptionalPackageData(OptionalPackage):
+ config_category = "package_data"
+
+
+class Dlls(OptionalPackageData):
+ """
+ On Windows, this packages any DLL files that can be found in the
+ lib/matplotlib/* directories.
+ """
+ name = "dlls"
+
+ def check_requirements(self):
+ if sys.platform != 'win32':
+ raise CheckFailed("Microsoft Windows only")
+
+ def get_package_data(self):
+ return {'': ['*.dll']}
+
+ @classmethod
+ def get_config(cls):
+ """
+ Look at `setup.cfg` and return one of ["auto", True, False] indicating
+ if the package is at default state ("auto"), forced by the user (True)
+ or opted-out (False).
+ """
+ try:
+ return config.getboolean(cls.config_category, cls.name)
+ except:
+ return False # <-- default