diff options
Diffstat (limited to 'development/python3-matplotlib')
| -rw-r--r-- | development/python3-matplotlib/README | 22 | ||||
| -rw-r--r-- | development/python3-matplotlib/python3-matplotlib.SlackBuild | 113 | ||||
| -rw-r--r-- | development/python3-matplotlib/python3-matplotlib.info | 10 | ||||
| -rw-r--r-- | development/python3-matplotlib/setupext.py | 1921 | ||||
| -rw-r--r-- | development/python3-matplotlib/slack-desc | 19 | 
5 files changed, 2085 insertions, 0 deletions
diff --git a/development/python3-matplotlib/README b/development/python3-matplotlib/README new file mode 100644 index 0000000000..abb309d987 --- /dev/null +++ b/development/python3-matplotlib/README @@ -0,0 +1,22 @@ +Matplotlib strives to produce publication quality 2D graphics for +interactive graphing, scientific publishing, user interface +development and web application servers targeting multiple user +interfaces and hardcopy output formats.  The 'pylab' mode +of ipython uses matplotlib to emulate matlab graphics. + +This is the Python 3 version of matplotlib and can coexist with +SBo's matplotlib package. + +NOTES: 1 - If you want to enable the optional subpackages tests +           and toolkits_tests you need to install Python 3 +           versions of nose and mock before matplotlib. THESE +           AREN'T YET AVAILABLE AS SLACKBUILDS! +           To enable the above mentioned subpackages you have to +           set the variables DISABLE_TESTS and DISABLE_TK_TESTS +           respectively to "no". +           toolkits_tests doesn't get installed, if test and/or +           toolkits are disabled. The installation of toolkits is +           done automatically. + +        2 - The python-dateutil and pytz dependencies must be +            compiled with Python 3 support. diff --git a/development/python3-matplotlib/python3-matplotlib.SlackBuild b/development/python3-matplotlib/python3-matplotlib.SlackBuild new file mode 100644 index 0000000000..39b5426fe4 --- /dev/null +++ b/development/python3-matplotlib/python3-matplotlib.SlackBuild @@ -0,0 +1,113 @@ +#!/bin/sh + +# Slackware build script for the Python 3 version of matplotlib + +# Copyright 2011-2017 Serban Udrea <s.udrea@gsi.de> +#                     Jeremy Hansen <jebrhansen+SBo -at- gmail.com> +# 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.5.2 by Serban Udrea <S.Udrea@gsi.de> +# Adapted for Python 3 by Jeremy Hansen + +PRGNAM=python3-matplotlib +SRCNAM=matplotlib +VERSION=${VERSION:-1.5.2} +BUILD=${BUILD:-1} +TAG=${TAG:-_SBo} + +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} + +if [ -z "$ARCH" ]; then +  case "$( uname -m )" in +    i?86) ARCH=i586 ;; +    arm*) ARCH=arm ;; +       *) ARCH=$( uname -m ) ;; +  esac +fi + +CWD=$(pwd) +TMP=${TMP:-/tmp/SBo} +PKG=${PKG:-$TMP/package-$PRGNAM} +OUTPUT=${OUTPUT:-/tmp} + +set -e + +rm -rf $PKG +mkdir -p $TMP $PKG $OUTPUT +cd $TMP +rm -rf $SRCNAM-$TARBALL_VERSION +tar xvf $CWD/$SRCNAM-$VERSION.tar.gz +cd $SRCNAM-$TARBALL_VERSION +chown -R root:root . +find -L . \ + \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \ +  -o -perm 511 \) -exec chmod 755 {} \; -o \ + \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \ +  -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; + +# 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) +DISABLE_TK_TESTS=$(echo "$DISABLE_TK_TESTS"|cut -b 1|tr a-z A-Z) + +if [ "$DISABLE_TESTS" = "Y" ] +then + sed -i "s|#tests = True|tests = False|" setup.cfg +else + python3 -c "import nose, mock" > /dev/null 2>&1 || \ + { echo "ERROR: Missing requirements nose and/or mock!" && exit 1; } +fi + +if [ "$DISABLE_TK_TESTS" = "Y" ] +then + sed -i "s|#toolkits_tests = auto|toolkits_tests = False|" setup.cfg +elif [ "$DISABLE_TESTS" = "Y" ] +then + echo "ERROR: Cannot enable toolkits_tests if tests are disabled!" && exit 1 +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 + +python3 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 + +mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION +cp -a CHANGELOG INSTALL $PKG/usr/doc/$PRGNAM-$VERSION +cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild + +mkdir -p $PKG/install +cat $CWD/slack-desc > $PKG/install/slack-desc + +cd $PKG +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.${PKGTYPE:-tgz} diff --git a/development/python3-matplotlib/python3-matplotlib.info b/development/python3-matplotlib/python3-matplotlib.info new file mode 100644 index 0000000000..b75ab6176d --- /dev/null +++ b/development/python3-matplotlib/python3-matplotlib.info @@ -0,0 +1,10 @@ +PRGNAM="python3-matplotlib" +VERSION="1.5.2" +HOMEPAGE="http://matplotlib.org/" +DOWNLOAD="https://pypi.python.org/packages/15/89/240b4ebcd63bcdde9aa522fbd2e13f0af3347bea443cb8ad111e3b4c6f3a/matplotlib-1.5.2.tar.gz" +MD5SUM="66f35e55cc15455eb37b415ae51f1e51" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="numpy3 python-dateutil pytz python3-tornado python3-pyparsing python3-cycler" +MAINTAINER="Serban Udrea" +EMAIL="S.Udrea@gsi.de" diff --git a/development/python3-matplotlib/setupext.py b/development/python3-matplotlib/setupext.py new file mode 100644 index 0000000000..5a1939fa12 --- /dev/null +++ b/development/python3-matplotlib/setupext.py @@ -0,0 +1,1921 @@ +from __future__ import print_function, absolute_import + +from distutils import sysconfig +from distutils import version +from distutils.core import Extension +import glob +import io +import multiprocessing +import os +import re +import subprocess +import sys +import warnings +from textwrap import fill + +import versioneer + + +PY3min = (sys.version_info[0] >= 3) +PY32min = (PY3min and sys.version_info[1] >= 2 or sys.version_info[0] > 3) + + +try: +    from subprocess import check_output +except ImportError: +    # check_output is not available in Python 2.6 +    def check_output(*popenargs, **kwargs): +        """ +        Run command with arguments and return its output as a byte +        string. + +        Backported from Python 2.7 as it's implemented as pure python +        on stdlib. +        """ +        process = subprocess.Popen( +            stdout=subprocess.PIPE, *popenargs, **kwargs) +        output, unused_err = process.communicate() +        retcode = process.poll() +        if retcode: +            cmd = kwargs.get("args") +            if cmd is None: +                cmd = popenargs[0] +            error = subprocess.CalledProcessError(retcode, cmd) +            error.output = output +            raise error +        return output + + +if sys.platform != 'win32': +    if not PY3min: +        from commands import getstatusoutput +    else: +        from subprocess import getstatusoutput + + +if PY3min: +    import configparser +else: +    import ConfigParser as configparser + + +# matplotlib build options, which can be altered using setup.cfg +options = { +    'display_status': True, +    'verbose': False, +    'backend': None, +    'basedirlist': None +    } + + +setup_cfg = os.environ.get('MPLSETUPCFG', 'setup.cfg') +if os.path.exists(setup_cfg): +    if PY32min: +        config = configparser.ConfigParser() +    else: +        config = configparser.SafeConfigParser() +    config.read(setup_cfg) + +    try: +        options['display_status'] = not config.getboolean("status", "suppress") +    except: +        pass + +    try: +        options['backend'] = config.get("rc_options", "backend") +    except: +        pass + +    try: +        options['basedirlist'] = [ +            x.strip() for x in +            config.get("directories", "basedirlist").split(',')] +    except: +        pass +else: +    config = None + + +def get_win32_compiler(): +    """ +    Determine the compiler being used on win32. +    """ +    # Used to determine mingw32 or msvc +    # This is pretty bad logic, someone know a better way? +    for v in sys.argv: +        if 'mingw32' in v: +            return 'mingw32' +    return 'msvc' +win32_compiler = get_win32_compiler() + + +def extract_versions(): +    """ +    Extracts version values from the main matplotlib __init__.py and +    returns them as a dictionary. +    """ +    with open('lib/matplotlib/__init__.py') as fd: +        for line in fd.readlines(): +            if (line.startswith('__version__numpy__')): +                exec(line.strip()) +    return locals() + + +def has_include_file(include_dirs, filename): +    """ +    Returns `True` if `filename` can be found in one of the +    directories in `include_dirs`. +    """ +    if sys.platform == 'win32': +        include_dirs += os.environ.get('INCLUDE', '.').split(';') +    for dir in include_dirs: +        if os.path.exists(os.path.join(dir, filename)): +            return True +    return False + + +def check_include_file(include_dirs, filename, package): +    """ +    Raises an exception if the given include file can not be found. +    """ +    if not has_include_file(include_dirs, filename): +        raise CheckFailed( +            "The C/C++ header for %s (%s) could not be found.  You " +            "may need to install the development package." % +            (package, filename)) + + +def get_base_dirs(): +    """ +    Returns a list of standard base directories on this platform. +    """ +    if options['basedirlist']: +        return options['basedirlist'] + +    basedir_map = { +        'win32': ['win32_static', ], +        'darwin': ['/usr/local/', '/usr', '/usr/X11', +                   '/opt/X11', '/opt/local'], +        'sunos5': [os.getenv('MPLIB_BASE') or '/usr/local', ], +        'gnu0': ['/usr'], +        'aix5': ['/usr/local'], +        } +    return basedir_map.get(sys.platform, ['/usr/local', '/usr']) + + +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)) +    return include_dirs + + +def is_min_version(found, minversion): +    """ +    Returns `True` if `found` is at least as high a version as +    `minversion`. +    """ +    expected_version = version.LooseVersion(minversion) +    found_version = version.LooseVersion(found) +    return found_version >= expected_version + + +# Define the display functions only if display_status is True. +if options['display_status']: +    def print_line(char='='): +        print(char * 76) + +    def print_status(package, status): +        initial_indent = "%22s: " % package +        indent = ' ' * 24 +        print(fill(str(status), width=76, +                   initial_indent=initial_indent, +                   subsequent_indent=indent)) + +    def print_message(message): +        indent = ' ' * 24 + "* " +        print(fill(str(message), width=76, +                   initial_indent=indent, +                   subsequent_indent=indent)) + +    def print_raw(section): +        print(section) +else: +    def print_line(*args, **kwargs): +        pass +    print_status = print_message = print_raw = print_line + + +# 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: +        compiler.compiler_so.remove('-Wstrict-prototypes') +    except (ValueError, AttributeError): +        pass +    return retval + +sysconfig.customize_compiler = my_customize_compiler + + +def make_extension(name, files, *args, **kwargs): +    """ +    Make a new extension.  Automatically sets include_dirs and +    library_dirs to the base directories appropriate for this +    platform. + +    `name` is the name of the extension. + +    `files` is a list of source files. + +    Any additional arguments are passed to the +    `distutils.core.Extension` constructor. +    """ +    ext = DelayedExtension(name, files, *args, **kwargs) +    for dir in get_base_dirs(): +        include_dir = os.path.join(dir, 'include') +        if os.path.exists(include_dir): +            ext.include_dirs.append(include_dir) +        for lib in ('lib', 'lib64'): +            lib_dir = os.path.join(dir, lib) +            if os.path.exists(lib_dir): +                ext.library_dirs.append(lib_dir) +    ext.include_dirs.append('.') + +    return ext + + +class PkgConfig(object): +    """ +    This is a class for communicating with pkg-config. +    """ +    def __init__(self): +        """ +        Determines whether pkg-config exists on this machine. +        """ +        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(self.pkg_config + " --help") +            self.has_pkgconfig = (status == 0) +            if not self.has_pkgconfig: +                print("IMPORTANT WARNING:") +                print( +                    "    pkg-config is not installed.\n" +                    "    matplotlib may not be able to find some of its dependencies") + +    def set_pkgconfig_path(self): +        pkgconfig_path = sysconfig.get_config_var('LIBDIR') +        if pkgconfig_path is None: +            return + +        pkgconfig_path = os.path.join(pkgconfig_path, 'pkgconfig') +        if not os.path.isdir(pkgconfig_path): +            return + +        try: +            os.environ['PKG_CONFIG_PATH'] += ':' + pkgconfig_path +        except KeyError: +            os.environ['PKG_CONFIG_PATH'] = pkgconfig_path + +    def setup_extension(self, ext, package, default_include_dirs=[], +                        default_library_dirs=[], default_libraries=[], +                        alt_exec=None): +        """ +        Add parameters to the given `ext` for the given `package`. +        """ +        flag_map = { +            '-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries'} + +        executable = alt_exec +        if self.has_pkgconfig: +            executable = (self.pkg_config + ' {0}').format(package) + +        use_defaults = True + +        if executable is not None: +            command = "{0} --libs --cflags ".format(executable) + +            try: +                output = check_output(command, shell=True, +                                      stderr=subprocess.STDOUT) +            except subprocess.CalledProcessError: +                pass +            else: +                output = output.decode(sys.getfilesystemencoding()) +                use_defaults = False +                for token in output.split(): +                    attr = flag_map.get(token[:2]) +                    if attr is not None: +                        getattr(ext, attr).insert(0, token[2:]) + +        if use_defaults: +            basedirs = get_base_dirs() +            for base in basedirs: +                for include in default_include_dirs: +                    dir = os.path.join(base, include) +                    if os.path.exists(dir): +                        ext.include_dirs.append(dir) +                for lib in default_library_dirs: +                    dir = os.path.join(base, lib) +                    if os.path.exists(dir): +                        ext.library_dirs.append(dir) +            ext.libraries.extend(default_libraries) +            return True + +        return False + +    def get_version(self, package): +        """ +        Get the version of the package from pkg-config. +        """ +        if not self.has_pkgconfig: +            return None + +        status, output = getstatusoutput( +            self.pkg_config + " %s --modversion" % (package)) +        if status == 0: +            return output +        return None + + +# The PkgConfig class should be used through this singleton +pkg_config = PkgConfig() + + +class CheckFailed(Exception): +    """ +    Exception thrown when a `SetupPackage.check` method fails. +    """ +    pass + + +class SetupPackage(object): +    optional = False + +    def check(self): +        """ +        Checks whether the dependencies are met.  Should raise a +        `CheckFailed` exception if the dependency could not be met, +        otherwise return a string indicating a version number or some +        other message indicating what was found. +        """ +        pass + +    def get_packages(self): +        """ +        Get a list of package names to add to the configuration. +        These are added to the `packages` list passed to +        `distutils.setup`. +        """ +        return [] + +    def get_namespace_packages(self): +        """ +        Get a list of namespace package names to add to the configuration. +        These are added to the `namespace_packages` list passed to +        `distutils.setup`. +        """ +        return [] + +    def get_py_modules(self): +        """ +        Get a list of top-level modules to add to the configuration. +        These are added to the `py_modules` list passed to +        `distutils.setup`. +        """ +        return [] + +    def get_package_data(self): +        """ +        Get a package data dictionary to add to the configuration. +        These are merged into to the `package_data` list passed to +        `distutils.setup`. +        """ +        return {} + +    def get_extension(self): +        """ +        Get a list of C extensions (`distutils.core.Extension` +        objects) to add to the configuration.  These are added to the +        `extensions` list passed to `distutils.setup`. +        """ +        return None + +    def get_install_requires(self): +        """ +        Get a list of Python packages that we require. +        pip/easy_install will attempt to download and install this +        package if it is not installed. +        """ +        return [] + +    def get_setup_requires(self): +        """ +        Get a list of Python packages that we require at build time. +        pip/easy_install will attempt to download and install this +        package if it is not installed. +        """ +        return [] + +    def _check_for_pkg_config(self, package, include_file, min_version=None, +                              version=None): +        """ +        A convenience function for writing checks for a +        pkg_config-defined dependency. + +        `package` is the pkg_config package name. + +        `include_file` is a top-level include file we expect to find. + +        `min_version` is the minimum version required. + +        `version` will override the found version if this package +        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) + +            if version is None: +                raise CheckFailed( +                    "pkg-config information for '%s' could not be found." % +                    package) + +        if min_version == 'PATCH': +            raise CheckFailed( +                "Requires patches that have not been merged upstream.") + +        if min_version and version != 'unknown': +            if (not is_min_version(version, min_version)): +                raise CheckFailed( +                    "Requires %s %s or later.  Found %s." % +                    (package, min_version, version)) + +        ext = self.get_extension() +        if ext is None: +            ext = make_extension('test', []) +            pkg_config.setup_extension(ext, package) + +        check_include_file( +            ext.include_dirs + get_include_dirs(), include_file, package) + +        return 'version %s' % version + + +class OptionalPackage(SetupPackage): +    optional = True +    force = False +    config_category = "packages" + +    @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 (case +        insensitively defined as 1, true, yes, on for True) or opted-out (case +        insensitively defined as 0, false, no, off for False). +        """ +        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): +        """ +        Do not override this method! + +        For custom dependency checks override self.check_requirements(). +        Two things are checked: Configuration file and requirements. +        """ +        # Check configuration file +        conf = self.get_config() +        # Default "auto" state or install forced by user +        if conf in [True, 'auto']: +            message = "installing" +            # Set non-optional if user sets `True` in config +            if conf is True: +                self.optional = False +        # Configuration opt-out by user +        else: +            # Some backend extensions (e.g. Agg) need to be built for certain +            # other GUI backends (e.g. TkAgg) even when manually disabled +            if self.force is True: +                message = "installing forced (config override)" +            else: +                raise CheckFailed("skipping due to configuration") + +        # Check requirements and add extra information (if any) to message. +        # If requirements are not met a CheckFailed should be raised in there. +        additional_info = self.check_requirements() +        if additional_info: +            message += ", " + additional_info + +        # No CheckFailed raised until now, return install message. +        return message + +    def check_requirements(self): +        """ +        Override this method to do custom dependency checks. + +         - Raise CheckFailed() if requirements are not met. +         - Return message with additional information, or an empty string +           (or None) for no additional information. +        """ +        return "" + + +class OptionalBackendPackage(OptionalPackage): +    config_category = "gui_support" + + +class Platform(SetupPackage): +    name = "platform" + +    def check(self): +        return sys.platform + + +class Python(SetupPackage): +    name = "python" + +    def check(self): +        major, minor1, minor2, s, tmp = sys.version_info + +        if major < 2: +            raise CheckFailed( +                "Requires Python 2.6 or later") +        elif major == 2 and minor1 < 6: +            raise CheckFailed( +                "Requires Python 2.6 or later (in the 2.x series)") +        elif major == 3 and minor1 < 1: +            raise CheckFailed( +                "Requires Python 3.1 or later (in the 3.x series)") + +        return sys.version + + +class Matplotlib(SetupPackage): +    name = "matplotlib" + +    def check(self): +        return versioneer.get_version() + +    def get_packages(self): +        return [ +            'matplotlib', +            'matplotlib.backends', +            'matplotlib.backends.qt_editor', +            'matplotlib.compat', +            'matplotlib.projections', +            'matplotlib.axes', +            'matplotlib.sphinxext', +            'matplotlib.style', +            'matplotlib.testing', +            'matplotlib.testing.jpl_units', +            'matplotlib.tri', +            ] + +    def get_py_modules(self): +        return ['pylab'] + +    def get_package_data(self): +        return { +            'matplotlib': +            [ +                'mpl-data/fonts/afm/*.afm', +                'mpl-data/fonts/pdfcorefonts/*.afm', +                'mpl-data/fonts/pdfcorefonts/*.txt', +                'mpl-data/fonts/ttf/*.ttf', +                'mpl-data/fonts/ttf/LICENSE_STIX', +                'mpl-data/fonts/ttf/COPYRIGHT.TXT', +                'mpl-data/fonts/ttf/README.TXT', +                'mpl-data/fonts/ttf/RELEASENOTES.TXT', +                '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/*.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/*', +                'mpl-data/stylelib/*.mplstyle', +             ]} + + +class SampleData(OptionalPackage): +    """ +    This handles the sample data that ships with matplotlib.  It is +    technically optional, though most often will be desired. +    """ +    name = "sample_data" + +    def get_package_data(self): +        return { +            'matplotlib': +            [ +                'mpl-data/sample_data/*.*', +                'mpl-data/sample_data/axes_grid/*.*', +            ]} + + +class Toolkits(OptionalPackage): +    name = "toolkits" + +    def get_packages(self): +        return [ +            'mpl_toolkits', +            'mpl_toolkits.mplot3d', +            'mpl_toolkits.axes_grid', +            'mpl_toolkits.axes_grid1', +            'mpl_toolkits.axisartist', +            ] + +    def get_namespace_packages(self): +        return ['mpl_toolkits'] + + +class Tests(OptionalPackage): +    name = "tests" +    nose_min_version = '0.11.1' + +    def check(self): +        super(Tests, self).check() + +        msgs = [] +        msg_template = ('{package} is required to run the matplotlib test ' +                        '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 +        ) +        try: +            import nose +            if is_min_version(nose.__version__, self.nose_min_version): +                msgs += ['using nose version %s' % nose.__version__] +            else: +                msgs += [bad_nose] +        except ImportError: +            msgs += [bad_nose] + +        if sys.version_info >= (3, 3): +            msgs += ['using unittest.mock'] +        else: +            try: +                import mock +                msgs += ['using mock %s' % mock.__version__] +            except ImportError: +                msgs += [msg_template.format(package='mock')] + +        return ' / '.join(msgs) + +    def get_packages(self): +        return [ +            'matplotlib.tests', +            'matplotlib.sphinxext.tests', +            ] + +    def get_package_data(self): +        baseline_images = [ +            'tests/baseline_images/%s/*' % x +            for x in os.listdir('lib/matplotlib/tests/baseline_images')] + +        return { +            'matplotlib': +            baseline_images + +            [ +                'tests/mpltest.ttf', +                'tests/test_rcparams.rc', +                'tests/test_utf32_be_rcparams.rc', +                'sphinxext/tests/tinypages/*.rst', +                'sphinxext/tests/tinypages/*.py', +                'sphinxext/tests/tinypages/_static/*', +            ]} + + +class Toolkits_Tests(Tests): +    name = "toolkits_tests" + +    def check_requirements(self): +        conf = self.get_config() +        toolkits_conf = Toolkits.get_config() +        tests_conf = Tests.get_config() + +        if conf is True: +            Tests.force = True +            Toolkits.force = True +        elif conf == "auto" and not (toolkits_conf and tests_conf): +            # Only auto-install if both toolkits and tests are set +            # to be installed +            raise CheckFailed("toolkits_tests needs 'toolkits' and 'tests'") +        return "" + +    def get_packages(self): +        return [ +            'mpl_toolkits.tests', +            ] + +    def get_package_data(self): +        baseline_images = [ +            'tests/baseline_images/%s/*' % x +            for x in os.listdir('lib/mpl_toolkits/tests/baseline_images')] + +        return {'mpl_toolkits': baseline_images} + +    def get_namespace_packages(self): +        return ['mpl_toolkits'] + + +class DelayedExtension(Extension, object): +    """ +    A distutils Extension subclass where some of its members +    may have delayed computation until reaching the build phase. + +    This is so we can, for example, get the Numpy include dirs +    after pip has installed Numpy for us if it wasn't already +    on the system. +    """ +    def __init__(self, *args, **kwargs): +        super(DelayedExtension, self).__init__(*args, **kwargs) +        self._finalized = False +        self._hooks = {} + +    def add_hook(self, member, func): +        """ +        Add a hook to dynamically compute a member. + +        Parameters +        ---------- +        member : string +            The name of the member + +        func : callable +            The function to call to get dynamically-computed values +            for the member. +        """ +        self._hooks[member] = func + +    def finalize(self): +        self._finalized = True + +    class DelayedMember(property): +        def __init__(self, name): +            self._name = name + +        def __get__(self, obj, objtype=None): +            result = getattr(obj, '_' + self._name, []) + +            if obj._finalized: +                if self._name in obj._hooks: +                    result = obj._hooks[self._name]() + result + +            return result + +        def __set__(self, obj, value): +            setattr(obj, '_' + self._name, value) + +    include_dirs = DelayedMember('include_dirs') + + +class Numpy(SetupPackage): +    name = "numpy" + +    @staticmethod +    def include_dirs_hook(): +        if sys.version_info[0] >= 3: +            import builtins +            if hasattr(builtins, '__NUMPY_SETUP__'): +                del builtins.__NUMPY_SETUP__ +            import imp +            import numpy +            imp.reload(numpy) +        else: +            import __builtin__ +            if hasattr(__builtin__, '__NUMPY_SETUP__'): +                del __builtin__.__NUMPY_SETUP__ +            import numpy +            reload(numpy) + +        ext = Extension('test', []) +        ext.include_dirs.append(numpy.get_include()) +        if not has_include_file( +                ext.include_dirs, os.path.join("numpy", "arrayobject.h")): +            warnings.warn( +                "The C headers for numpy could not be found. " +                "You may need to install the development package") + +        return [numpy.get_include()] + +    def check(self): +        min_version = extract_versions()['__version__numpy__'] +        try: +            import numpy +        except ImportError: +            raise CheckFailed( +                    "could not be found" ) +        if not is_min_version(numpy.__version__, min_version): +            raise CheckFailed( +                "requires numpy %s or later to build.  (Found %s)" % +                (min_version, numpy.__version__)) + +        return 'version %s' % numpy.__version__ + +    def add_flags(self, ext): +        # Ensure that PY_ARRAY_UNIQUE_SYMBOL is uniquely defined for +        # each extension +        array_api_name = 'MPL_' + ext.name.replace('.', '_') + '_ARRAY_API' + +        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'] + +    def get_install_requires(self): +        return ['numpy>=1.6'] + + +class LibAgg(SetupPackage): +    name = 'libagg' + +    def check(self): +        self.__class__.found_external = True +        try: +            return self._check_for_pkg_config( +                'libagg', 'agg2/agg_basics.h', min_version='PATCH') +        except CheckFailed as e: +            self.__class__.found_external = False +            return str(e) + ' Using local copy.' + +    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-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): +    name = "freetype" + +    def check(self): +        if sys.platform == 'win32': +            check_include_file(get_include_dirs(), 'ft2build.h', 'freetype') +            return 'Using unknown version found on system.' + +        status, output = getstatusoutput("freetype-config --ftversion") +        if status == 0: +            version = output +        else: +            version = None + +        # Early versions of freetype grep badly inside freetype-config, +        # so catch those cases. (tested with 2.5.3). +        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 = 'unknown' +        ext = self.get_extension() +        if ext is None: +            return version +        # Return the first version found in the include dirs. +        for include_dir in ext.include_dirs: +            header_fname = os.path.join(include_dir, 'freetype.h') +            if os.path.exists(header_fname): +                major, minor, patch = 0, 0, 0 +                with open(header_fname, 'r') as fh: +                    for line in fh: +                        if line.startswith('#define FREETYPE_'): +                            value = line.rsplit(' ', 1)[1].strip() +                            if 'MAJOR' in line: +                                major = value +                            elif 'MINOR' in line: +                                minor = value +                            else: +                                patch = value +                return '.'.join([major, minor, patch]) + +    def add_flags(self, ext): +        pkg_config.setup_extension( +            ext, 'freetype2', +            default_include_dirs=[ +                'include/freetype2', 'freetype2', +                'lib/freetype2/include', +                'lib/freetype2/include/freetype2'], +            default_library_dirs=[ +                'freetype2/lib'], +            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) +        return ext + + +class Png(SetupPackage): +    name = "png" + +    def check(self): +        if sys.platform == 'win32': +            check_include_file(get_include_dirs(), 'png.h', 'png') +            return 'Using unknown version found on system.' + +        status, output = getstatusoutput("libpng-config --version") +        if status == 0: +            version = output +        else: +            version = None + +        try: +            return self._check_for_pkg_config( +                'libpng', 'png.h', +                min_version='1.2', version=version) +        except CheckFailed as e: +            if has_include_file(get_include_dirs(), 'png.h'): +                return str(e) + ' Using unknown version found on system.' +            raise + +    def get_extension(self): +        sources = [ +            '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) +        return ext + + +class Qhull(SetupPackage): +    name = "qhull" + +    def check(self): +        self.__class__.found_external = True +        try: +            return self._check_for_pkg_config( +                'qhull', 'qhull/qhull_a.h', min_version='2003.1') +        except CheckFailed as e: +            self.__class__.found_pkgconfig = False +            # Qhull may not be in the pkg-config system but may still be +            # present on this system, so check if the header files can be +            # found. +            include_dirs = [ +                os.path.join(x, 'qhull') for x in get_include_dirs()] +            if has_include_file(include_dirs, 'qhull_a.h'): +                return 'Using system Qhull (version unknown, no pkg-config info)' +            else: +                self.__class__.found_external = False +                return str(e) + ' Using local copy.' + +    def add_flags(self, ext): +        if self.found_external: +            pkg_config.setup_extension(ext, 'qhull', +                                       default_libraries=['qhull']) +        else: +            ext.include_dirs.append('extern') +            ext.sources.extend(glob.glob('extern/qhull/*.c')) + + +class TTConv(SetupPackage): +    name = "ttconv" + +    def get_extension(self): +        sources = [ +            'src/_ttconv.cpp', +            'extern/ttconv/pprdrv_tt.cpp', +            'extern/ttconv/pprdrv_tt2.cpp', +            'extern/ttconv/ttutil.cpp' +            ] +        ext = make_extension('matplotlib.ttconv', sources) +        Numpy().add_flags(ext) +        ext.include_dirs.append('extern') +        return ext + + +class Path(SetupPackage): +    name = "path" + +    def get_extension(self): +        sources = [ +            'src/py_converters.cpp', +            'src/_path_wrapper.cpp' +            ] + +        ext = make_extension('matplotlib._path', sources) +        Numpy().add_flags(ext) +        LibAgg().add_flags(ext) +        return ext + + +class Image(SetupPackage): +    name = "image" + +    def get_extension(self): +        sources = [ +            'src/_image.cpp', +            'src/mplutils.cpp', +            'src/_image_wrapper.cpp' +            ] +        ext = make_extension('matplotlib._image', sources) +        Numpy().add_flags(ext) +        LibAgg().add_flags(ext) +        return ext + + +class ContourLegacy(SetupPackage): +    name = "contour_legacy" + +    def get_extension(self): +        sources = [ +            "src/cntr.c" +            ] +        ext = make_extension('matplotlib._cntr', sources) +        Numpy().add_flags(ext) +        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" + +    def get_packages(self): +        return ['matplotlib.delaunay'] + +    def get_extension(self): +        sources = ["_delaunay.cpp", "VoronoiDiagramGenerator.cpp", +                   "delaunay_utils.cpp", "natneighbors.cpp"] +        sources = [os.path.join('lib/matplotlib/delaunay', s) for s in sources] +        ext = make_extension('matplotlib._delaunay', sources) +        Numpy().add_flags(ext) +        return ext + + +class QhullWrap(SetupPackage): +    name = "qhull_wrap" + +    def get_extension(self): +        sources = ['src/qhull_wrap.c'] +        ext = make_extension('matplotlib._qhull', sources, +                             define_macros=[('MPL_DEVNULL', os.devnull)]) +        Numpy().add_flags(ext) +        Qhull().add_flags(ext) +        return ext + + +class Tri(SetupPackage): +    name = "tri" + +    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) +        return ext + + +class Externals(SetupPackage): +    name = "externals" + +    def get_packages(self): +        return ['matplotlib.externals'] + + +class Pytz(SetupPackage): +    name = "pytz" + +    def check(self): +        try: +            import pytz +        except ImportError: +            raise CheckFailed( +                    "could not be found") + +        return "using pytz version %s" % pytz.__version__ + +    def get_install_requires(self): +        return ['pytz'] + + +class Cycler(SetupPackage): +    name = "cycler" + +    def check(self): +        try: +            import cycler +        except ImportError: +            raise CheckFailed( +                "could not be found") + +        return "using cycler version %s" % cycler.__version__ + +    def get_install_requires(self): +        return ['cycler'] + + +class Dateutil(SetupPackage): +    name = "dateutil" + +    def __init__(self, version=None): +        self.version = version + +    def check(self): +        try: +            import dateutil +        except ImportError: +            # dateutil 2.1 has a file encoding bug that breaks installation on +            # python 3.3 +            # https://github.com/matplotlib/matplotlib/issues/2373 +            # hack around the problem by installing the (working) v2.0 +            #major, minor1, _, _, _ = sys.version_info +            #if self.version is None and (major, minor1) == (3, 3): +                #self.version = '!=2.1' + +            raise CheckFailed ( +                    "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") +        return "using dateutil version %s" % dateutil.__version__ + +    def get_install_requires(self): +        dateutil = 'python-dateutil' +        if self.version is not None: +            dateutil += self.version +        return [dateutil] + + +class Tornado(SetupPackage): +    name = "tornado" + +    def check(self): +        try: +            import tornado +        except ImportError: +            raise CheckFailed ( +                    "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: +            import pyparsing +            f = pyparsing.Forward() +            f <<= pyparsing.Literal('a') +            return f is not None +        except (ImportError, TypeError): +            return False + +    def check(self): +        try: +            import pyparsing +        except ImportError: +            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}".format( +                    '.'.join(str(x) for x in required))) + +        if not self.is_ok(): +            return ( +                "Your pyparsing contains a bug that will be monkey-patched by " +                "matplotlib.  For best results, upgrade to pyparsing 2.0.1 or " +                "later.") + +        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 [versionstring] +        else: +            return [versionstring + ',!=2.0.0'] + + +class BackendAgg(OptionalBackendPackage): +    name = "agg" +    force = True + +    def get_extension(self): +        sources = [ +            "src/mplutils.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) +        return ext + + +class BackendTkAgg(OptionalBackendPackage): +    name = "tkagg" +    force = True + +    def check(self): +        return "installing; run-time loading from Python Tcl / Tk" + +    def get_extension(self): +        sources = [ +            '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, add_sources=False) +        return ext + +    def add_flags(self, ext): +        ext.include_dirs.extend(['src']) +        if sys.platform == 'win32': +            # PSAPI library needed for finding Tcl / Tk at run time +            ext.libraries.extend(['psapi']) + + +class BackendGtk(OptionalBackendPackage): +    name = "gtk" + +    def check_requirements(self): +        try: +            import gtk +        except ImportError: +            raise CheckFailed("Requires pygtk") +        except RuntimeError: +            raise CheckFailed('pygtk present, but import failed.') +        else: +            version = (2, 2, 0) +            if gtk.pygtk_version < version: +                raise CheckFailed( +                    "Requires pygtk %d.%d.%d or later. " +                    "Found %d.%d.%d" % (version + gtk.pygtk_version)) + +        ext = self.get_extension() +        self.add_flags(ext) +        check_include_file(ext.include_dirs, +                           os.path.join("gtk", "gtk.h"), +                           'gtk') +        check_include_file(ext.include_dirs, +                           os.path.join("pygtk", "pygtk.h"), +                           'pygtk') + +        return 'Gtk: %s pygtk: %s' % ( +            ".".join(str(x) for x in gtk.gtk_version), +            ".".join(str(x) for x in gtk.pygtk_version)) + +    def get_package_data(self): +        return {'matplotlib': ['mpl-data/*.glade']} + +    def get_extension(self): +        sources = [ +            'src/_backend_gdk.c' +            ] +        ext = make_extension('matplotlib.backends._backend_gdk', sources) +        self.add_flags(ext) +        Numpy().add_flags(ext) +        return ext + +    def add_flags(self, ext): +        if sys.platform == 'win32': +            def getoutput(s): +                ret = os.popen(s).read().strip() +                return ret + +            if 'PKG_CONFIG_PATH' not in os.environ: +                # If Gtk+ is installed, pkg-config is required to be installed +                os.environ['PKG_CONFIG_PATH'] = 'C:\\GTK\\lib\\pkgconfig' + +                # popen broken on my win32 plaform so I can't use pkgconfig +                ext.library_dirs.extend( +                    ['C:/GTK/bin', 'C:/GTK/lib']) + +                ext.include_dirs.extend( +                    ['win32_static/include/pygtk-2.0', +                     'C:/GTK/include', +                     'C:/GTK/include/gobject', +                     'C:/GTK/include/gext', +                     'C:/GTK/include/glib', +                     'C:/GTK/include/pango', +                     'C:/GTK/include/atk', +                     'C:/GTK/include/X11', +                     'C:/GTK/include/cairo', +                     'C:/GTK/include/gdk', +                     'C:/GTK/include/gdk-pixbuf', +                     'C:/GTK/include/gtk', +                     ]) + +            pygtkIncludes = getoutput( +                'pkg-config --cflags-only-I pygtk-2.0').split() +            gtkIncludes = getoutput( +                'pkg-config --cflags-only-I gtk+-2.0').split() +            includes = pygtkIncludes + gtkIncludes +            ext.include_dirs.extend([include[2:] for include in includes]) + +            pygtkLinker = getoutput('pkg-config --libs pygtk-2.0').split() +            gtkLinker = getoutput('pkg-config --libs gtk+-2.0').split() +            linkerFlags = pygtkLinker + gtkLinker + +            ext.libraries.extend( +                [flag[2:] for flag in linkerFlags if flag.startswith('-l')]) + +            ext.library_dirs.extend( +                [flag[2:] for flag in linkerFlags if flag.startswith('-L')]) + +            ext.extra_link_args.extend( +                [flag for flag in linkerFlags if not +                 (flag.startswith('-l') or flag.startswith('-L'))]) + +            # visual studio doesn't need the math library +            if (sys.platform == 'win32' and +                win32_compiler == 'msvc' and +                'm' in ext.libraries): +                ext.libraries.remove('m') + +        elif sys.platform != 'win32': +            pkg_config.setup_extension(ext, 'pygtk-2.0') +            pkg_config.setup_extension(ext, 'gtk+-2.0') + + +class BackendGtkAgg(BackendGtk): +    name = "gtkagg" + +    def check(self): +        try: +            return super(BackendGtkAgg, self).check() +        except: +            raise + +    def get_package_data(self): +        return {'matplotlib': ['mpl-data/*.glade']} + +    def get_extension(self): +        sources = [ +            '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) +        Numpy().add_flags(ext) +        return ext + + +def backend_gtk3agg_internal_check(x): +    try: +        import gi +    except ImportError: +        return (False, "Requires pygobject to be installed.") + +    try: +        gi.require_version("Gtk", "3.0") +    except ValueError: +        return (False, "Requires gtk3 development files to be installed.") +    except AttributeError: +        return (False, "pygobject version too old.") + +    try: +        from gi.repository import Gtk, Gdk, GObject +    except (ImportError, RuntimeError): +        return (False, "Requires pygobject to be installed.") + +    return (True, "version %s.%s.%s" % ( +        Gtk.get_major_version(), +        Gtk.get_micro_version(), +        Gtk.get_minor_version())) + + +class BackendGtk3Agg(OptionalBackendPackage): +    name = "gtk3agg" + +    def check_requirements(self): +        if 'TRAVIS' in os.environ: +            raise CheckFailed("Can't build with Travis") + +        # This check needs to be performed out-of-process, because +        # importing gi and then importing regular old pygtk afterward +        # segfaults the interpreter. +        try: +            p = multiprocessing.Pool() +        except: +            return "unknown (can not use multiprocessing to determine)" +        try: +            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" +            raise +        else: +            p.close() +        finally: +            p.join() + +        if success: +            return msg +        else: +            raise CheckFailed(msg) + +    def get_package_data(self): +        return {'matplotlib': ['mpl-data/*.glade']} + + +def backend_gtk3cairo_internal_check(x): +    try: +        import cairocffi +    except ImportError: +        try: +            import cairo +        except ImportError: +            return (False, "Requires cairocffi or pycairo to be installed.") + +    try: +        import gi +    except ImportError: +        return (False, "Requires pygobject to be installed.") + +    try: +        gi.require_version("Gtk", "3.0") +    except ValueError: +        return (False, "Requires gtk3 development files to be installed.") +    except AttributeError: +        return (False, "pygobject version too old.") + +    try: +        from gi.repository import Gtk, Gdk, GObject +    except (RuntimeError, ImportError): +        return (False, "Requires pygobject to be installed.") + +    return (True, "version %s.%s.%s" % ( +        Gtk.get_major_version(), +        Gtk.get_micro_version(), +        Gtk.get_minor_version())) + + +class BackendGtk3Cairo(OptionalBackendPackage): +    name = "gtk3cairo" + +    def check_requirements(self): +        if 'TRAVIS' in os.environ: +            raise CheckFailed("Can't build with Travis") + +        # This check needs to be performed out-of-process, because +        # importing gi and then importing regular old pygtk afterward +        # segfaults the interpreter. +        try: +            p = multiprocessing.Pool() +        except: +            return "unknown (can not use multiprocessing to determine)" +        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) + +    def get_package_data(self): +        return {'matplotlib': ['mpl-data/*.glade']} + + +class BackendWxAgg(OptionalBackendPackage): +    name = "wxagg" + +    def check_requirements(self): +        wxversioninstalled = True +        try: +            import wxversion +        except ImportError: +            wxversioninstalled = False + +        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: +            import wx +            backend_version = wx.VERSION_STRING +        except ImportError: +            raise CheckFailed("requires wxPython") + +        # Extra version check in case wxversion lacks AlreadyImportedError; +        # then VersionError might have been raised and ignored when +        # there really *is* a problem with the version. +        major, minor = [int(n) for n in backend_version.split('.')[:2]] +        if major < 2 or (major < 3 and minor < 8): +            raise CheckFailed( +                "Requires wxPython 2.8, found %s" % backend_version) + +        return "version %s" % backend_version + + +class BackendMacOSX(OptionalBackendPackage): +    name = 'macosx' + +    def check_requirements(self): +        if sys.platform != 'darwin': +            raise CheckFailed("Mac OS-X only") + +        return 'darwin' + +    def get_extension(self): +        sources = [ +            'src/_macosx.m', +            'src/py_converters.cpp', +            'src/path_cleanup.cpp' +            ] + +        ext = make_extension('matplotlib.backends._macosx', sources) +        Numpy().add_flags(ext) +        LibAgg().add_flags(ext) +        ext.extra_link_args.extend(['-framework', 'Cocoa']) +        return ext + + +class Windowing(OptionalBackendPackage): +    """ +    Builds the windowing extension. +    """ +    name = "windowing" + +    def check_requirements(self): +        if sys.platform != 'win32': +            raise CheckFailed("Microsoft Windows only") +        config = self.get_config() +        if config is False: +            raise CheckFailed("skipping due to configuration") +        return "" + +    def get_extension(self): +        sources = [ +            "src/_windowing.cpp" +            ] +        ext = make_extension('matplotlib._windowing', sources) +        ext.include_dirs.extend(['C:/include']) +        ext.libraries.extend(['user32']) +        ext.library_dirs.extend(['C:/lib']) +        ext.extra_link_args.append("-mwindows") +        return ext + + +class BackendQtBase(OptionalBackendPackage): + +    def convert_qt_version(self, version): +        version = '%x' % version +        temp = [] +        while len(version) > 0: +            version, chunk = version[:-2], version[-2:] +            temp.insert(0, str(int(chunk, 16))) +        return '.'.join(temp) + +    def check_requirements(self): +        ''' +        If PyQt4/PyQt5 is already imported, importing PyQt5/PyQt4 will fail +        so we need to test in a subprocess (as for Gtk3). +        ''' +        try: +            p = multiprocessing.Pool() + +        except: +            # Can't do multiprocessing, fall back to normal approach ( this will fail if importing both PyQt4 and PyQt5 ) +            try: +                # Try in-process +                msg = self.callback(self) + +            except RuntimeError: +                raise CheckFailed("Could not import: are PyQt4 & PyQt5 both installed?") + +            except: +                # Raise any other exceptions +                raise + +        else: +            # Multiprocessing OK +            try: +                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: +                # Some other error. +                p.close() +                raise +            else: +                # Clean exit +                p.close() +            finally: +                # Tidy up multiprocessing +                p.join() + +        return msg + + +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: +        raise CheckFailed("PyQt4 not found") + +    try: +        qt_version = QtCore.QT_VERSION +        pyqt_version_str = QtCore.QT_VERSION_STR +    except AttributeError: +        raise CheckFailed('PyQt4 not correctly imported') +    else: +        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" + +    def __init__(self, *args, **kwargs): +        BackendQtBase.__init__(self, *args, **kwargs) +        self.callback = backend_qt4_internal_check + + +def backend_qt5_internal_check(self): +    try: +        from PyQt5 import QtCore +    except ImportError: +        raise CheckFailed("PyQt5 not found") + +    try: +        qt_version = QtCore.QT_VERSION +        pyqt_version_str = QtCore.QT_VERSION_STR +    except AttributeError: +        raise CheckFailed('PyQt5 not correctly imported') +    else: +        return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str)) + + +class BackendQt5(BackendQtBase): +    name = "qt5agg" + +    def __init__(self, *args, **kwargs): +        BackendQtBase.__init__(self, *args, **kwargs) +        self.callback = backend_qt5_internal_check + + +class BackendCairo(OptionalBackendPackage): +    name = "cairo" + +    def check_requirements(self): +        try: +            import cairocffi +        except ImportError: +            try: +                import cairo +            except ImportError: +                raise CheckFailed("cairocffi or pycairo not found") +            else: +                return "pycairo version %s" % cairo.version +        else: +            return "cairocffi version %s" % cairocffi.version + + +class DviPng(SetupPackage): +    name = "dvipng" +    optional = True + +    def check(self): +        try: +            output = check_output('dvipng -version', shell=True, +                                  stderr=subprocess.STDOUT) +            return "version %s" % output.splitlines()[1].decode().split()[-1] +        except (IndexError, ValueError, subprocess.CalledProcessError): +            raise CheckFailed() + + +class Ghostscript(SetupPackage): +    name = "ghostscript" +    optional = True + +    def check(self): +        try: +            if sys.platform == 'win32': +                command = 'gswin32c --version' +                try: +                    output = check_output(command, shell=True, +                                          stderr=subprocess.STDOUT) +                except subprocess.CalledProcessError: +                    command = 'gswin64c --version' +                    output = check_output(command, shell=True, +                                          stderr=subprocess.STDOUT) +            else: +                command = 'gs --version' +                output = check_output(command, shell=True, +                                      stderr=subprocess.STDOUT) +            return "version %s" % output.decode()[:-1] +        except (IndexError, ValueError, subprocess.CalledProcessError): +            raise CheckFailed() + + +class LaTeX(SetupPackage): +    name = "latex" +    optional = True + +    def check(self): +        try: +            output = check_output('latex -version', shell=True, +                                  stderr=subprocess.STDOUT) +            line = output.splitlines()[0].decode() +            pattern = '(3\.1\d+)|(MiKTeX \d+.\d+)' +            match = re.search(pattern, line) +            return "version %s" % match.group(0) +        except (IndexError, ValueError, AttributeError, subprocess.CalledProcessError): +            raise CheckFailed() + + +class PdfToPs(SetupPackage): +    name = "pdftops" +    optional = True + +    def check(self): +        try: +            output = check_output('pdftops -v', shell=True, +                                  stderr=subprocess.STDOUT) +            for line in output.splitlines(): +                line = line.decode() +                if 'version' in line: +                    return "version %s" % line.split()[2] +        except (IndexError, ValueError, subprocess.CalledProcessError): +            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 diff --git a/development/python3-matplotlib/slack-desc b/development/python3-matplotlib/slack-desc new file mode 100644 index 0000000000..da2208fe1b --- /dev/null +++ b/development/python3-matplotlib/slack-desc @@ -0,0 +1,19 @@ +# HOW TO EDIT THIS FILE: +# The "handy ruler" below makes it easier to edit a package description. +# Line up the first '|' above the ':' following the base package name, and +# the '|' on the right side marks the last column you can put a character in. +# You must make exactly 11 lines for the formatting to be correct.  It's also +# customary to leave one space after the ':' except on otherwise blank lines. + +                  |-----handy-ruler------------------------------------------------------| +python3-matplotlib: python3-matplotlib (a Python 2D plotting library) +python3-matplotlib: +python3-matplotlib: Matplotlib is a plotting library for Python which uses +python3-matplotlib: syntax similar to MATLAB.  Matplotlib produces publication +python3-matplotlib: quality figures in a variety of hardcopy formats and +python3-matplotlib: interactive environments across platforms. +python3-matplotlib: +python3-matplotlib: Homepage: http://matplotlib.sourceforge.net/ +python3-matplotlib: +python3-matplotlib: This is the Python 3 version of matplotlib and can coexist with SBo's +python3-matplotlib: matplotlib package.  | 
