diff --git a/channel.py b/channel.py index e2c3205..0e58de7 100644 --- a/channel.py +++ b/channel.py @@ -53,8 +53,6 @@ def estimate(in_data, pilots=0): H_est_phase = scipy.interpolate.interp1d(pilot_carriers, np.angle(H_est_pilots), kind='linear', fill_value='extrapolate')(all_carriers) H_est += H_est_abs * np.exp(1j*H_est_phase) - print(H_est_abs) - H_est = H_est / len(in_data) return H_est diff --git a/main.py b/main.py index a6bb168..c8ac882 100755 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.7 +#!/usr/bin/env python3 """ Shitty OFDM simulator designed to make it so I understand OFDM. @@ -74,5 +74,4 @@ if __name__ == '__main__': to_serialise = qam.demodulate(to_decode, pilots=10) data = serialise(64, to_serialise) - print(data) diff --git a/venv/bin/activate b/venv/bin/activate new file mode 100644 index 0000000..7352aee --- /dev/null +++ b/venv/bin/activate @@ -0,0 +1,84 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + + +if [ "${BASH_SOURCE-}" = "$0" ]; then + echo "You must source this script: \$ source $0" >&2 + exit 33 +fi + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then + PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/home/david/Documents/Clubs/ARVP/python-ofdm/venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1-}" + if [ "x" != x ] ; then + PS1="${PS1-}" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true + +pydoc () { + python -m pydoc "$@" +} + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh new file mode 100644 index 0000000..e55b4ec --- /dev/null +++ b/venv/bin/activate.csh @@ -0,0 +1,55 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . + +set newline='\ +' + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/home/david/Documents/Clubs/ARVP/python-ofdm/venv" + +set _OLD_VIRTUAL_PATH="$PATH:q" +setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q" + + + +if ("" != "") then + set env_name = "" +else + set env_name = '('"$VIRTUAL_ENV:t:q"') ' +endif + +if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then + if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then + set do_prompt = "1" + else + set do_prompt = "0" + endif +else + set do_prompt = "1" +endif + +if ( $do_prompt == "1" ) then + # Could be in a non-interactive environment, + # in which case, $prompt is undefined and we wouldn't + # care about the prompt anyway. + if ( $?prompt ) then + set _OLD_VIRTUAL_PROMPT="$prompt:q" + if ( "$prompt:q" =~ *"$newline:q"* ) then + : + else + set prompt = "$env_name:q$prompt:q" + endif + endif +endif + +unset env_name +unset do_prompt + +alias pydoc python -m pydoc + +rehash diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish new file mode 100644 index 0000000..80b50fa --- /dev/null +++ b/venv/bin/activate.fish @@ -0,0 +1,102 @@ +# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. +# Do not run it directly. + +function _bashify_path -d "Converts a fish path to something bash can recognize" + set fishy_path $argv + set bashy_path $fishy_path[1] + for path_part in $fishy_path[2..-1] + set bashy_path "$bashy_path:$path_part" + end + echo $bashy_path +end + +function _fishify_path -d "Converts a bash path to something fish can recognize" + echo $argv | tr ':' '\n' +end + +function deactivate -d 'Exit virtualenv mode and return to the normal environment.' + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + # https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling + if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3 + set -gx PATH (_fishify_path $_OLD_VIRTUAL_PATH) + else + set -gx PATH $_OLD_VIRTUAL_PATH + end + set -e _OLD_VIRTUAL_PATH + end + + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + and functions -q _old_fish_prompt + # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. + set -l fish_function_path + + # Erase virtualenv's `fish_prompt` and restore the original. + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + end + + set -e VIRTUAL_ENV + + if test "$argv[1]" != 'nondestructive' + # Self-destruct! + functions -e pydoc + functions -e deactivate + functions -e _bashify_path + functions -e _fishify_path + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/home/david/Documents/Clubs/ARVP/python-ofdm/venv" + +# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling +if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3 + set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH) +else + set -gx _OLD_VIRTUAL_PATH $PATH +end +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset `$PYTHONHOME` if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +function pydoc + python -m pydoc $argv +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # Copy the current `fish_prompt` function as `_old_fish_prompt`. + functions -c fish_prompt _old_fish_prompt + + function fish_prompt + # Save the current $status, for fish_prompts that display it. + set -l old_status $status + + # Prompt override provided? + # If not, just prepend the environment name. + if test -n "" + printf '%s%s' "" (set_color normal) + else + printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") + end + + # Restore the original $status + echo "exit $old_status" | source + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/venv/bin/activate.ps1 b/venv/bin/activate.ps1 new file mode 100644 index 0000000..95504d3 --- /dev/null +++ b/venv/bin/activate.ps1 @@ -0,0 +1,60 @@ +$script:THIS_PATH = $myinvocation.mycommand.path +$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent + +function global:deactivate([switch] $NonDestructive) { + if (Test-Path variable:_OLD_VIRTUAL_PATH) { + $env:PATH = $variable:_OLD_VIRTUAL_PATH + Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global + } + + if (Test-Path function:_old_virtual_prompt) { + $function:prompt = $function:_old_virtual_prompt + Remove-Item function:\_old_virtual_prompt + } + + if ($env:VIRTUAL_ENV) { + Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue + } + + if (!$NonDestructive) { + # Self destruct! + Remove-Item function:deactivate + Remove-Item function:pydoc + } +} + +function global:pydoc { + python -m pydoc $args +} + +# unset irrelevant variables +deactivate -nondestructive + +$VIRTUAL_ENV = $BASE_DIR +$env:VIRTUAL_ENV = $VIRTUAL_ENV + +New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH + +$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH +if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) { + function global:_old_virtual_prompt { + "" + } + $function:_old_virtual_prompt = $function:prompt + + if ("" -ne "") { + function global:prompt { + # Add the custom prefix to the existing prompt + $previous_prompt_value = & $function:_old_virtual_prompt + ("" + $previous_prompt_value) + } + } + else { + function global:prompt { + # Add a prefix to the current prompt, but don't discard it. + $previous_prompt_value = & $function:_old_virtual_prompt + $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) " + ($new_prompt_value + $previous_prompt_value) + } + } +} diff --git a/venv/bin/activate.xsh b/venv/bin/activate.xsh new file mode 100644 index 0000000..38337c5 --- /dev/null +++ b/venv/bin/activate.xsh @@ -0,0 +1,46 @@ +"""Xonsh activate script for virtualenv""" +from xonsh.tools import get_sep as _get_sep + +def _deactivate(args): + if "pydoc" in aliases: + del aliases["pydoc"] + + if ${...}.get("_OLD_VIRTUAL_PATH", ""): + $PATH = $_OLD_VIRTUAL_PATH + del $_OLD_VIRTUAL_PATH + + if ${...}.get("_OLD_VIRTUAL_PYTHONHOME", ""): + $PYTHONHOME = $_OLD_VIRTUAL_PYTHONHOME + del $_OLD_VIRTUAL_PYTHONHOME + + if "VIRTUAL_ENV" in ${...}: + del $VIRTUAL_ENV + + if "VIRTUAL_ENV_PROMPT" in ${...}: + del $VIRTUAL_ENV_PROMPT + + if "nondestructive" not in args: + # Self destruct! + del aliases["deactivate"] + + +# unset irrelevant variables +_deactivate(["nondestructive"]) +aliases["deactivate"] = _deactivate + +$VIRTUAL_ENV = r"/home/david/Documents/Clubs/ARVP/python-ofdm/venv" + +$_OLD_VIRTUAL_PATH = $PATH +$PATH = $PATH[:] +$PATH.add($VIRTUAL_ENV + _get_sep() + "bin", front=True, replace=True) + +if ${...}.get("PYTHONHOME", ""): + # unset PYTHONHOME if set + $_OLD_VIRTUAL_PYTHONHOME = $PYTHONHOME + del $PYTHONHOME + +$VIRTUAL_ENV_PROMPT = "" +if not $VIRTUAL_ENV_PROMPT: + del $VIRTUAL_ENV_PROMPT + +aliases["pydoc"] = ["python", "-m", "pydoc"] diff --git a/venv/bin/activate_this.py b/venv/bin/activate_this.py new file mode 100644 index 0000000..aa96457 --- /dev/null +++ b/venv/bin/activate_this.py @@ -0,0 +1,46 @@ +"""Activate virtualenv for current interpreter: + +Use exec(open(this_file).read(), {'__file__': this_file}). + +This can be used when you must use an existing Python interpreter, not the virtualenv bin/python. +""" +import os +import site +import sys + +try: + __file__ +except NameError: + raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))") + +# prepend bin to PATH (this file is inside the bin directory) +bin_dir = os.path.dirname(os.path.abspath(__file__)) +os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep)) + +base = os.path.dirname(bin_dir) + +# virtual env is right above bin directory +os.environ["VIRTUAL_ENV"] = base + +# add the virtual environments site-package to the host python import mechanism +IS_PYPY = hasattr(sys, "pypy_version_info") +IS_JYTHON = sys.platform.startswith("java") +if IS_JYTHON: + site_packages = os.path.join(base, "Lib", "site-packages") +elif IS_PYPY: + site_packages = os.path.join(base, "site-packages") +else: + IS_WIN = sys.platform == "win32" + if IS_WIN: + site_packages = os.path.join(base, "Lib", "site-packages") + else: + site_packages = os.path.join(base, "lib", "python{}.{}".format(*sys.version_info), "site-packages") + +prev = set(sys.path) +site.addsitedir(site_packages) +sys.real_prefix = sys.prefix +sys.prefix = base + +# Move the added items to the front of the path, in place +new = list(sys.path) +sys.path[:] = [i for i in new if i not in prev] + [i for i in new if i in prev] diff --git a/venv/bin/easy_install b/venv/bin/easy_install new file mode 100755 index 0000000..511f50b --- /dev/null +++ b/venv/bin/easy_install @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from setuptools.command.easy_install import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/easy_install-3.6 b/venv/bin/easy_install-3.6 new file mode 100755 index 0000000..511f50b --- /dev/null +++ b/venv/bin/easy_install-3.6 @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from setuptools.command.easy_install import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/f2py b/venv/bin/f2py new file mode 100755 index 0000000..4eaecee --- /dev/null +++ b/venv/bin/f2py @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from numpy.f2py.f2py2e import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/f2py3 b/venv/bin/f2py3 new file mode 100755 index 0000000..4eaecee --- /dev/null +++ b/venv/bin/f2py3 @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from numpy.f2py.f2py2e import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/f2py3.6 b/venv/bin/f2py3.6 new file mode 100755 index 0000000..4eaecee --- /dev/null +++ b/venv/bin/f2py3.6 @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from numpy.f2py.f2py2e import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip b/venv/bin/pip new file mode 100755 index 0000000..92a9100 --- /dev/null +++ b/venv/bin/pip @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from pip._internal import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3 b/venv/bin/pip3 new file mode 100755 index 0000000..92a9100 --- /dev/null +++ b/venv/bin/pip3 @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from pip._internal import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3.6 b/venv/bin/pip3.6 new file mode 100755 index 0000000..92a9100 --- /dev/null +++ b/venv/bin/pip3.6 @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from pip._internal import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/python b/venv/bin/python new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/venv/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/venv/bin/python-config b/venv/bin/python-config new file mode 100755 index 0000000..eb5743c --- /dev/null +++ b/venv/bin/python-config @@ -0,0 +1,78 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python + +import sys +import getopt +import sysconfig + +valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', + 'ldflags', 'help'] + +if sys.version_info >= (3, 2): + valid_opts.insert(-1, 'extension-suffix') + valid_opts.append('abiflags') +if sys.version_info >= (3, 3): + valid_opts.append('configdir') + + +def exit_with_usage(code=1): + sys.stderr.write("Usage: {0} [{1}]\n".format( + sys.argv[0], '|'.join('--'+opt for opt in valid_opts))) + sys.exit(code) + +try: + opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) +except getopt.error: + exit_with_usage() + +if not opts: + exit_with_usage() + +pyver = sysconfig.get_config_var('VERSION') +getvar = sysconfig.get_config_var + +opt_flags = [flag for (flag, val) in opts] + +if '--help' in opt_flags: + exit_with_usage(code=0) + +for opt in opt_flags: + if opt == '--prefix': + print(sysconfig.get_config_var('prefix')) + + elif opt == '--exec-prefix': + print(sysconfig.get_config_var('exec_prefix')) + + elif opt in ('--includes', '--cflags'): + flags = ['-I' + sysconfig.get_path('include'), + '-I' + sysconfig.get_path('platinclude')] + if opt == '--cflags': + flags.extend(getvar('CFLAGS').split()) + print(' '.join(flags)) + + elif opt in ('--libs', '--ldflags'): + abiflags = getattr(sys, 'abiflags', '') + libs = ['-lpython' + pyver + abiflags] + libs += getvar('LIBS').split() + libs += getvar('SYSLIBS').split() + # add the prefix/lib/pythonX.Y/config dir, but only if there is no + # shared library in prefix/lib/. + if opt == '--ldflags': + if not getvar('Py_ENABLE_SHARED'): + libs.insert(0, '-L' + getvar('LIBPL')) + if not getvar('PYTHONFRAMEWORK'): + libs.extend(getvar('LINKFORSHARED').split()) + print(' '.join(libs)) + + elif opt == '--extension-suffix': + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + if ext_suffix is None: + ext_suffix = sysconfig.get_config_var('SO') + print(ext_suffix) + + elif opt == '--abiflags': + if not getattr(sys, 'abiflags', None): + exit_with_usage() + print(sys.abiflags) + + elif opt == '--configdir': + print(sysconfig.get_config_var('LIBPL')) diff --git a/venv/bin/python3 b/venv/bin/python3 new file mode 100755 index 0000000..2871802 Binary files /dev/null and b/venv/bin/python3 differ diff --git a/venv/bin/python3.6 b/venv/bin/python3.6 new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/venv/bin/python3.6 @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/venv/bin/wheel b/venv/bin/wheel new file mode 100755 index 0000000..3aa3e35 --- /dev/null +++ b/venv/bin/wheel @@ -0,0 +1,10 @@ +#!/home/david/Documents/Clubs/ARVP/python-ofdm/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys + +from wheel.cli import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/include/python3.6m b/venv/include/python3.6m new file mode 120000 index 0000000..ba3a1bf --- /dev/null +++ b/venv/include/python3.6m @@ -0,0 +1 @@ +/usr/include/python3.6m \ No newline at end of file diff --git a/venv/lib/python3.6/LICENSE.txt b/venv/lib/python3.6/LICENSE.txt new file mode 120000 index 0000000..2b6e203 --- /dev/null +++ b/venv/lib/python3.6/LICENSE.txt @@ -0,0 +1 @@ +/usr/lib/python3.6/LICENSE.txt \ No newline at end of file diff --git a/venv/lib/python3.6/__future__.py b/venv/lib/python3.6/__future__.py new file mode 120000 index 0000000..8b63554 --- /dev/null +++ b/venv/lib/python3.6/__future__.py @@ -0,0 +1 @@ +/usr/lib/python3.6/__future__.py \ No newline at end of file diff --git a/venv/lib/python3.6/__pycache__/__future__.cpython-36.pyc b/venv/lib/python3.6/__pycache__/__future__.cpython-36.pyc new file mode 100644 index 0000000..d94517f Binary files /dev/null and b/venv/lib/python3.6/__pycache__/__future__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/_bootlocale.cpython-36.pyc b/venv/lib/python3.6/__pycache__/_bootlocale.cpython-36.pyc new file mode 100644 index 0000000..a61a162 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/_bootlocale.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/_collections_abc.cpython-36.pyc b/venv/lib/python3.6/__pycache__/_collections_abc.cpython-36.pyc new file mode 100644 index 0000000..fb44a41 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/_collections_abc.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/_weakrefset.cpython-36.pyc b/venv/lib/python3.6/__pycache__/_weakrefset.cpython-36.pyc new file mode 100644 index 0000000..7b70df2 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/_weakrefset.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/abc.cpython-36.pyc b/venv/lib/python3.6/__pycache__/abc.cpython-36.pyc new file mode 100644 index 0000000..f57bc82 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/abc.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/base64.cpython-36.pyc b/venv/lib/python3.6/__pycache__/base64.cpython-36.pyc new file mode 100644 index 0000000..53b4575 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/base64.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/bisect.cpython-36.pyc b/venv/lib/python3.6/__pycache__/bisect.cpython-36.pyc new file mode 100644 index 0000000..b1f5048 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/bisect.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/codecs.cpython-36.pyc b/venv/lib/python3.6/__pycache__/codecs.cpython-36.pyc new file mode 100644 index 0000000..c51ad22 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/codecs.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/copy.cpython-36.pyc b/venv/lib/python3.6/__pycache__/copy.cpython-36.pyc new file mode 100644 index 0000000..8d7d077 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/copy.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/copyreg.cpython-36.pyc b/venv/lib/python3.6/__pycache__/copyreg.cpython-36.pyc new file mode 100644 index 0000000..8e6ed69 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/copyreg.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/enum.cpython-36.pyc b/venv/lib/python3.6/__pycache__/enum.cpython-36.pyc new file mode 100644 index 0000000..86cdf97 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/enum.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/fnmatch.cpython-36.pyc b/venv/lib/python3.6/__pycache__/fnmatch.cpython-36.pyc new file mode 100644 index 0000000..87c8c75 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/fnmatch.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/functools.cpython-36.pyc b/venv/lib/python3.6/__pycache__/functools.cpython-36.pyc new file mode 100644 index 0000000..60d863c Binary files /dev/null and b/venv/lib/python3.6/__pycache__/functools.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/genericpath.cpython-36.pyc b/venv/lib/python3.6/__pycache__/genericpath.cpython-36.pyc new file mode 100644 index 0000000..944a4c7 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/genericpath.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/hashlib.cpython-36.pyc b/venv/lib/python3.6/__pycache__/hashlib.cpython-36.pyc new file mode 100644 index 0000000..361843b Binary files /dev/null and b/venv/lib/python3.6/__pycache__/hashlib.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/heapq.cpython-36.pyc b/venv/lib/python3.6/__pycache__/heapq.cpython-36.pyc new file mode 100644 index 0000000..de7c5a1 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/heapq.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/hmac.cpython-36.pyc b/venv/lib/python3.6/__pycache__/hmac.cpython-36.pyc new file mode 100644 index 0000000..25ef6d9 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/hmac.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/io.cpython-36.pyc b/venv/lib/python3.6/__pycache__/io.cpython-36.pyc new file mode 100644 index 0000000..b37fdde Binary files /dev/null and b/venv/lib/python3.6/__pycache__/io.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/keyword.cpython-36.pyc b/venv/lib/python3.6/__pycache__/keyword.cpython-36.pyc new file mode 100644 index 0000000..ffc64fb Binary files /dev/null and b/venv/lib/python3.6/__pycache__/keyword.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/linecache.cpython-36.pyc b/venv/lib/python3.6/__pycache__/linecache.cpython-36.pyc new file mode 100644 index 0000000..fc753aa Binary files /dev/null and b/venv/lib/python3.6/__pycache__/linecache.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/locale.cpython-36.pyc b/venv/lib/python3.6/__pycache__/locale.cpython-36.pyc new file mode 100644 index 0000000..e9840f5 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/locale.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/ntpath.cpython-36.pyc b/venv/lib/python3.6/__pycache__/ntpath.cpython-36.pyc new file mode 100644 index 0000000..5823c6a Binary files /dev/null and b/venv/lib/python3.6/__pycache__/ntpath.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/operator.cpython-36.pyc b/venv/lib/python3.6/__pycache__/operator.cpython-36.pyc new file mode 100644 index 0000000..f6651ad Binary files /dev/null and b/venv/lib/python3.6/__pycache__/operator.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/os.cpython-36.pyc b/venv/lib/python3.6/__pycache__/os.cpython-36.pyc new file mode 100644 index 0000000..54db069 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/os.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/posixpath.cpython-36.pyc b/venv/lib/python3.6/__pycache__/posixpath.cpython-36.pyc new file mode 100644 index 0000000..74bed71 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/posixpath.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/random.cpython-36.pyc b/venv/lib/python3.6/__pycache__/random.cpython-36.pyc new file mode 100644 index 0000000..ea19a94 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/random.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/re.cpython-36.pyc b/venv/lib/python3.6/__pycache__/re.cpython-36.pyc new file mode 100644 index 0000000..d7e6e23 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/re.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/reprlib.cpython-36.pyc b/venv/lib/python3.6/__pycache__/reprlib.cpython-36.pyc new file mode 100644 index 0000000..d058845 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/reprlib.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/shutil.cpython-36.pyc b/venv/lib/python3.6/__pycache__/shutil.cpython-36.pyc new file mode 100644 index 0000000..47e6837 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/shutil.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/site.cpython-36.pyc b/venv/lib/python3.6/__pycache__/site.cpython-36.pyc new file mode 100644 index 0000000..320ae6a Binary files /dev/null and b/venv/lib/python3.6/__pycache__/site.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/sre_compile.cpython-36.pyc b/venv/lib/python3.6/__pycache__/sre_compile.cpython-36.pyc new file mode 100644 index 0000000..8faf58e Binary files /dev/null and b/venv/lib/python3.6/__pycache__/sre_compile.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/sre_constants.cpython-36.pyc b/venv/lib/python3.6/__pycache__/sre_constants.cpython-36.pyc new file mode 100644 index 0000000..93b49f5 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/sre_constants.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/sre_parse.cpython-36.pyc b/venv/lib/python3.6/__pycache__/sre_parse.cpython-36.pyc new file mode 100644 index 0000000..174c982 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/sre_parse.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/stat.cpython-36.pyc b/venv/lib/python3.6/__pycache__/stat.cpython-36.pyc new file mode 100644 index 0000000..5ee9f82 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/stat.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/struct.cpython-36.pyc b/venv/lib/python3.6/__pycache__/struct.cpython-36.pyc new file mode 100644 index 0000000..31645d0 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/struct.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/tarfile.cpython-36.pyc b/venv/lib/python3.6/__pycache__/tarfile.cpython-36.pyc new file mode 100644 index 0000000..6ad727e Binary files /dev/null and b/venv/lib/python3.6/__pycache__/tarfile.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/tempfile.cpython-36.pyc b/venv/lib/python3.6/__pycache__/tempfile.cpython-36.pyc new file mode 100644 index 0000000..da2c3b3 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/tempfile.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/token.cpython-36.pyc b/venv/lib/python3.6/__pycache__/token.cpython-36.pyc new file mode 100644 index 0000000..eb4afc8 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/token.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/tokenize.cpython-36.pyc b/venv/lib/python3.6/__pycache__/tokenize.cpython-36.pyc new file mode 100644 index 0000000..1f61152 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/tokenize.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/types.cpython-36.pyc b/venv/lib/python3.6/__pycache__/types.cpython-36.pyc new file mode 100644 index 0000000..f0ee394 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/types.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/warnings.cpython-36.pyc b/venv/lib/python3.6/__pycache__/warnings.cpython-36.pyc new file mode 100644 index 0000000..c66e517 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/warnings.cpython-36.pyc differ diff --git a/venv/lib/python3.6/__pycache__/weakref.cpython-36.pyc b/venv/lib/python3.6/__pycache__/weakref.cpython-36.pyc new file mode 100644 index 0000000..fd53439 Binary files /dev/null and b/venv/lib/python3.6/__pycache__/weakref.cpython-36.pyc differ diff --git a/venv/lib/python3.6/_bootlocale.py b/venv/lib/python3.6/_bootlocale.py new file mode 120000 index 0000000..a5370e5 --- /dev/null +++ b/venv/lib/python3.6/_bootlocale.py @@ -0,0 +1 @@ +/usr/lib/python3.6/_bootlocale.py \ No newline at end of file diff --git a/venv/lib/python3.6/_collections_abc.py b/venv/lib/python3.6/_collections_abc.py new file mode 120000 index 0000000..0de5ea0 --- /dev/null +++ b/venv/lib/python3.6/_collections_abc.py @@ -0,0 +1 @@ +/usr/lib/python3.6/_collections_abc.py \ No newline at end of file diff --git a/venv/lib/python3.6/_dummy_thread.py b/venv/lib/python3.6/_dummy_thread.py new file mode 120000 index 0000000..cfb202b --- /dev/null +++ b/venv/lib/python3.6/_dummy_thread.py @@ -0,0 +1 @@ +/usr/lib/python3.6/_dummy_thread.py \ No newline at end of file diff --git a/venv/lib/python3.6/_weakrefset.py b/venv/lib/python3.6/_weakrefset.py new file mode 120000 index 0000000..028d5b0 --- /dev/null +++ b/venv/lib/python3.6/_weakrefset.py @@ -0,0 +1 @@ +/usr/lib/python3.6/_weakrefset.py \ No newline at end of file diff --git a/venv/lib/python3.6/abc.py b/venv/lib/python3.6/abc.py new file mode 120000 index 0000000..6027384 --- /dev/null +++ b/venv/lib/python3.6/abc.py @@ -0,0 +1 @@ +/usr/lib/python3.6/abc.py \ No newline at end of file diff --git a/venv/lib/python3.6/base64.py b/venv/lib/python3.6/base64.py new file mode 120000 index 0000000..3071a9d --- /dev/null +++ b/venv/lib/python3.6/base64.py @@ -0,0 +1 @@ +/usr/lib/python3.6/base64.py \ No newline at end of file diff --git a/venv/lib/python3.6/bisect.py b/venv/lib/python3.6/bisect.py new file mode 120000 index 0000000..bc79a0f --- /dev/null +++ b/venv/lib/python3.6/bisect.py @@ -0,0 +1 @@ +/usr/lib/python3.6/bisect.py \ No newline at end of file diff --git a/venv/lib/python3.6/codecs.py b/venv/lib/python3.6/codecs.py new file mode 120000 index 0000000..fd7a223 --- /dev/null +++ b/venv/lib/python3.6/codecs.py @@ -0,0 +1 @@ +/usr/lib/python3.6/codecs.py \ No newline at end of file diff --git a/venv/lib/python3.6/collections b/venv/lib/python3.6/collections new file mode 120000 index 0000000..c29d5e2 --- /dev/null +++ b/venv/lib/python3.6/collections @@ -0,0 +1 @@ +/usr/lib/python3.6/collections \ No newline at end of file diff --git a/venv/lib/python3.6/config-3.6m-x86_64-linux-gnu b/venv/lib/python3.6/config-3.6m-x86_64-linux-gnu new file mode 120000 index 0000000..4f26ccf --- /dev/null +++ b/venv/lib/python3.6/config-3.6m-x86_64-linux-gnu @@ -0,0 +1 @@ +/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu \ No newline at end of file diff --git a/venv/lib/python3.6/copy.py b/venv/lib/python3.6/copy.py new file mode 120000 index 0000000..55335c7 --- /dev/null +++ b/venv/lib/python3.6/copy.py @@ -0,0 +1 @@ +/usr/lib/python3.6/copy.py \ No newline at end of file diff --git a/venv/lib/python3.6/copyreg.py b/venv/lib/python3.6/copyreg.py new file mode 120000 index 0000000..f204ea6 --- /dev/null +++ b/venv/lib/python3.6/copyreg.py @@ -0,0 +1 @@ +/usr/lib/python3.6/copyreg.py \ No newline at end of file diff --git a/venv/lib/python3.6/distutils/__init__.py b/venv/lib/python3.6/distutils/__init__.py new file mode 100644 index 0000000..b9b0f24 --- /dev/null +++ b/venv/lib/python3.6/distutils/__init__.py @@ -0,0 +1,134 @@ +import os +import sys +import warnings + +# opcode is not a virtualenv module, so we can use it to find the stdlib +# Important! To work on pypy, this must be a module that resides in the +# lib-python/modified-x.y.z directory +import opcode + +dirname = os.path.dirname + +distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils") +if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)): + warnings.warn("The virtualenv distutils package at %s appears to be in the same location as the system distutils?") +else: + __path__.insert(0, distutils_path) # noqa: F821 + if sys.version_info < (3, 4): + import imp + + real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ("", "", imp.PKG_DIRECTORY)) + else: + import importlib.machinery + + distutils_path = os.path.join(distutils_path, "__init__.py") + loader = importlib.machinery.SourceFileLoader("_virtualenv_distutils", distutils_path) + if sys.version_info < (3, 5): + import types + + real_distutils = types.ModuleType(loader.name) + else: + import importlib.util + + spec = importlib.util.spec_from_loader(loader.name, loader) + real_distutils = importlib.util.module_from_spec(spec) + loader.exec_module(real_distutils) + + # Copy the relevant attributes + try: + __revision__ = real_distutils.__revision__ + except AttributeError: + pass + __version__ = real_distutils.__version__ + +from distutils import dist, sysconfig # isort:skip + +try: + basestring +except NameError: + basestring = str + +# patch build_ext (distutils doesn't know how to get the libs directory +# path on windows - it hardcodes the paths around the patched sys.prefix) + +if sys.platform == "win32": + from distutils.command.build_ext import build_ext as old_build_ext + + class build_ext(old_build_ext): + def finalize_options(self): + if self.library_dirs is None: + self.library_dirs = [] + elif isinstance(self.library_dirs, basestring): + self.library_dirs = self.library_dirs.split(os.pathsep) + + self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs")) + old_build_ext.finalize_options(self) + + from distutils.command import build_ext as build_ext_module + + build_ext_module.build_ext = build_ext + +# distutils.dist patches: + +old_find_config_files = dist.Distribution.find_config_files + + +def find_config_files(self): + found = old_find_config_files(self) + if os.name == "posix": + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + user_filename = os.path.join(sys.prefix, user_filename) + if os.path.isfile(user_filename): + for item in list(found): + if item.endswith("pydistutils.cfg"): + found.remove(item) + found.append(user_filename) + return found + + +dist.Distribution.find_config_files = find_config_files + +# distutils.sysconfig patches: + +old_get_python_inc = sysconfig.get_python_inc + + +def sysconfig_get_python_inc(plat_specific=0, prefix=None): + if prefix is None: + prefix = sys.real_prefix + return old_get_python_inc(plat_specific, prefix) + + +sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__ +sysconfig.get_python_inc = sysconfig_get_python_inc + +old_get_python_lib = sysconfig.get_python_lib + + +def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + if standard_lib and prefix is None: + prefix = sys.real_prefix + return old_get_python_lib(plat_specific, standard_lib, prefix) + + +sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__ +sysconfig.get_python_lib = sysconfig_get_python_lib + +old_get_config_vars = sysconfig.get_config_vars + + +def sysconfig_get_config_vars(*args): + real_vars = old_get_config_vars(*args) + if sys.platform == "win32": + lib_dir = os.path.join(sys.real_prefix, "libs") + if isinstance(real_vars, dict) and "LIBDIR" not in real_vars: + real_vars["LIBDIR"] = lib_dir # asked for all + elif isinstance(real_vars, list) and "LIBDIR" in args: + real_vars = real_vars + [lib_dir] # asked for list + return real_vars + + +sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__ +sysconfig.get_config_vars = sysconfig_get_config_vars diff --git a/venv/lib/python3.6/distutils/__pycache__/__init__.cpython-36.pyc b/venv/lib/python3.6/distutils/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..7444133 Binary files /dev/null and b/venv/lib/python3.6/distutils/__pycache__/__init__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/distutils/distutils.cfg b/venv/lib/python3.6/distutils/distutils.cfg new file mode 100644 index 0000000..1af230e --- /dev/null +++ b/venv/lib/python3.6/distutils/distutils.cfg @@ -0,0 +1,6 @@ +# This is a config file local to this virtualenv installation +# You may include options that will be used by all distutils commands, +# and by easy_install. For instance: +# +# [easy_install] +# find_links = http://mylocalsite diff --git a/venv/lib/python3.6/encodings b/venv/lib/python3.6/encodings new file mode 120000 index 0000000..2a95cd3 --- /dev/null +++ b/venv/lib/python3.6/encodings @@ -0,0 +1 @@ +/usr/lib/python3.6/encodings \ No newline at end of file diff --git a/venv/lib/python3.6/enum.py b/venv/lib/python3.6/enum.py new file mode 120000 index 0000000..253ba18 --- /dev/null +++ b/venv/lib/python3.6/enum.py @@ -0,0 +1 @@ +/usr/lib/python3.6/enum.py \ No newline at end of file diff --git a/venv/lib/python3.6/fnmatch.py b/venv/lib/python3.6/fnmatch.py new file mode 120000 index 0000000..9eaf344 --- /dev/null +++ b/venv/lib/python3.6/fnmatch.py @@ -0,0 +1 @@ +/usr/lib/python3.6/fnmatch.py \ No newline at end of file diff --git a/venv/lib/python3.6/functools.py b/venv/lib/python3.6/functools.py new file mode 120000 index 0000000..2cd14d2 --- /dev/null +++ b/venv/lib/python3.6/functools.py @@ -0,0 +1 @@ +/usr/lib/python3.6/functools.py \ No newline at end of file diff --git a/venv/lib/python3.6/genericpath.py b/venv/lib/python3.6/genericpath.py new file mode 120000 index 0000000..40c6098 --- /dev/null +++ b/venv/lib/python3.6/genericpath.py @@ -0,0 +1 @@ +/usr/lib/python3.6/genericpath.py \ No newline at end of file diff --git a/venv/lib/python3.6/hashlib.py b/venv/lib/python3.6/hashlib.py new file mode 120000 index 0000000..2da3e78 --- /dev/null +++ b/venv/lib/python3.6/hashlib.py @@ -0,0 +1 @@ +/usr/lib/python3.6/hashlib.py \ No newline at end of file diff --git a/venv/lib/python3.6/heapq.py b/venv/lib/python3.6/heapq.py new file mode 120000 index 0000000..c767b16 --- /dev/null +++ b/venv/lib/python3.6/heapq.py @@ -0,0 +1 @@ +/usr/lib/python3.6/heapq.py \ No newline at end of file diff --git a/venv/lib/python3.6/hmac.py b/venv/lib/python3.6/hmac.py new file mode 120000 index 0000000..b179131 --- /dev/null +++ b/venv/lib/python3.6/hmac.py @@ -0,0 +1 @@ +/usr/lib/python3.6/hmac.py \ No newline at end of file diff --git a/venv/lib/python3.6/imp.py b/venv/lib/python3.6/imp.py new file mode 120000 index 0000000..6274155 --- /dev/null +++ b/venv/lib/python3.6/imp.py @@ -0,0 +1 @@ +/usr/lib/python3.6/imp.py \ No newline at end of file diff --git a/venv/lib/python3.6/importlib b/venv/lib/python3.6/importlib new file mode 120000 index 0000000..abbdad2 --- /dev/null +++ b/venv/lib/python3.6/importlib @@ -0,0 +1 @@ +/usr/lib/python3.6/importlib \ No newline at end of file diff --git a/venv/lib/python3.6/io.py b/venv/lib/python3.6/io.py new file mode 120000 index 0000000..9a12e78 --- /dev/null +++ b/venv/lib/python3.6/io.py @@ -0,0 +1 @@ +/usr/lib/python3.6/io.py \ No newline at end of file diff --git a/venv/lib/python3.6/keyword.py b/venv/lib/python3.6/keyword.py new file mode 120000 index 0000000..7d849a1 --- /dev/null +++ b/venv/lib/python3.6/keyword.py @@ -0,0 +1 @@ +/usr/lib/python3.6/keyword.py \ No newline at end of file diff --git a/venv/lib/python3.6/lib-dynload b/venv/lib/python3.6/lib-dynload new file mode 120000 index 0000000..17a60bd --- /dev/null +++ b/venv/lib/python3.6/lib-dynload @@ -0,0 +1 @@ +/usr/lib/python3.6/lib-dynload \ No newline at end of file diff --git a/venv/lib/python3.6/linecache.py b/venv/lib/python3.6/linecache.py new file mode 120000 index 0000000..4b59086 --- /dev/null +++ b/venv/lib/python3.6/linecache.py @@ -0,0 +1 @@ +/usr/lib/python3.6/linecache.py \ No newline at end of file diff --git a/venv/lib/python3.6/locale.py b/venv/lib/python3.6/locale.py new file mode 120000 index 0000000..8bf42b4 --- /dev/null +++ b/venv/lib/python3.6/locale.py @@ -0,0 +1 @@ +/usr/lib/python3.6/locale.py \ No newline at end of file diff --git a/venv/lib/python3.6/no-global-site-packages.txt b/venv/lib/python3.6/no-global-site-packages.txt new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.6/ntpath.py b/venv/lib/python3.6/ntpath.py new file mode 120000 index 0000000..46146ed --- /dev/null +++ b/venv/lib/python3.6/ntpath.py @@ -0,0 +1 @@ +/usr/lib/python3.6/ntpath.py \ No newline at end of file diff --git a/venv/lib/python3.6/operator.py b/venv/lib/python3.6/operator.py new file mode 120000 index 0000000..d7535c4 --- /dev/null +++ b/venv/lib/python3.6/operator.py @@ -0,0 +1 @@ +/usr/lib/python3.6/operator.py \ No newline at end of file diff --git a/venv/lib/python3.6/orig-prefix.txt b/venv/lib/python3.6/orig-prefix.txt new file mode 100644 index 0000000..e25db58 --- /dev/null +++ b/venv/lib/python3.6/orig-prefix.txt @@ -0,0 +1 @@ +/usr \ No newline at end of file diff --git a/venv/lib/python3.6/os.py b/venv/lib/python3.6/os.py new file mode 120000 index 0000000..656717d --- /dev/null +++ b/venv/lib/python3.6/os.py @@ -0,0 +1 @@ +/usr/lib/python3.6/os.py \ No newline at end of file diff --git a/venv/lib/python3.6/posixpath.py b/venv/lib/python3.6/posixpath.py new file mode 120000 index 0000000..0589464 --- /dev/null +++ b/venv/lib/python3.6/posixpath.py @@ -0,0 +1 @@ +/usr/lib/python3.6/posixpath.py \ No newline at end of file diff --git a/venv/lib/python3.6/random.py b/venv/lib/python3.6/random.py new file mode 120000 index 0000000..6e4e629 --- /dev/null +++ b/venv/lib/python3.6/random.py @@ -0,0 +1 @@ +/usr/lib/python3.6/random.py \ No newline at end of file diff --git a/venv/lib/python3.6/re.py b/venv/lib/python3.6/re.py new file mode 120000 index 0000000..a8d6c74 --- /dev/null +++ b/venv/lib/python3.6/re.py @@ -0,0 +1 @@ +/usr/lib/python3.6/re.py \ No newline at end of file diff --git a/venv/lib/python3.6/reprlib.py b/venv/lib/python3.6/reprlib.py new file mode 120000 index 0000000..f44dc1b --- /dev/null +++ b/venv/lib/python3.6/reprlib.py @@ -0,0 +1 @@ +/usr/lib/python3.6/reprlib.py \ No newline at end of file diff --git a/venv/lib/python3.6/rlcompleter.py b/venv/lib/python3.6/rlcompleter.py new file mode 120000 index 0000000..60afc48 --- /dev/null +++ b/venv/lib/python3.6/rlcompleter.py @@ -0,0 +1 @@ +/usr/lib/python3.6/rlcompleter.py \ No newline at end of file diff --git a/venv/lib/python3.6/shutil.py b/venv/lib/python3.6/shutil.py new file mode 120000 index 0000000..bb00b81 --- /dev/null +++ b/venv/lib/python3.6/shutil.py @@ -0,0 +1 @@ +/usr/lib/python3.6/shutil.py \ No newline at end of file diff --git a/venv/lib/python3.6/site-packages/__pycache__/cycler.cpython-36.pyc b/venv/lib/python3.6/site-packages/__pycache__/cycler.cpython-36.pyc new file mode 100644 index 0000000..2856152 Binary files /dev/null and b/venv/lib/python3.6/site-packages/__pycache__/cycler.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/__pycache__/easy_install.cpython-36.pyc b/venv/lib/python3.6/site-packages/__pycache__/easy_install.cpython-36.pyc new file mode 100644 index 0000000..d2595f7 Binary files /dev/null and b/venv/lib/python3.6/site-packages/__pycache__/easy_install.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/__pycache__/pylab.cpython-36.pyc b/venv/lib/python3.6/site-packages/__pycache__/pylab.cpython-36.pyc new file mode 100644 index 0000000..be43d21 Binary files /dev/null and b/venv/lib/python3.6/site-packages/__pycache__/pylab.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/__pycache__/pyparsing.cpython-36.pyc b/venv/lib/python3.6/site-packages/__pycache__/pyparsing.cpython-36.pyc new file mode 100644 index 0000000..9daaec7 Binary files /dev/null and b/venv/lib/python3.6/site-packages/__pycache__/pyparsing.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/__pycache__/six.cpython-36.pyc b/venv/lib/python3.6/site-packages/__pycache__/six.cpython-36.pyc new file mode 100644 index 0000000..1d179c3 Binary files /dev/null and b/venv/lib/python3.6/site-packages/__pycache__/six.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/DESCRIPTION.rst b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..e118723 --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/DESCRIPTION.rst @@ -0,0 +1,3 @@ +UNKNOWN + + diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/INSTALLER b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/METADATA b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/METADATA new file mode 100644 index 0000000..b232cee --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/METADATA @@ -0,0 +1,25 @@ +Metadata-Version: 2.0 +Name: cycler +Version: 0.10.0 +Summary: Composable style cycles +Home-page: http://github.com/matplotlib/cycler +Author: Thomas A Caswell +Author-email: matplotlib-users@python.org +License: BSD +Keywords: cycle kwargs +Platform: Cross platform (Linux +Platform: Mac OSX +Platform: Windows) +Classifier: Development Status :: 4 - Beta +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Requires-Dist: six + +UNKNOWN + + diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/RECORD b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/RECORD new file mode 100644 index 0000000..44cc61e --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/RECORD @@ -0,0 +1,9 @@ +__pycache__/cycler.cpython-36.pyc,, +cycler-0.10.0.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 +cycler-0.10.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cycler-0.10.0.dist-info/METADATA,sha256=aWX1pyo7D2hSDNZ2Q6Zl7DxhUQdpyu1O5uNABnvz000,722 +cycler-0.10.0.dist-info/RECORD,, +cycler-0.10.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +cycler-0.10.0.dist-info/metadata.json,sha256=CCBpg-KQU-VRL1unJcHPWKQeQbB84G0j7-BeCj7YUbU,875 +cycler-0.10.0.dist-info/top_level.txt,sha256=D8BVVDdAAelLb2FOEz7lDpc6-AL21ylKPrMhtG6yzyE,7 +cycler.py,sha256=ed3G39unvVEBrBZVDwnE0FFroRNsOLkbJ_TwIT5CjCU,15959 diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/WHEEL b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/WHEEL new file mode 100644 index 0000000..8b6dd1b --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/metadata.json b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/metadata.json new file mode 100644 index 0000000..6082129 --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 4 - Beta", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5"], "extensions": {"python.details": {"contacts": [{"email": "matplotlib-users@python.org", "name": "Thomas A Caswell", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/matplotlib/cycler"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "keywords": ["cycle", "kwargs"], "license": "BSD", "metadata_version": "2.0", "name": "cycler", "platform": "Cross platform (Linux", "run_requires": [{"requires": ["six"]}], "summary": "Composable style cycles", "version": "0.10.0"} \ No newline at end of file diff --git a/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/top_level.txt b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/top_level.txt new file mode 100644 index 0000000..2254644 --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler-0.10.0.dist-info/top_level.txt @@ -0,0 +1 @@ +cycler diff --git a/venv/lib/python3.6/site-packages/cycler.py b/venv/lib/python3.6/site-packages/cycler.py new file mode 100644 index 0000000..3c3eb2d --- /dev/null +++ b/venv/lib/python3.6/site-packages/cycler.py @@ -0,0 +1,558 @@ +""" +Cycler +====== + +Cycling through combinations of values, producing dictionaries. + +You can add cyclers:: + + from cycler import cycler + cc = (cycler(color=list('rgb')) + + cycler(linestyle=['-', '--', '-.'])) + for d in cc: + print(d) + +Results in:: + + {'color': 'r', 'linestyle': '-'} + {'color': 'g', 'linestyle': '--'} + {'color': 'b', 'linestyle': '-.'} + + +You can multiply cyclers:: + + from cycler import cycler + cc = (cycler(color=list('rgb')) * + cycler(linestyle=['-', '--', '-.'])) + for d in cc: + print(d) + +Results in:: + + {'color': 'r', 'linestyle': '-'} + {'color': 'r', 'linestyle': '--'} + {'color': 'r', 'linestyle': '-.'} + {'color': 'g', 'linestyle': '-'} + {'color': 'g', 'linestyle': '--'} + {'color': 'g', 'linestyle': '-.'} + {'color': 'b', 'linestyle': '-'} + {'color': 'b', 'linestyle': '--'} + {'color': 'b', 'linestyle': '-.'} +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from itertools import product, cycle +from six.moves import zip, reduce +from operator import mul, add +import copy + +__version__ = '0.10.0' + + +def _process_keys(left, right): + """ + Helper function to compose cycler keys + + Parameters + ---------- + left, right : iterable of dictionaries or None + The cyclers to be composed + Returns + ------- + keys : set + The keys in the composition of the two cyclers + """ + l_peek = next(iter(left)) if left is not None else {} + r_peek = next(iter(right)) if right is not None else {} + l_key = set(l_peek.keys()) + r_key = set(r_peek.keys()) + if l_key & r_key: + raise ValueError("Can not compose overlapping cycles") + return l_key | r_key + + +class Cycler(object): + """ + Composable cycles + + This class has compositions methods: + + ``+`` + for 'inner' products (zip) + + ``+=`` + in-place ``+`` + + ``*`` + for outer products (itertools.product) and integer multiplication + + ``*=`` + in-place ``*`` + + and supports basic slicing via ``[]`` + + Parameters + ---------- + left : Cycler or None + The 'left' cycler + + right : Cycler or None + The 'right' cycler + + op : func or None + Function which composes the 'left' and 'right' cyclers. + + """ + def __call__(self): + return cycle(self) + + def __init__(self, left, right=None, op=None): + """Semi-private init + + Do not use this directly, use `cycler` function instead. + """ + if isinstance(left, Cycler): + self._left = Cycler(left._left, left._right, left._op) + elif left is not None: + # Need to copy the dictionary or else that will be a residual + # mutable that could lead to strange errors + self._left = [copy.copy(v) for v in left] + else: + self._left = None + + if isinstance(right, Cycler): + self._right = Cycler(right._left, right._right, right._op) + elif right is not None: + # Need to copy the dictionary or else that will be a residual + # mutable that could lead to strange errors + self._right = [copy.copy(v) for v in right] + else: + self._right = None + + self._keys = _process_keys(self._left, self._right) + self._op = op + + @property + def keys(self): + """ + The keys this Cycler knows about + """ + return set(self._keys) + + def change_key(self, old, new): + """ + Change a key in this cycler to a new name. + Modification is performed in-place. + + Does nothing if the old key is the same as the new key. + Raises a ValueError if the new key is already a key. + Raises a KeyError if the old key isn't a key. + + """ + if old == new: + return + if new in self._keys: + raise ValueError("Can't replace %s with %s, %s is already a key" % + (old, new, new)) + if old not in self._keys: + raise KeyError("Can't replace %s with %s, %s is not a key" % + (old, new, old)) + + self._keys.remove(old) + self._keys.add(new) + + if self._right is not None and old in self._right.keys: + self._right.change_key(old, new) + + # self._left should always be non-None + # if self._keys is non-empty. + elif isinstance(self._left, Cycler): + self._left.change_key(old, new) + else: + # It should be completely safe at this point to + # assume that the old key can be found in each + # iteration. + self._left = [{new: entry[old]} for entry in self._left] + + def _compose(self): + """ + Compose the 'left' and 'right' components of this cycle + with the proper operation (zip or product as of now) + """ + for a, b in self._op(self._left, self._right): + out = dict() + out.update(a) + out.update(b) + yield out + + @classmethod + def _from_iter(cls, label, itr): + """ + Class method to create 'base' Cycler objects + that do not have a 'right' or 'op' and for which + the 'left' object is not another Cycler. + + Parameters + ---------- + label : str + The property key. + + itr : iterable + Finite length iterable of the property values. + + Returns + ------- + cycler : Cycler + New 'base' `Cycler` + """ + ret = cls(None) + ret._left = list({label: v} for v in itr) + ret._keys = set([label]) + return ret + + def __getitem__(self, key): + # TODO : maybe add numpy style fancy slicing + if isinstance(key, slice): + trans = self.by_key() + return reduce(add, (_cycler(k, v[key]) + for k, v in six.iteritems(trans))) + else: + raise ValueError("Can only use slices with Cycler.__getitem__") + + def __iter__(self): + if self._right is None: + return iter(dict(l) for l in self._left) + + return self._compose() + + def __add__(self, other): + """ + Pair-wise combine two equal length cycles (zip) + + Parameters + ---------- + other : Cycler + The second Cycler + """ + if len(self) != len(other): + raise ValueError("Can only add equal length cycles, " + "not {0} and {1}".format(len(self), len(other))) + return Cycler(self, other, zip) + + def __mul__(self, other): + """ + Outer product of two cycles (`itertools.product`) or integer + multiplication. + + Parameters + ---------- + other : Cycler or int + The second Cycler or integer + """ + if isinstance(other, Cycler): + return Cycler(self, other, product) + elif isinstance(other, int): + trans = self.by_key() + return reduce(add, (_cycler(k, v*other) + for k, v in six.iteritems(trans))) + else: + return NotImplemented + + def __rmul__(self, other): + return self * other + + def __len__(self): + op_dict = {zip: min, product: mul} + if self._right is None: + return len(self._left) + l_len = len(self._left) + r_len = len(self._right) + return op_dict[self._op](l_len, r_len) + + def __iadd__(self, other): + """ + In-place pair-wise combine two equal length cycles (zip) + + Parameters + ---------- + other : Cycler + The second Cycler + """ + if not isinstance(other, Cycler): + raise TypeError("Cannot += with a non-Cycler object") + # True shallow copy of self is fine since this is in-place + old_self = copy.copy(self) + self._keys = _process_keys(old_self, other) + self._left = old_self + self._op = zip + self._right = Cycler(other._left, other._right, other._op) + return self + + def __imul__(self, other): + """ + In-place outer product of two cycles (`itertools.product`) + + Parameters + ---------- + other : Cycler + The second Cycler + """ + if not isinstance(other, Cycler): + raise TypeError("Cannot *= with a non-Cycler object") + # True shallow copy of self is fine since this is in-place + old_self = copy.copy(self) + self._keys = _process_keys(old_self, other) + self._left = old_self + self._op = product + self._right = Cycler(other._left, other._right, other._op) + return self + + def __eq__(self, other): + """ + Check equality + """ + if len(self) != len(other): + return False + if self.keys ^ other.keys: + return False + + return all(a == b for a, b in zip(self, other)) + + def __repr__(self): + op_map = {zip: '+', product: '*'} + if self._right is None: + lab = self.keys.pop() + itr = list(v[lab] for v in self) + return "cycler({lab!r}, {itr!r})".format(lab=lab, itr=itr) + else: + op = op_map.get(self._op, '?') + msg = "({left!r} {op} {right!r})" + return msg.format(left=self._left, op=op, right=self._right) + + def _repr_html_(self): + # an table showing the value of each key through a full cycle + output = "" + sorted_keys = sorted(self.keys, key=repr) + for key in sorted_keys: + output += "".format(key=key) + for d in iter(self): + output += "" + for k in sorted_keys: + output += "".format(val=d[k]) + output += "" + output += "
{key!r}
{val!r}
" + return output + + def by_key(self): + """Values by key + + This returns the transposed values of the cycler. Iterating + over a `Cycler` yields dicts with a single value for each key, + this method returns a `dict` of `list` which are the values + for the given key. + + The returned value can be used to create an equivalent `Cycler` + using only `+`. + + Returns + ------- + transpose : dict + dict of lists of the values for each key. + """ + + # TODO : sort out if this is a bottle neck, if there is a better way + # and if we care. + + keys = self.keys + # change this to dict comprehension when drop 2.6 + out = dict((k, list()) for k in keys) + + for d in self: + for k in keys: + out[k].append(d[k]) + return out + + # for back compatibility + _transpose = by_key + + def simplify(self): + """Simplify the Cycler + + Returned as a composition using only sums (no multiplications) + + Returns + ------- + simple : Cycler + An equivalent cycler using only summation""" + # TODO: sort out if it is worth the effort to make sure this is + # balanced. Currently it is is + # (((a + b) + c) + d) vs + # ((a + b) + (c + d)) + # I would believe that there is some performance implications + + trans = self.by_key() + return reduce(add, (_cycler(k, v) for k, v in six.iteritems(trans))) + + def concat(self, other): + """Concatenate this cycler and an other. + + The keys must match exactly. + + This returns a single Cycler which is equivalent to + `itertools.chain(self, other)` + + Examples + -------- + + >>> num = cycler('a', range(3)) + >>> let = cycler('a', 'abc') + >>> num.concat(let) + cycler('a', [0, 1, 2, 'a', 'b', 'c']) + + Parameters + ---------- + other : `Cycler` + The `Cycler` to concatenate to this one. + + Returns + ------- + ret : `Cycler` + The concatenated `Cycler` + """ + return concat(self, other) + + +def concat(left, right): + """Concatenate two cyclers. + + The keys must match exactly. + + This returns a single Cycler which is equivalent to + `itertools.chain(left, right)` + + Examples + -------- + + >>> num = cycler('a', range(3)) + >>> let = cycler('a', 'abc') + >>> num.concat(let) + cycler('a', [0, 1, 2, 'a', 'b', 'c']) + + Parameters + ---------- + left, right : `Cycler` + The two `Cycler` instances to concatenate + + Returns + ------- + ret : `Cycler` + The concatenated `Cycler` + """ + if left.keys != right.keys: + msg = '\n\t'.join(["Keys do not match:", + "Intersection: {both!r}", + "Disjoint: {just_one!r}"]).format( + both=left.keys & right.keys, + just_one=left.keys ^ right.keys) + + raise ValueError(msg) + + _l = left.by_key() + _r = right.by_key() + return reduce(add, (_cycler(k, _l[k] + _r[k]) for k in left.keys)) + + +def cycler(*args, **kwargs): + """ + Create a new `Cycler` object from a single positional argument, + a pair of positional arguments, or the combination of keyword arguments. + + cycler(arg) + cycler(label1=itr1[, label2=iter2[, ...]]) + cycler(label, itr) + + Form 1 simply copies a given `Cycler` object. + + Form 2 composes a `Cycler` as an inner product of the + pairs of keyword arguments. In other words, all of the + iterables are cycled simultaneously, as if through zip(). + + Form 3 creates a `Cycler` from a label and an iterable. + This is useful for when the label cannot be a keyword argument + (e.g., an integer or a name that has a space in it). + + Parameters + ---------- + arg : Cycler + Copy constructor for Cycler (does a shallow copy of iterables). + + label : name + The property key. In the 2-arg form of the function, + the label can be any hashable object. In the keyword argument + form of the function, it must be a valid python identifier. + + itr : iterable + Finite length iterable of the property values. + Can be a single-property `Cycler` that would + be like a key change, but as a shallow copy. + + Returns + ------- + cycler : Cycler + New `Cycler` for the given property + + """ + if args and kwargs: + raise TypeError("cyl() can only accept positional OR keyword " + "arguments -- not both.") + + if len(args) == 1: + if not isinstance(args[0], Cycler): + raise TypeError("If only one positional argument given, it must " + " be a Cycler instance.") + return Cycler(args[0]) + elif len(args) == 2: + return _cycler(*args) + elif len(args) > 2: + raise TypeError("Only a single Cycler can be accepted as the lone " + "positional argument. Use keyword arguments instead.") + + if kwargs: + return reduce(add, (_cycler(k, v) for k, v in six.iteritems(kwargs))) + + raise TypeError("Must have at least a positional OR keyword arguments") + + +def _cycler(label, itr): + """ + Create a new `Cycler` object from a property name and + iterable of values. + + Parameters + ---------- + label : hashable + The property key. + + itr : iterable + Finite length iterable of the property values. + + Returns + ------- + cycler : Cycler + New `Cycler` for the given property + """ + if isinstance(itr, Cycler): + keys = itr.keys + if len(keys) != 1: + msg = "Can not create Cycler from a multi-property Cycler" + raise ValueError(msg) + + lab = keys.pop() + # Doesn't need to be a new list because + # _from_iter() will be creating that new list anyway. + itr = (v[lab] for v in itr) + + return Cycler._from_iter(label, itr) diff --git a/venv/lib/python3.6/site-packages/dateutil/__init__.py b/venv/lib/python3.6/site-packages/dateutil/__init__.py new file mode 100644 index 0000000..0defb82 --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +try: + from ._version import version as __version__ +except ImportError: + __version__ = 'unknown' + +__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz', + 'utils', 'zoneinfo'] diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/__init__.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..1c25048 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/__init__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/_common.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/_common.cpython-36.pyc new file mode 100644 index 0000000..c3adc8d Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/_common.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/_version.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/_version.cpython-36.pyc new file mode 100644 index 0000000..f8edb88 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/_version.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/easter.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/easter.cpython-36.pyc new file mode 100644 index 0000000..4b613d7 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/easter.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/relativedelta.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/relativedelta.cpython-36.pyc new file mode 100644 index 0000000..dd2bad2 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/relativedelta.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/rrule.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/rrule.cpython-36.pyc new file mode 100644 index 0000000..7f399c5 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/rrule.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/tzwin.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/tzwin.cpython-36.pyc new file mode 100644 index 0000000..0afcd3b Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/tzwin.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/__pycache__/utils.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/__pycache__/utils.cpython-36.pyc new file mode 100644 index 0000000..7af7583 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/__pycache__/utils.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/_common.py b/venv/lib/python3.6/site-packages/dateutil/_common.py new file mode 100644 index 0000000..4eb2659 --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/_common.py @@ -0,0 +1,43 @@ +""" +Common code used in multiple modules. +""" + + +class weekday(object): + __slots__ = ["weekday", "n"] + + def __init__(self, weekday, n=None): + self.weekday = weekday + self.n = n + + def __call__(self, n): + if n == self.n: + return self + else: + return self.__class__(self.weekday, n) + + def __eq__(self, other): + try: + if self.weekday != other.weekday or self.n != other.n: + return False + except AttributeError: + return False + return True + + def __hash__(self): + return hash(( + self.weekday, + self.n, + )) + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] + if not self.n: + return s + else: + return "%s(%+d)" % (s, self.n) + +# vim:ts=4:sw=4:et diff --git a/venv/lib/python3.6/site-packages/dateutil/_version.py b/venv/lib/python3.6/site-packages/dateutil/_version.py new file mode 100644 index 0000000..670d7ab --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/_version.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# file generated by setuptools_scm +# don't change, don't track in version control +version = '2.8.0' diff --git a/venv/lib/python3.6/site-packages/dateutil/easter.py b/venv/lib/python3.6/site-packages/dateutil/easter.py new file mode 100644 index 0000000..53b7c78 --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/easter.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +""" +This module offers a generic easter computing method for any given year, using +Western, Orthodox or Julian algorithms. +""" + +import datetime + +__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] + +EASTER_JULIAN = 1 +EASTER_ORTHODOX = 2 +EASTER_WESTERN = 3 + + +def easter(year, method=EASTER_WESTERN): + """ + This method was ported from the work done by GM Arts, + on top of the algorithm by Claus Tondering, which was + based in part on the algorithm of Ouding (1940), as + quoted in "Explanatory Supplement to the Astronomical + Almanac", P. Kenneth Seidelmann, editor. + + This algorithm implements three different easter + calculation methods: + + 1 - Original calculation in Julian calendar, valid in + dates after 326 AD + 2 - Original method, with date converted to Gregorian + calendar, valid in years 1583 to 4099 + 3 - Revised method, in Gregorian calendar, valid in + years 1583 to 4099 as well + + These methods are represented by the constants: + + * ``EASTER_JULIAN = 1`` + * ``EASTER_ORTHODOX = 2`` + * ``EASTER_WESTERN = 3`` + + The default method is method 3. + + More about the algorithm may be found at: + + `GM Arts: Easter Algorithms `_ + + and + + `The Calendar FAQ: Easter `_ + + """ + + if not (1 <= method <= 3): + raise ValueError("invalid method") + + # g - Golden year - 1 + # c - Century + # h - (23 - Epact) mod 30 + # i - Number of days from March 21 to Paschal Full Moon + # j - Weekday for PFM (0=Sunday, etc) + # p - Number of days from March 21 to Sunday on or before PFM + # (-6 to 28 methods 1 & 3, to 56 for method 2) + # e - Extra days to add for method 2 (converting Julian + # date to Gregorian date) + + y = year + g = y % 19 + e = 0 + if method < 3: + # Old method + i = (19*g + 15) % 30 + j = (y + y//4 + i) % 7 + if method == 2: + # Extra dates to convert Julian to Gregorian date + e = 10 + if y > 1600: + e = e + y//100 - 16 - (y//100 - 16)//4 + else: + # New method + c = y//100 + h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30 + i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11)) + j = (y + y//4 + i + 2 - c + c//4) % 7 + + # p can be from -6 to 56 corresponding to dates 22 March to 23 May + # (later dates apply to method 2, although 23 May never actually occurs) + p = i - j + e + d = 1 + (p + 27 + (p + 6)//40) % 31 + m = 3 + (p + 26)//30 + return datetime.date(int(y), int(m), int(d)) diff --git a/venv/lib/python3.6/site-packages/dateutil/parser/__init__.py b/venv/lib/python3.6/site-packages/dateutil/parser/__init__.py new file mode 100644 index 0000000..216762c --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/parser/__init__.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +from ._parser import parse, parser, parserinfo +from ._parser import DEFAULTPARSER, DEFAULTTZPARSER +from ._parser import UnknownTimezoneWarning + +from ._parser import __doc__ + +from .isoparser import isoparser, isoparse + +__all__ = ['parse', 'parser', 'parserinfo', + 'isoparse', 'isoparser', + 'UnknownTimezoneWarning'] + + +### +# Deprecate portions of the private interface so that downstream code that +# is improperly relying on it is given *some* notice. + + +def __deprecated_private_func(f): + from functools import wraps + import warnings + + msg = ('{name} is a private function and may break without warning, ' + 'it will be moved and or renamed in future versions.') + msg = msg.format(name=f.__name__) + + @wraps(f) + def deprecated_func(*args, **kwargs): + warnings.warn(msg, DeprecationWarning) + return f(*args, **kwargs) + + return deprecated_func + +def __deprecate_private_class(c): + import warnings + + msg = ('{name} is a private class and may break without warning, ' + 'it will be moved and or renamed in future versions.') + msg = msg.format(name=c.__name__) + + class private_class(c): + __doc__ = c.__doc__ + + def __init__(self, *args, **kwargs): + warnings.warn(msg, DeprecationWarning) + super(private_class, self).__init__(*args, **kwargs) + + private_class.__name__ = c.__name__ + + return private_class + + +from ._parser import _timelex, _resultbase +from ._parser import _tzparser, _parsetz + +_timelex = __deprecate_private_class(_timelex) +_tzparser = __deprecate_private_class(_tzparser) +_resultbase = __deprecate_private_class(_resultbase) +_parsetz = __deprecated_private_func(_parsetz) diff --git a/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/__init__.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..3a92165 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/__init__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/_parser.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/_parser.cpython-36.pyc new file mode 100644 index 0000000..a2326c5 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/_parser.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/isoparser.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/isoparser.cpython-36.pyc new file mode 100644 index 0000000..5db1cd5 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/parser/__pycache__/isoparser.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/parser/_parser.py b/venv/lib/python3.6/site-packages/dateutil/parser/_parser.py new file mode 100644 index 0000000..0da0f3e --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/parser/_parser.py @@ -0,0 +1,1580 @@ +# -*- coding: utf-8 -*- +""" +This module offers a generic date/time string parser which is able to parse +most known formats to represent a date and/or time. + +This module attempts to be forgiving with regards to unlikely input formats, +returning a datetime object even for dates which are ambiguous. If an element +of a date/time stamp is omitted, the following rules are applied: + +- If AM or PM is left unspecified, a 24-hour clock is assumed, however, an hour + on a 12-hour clock (``0 <= hour <= 12``) *must* be specified if AM or PM is + specified. +- If a time zone is omitted, a timezone-naive datetime is returned. + +If any other elements are missing, they are taken from the +:class:`datetime.datetime` object passed to the parameter ``default``. If this +results in a day number exceeding the valid number of days per month, the +value falls back to the end of the month. + +Additional resources about date/time string formats can be found below: + +- `A summary of the international standard date and time notation + `_ +- `W3C Date and Time Formats `_ +- `Time Formats (Planetary Rings Node) `_ +- `CPAN ParseDate module + `_ +- `Java SimpleDateFormat Class + `_ +""" +from __future__ import unicode_literals + +import datetime +import re +import string +import time +import warnings + +from calendar import monthrange +from io import StringIO + +import six +from six import integer_types, text_type + +from decimal import Decimal + +from warnings import warn + +from .. import relativedelta +from .. import tz + +__all__ = ["parse", "parserinfo"] + + +# TODO: pandas.core.tools.datetimes imports this explicitly. Might be worth +# making public and/or figuring out if there is something we can +# take off their plate. +class _timelex(object): + # Fractional seconds are sometimes split by a comma + _split_decimal = re.compile("([.,])") + + def __init__(self, instream): + if six.PY2: + # In Python 2, we can't duck type properly because unicode has + # a 'decode' function, and we'd be double-decoding + if isinstance(instream, (bytes, bytearray)): + instream = instream.decode() + else: + if getattr(instream, 'decode', None) is not None: + instream = instream.decode() + + if isinstance(instream, text_type): + instream = StringIO(instream) + elif getattr(instream, 'read', None) is None: + raise TypeError('Parser must be a string or character stream, not ' + '{itype}'.format(itype=instream.__class__.__name__)) + + self.instream = instream + self.charstack = [] + self.tokenstack = [] + self.eof = False + + def get_token(self): + """ + This function breaks the time string into lexical units (tokens), which + can be parsed by the parser. Lexical units are demarcated by changes in + the character set, so any continuous string of letters is considered + one unit, any continuous string of numbers is considered one unit. + + The main complication arises from the fact that dots ('.') can be used + both as separators (e.g. "Sep.20.2009") or decimal points (e.g. + "4:30:21.447"). As such, it is necessary to read the full context of + any dot-separated strings before breaking it into tokens; as such, this + function maintains a "token stack", for when the ambiguous context + demands that multiple tokens be parsed at once. + """ + if self.tokenstack: + return self.tokenstack.pop(0) + + seenletters = False + token = None + state = None + + while not self.eof: + # We only realize that we've reached the end of a token when we + # find a character that's not part of the current token - since + # that character may be part of the next token, it's stored in the + # charstack. + if self.charstack: + nextchar = self.charstack.pop(0) + else: + nextchar = self.instream.read(1) + while nextchar == '\x00': + nextchar = self.instream.read(1) + + if not nextchar: + self.eof = True + break + elif not state: + # First character of the token - determines if we're starting + # to parse a word, a number or something else. + token = nextchar + if self.isword(nextchar): + state = 'a' + elif self.isnum(nextchar): + state = '0' + elif self.isspace(nextchar): + token = ' ' + break # emit token + else: + break # emit token + elif state == 'a': + # If we've already started reading a word, we keep reading + # letters until we find something that's not part of a word. + seenletters = True + if self.isword(nextchar): + token += nextchar + elif nextchar == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0': + # If we've already started reading a number, we keep reading + # numbers until we find something that doesn't fit. + if self.isnum(nextchar): + token += nextchar + elif nextchar == '.' or (nextchar == ',' and len(token) >= 2): + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == 'a.': + # If we've seen some letters and a dot separator, continue + # parsing, and the tokens will be broken up later. + seenletters = True + if nextchar == '.' or self.isword(nextchar): + token += nextchar + elif self.isnum(nextchar) and token[-1] == '.': + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0.': + # If we've seen at least one dot separator, keep going, we'll + # break up the tokens later. + if nextchar == '.' or self.isnum(nextchar): + token += nextchar + elif self.isword(nextchar) and token[-1] == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + + if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or + token[-1] in '.,')): + l = self._split_decimal.split(token) + token = l[0] + for tok in l[1:]: + if tok: + self.tokenstack.append(tok) + + if state == '0.' and token.count('.') == 0: + token = token.replace(',', '.') + + return token + + def __iter__(self): + return self + + def __next__(self): + token = self.get_token() + if token is None: + raise StopIteration + + return token + + def next(self): + return self.__next__() # Python 2.x support + + @classmethod + def split(cls, s): + return list(cls(s)) + + @classmethod + def isword(cls, nextchar): + """ Whether or not the next character is part of a word """ + return nextchar.isalpha() + + @classmethod + def isnum(cls, nextchar): + """ Whether the next character is part of a number """ + return nextchar.isdigit() + + @classmethod + def isspace(cls, nextchar): + """ Whether the next character is whitespace """ + return nextchar.isspace() + + +class _resultbase(object): + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def _repr(self, classname): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (classname, ", ".join(l)) + + def __len__(self): + return (sum(getattr(self, attr) is not None + for attr in self.__slots__)) + + def __repr__(self): + return self._repr(self.__class__.__name__) + + +class parserinfo(object): + """ + Class which handles what inputs are accepted. Subclass this to customize + the language and acceptable values for each parameter. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM + and YMD. Default is ``False``. + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken + to be the year, otherwise the last number is taken to be the year. + Default is ``False``. + """ + + # m from a.m/p.m, t from ISO T separator + JUMP = [" ", ".", ",", ";", "-", "/", "'", + "at", "on", "and", "ad", "m", "t", "of", + "st", "nd", "rd", "th"] + + WEEKDAYS = [("Mon", "Monday"), + ("Tue", "Tuesday"), # TODO: "Tues" + ("Wed", "Wednesday"), + ("Thu", "Thursday"), # TODO: "Thurs" + ("Fri", "Friday"), + ("Sat", "Saturday"), + ("Sun", "Sunday")] + MONTHS = [("Jan", "January"), + ("Feb", "February"), # TODO: "Febr" + ("Mar", "March"), + ("Apr", "April"), + ("May", "May"), + ("Jun", "June"), + ("Jul", "July"), + ("Aug", "August"), + ("Sep", "Sept", "September"), + ("Oct", "October"), + ("Nov", "November"), + ("Dec", "December")] + HMS = [("h", "hour", "hours"), + ("m", "minute", "minutes"), + ("s", "second", "seconds")] + AMPM = [("am", "a"), + ("pm", "p")] + UTCZONE = ["UTC", "GMT", "Z", "z"] + PERTAIN = ["of"] + TZOFFSET = {} + # TODO: ERA = ["AD", "BC", "CE", "BCE", "Stardate", + # "Anno Domini", "Year of Our Lord"] + + def __init__(self, dayfirst=False, yearfirst=False): + self._jump = self._convert(self.JUMP) + self._weekdays = self._convert(self.WEEKDAYS) + self._months = self._convert(self.MONTHS) + self._hms = self._convert(self.HMS) + self._ampm = self._convert(self.AMPM) + self._utczone = self._convert(self.UTCZONE) + self._pertain = self._convert(self.PERTAIN) + + self.dayfirst = dayfirst + self.yearfirst = yearfirst + + self._year = time.localtime().tm_year + self._century = self._year // 100 * 100 + + def _convert(self, lst): + dct = {} + for i, v in enumerate(lst): + if isinstance(v, tuple): + for v in v: + dct[v.lower()] = i + else: + dct[v.lower()] = i + return dct + + def jump(self, name): + return name.lower() in self._jump + + def weekday(self, name): + try: + return self._weekdays[name.lower()] + except KeyError: + pass + return None + + def month(self, name): + try: + return self._months[name.lower()] + 1 + except KeyError: + pass + return None + + def hms(self, name): + try: + return self._hms[name.lower()] + except KeyError: + return None + + def ampm(self, name): + try: + return self._ampm[name.lower()] + except KeyError: + return None + + def pertain(self, name): + return name.lower() in self._pertain + + def utczone(self, name): + return name.lower() in self._utczone + + def tzoffset(self, name): + if name in self._utczone: + return 0 + + return self.TZOFFSET.get(name) + + def convertyear(self, year, century_specified=False): + """ + Converts two-digit years to year within [-50, 49] + range of self._year (current local time) + """ + + # Function contract is that the year is always positive + assert year >= 0 + + if year < 100 and not century_specified: + # assume current century to start + year += self._century + + if year >= self._year + 50: # if too far in future + year -= 100 + elif year < self._year - 50: # if too far in past + year += 100 + + return year + + def validate(self, res): + # move to info + if res.year is not None: + res.year = self.convertyear(res.year, res.century_specified) + + if ((res.tzoffset == 0 and not res.tzname) or + (res.tzname == 'Z' or res.tzname == 'z')): + res.tzname = "UTC" + res.tzoffset = 0 + elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): + res.tzoffset = 0 + return True + + +class _ymd(list): + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + self.century_specified = False + self.dstridx = None + self.mstridx = None + self.ystridx = None + + @property + def has_year(self): + return self.ystridx is not None + + @property + def has_month(self): + return self.mstridx is not None + + @property + def has_day(self): + return self.dstridx is not None + + def could_be_day(self, value): + if self.has_day: + return False + elif not self.has_month: + return 1 <= value <= 31 + elif not self.has_year: + # Be permissive, assume leapyear + month = self[self.mstridx] + return 1 <= value <= monthrange(2000, month)[1] + else: + month = self[self.mstridx] + year = self[self.ystridx] + return 1 <= value <= monthrange(year, month)[1] + + def append(self, val, label=None): + if hasattr(val, '__len__'): + if val.isdigit() and len(val) > 2: + self.century_specified = True + if label not in [None, 'Y']: # pragma: no cover + raise ValueError(label) + label = 'Y' + elif val > 100: + self.century_specified = True + if label not in [None, 'Y']: # pragma: no cover + raise ValueError(label) + label = 'Y' + + super(self.__class__, self).append(int(val)) + + if label == 'M': + if self.has_month: + raise ValueError('Month is already set') + self.mstridx = len(self) - 1 + elif label == 'D': + if self.has_day: + raise ValueError('Day is already set') + self.dstridx = len(self) - 1 + elif label == 'Y': + if self.has_year: + raise ValueError('Year is already set') + self.ystridx = len(self) - 1 + + def _resolve_from_stridxs(self, strids): + """ + Try to resolve the identities of year/month/day elements using + ystridx, mstridx, and dstridx, if enough of these are specified. + """ + if len(self) == 3 and len(strids) == 2: + # we can back out the remaining stridx value + missing = [x for x in range(3) if x not in strids.values()] + key = [x for x in ['y', 'm', 'd'] if x not in strids] + assert len(missing) == len(key) == 1 + key = key[0] + val = missing[0] + strids[key] = val + + assert len(self) == len(strids) # otherwise this should not be called + out = {key: self[strids[key]] for key in strids} + return (out.get('y'), out.get('m'), out.get('d')) + + def resolve_ymd(self, yearfirst, dayfirst): + len_ymd = len(self) + year, month, day = (None, None, None) + + strids = (('y', self.ystridx), + ('m', self.mstridx), + ('d', self.dstridx)) + + strids = {key: val for key, val in strids if val is not None} + if (len(self) == len(strids) > 0 or + (len(self) == 3 and len(strids) == 2)): + return self._resolve_from_stridxs(strids) + + mstridx = self.mstridx + + if len_ymd > 3: + raise ValueError("More than three YMD values") + elif len_ymd == 1 or (mstridx is not None and len_ymd == 2): + # One member, or two members with a month string + if mstridx is not None: + month = self[mstridx] + # since mstridx is 0 or 1, self[mstridx-1] always + # looks up the other element + other = self[mstridx - 1] + else: + other = self[0] + + if len_ymd > 1 or mstridx is None: + if other > 31: + year = other + else: + day = other + + elif len_ymd == 2: + # Two members with numbers + if self[0] > 31: + # 99-01 + year, month = self + elif self[1] > 31: + # 01-99 + month, year = self + elif dayfirst and self[1] <= 12: + # 13-01 + day, month = self + else: + # 01-13 + month, day = self + + elif len_ymd == 3: + # Three members + if mstridx == 0: + if self[1] > 31: + # Apr-2003-25 + month, year, day = self + else: + month, day, year = self + elif mstridx == 1: + if self[0] > 31 or (yearfirst and self[2] <= 31): + # 99-Jan-01 + year, month, day = self + else: + # 01-Jan-01 + # Give precendence to day-first, since + # two-digit years is usually hand-written. + day, month, year = self + + elif mstridx == 2: + # WTF!? + if self[1] > 31: + # 01-99-Jan + day, year, month = self + else: + # 99-01-Jan + year, day, month = self + + else: + if (self[0] > 31 or + self.ystridx == 0 or + (yearfirst and self[1] <= 12 and self[2] <= 31)): + # 99-01-01 + if dayfirst and self[2] <= 12: + year, day, month = self + else: + year, month, day = self + elif self[0] > 12 or (dayfirst and self[1] <= 12): + # 13-01-01 + day, month, year = self + else: + # 01-13-01 + month, day, year = self + + return year, month, day + + +class parser(object): + def __init__(self, info=None): + self.info = info or parserinfo() + + def parse(self, timestr, default=None, + ignoretz=False, tzinfos=None, **kwargs): + """ + Parse the date/time string into a :class:`datetime.datetime` object. + + :param timestr: + Any date/time string using the supported formats. + + :param default: + The default datetime object, if this is a datetime object and not + ``None``, elements specified in ``timestr`` replace elements in the + default object. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a + naive :class:`datetime.datetime` object is returned. + + :param tzinfos: + Additional time zone names / aliases which may be present in the + string. This argument maps time zone names (and optionally offsets + from those time zones) to time zones. This parameter can be a + dictionary with timezone aliases mapping time zone names to time + zones or a function taking two parameters (``tzname`` and + ``tzoffset``) and returning a time zone. + + The timezones to which the names are mapped can be an integer + offset from UTC in seconds or a :class:`tzinfo` object. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> from dateutil.parser import parse + >>> from dateutil.tz import gettz + >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} + >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) + >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, + tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) + + This parameter is ignored if ``ignoretz`` is set. + + :param \\*\\*kwargs: + Keyword arguments as passed to ``_parse()``. + + :return: + Returns a :class:`datetime.datetime` object or, if the + ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the + first element being a :class:`datetime.datetime` object, the second + a tuple containing the fuzzy tokens. + + :raises ValueError: + Raised for invalid or unknown string format, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date + would be created. + + :raises TypeError: + Raised for non-string or character stream input. + + :raises OverflowError: + Raised if the parsed date exceeds the largest valid C integer on + your system. + """ + + if default is None: + default = datetime.datetime.now().replace(hour=0, minute=0, + second=0, microsecond=0) + + res, skipped_tokens = self._parse(timestr, **kwargs) + + if res is None: + raise ValueError("Unknown string format:", timestr) + + if len(res) == 0: + raise ValueError("String does not contain a date:", timestr) + + ret = self._build_naive(res, default) + + if not ignoretz: + ret = self._build_tzaware(ret, res, tzinfos) + + if kwargs.get('fuzzy_with_tokens', False): + return ret, skipped_tokens + else: + return ret + + class _result(_resultbase): + __slots__ = ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond", + "tzname", "tzoffset", "ampm","any_unused_tokens"] + + def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False, + fuzzy_with_tokens=False): + """ + Private method which performs the heavy lifting of parsing, called from + ``parse()``, which passes on its ``kwargs`` to this function. + + :param timestr: + The string to parse. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM + and YMD. If set to ``None``, this value is retrieved from the + current :class:`parserinfo` object (which itself defaults to + ``False``). + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken + to be the year, otherwise the last number is taken to be the year. + If this is set to ``None``, the value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param fuzzy: + Whether to allow fuzzy parsing, allowing for string like "Today is + January 1, 2047 at 8:21:00AM". + + :param fuzzy_with_tokens: + If ``True``, ``fuzzy`` is automatically set to True, and the parser + will return a tuple where the first element is the parsed + :class:`datetime.datetime` datetimestamp and the second element is + a tuple containing the portions of the string which were ignored: + + .. doctest:: + + >>> from dateutil.parser import parse + >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) + (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) + + """ + if fuzzy_with_tokens: + fuzzy = True + + info = self.info + + if dayfirst is None: + dayfirst = info.dayfirst + + if yearfirst is None: + yearfirst = info.yearfirst + + res = self._result() + l = _timelex.split(timestr) # Splits the timestr into tokens + + skipped_idxs = [] + + # year/month/day list + ymd = _ymd() + + len_l = len(l) + i = 0 + try: + while i < len_l: + + # Check if it's a number + value_repr = l[i] + try: + value = float(value_repr) + except ValueError: + value = None + + if value is not None: + # Numeric token + i = self._parse_numeric_token(l, i, info, ymd, res, fuzzy) + + # Check weekday + elif info.weekday(l[i]) is not None: + value = info.weekday(l[i]) + res.weekday = value + + # Check month name + elif info.month(l[i]) is not None: + value = info.month(l[i]) + ymd.append(value, 'M') + + if i + 1 < len_l: + if l[i + 1] in ('-', '/'): + # Jan-01[-99] + sep = l[i + 1] + ymd.append(l[i + 2]) + + if i + 3 < len_l and l[i + 3] == sep: + # Jan-01-99 + ymd.append(l[i + 4]) + i += 2 + + i += 2 + + elif (i + 4 < len_l and l[i + 1] == l[i + 3] == ' ' and + info.pertain(l[i + 2])): + # Jan of 01 + # In this case, 01 is clearly year + if l[i + 4].isdigit(): + # Convert it here to become unambiguous + value = int(l[i + 4]) + year = str(info.convertyear(value)) + ymd.append(year, 'Y') + else: + # Wrong guess + pass + # TODO: not hit in tests + i += 4 + + # Check am/pm + elif info.ampm(l[i]) is not None: + value = info.ampm(l[i]) + val_is_ampm = self._ampm_valid(res.hour, res.ampm, fuzzy) + + if val_is_ampm: + res.hour = self._adjust_ampm(res.hour, value) + res.ampm = value + + elif fuzzy: + skipped_idxs.append(i) + + # Check for a timezone name + elif self._could_be_tzname(res.hour, res.tzname, res.tzoffset, l[i]): + res.tzname = l[i] + res.tzoffset = info.tzoffset(res.tzname) + + # Check for something like GMT+3, or BRST+3. Notice + # that it doesn't mean "I am 3 hours after GMT", but + # "my time +3 is GMT". If found, we reverse the + # logic so that timezone parsing code will get it + # right. + if i + 1 < len_l and l[i + 1] in ('+', '-'): + l[i + 1] = ('+', '-')[l[i + 1] == '+'] + res.tzoffset = None + if info.utczone(res.tzname): + # With something like GMT+3, the timezone + # is *not* GMT. + res.tzname = None + + # Check for a numbered timezone + elif res.hour is not None and l[i] in ('+', '-'): + signal = (-1, 1)[l[i] == '+'] + len_li = len(l[i + 1]) + + # TODO: check that l[i + 1] is integer? + if len_li == 4: + # -0300 + hour_offset = int(l[i + 1][:2]) + min_offset = int(l[i + 1][2:]) + elif i + 2 < len_l and l[i + 2] == ':': + # -03:00 + hour_offset = int(l[i + 1]) + min_offset = int(l[i + 3]) # TODO: Check that l[i+3] is minute-like? + i += 2 + elif len_li <= 2: + # -[0]3 + hour_offset = int(l[i + 1][:2]) + min_offset = 0 + else: + raise ValueError(timestr) + + res.tzoffset = signal * (hour_offset * 3600 + min_offset * 60) + + # Look for a timezone name between parenthesis + if (i + 5 < len_l and + info.jump(l[i + 2]) and l[i + 3] == '(' and + l[i + 5] == ')' and + 3 <= len(l[i + 4]) and + self._could_be_tzname(res.hour, res.tzname, + None, l[i + 4])): + # -0300 (BRST) + res.tzname = l[i + 4] + i += 4 + + i += 1 + + # Check jumps + elif not (info.jump(l[i]) or fuzzy): + raise ValueError(timestr) + + else: + skipped_idxs.append(i) + i += 1 + + # Process year/month/day + year, month, day = ymd.resolve_ymd(yearfirst, dayfirst) + + res.century_specified = ymd.century_specified + res.year = year + res.month = month + res.day = day + + except (IndexError, ValueError): + return None, None + + if not info.validate(res): + return None, None + + if fuzzy_with_tokens: + skipped_tokens = self._recombine_skipped(l, skipped_idxs) + return res, tuple(skipped_tokens) + else: + return res, None + + def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy): + # Token is a number + value_repr = tokens[idx] + try: + value = self._to_decimal(value_repr) + except Exception as e: + six.raise_from(ValueError('Unknown numeric token'), e) + + len_li = len(value_repr) + + len_l = len(tokens) + + if (len(ymd) == 3 and len_li in (2, 4) and + res.hour is None and + (idx + 1 >= len_l or + (tokens[idx + 1] != ':' and + info.hms(tokens[idx + 1]) is None))): + # 19990101T23[59] + s = tokens[idx] + res.hour = int(s[:2]) + + if len_li == 4: + res.minute = int(s[2:]) + + elif len_li == 6 or (len_li > 6 and tokens[idx].find('.') == 6): + # YYMMDD or HHMMSS[.ss] + s = tokens[idx] + + if not ymd and '.' not in tokens[idx]: + ymd.append(s[:2]) + ymd.append(s[2:4]) + ymd.append(s[4:]) + else: + # 19990101T235959[.59] + + # TODO: Check if res attributes already set. + res.hour = int(s[:2]) + res.minute = int(s[2:4]) + res.second, res.microsecond = self._parsems(s[4:]) + + elif len_li in (8, 12, 14): + # YYYYMMDD + s = tokens[idx] + ymd.append(s[:4], 'Y') + ymd.append(s[4:6]) + ymd.append(s[6:8]) + + if len_li > 8: + res.hour = int(s[8:10]) + res.minute = int(s[10:12]) + + if len_li > 12: + res.second = int(s[12:]) + + elif self._find_hms_idx(idx, tokens, info, allow_jump=True) is not None: + # HH[ ]h or MM[ ]m or SS[.ss][ ]s + hms_idx = self._find_hms_idx(idx, tokens, info, allow_jump=True) + (idx, hms) = self._parse_hms(idx, tokens, info, hms_idx) + if hms is not None: + # TODO: checking that hour/minute/second are not + # already set? + self._assign_hms(res, value_repr, hms) + + elif idx + 2 < len_l and tokens[idx + 1] == ':': + # HH:MM[:SS[.ss]] + res.hour = int(value) + value = self._to_decimal(tokens[idx + 2]) # TODO: try/except for this? + (res.minute, res.second) = self._parse_min_sec(value) + + if idx + 4 < len_l and tokens[idx + 3] == ':': + res.second, res.microsecond = self._parsems(tokens[idx + 4]) + + idx += 2 + + idx += 2 + + elif idx + 1 < len_l and tokens[idx + 1] in ('-', '/', '.'): + sep = tokens[idx + 1] + ymd.append(value_repr) + + if idx + 2 < len_l and not info.jump(tokens[idx + 2]): + if tokens[idx + 2].isdigit(): + # 01-01[-01] + ymd.append(tokens[idx + 2]) + else: + # 01-Jan[-01] + value = info.month(tokens[idx + 2]) + + if value is not None: + ymd.append(value, 'M') + else: + raise ValueError() + + if idx + 3 < len_l and tokens[idx + 3] == sep: + # We have three members + value = info.month(tokens[idx + 4]) + + if value is not None: + ymd.append(value, 'M') + else: + ymd.append(tokens[idx + 4]) + idx += 2 + + idx += 1 + idx += 1 + + elif idx + 1 >= len_l or info.jump(tokens[idx + 1]): + if idx + 2 < len_l and info.ampm(tokens[idx + 2]) is not None: + # 12 am + hour = int(value) + res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 2])) + idx += 1 + else: + # Year, month or day + ymd.append(value) + idx += 1 + + elif info.ampm(tokens[idx + 1]) is not None and (0 <= value < 24): + # 12am + hour = int(value) + res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 1])) + idx += 1 + + elif ymd.could_be_day(value): + ymd.append(value) + + elif not fuzzy: + raise ValueError() + + return idx + + def _find_hms_idx(self, idx, tokens, info, allow_jump): + len_l = len(tokens) + + if idx+1 < len_l and info.hms(tokens[idx+1]) is not None: + # There is an "h", "m", or "s" label following this token. We take + # assign the upcoming label to the current token. + # e.g. the "12" in 12h" + hms_idx = idx + 1 + + elif (allow_jump and idx+2 < len_l and tokens[idx+1] == ' ' and + info.hms(tokens[idx+2]) is not None): + # There is a space and then an "h", "m", or "s" label. + # e.g. the "12" in "12 h" + hms_idx = idx + 2 + + elif idx > 0 and info.hms(tokens[idx-1]) is not None: + # There is a "h", "m", or "s" preceeding this token. Since neither + # of the previous cases was hit, there is no label following this + # token, so we use the previous label. + # e.g. the "04" in "12h04" + hms_idx = idx-1 + + elif (1 < idx == len_l-1 and tokens[idx-1] == ' ' and + info.hms(tokens[idx-2]) is not None): + # If we are looking at the final token, we allow for a + # backward-looking check to skip over a space. + # TODO: Are we sure this is the right condition here? + hms_idx = idx - 2 + + else: + hms_idx = None + + return hms_idx + + def _assign_hms(self, res, value_repr, hms): + # See GH issue #427, fixing float rounding + value = self._to_decimal(value_repr) + + if hms == 0: + # Hour + res.hour = int(value) + if value % 1: + res.minute = int(60*(value % 1)) + + elif hms == 1: + (res.minute, res.second) = self._parse_min_sec(value) + + elif hms == 2: + (res.second, res.microsecond) = self._parsems(value_repr) + + def _could_be_tzname(self, hour, tzname, tzoffset, token): + return (hour is not None and + tzname is None and + tzoffset is None and + len(token) <= 5 and + (all(x in string.ascii_uppercase for x in token) + or token in self.info.UTCZONE)) + + def _ampm_valid(self, hour, ampm, fuzzy): + """ + For fuzzy parsing, 'a' or 'am' (both valid English words) + may erroneously trigger the AM/PM flag. Deal with that + here. + """ + val_is_ampm = True + + # If there's already an AM/PM flag, this one isn't one. + if fuzzy and ampm is not None: + val_is_ampm = False + + # If AM/PM is found and hour is not, raise a ValueError + if hour is None: + if fuzzy: + val_is_ampm = False + else: + raise ValueError('No hour specified with AM or PM flag.') + elif not 0 <= hour <= 12: + # If AM/PM is found, it's a 12 hour clock, so raise + # an error for invalid range + if fuzzy: + val_is_ampm = False + else: + raise ValueError('Invalid hour specified for 12-hour clock.') + + return val_is_ampm + + def _adjust_ampm(self, hour, ampm): + if hour < 12 and ampm == 1: + hour += 12 + elif hour == 12 and ampm == 0: + hour = 0 + return hour + + def _parse_min_sec(self, value): + # TODO: Every usage of this function sets res.second to the return + # value. Are there any cases where second will be returned as None and + # we *dont* want to set res.second = None? + minute = int(value) + second = None + + sec_remainder = value % 1 + if sec_remainder: + second = int(60 * sec_remainder) + return (minute, second) + + def _parsems(self, value): + """Parse a I[.F] seconds value into (seconds, microseconds).""" + if "." not in value: + return int(value), 0 + else: + i, f = value.split(".") + return int(i), int(f.ljust(6, "0")[:6]) + + def _parse_hms(self, idx, tokens, info, hms_idx): + # TODO: Is this going to admit a lot of false-positives for when we + # just happen to have digits and "h", "m" or "s" characters in non-date + # text? I guess hex hashes won't have that problem, but there's plenty + # of random junk out there. + if hms_idx is None: + hms = None + new_idx = idx + elif hms_idx > idx: + hms = info.hms(tokens[hms_idx]) + new_idx = hms_idx + else: + # Looking backwards, increment one. + hms = info.hms(tokens[hms_idx]) + 1 + new_idx = idx + + return (new_idx, hms) + + def _recombine_skipped(self, tokens, skipped_idxs): + """ + >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"] + >>> skipped_idxs = [0, 1, 2, 5] + >>> _recombine_skipped(tokens, skipped_idxs) + ["foo bar", "baz"] + """ + skipped_tokens = [] + for i, idx in enumerate(sorted(skipped_idxs)): + if i > 0 and idx - 1 == skipped_idxs[i - 1]: + skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx] + else: + skipped_tokens.append(tokens[idx]) + + return skipped_tokens + + def _build_tzinfo(self, tzinfos, tzname, tzoffset): + if callable(tzinfos): + tzdata = tzinfos(tzname, tzoffset) + else: + tzdata = tzinfos.get(tzname) + # handle case where tzinfo is paased an options that returns None + # eg tzinfos = {'BRST' : None} + if isinstance(tzdata, datetime.tzinfo) or tzdata is None: + tzinfo = tzdata + elif isinstance(tzdata, text_type): + tzinfo = tz.tzstr(tzdata) + elif isinstance(tzdata, integer_types): + tzinfo = tz.tzoffset(tzname, tzdata) + return tzinfo + + def _build_tzaware(self, naive, res, tzinfos): + if (callable(tzinfos) or (tzinfos and res.tzname in tzinfos)): + tzinfo = self._build_tzinfo(tzinfos, res.tzname, res.tzoffset) + aware = naive.replace(tzinfo=tzinfo) + aware = self._assign_tzname(aware, res.tzname) + + elif res.tzname and res.tzname in time.tzname: + aware = naive.replace(tzinfo=tz.tzlocal()) + + # Handle ambiguous local datetime + aware = self._assign_tzname(aware, res.tzname) + + # This is mostly relevant for winter GMT zones parsed in the UK + if (aware.tzname() != res.tzname and + res.tzname in self.info.UTCZONE): + aware = aware.replace(tzinfo=tz.tzutc()) + + elif res.tzoffset == 0: + aware = naive.replace(tzinfo=tz.tzutc()) + + elif res.tzoffset: + aware = naive.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) + + elif not res.tzname and not res.tzoffset: + # i.e. no timezone information was found. + aware = naive + + elif res.tzname: + # tz-like string was parsed but we don't know what to do + # with it + warnings.warn("tzname {tzname} identified but not understood. " + "Pass `tzinfos` argument in order to correctly " + "return a timezone-aware datetime. In a future " + "version, this will raise an " + "exception.".format(tzname=res.tzname), + category=UnknownTimezoneWarning) + aware = naive + + return aware + + def _build_naive(self, res, default): + repl = {} + for attr in ("year", "month", "day", "hour", + "minute", "second", "microsecond"): + value = getattr(res, attr) + if value is not None: + repl[attr] = value + + if 'day' not in repl: + # If the default day exceeds the last day of the month, fall back + # to the end of the month. + cyear = default.year if res.year is None else res.year + cmonth = default.month if res.month is None else res.month + cday = default.day if res.day is None else res.day + + if cday > monthrange(cyear, cmonth)[1]: + repl['day'] = monthrange(cyear, cmonth)[1] + + naive = default.replace(**repl) + + if res.weekday is not None and not res.day: + naive = naive + relativedelta.relativedelta(weekday=res.weekday) + + return naive + + def _assign_tzname(self, dt, tzname): + if dt.tzname() != tzname: + new_dt = tz.enfold(dt, fold=1) + if new_dt.tzname() == tzname: + return new_dt + + return dt + + def _to_decimal(self, val): + try: + decimal_value = Decimal(val) + # See GH 662, edge case, infinite value should not be converted via `_to_decimal` + if not decimal_value.is_finite(): + raise ValueError("Converted decimal value is infinite or NaN") + except Exception as e: + msg = "Could not convert %s to decimal" % val + six.raise_from(ValueError(msg), e) + else: + return decimal_value + + +DEFAULTPARSER = parser() + + +def parse(timestr, parserinfo=None, **kwargs): + """ + + Parse a string in one of the supported formats, using the + ``parserinfo`` parameters. + + :param timestr: + A string containing a date/time stamp. + + :param parserinfo: + A :class:`parserinfo` object containing parameters for the parser. + If ``None``, the default arguments to the :class:`parserinfo` + constructor are used. + + The ``**kwargs`` parameter takes the following keyword arguments: + + :param default: + The default datetime object, if this is a datetime object and not + ``None``, elements specified in ``timestr`` replace elements in the + default object. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime` object is returned. + + :param tzinfos: + Additional time zone names / aliases which may be present in the + string. This argument maps time zone names (and optionally offsets + from those time zones) to time zones. This parameter can be a + dictionary with timezone aliases mapping time zone names to time + zones or a function taking two parameters (``tzname`` and + ``tzoffset``) and returning a time zone. + + The timezones to which the names are mapped can be an integer + offset from UTC in seconds or a :class:`tzinfo` object. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> from dateutil.parser import parse + >>> from dateutil.tz import gettz + >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} + >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) + >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, + tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) + + This parameter is ignored if ``ignoretz`` is set. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM and + YMD. If set to ``None``, this value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken to + be the year, otherwise the last number is taken to be the year. If + this is set to ``None``, the value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param fuzzy: + Whether to allow fuzzy parsing, allowing for string like "Today is + January 1, 2047 at 8:21:00AM". + + :param fuzzy_with_tokens: + If ``True``, ``fuzzy`` is automatically set to True, and the parser + will return a tuple where the first element is the parsed + :class:`datetime.datetime` datetimestamp and the second element is + a tuple containing the portions of the string which were ignored: + + .. doctest:: + + >>> from dateutil.parser import parse + >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) + (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) + + :return: + Returns a :class:`datetime.datetime` object or, if the + ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the + first element being a :class:`datetime.datetime` object, the second + a tuple containing the fuzzy tokens. + + :raises ValueError: + Raised for invalid or unknown string format, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date + would be created. + + :raises OverflowError: + Raised if the parsed date exceeds the largest valid C integer on + your system. + """ + if parserinfo: + return parser(parserinfo).parse(timestr, **kwargs) + else: + return DEFAULTPARSER.parse(timestr, **kwargs) + + +class _tzparser(object): + + class _result(_resultbase): + + __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", + "start", "end"] + + class _attr(_resultbase): + __slots__ = ["month", "week", "weekday", + "yday", "jyday", "day", "time"] + + def __repr__(self): + return self._repr("") + + def __init__(self): + _resultbase.__init__(self) + self.start = self._attr() + self.end = self._attr() + + def parse(self, tzstr): + res = self._result() + l = [x for x in re.split(r'([,:.]|[a-zA-Z]+|[0-9]+)',tzstr) if x] + used_idxs = list() + try: + + len_l = len(l) + + i = 0 + while i < len_l: + # BRST+3[BRDT[+2]] + j = i + while j < len_l and not [x for x in l[j] + if x in "0123456789:,-+"]: + j += 1 + if j != i: + if not res.stdabbr: + offattr = "stdoffset" + res.stdabbr = "".join(l[i:j]) + else: + offattr = "dstoffset" + res.dstabbr = "".join(l[i:j]) + + for ii in range(j): + used_idxs.append(ii) + i = j + if (i < len_l and (l[i] in ('+', '-') or l[i][0] in + "0123456789")): + if l[i] in ('+', '-'): + # Yes, that's right. See the TZ variable + # documentation. + signal = (1, -1)[l[i] == '+'] + used_idxs.append(i) + i += 1 + else: + signal = -1 + len_li = len(l[i]) + if len_li == 4: + # -0300 + setattr(res, offattr, (int(l[i][:2]) * 3600 + + int(l[i][2:]) * 60) * signal) + elif i + 1 < len_l and l[i + 1] == ':': + # -03:00 + setattr(res, offattr, + (int(l[i]) * 3600 + + int(l[i + 2]) * 60) * signal) + used_idxs.append(i) + i += 2 + elif len_li <= 2: + # -[0]3 + setattr(res, offattr, + int(l[i][:2]) * 3600 * signal) + else: + return None + used_idxs.append(i) + i += 1 + if res.dstabbr: + break + else: + break + + + if i < len_l: + for j in range(i, len_l): + if l[j] == ';': + l[j] = ',' + + assert l[i] == ',' + + i += 1 + + if i >= len_l: + pass + elif (8 <= l.count(',') <= 9 and + not [y for x in l[i:] if x != ',' + for y in x if y not in "0123456789+-"]): + # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] + for x in (res.start, res.end): + x.month = int(l[i]) + used_idxs.append(i) + i += 2 + if l[i] == '-': + value = int(l[i + 1]) * -1 + used_idxs.append(i) + i += 1 + else: + value = int(l[i]) + used_idxs.append(i) + i += 2 + if value: + x.week = value + x.weekday = (int(l[i]) - 1) % 7 + else: + x.day = int(l[i]) + used_idxs.append(i) + i += 2 + x.time = int(l[i]) + used_idxs.append(i) + i += 2 + if i < len_l: + if l[i] in ('-', '+'): + signal = (-1, 1)[l[i] == "+"] + used_idxs.append(i) + i += 1 + else: + signal = 1 + used_idxs.append(i) + res.dstoffset = (res.stdoffset + int(l[i]) * signal) + + # This was a made-up format that is not in normal use + warn(('Parsed time zone "%s"' % tzstr) + + 'is in a non-standard dateutil-specific format, which ' + + 'is now deprecated; support for parsing this format ' + + 'will be removed in future versions. It is recommended ' + + 'that you switch to a standard format like the GNU ' + + 'TZ variable format.', tz.DeprecatedTzFormatWarning) + elif (l.count(',') == 2 and l[i:].count('/') <= 2 and + not [y for x in l[i:] if x not in (',', '/', 'J', 'M', + '.', '-', ':') + for y in x if y not in "0123456789"]): + for x in (res.start, res.end): + if l[i] == 'J': + # non-leap year day (1 based) + used_idxs.append(i) + i += 1 + x.jyday = int(l[i]) + elif l[i] == 'M': + # month[-.]week[-.]weekday + used_idxs.append(i) + i += 1 + x.month = int(l[i]) + used_idxs.append(i) + i += 1 + assert l[i] in ('-', '.') + used_idxs.append(i) + i += 1 + x.week = int(l[i]) + if x.week == 5: + x.week = -1 + used_idxs.append(i) + i += 1 + assert l[i] in ('-', '.') + used_idxs.append(i) + i += 1 + x.weekday = (int(l[i]) - 1) % 7 + else: + # year day (zero based) + x.yday = int(l[i]) + 1 + + used_idxs.append(i) + i += 1 + + if i < len_l and l[i] == '/': + used_idxs.append(i) + i += 1 + # start time + len_li = len(l[i]) + if len_li == 4: + # -0300 + x.time = (int(l[i][:2]) * 3600 + + int(l[i][2:]) * 60) + elif i + 1 < len_l and l[i + 1] == ':': + # -03:00 + x.time = int(l[i]) * 3600 + int(l[i + 2]) * 60 + used_idxs.append(i) + i += 2 + if i + 1 < len_l and l[i + 1] == ':': + used_idxs.append(i) + i += 2 + x.time += int(l[i]) + elif len_li <= 2: + # -[0]3 + x.time = (int(l[i][:2]) * 3600) + else: + return None + used_idxs.append(i) + i += 1 + + assert i == len_l or l[i] == ',' + + i += 1 + + assert i >= len_l + + except (IndexError, ValueError, AssertionError): + return None + + unused_idxs = set(range(len_l)).difference(used_idxs) + res.any_unused_tokens = not {l[n] for n in unused_idxs}.issubset({",",":"}) + return res + + +DEFAULTTZPARSER = _tzparser() + + +def _parsetz(tzstr): + return DEFAULTTZPARSER.parse(tzstr) + +class UnknownTimezoneWarning(RuntimeWarning): + """Raised when the parser finds a timezone it cannot parse into a tzinfo""" +# vim:ts=4:sw=4:et diff --git a/venv/lib/python3.6/site-packages/dateutil/parser/isoparser.py b/venv/lib/python3.6/site-packages/dateutil/parser/isoparser.py new file mode 100644 index 0000000..e3cf6d8 --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/parser/isoparser.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +""" +This module offers a parser for ISO-8601 strings + +It is intended to support all valid date, time and datetime formats per the +ISO-8601 specification. + +..versionadded:: 2.7.0 +""" +from datetime import datetime, timedelta, time, date +import calendar +from dateutil import tz + +from functools import wraps + +import re +import six + +__all__ = ["isoparse", "isoparser"] + + +def _takes_ascii(f): + @wraps(f) + def func(self, str_in, *args, **kwargs): + # If it's a stream, read the whole thing + str_in = getattr(str_in, 'read', lambda: str_in)() + + # If it's unicode, turn it into bytes, since ISO-8601 only covers ASCII + if isinstance(str_in, six.text_type): + # ASCII is the same in UTF-8 + try: + str_in = str_in.encode('ascii') + except UnicodeEncodeError as e: + msg = 'ISO-8601 strings should contain only ASCII characters' + six.raise_from(ValueError(msg), e) + + return f(self, str_in, *args, **kwargs) + + return func + + +class isoparser(object): + def __init__(self, sep=None): + """ + :param sep: + A single character that separates date and time portions. If + ``None``, the parser will accept any single character. + For strict ISO-8601 adherence, pass ``'T'``. + """ + if sep is not None: + if (len(sep) != 1 or ord(sep) >= 128 or sep in '0123456789'): + raise ValueError('Separator must be a single, non-numeric ' + + 'ASCII character') + + sep = sep.encode('ascii') + + self._sep = sep + + @_takes_ascii + def isoparse(self, dt_str): + """ + Parse an ISO-8601 datetime string into a :class:`datetime.datetime`. + + An ISO-8601 datetime string consists of a date portion, followed + optionally by a time portion - the date and time portions are separated + by a single character separator, which is ``T`` in the official + standard. Incomplete date formats (such as ``YYYY-MM``) may *not* be + combined with a time portion. + + Supported date formats are: + + Common: + + - ``YYYY`` + - ``YYYY-MM`` or ``YYYYMM`` + - ``YYYY-MM-DD`` or ``YYYYMMDD`` + + Uncommon: + + - ``YYYY-Www`` or ``YYYYWww`` - ISO week (day defaults to 0) + - ``YYYY-Www-D`` or ``YYYYWwwD`` - ISO week and day + + The ISO week and day numbering follows the same logic as + :func:`datetime.date.isocalendar`. + + Supported time formats are: + + - ``hh`` + - ``hh:mm`` or ``hhmm`` + - ``hh:mm:ss`` or ``hhmmss`` + - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) + + Midnight is a special case for `hh`, as the standard supports both + 00:00 and 24:00 as a representation. The decimal separator can be + either a dot or a comma. + + + .. caution:: + + Support for fractional components other than seconds is part of the + ISO-8601 standard, but is not currently implemented in this parser. + + Supported time zone offset formats are: + + - `Z` (UTC) + - `±HH:MM` + - `±HHMM` + - `±HH` + + Offsets will be represented as :class:`dateutil.tz.tzoffset` objects, + with the exception of UTC, which will be represented as + :class:`dateutil.tz.tzutc`. Time zone offsets equivalent to UTC (such + as `+00:00`) will also be represented as :class:`dateutil.tz.tzutc`. + + :param dt_str: + A string or stream containing only an ISO-8601 datetime string + + :return: + Returns a :class:`datetime.datetime` representing the string. + Unspecified components default to their lowest value. + + .. warning:: + + As of version 2.7.0, the strictness of the parser should not be + considered a stable part of the contract. Any valid ISO-8601 string + that parses correctly with the default settings will continue to + parse correctly in future versions, but invalid strings that + currently fail (e.g. ``2017-01-01T00:00+00:00:00``) are not + guaranteed to continue failing in future versions if they encode + a valid date. + + .. versionadded:: 2.7.0 + """ + components, pos = self._parse_isodate(dt_str) + + if len(dt_str) > pos: + if self._sep is None or dt_str[pos:pos + 1] == self._sep: + components += self._parse_isotime(dt_str[pos + 1:]) + else: + raise ValueError('String contains unknown ISO components') + + if len(components) > 3 and components[3] == 24: + components[3] = 0 + return datetime(*components) + timedelta(days=1) + + return datetime(*components) + + @_takes_ascii + def parse_isodate(self, datestr): + """ + Parse the date portion of an ISO string. + + :param datestr: + The string portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.date` object + """ + components, pos = self._parse_isodate(datestr) + if pos < len(datestr): + raise ValueError('String contains unknown ISO ' + + 'components: {}'.format(datestr)) + return date(*components) + + @_takes_ascii + def parse_isotime(self, timestr): + """ + Parse the time portion of an ISO string. + + :param timestr: + The time portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.time` object + """ + components = self._parse_isotime(timestr) + if components[0] == 24: + components[0] = 0 + return time(*components) + + @_takes_ascii + def parse_tzstr(self, tzstr, zero_as_utc=True): + """ + Parse a valid ISO time zone string. + + See :func:`isoparser.isoparse` for details on supported formats. + + :param tzstr: + A string representing an ISO time zone offset + + :param zero_as_utc: + Whether to return :class:`dateutil.tz.tzutc` for zero-offset zones + + :return: + Returns :class:`dateutil.tz.tzoffset` for offsets and + :class:`dateutil.tz.tzutc` for ``Z`` and (if ``zero_as_utc`` is + specified) offsets equivalent to UTC. + """ + return self._parse_tzstr(tzstr, zero_as_utc=zero_as_utc) + + # Constants + _DATE_SEP = b'-' + _TIME_SEP = b':' + _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') + + def _parse_isodate(self, dt_str): + try: + return self._parse_isodate_common(dt_str) + except ValueError: + return self._parse_isodate_uncommon(dt_str) + + def _parse_isodate_common(self, dt_str): + len_str = len(dt_str) + components = [1, 1, 1] + + if len_str < 4: + raise ValueError('ISO string too short') + + # Year + components[0] = int(dt_str[0:4]) + pos = 4 + if pos >= len_str: + return components, pos + + has_sep = dt_str[pos:pos + 1] == self._DATE_SEP + if has_sep: + pos += 1 + + # Month + if len_str - pos < 2: + raise ValueError('Invalid common month') + + components[1] = int(dt_str[pos:pos + 2]) + pos += 2 + + if pos >= len_str: + if has_sep: + return components, pos + else: + raise ValueError('Invalid ISO format') + + if has_sep: + if dt_str[pos:pos + 1] != self._DATE_SEP: + raise ValueError('Invalid separator in ISO string') + pos += 1 + + # Day + if len_str - pos < 2: + raise ValueError('Invalid common day') + components[2] = int(dt_str[pos:pos + 2]) + return components, pos + 2 + + def _parse_isodate_uncommon(self, dt_str): + if len(dt_str) < 4: + raise ValueError('ISO string too short') + + # All ISO formats start with the year + year = int(dt_str[0:4]) + + has_sep = dt_str[4:5] == self._DATE_SEP + + pos = 4 + has_sep # Skip '-' if it's there + if dt_str[pos:pos + 1] == b'W': + # YYYY-?Www-?D? + pos += 1 + weekno = int(dt_str[pos:pos + 2]) + pos += 2 + + dayno = 1 + if len(dt_str) > pos: + if (dt_str[pos:pos + 1] == self._DATE_SEP) != has_sep: + raise ValueError('Inconsistent use of dash separator') + + pos += has_sep + + dayno = int(dt_str[pos:pos + 1]) + pos += 1 + + base_date = self._calculate_weekdate(year, weekno, dayno) + else: + # YYYYDDD or YYYY-DDD + if len(dt_str) - pos < 3: + raise ValueError('Invalid ordinal day') + + ordinal_day = int(dt_str[pos:pos + 3]) + pos += 3 + + if ordinal_day < 1 or ordinal_day > (365 + calendar.isleap(year)): + raise ValueError('Invalid ordinal day' + + ' {} for year {}'.format(ordinal_day, year)) + + base_date = date(year, 1, 1) + timedelta(days=ordinal_day - 1) + + components = [base_date.year, base_date.month, base_date.day] + return components, pos + + def _calculate_weekdate(self, year, week, day): + """ + Calculate the day of corresponding to the ISO year-week-day calendar. + + This function is effectively the inverse of + :func:`datetime.date.isocalendar`. + + :param year: + The year in the ISO calendar + + :param week: + The week in the ISO calendar - range is [1, 53] + + :param day: + The day in the ISO calendar - range is [1 (MON), 7 (SUN)] + + :return: + Returns a :class:`datetime.date` + """ + if not 0 < week < 54: + raise ValueError('Invalid week: {}'.format(week)) + + if not 0 < day < 8: # Range is 1-7 + raise ValueError('Invalid weekday: {}'.format(day)) + + # Get week 1 for the specific year: + jan_4 = date(year, 1, 4) # Week 1 always has January 4th in it + week_1 = jan_4 - timedelta(days=jan_4.isocalendar()[2] - 1) + + # Now add the specific number of weeks and days to get what we want + week_offset = (week - 1) * 7 + (day - 1) + return week_1 + timedelta(days=week_offset) + + def _parse_isotime(self, timestr): + len_str = len(timestr) + components = [0, 0, 0, 0, None] + pos = 0 + comp = -1 + + if len(timestr) < 2: + raise ValueError('ISO time too short') + + has_sep = len_str >= 3 and timestr[2:3] == self._TIME_SEP + + while pos < len_str and comp < 5: + comp += 1 + + if timestr[pos:pos + 1] in b'-+Zz': + # Detect time zone boundary + components[-1] = self._parse_tzstr(timestr[pos:]) + pos = len_str + break + + if comp < 3: + # Hour, minute, second + components[comp] = int(timestr[pos:pos + 2]) + pos += 2 + if (has_sep and pos < len_str and + timestr[pos:pos + 1] == self._TIME_SEP): + pos += 1 + + if comp == 3: + # Fraction of a second + frac = self._FRACTION_REGEX.match(timestr[pos:]) + if not frac: + continue + + us_str = frac.group(1)[:6] # Truncate to microseconds + components[comp] = int(us_str) * 10**(6 - len(us_str)) + pos += len(frac.group()) + + if pos < len_str: + raise ValueError('Unused components in ISO string') + + if components[0] == 24: + # Standard supports 00:00 and 24:00 as representations of midnight + if any(component != 0 for component in components[1:4]): + raise ValueError('Hour may only be 24 at 24:00:00.000') + + return components + + def _parse_tzstr(self, tzstr, zero_as_utc=True): + if tzstr == b'Z' or tzstr == b'z': + return tz.tzutc() + + if len(tzstr) not in {3, 5, 6}: + raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters') + + if tzstr[0:1] == b'-': + mult = -1 + elif tzstr[0:1] == b'+': + mult = 1 + else: + raise ValueError('Time zone offset requires sign') + + hours = int(tzstr[1:3]) + if len(tzstr) == 3: + minutes = 0 + else: + minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):]) + + if zero_as_utc and hours == 0 and minutes == 0: + return tz.tzutc() + else: + if minutes > 59: + raise ValueError('Invalid minutes in time zone offset') + + if hours > 23: + raise ValueError('Invalid hours in time zone offset') + + return tz.tzoffset(None, mult * (hours * 60 + minutes) * 60) + + +DEFAULT_ISOPARSER = isoparser() +isoparse = DEFAULT_ISOPARSER.isoparse diff --git a/venv/lib/python3.6/site-packages/dateutil/relativedelta.py b/venv/lib/python3.6/site-packages/dateutil/relativedelta.py new file mode 100644 index 0000000..c65c66e --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/relativedelta.py @@ -0,0 +1,599 @@ +# -*- coding: utf-8 -*- +import datetime +import calendar + +import operator +from math import copysign + +from six import integer_types +from warnings import warn + +from ._common import weekday + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) + +__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + + +class relativedelta(object): + """ + The relativedelta type is designed to be applied to an existing datetime and + can replace specific components of that datetime, or represents an interval + of time. + + It is based on the specification of the excellent work done by M.-A. Lemburg + in his + `mx.DateTime `_ extension. + However, notice that this type does *NOT* implement the same algorithm as + his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. + + There are two different ways to build a relativedelta instance. The + first one is passing it two date/datetime classes:: + + relativedelta(datetime1, datetime2) + + The second one is passing it any number of the following keyword arguments:: + + relativedelta(arg1=x,arg2=y,arg3=z...) + + year, month, day, hour, minute, second, microsecond: + Absolute information (argument is singular); adding or subtracting a + relativedelta with absolute information does not perform an arithmetic + operation, but rather REPLACES the corresponding value in the + original datetime with the value(s) in relativedelta. + + years, months, weeks, days, hours, minutes, seconds, microseconds: + Relative information, may be negative (argument is plural); adding + or subtracting a relativedelta with relative information performs + the corresponding aritmetic operation on the original datetime value + with the information in the relativedelta. + + weekday: + One of the weekday instances (MO, TU, etc) available in the + relativedelta module. These instances may receive a parameter N, + specifying the Nth weekday, which could be positive or negative + (like MO(+1) or MO(-2)). Not specifying it is the same as specifying + +1. You can also use an integer, where 0=MO. This argument is always + relative e.g. if the calculated date is already Monday, using MO(1) + or MO(-1) won't change the day. To effectively make it absolute, use + it in combination with the day argument (e.g. day=1, MO(1) for first + Monday of the month). + + leapdays: + Will add given days to the date found, if year is a leap + year, and the date found is post 28 of february. + + yearday, nlyearday: + Set the yearday or the non-leap year day (jump leap days). + These are converted to day/month/leapdays information. + + There are relative and absolute forms of the keyword + arguments. The plural is relative, and the singular is + absolute. For each argument in the order below, the absolute form + is applied first (by setting each attribute to that value) and + then the relative form (by adding the value to the attribute). + + The order of attributes considered when this relativedelta is + added to a datetime is: + + 1. Year + 2. Month + 3. Day + 4. Hours + 5. Minutes + 6. Seconds + 7. Microseconds + + Finally, weekday is applied, using the rule described above. + + For example + + >>> from datetime import datetime + >>> from dateutil.relativedelta import relativedelta, MO + >>> dt = datetime(2018, 4, 9, 13, 37, 0) + >>> delta = relativedelta(hours=25, day=1, weekday=MO(1)) + >>> dt + delta + datetime.datetime(2018, 4, 2, 14, 37) + + First, the day is set to 1 (the first of the month), then 25 hours + are added, to get to the 2nd day and 14th hour, finally the + weekday is applied, but since the 2nd is already a Monday there is + no effect. + + """ + + def __init__(self, dt1=None, dt2=None, + years=0, months=0, days=0, leapdays=0, weeks=0, + hours=0, minutes=0, seconds=0, microseconds=0, + year=None, month=None, day=None, weekday=None, + yearday=None, nlyearday=None, + hour=None, minute=None, second=None, microsecond=None): + + if dt1 and dt2: + # datetime is a subclass of date. So both must be date + if not (isinstance(dt1, datetime.date) and + isinstance(dt2, datetime.date)): + raise TypeError("relativedelta only diffs datetime/date") + + # We allow two dates, or two datetimes, so we coerce them to be + # of the same type + if (isinstance(dt1, datetime.datetime) != + isinstance(dt2, datetime.datetime)): + if not isinstance(dt1, datetime.datetime): + dt1 = datetime.datetime.fromordinal(dt1.toordinal()) + elif not isinstance(dt2, datetime.datetime): + dt2 = datetime.datetime.fromordinal(dt2.toordinal()) + + self.years = 0 + self.months = 0 + self.days = 0 + self.leapdays = 0 + self.hours = 0 + self.minutes = 0 + self.seconds = 0 + self.microseconds = 0 + self.year = None + self.month = None + self.day = None + self.weekday = None + self.hour = None + self.minute = None + self.second = None + self.microsecond = None + self._has_time = 0 + + # Get year / month delta between the two + months = (dt1.year - dt2.year) * 12 + (dt1.month - dt2.month) + self._set_months(months) + + # Remove the year/month delta so the timedelta is just well-defined + # time units (seconds, days and microseconds) + dtm = self.__radd__(dt2) + + # If we've overshot our target, make an adjustment + if dt1 < dt2: + compare = operator.gt + increment = 1 + else: + compare = operator.lt + increment = -1 + + while compare(dt1, dtm): + months += increment + self._set_months(months) + dtm = self.__radd__(dt2) + + # Get the timedelta between the "months-adjusted" date and dt1 + delta = dt1 - dtm + self.seconds = delta.seconds + delta.days * 86400 + self.microseconds = delta.microseconds + else: + # Check for non-integer values in integer-only quantities + if any(x is not None and x != int(x) for x in (years, months)): + raise ValueError("Non-integer years and months are " + "ambiguous and not currently supported.") + + # Relative information + self.years = int(years) + self.months = int(months) + self.days = days + weeks * 7 + self.leapdays = leapdays + self.hours = hours + self.minutes = minutes + self.seconds = seconds + self.microseconds = microseconds + + # Absolute information + self.year = year + self.month = month + self.day = day + self.hour = hour + self.minute = minute + self.second = second + self.microsecond = microsecond + + if any(x is not None and int(x) != x + for x in (year, month, day, hour, + minute, second, microsecond)): + # For now we'll deprecate floats - later it'll be an error. + warn("Non-integer value passed as absolute information. " + + "This is not a well-defined condition and will raise " + + "errors in future versions.", DeprecationWarning) + + if isinstance(weekday, integer_types): + self.weekday = weekdays[weekday] + else: + self.weekday = weekday + + yday = 0 + if nlyearday: + yday = nlyearday + elif yearday: + yday = yearday + if yearday > 59: + self.leapdays = -1 + if yday: + ydayidx = [31, 59, 90, 120, 151, 181, 212, + 243, 273, 304, 334, 366] + for idx, ydays in enumerate(ydayidx): + if yday <= ydays: + self.month = idx+1 + if idx == 0: + self.day = yday + else: + self.day = yday-ydayidx[idx-1] + break + else: + raise ValueError("invalid year day (%d)" % yday) + + self._fix() + + def _fix(self): + if abs(self.microseconds) > 999999: + s = _sign(self.microseconds) + div, mod = divmod(self.microseconds * s, 1000000) + self.microseconds = mod * s + self.seconds += div * s + if abs(self.seconds) > 59: + s = _sign(self.seconds) + div, mod = divmod(self.seconds * s, 60) + self.seconds = mod * s + self.minutes += div * s + if abs(self.minutes) > 59: + s = _sign(self.minutes) + div, mod = divmod(self.minutes * s, 60) + self.minutes = mod * s + self.hours += div * s + if abs(self.hours) > 23: + s = _sign(self.hours) + div, mod = divmod(self.hours * s, 24) + self.hours = mod * s + self.days += div * s + if abs(self.months) > 11: + s = _sign(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years += div * s + if (self.hours or self.minutes or self.seconds or self.microseconds + or self.hour is not None or self.minute is not None or + self.second is not None or self.microsecond is not None): + self._has_time = 1 + else: + self._has_time = 0 + + @property + def weeks(self): + return int(self.days / 7.0) + + @weeks.setter + def weeks(self, value): + self.days = self.days - (self.weeks * 7) + value * 7 + + def _set_months(self, months): + self.months = months + if abs(self.months) > 11: + s = _sign(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years = div * s + else: + self.years = 0 + + def normalized(self): + """ + Return a version of this object represented entirely using integer + values for the relative attributes. + + >>> relativedelta(days=1.5, hours=2).normalized() + relativedelta(days=+1, hours=+14) + + :return: + Returns a :class:`dateutil.relativedelta.relativedelta` object. + """ + # Cascade remainders down (rounding each to roughly nearest microsecond) + days = int(self.days) + + hours_f = round(self.hours + 24 * (self.days - days), 11) + hours = int(hours_f) + + minutes_f = round(self.minutes + 60 * (hours_f - hours), 10) + minutes = int(minutes_f) + + seconds_f = round(self.seconds + 60 * (minutes_f - minutes), 8) + seconds = int(seconds_f) + + microseconds = round(self.microseconds + 1e6 * (seconds_f - seconds)) + + # Constructor carries overflow back up with call to _fix() + return self.__class__(years=self.years, months=self.months, + days=days, hours=hours, minutes=minutes, + seconds=seconds, microseconds=microseconds, + leapdays=self.leapdays, year=self.year, + month=self.month, day=self.day, + weekday=self.weekday, hour=self.hour, + minute=self.minute, second=self.second, + microsecond=self.microsecond) + + def __add__(self, other): + if isinstance(other, relativedelta): + return self.__class__(years=other.years + self.years, + months=other.months + self.months, + days=other.days + self.days, + hours=other.hours + self.hours, + minutes=other.minutes + self.minutes, + seconds=other.seconds + self.seconds, + microseconds=(other.microseconds + + self.microseconds), + leapdays=other.leapdays or self.leapdays, + year=(other.year if other.year is not None + else self.year), + month=(other.month if other.month is not None + else self.month), + day=(other.day if other.day is not None + else self.day), + weekday=(other.weekday if other.weekday is not None + else self.weekday), + hour=(other.hour if other.hour is not None + else self.hour), + minute=(other.minute if other.minute is not None + else self.minute), + second=(other.second if other.second is not None + else self.second), + microsecond=(other.microsecond if other.microsecond + is not None else + self.microsecond)) + if isinstance(other, datetime.timedelta): + return self.__class__(years=self.years, + months=self.months, + days=self.days + other.days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds + other.seconds, + microseconds=self.microseconds + other.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + if not isinstance(other, datetime.date): + return NotImplemented + elif self._has_time and not isinstance(other, datetime.datetime): + other = datetime.datetime.fromordinal(other.toordinal()) + year = (self.year or other.year)+self.years + month = self.month or other.month + if self.months: + assert 1 <= abs(self.months) <= 12 + month += self.months + if month > 12: + year += 1 + month -= 12 + elif month < 1: + year -= 1 + month += 12 + day = min(calendar.monthrange(year, month)[1], + self.day or other.day) + repl = {"year": year, "month": month, "day": day} + for attr in ["hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + repl[attr] = value + days = self.days + if self.leapdays and month > 2 and calendar.isleap(year): + days += self.leapdays + ret = (other.replace(**repl) + + datetime.timedelta(days=days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds, + microseconds=self.microseconds)) + if self.weekday: + weekday, nth = self.weekday.weekday, self.weekday.n or 1 + jumpdays = (abs(nth) - 1) * 7 + if nth > 0: + jumpdays += (7 - ret.weekday() + weekday) % 7 + else: + jumpdays += (ret.weekday() - weekday) % 7 + jumpdays *= -1 + ret += datetime.timedelta(days=jumpdays) + return ret + + def __radd__(self, other): + return self.__add__(other) + + def __rsub__(self, other): + return self.__neg__().__radd__(other) + + def __sub__(self, other): + if not isinstance(other, relativedelta): + return NotImplemented # In case the other object defines __rsub__ + return self.__class__(years=self.years - other.years, + months=self.months - other.months, + days=self.days - other.days, + hours=self.hours - other.hours, + minutes=self.minutes - other.minutes, + seconds=self.seconds - other.seconds, + microseconds=self.microseconds - other.microseconds, + leapdays=self.leapdays or other.leapdays, + year=(self.year if self.year is not None + else other.year), + month=(self.month if self.month is not None else + other.month), + day=(self.day if self.day is not None else + other.day), + weekday=(self.weekday if self.weekday is not None else + other.weekday), + hour=(self.hour if self.hour is not None else + other.hour), + minute=(self.minute if self.minute is not None else + other.minute), + second=(self.second if self.second is not None else + other.second), + microsecond=(self.microsecond if self.microsecond + is not None else + other.microsecond)) + + def __abs__(self): + return self.__class__(years=abs(self.years), + months=abs(self.months), + days=abs(self.days), + hours=abs(self.hours), + minutes=abs(self.minutes), + seconds=abs(self.seconds), + microseconds=abs(self.microseconds), + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __neg__(self): + return self.__class__(years=-self.years, + months=-self.months, + days=-self.days, + hours=-self.hours, + minutes=-self.minutes, + seconds=-self.seconds, + microseconds=-self.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __bool__(self): + return not (not self.years and + not self.months and + not self.days and + not self.hours and + not self.minutes and + not self.seconds and + not self.microseconds and + not self.leapdays and + self.year is None and + self.month is None and + self.day is None and + self.weekday is None and + self.hour is None and + self.minute is None and + self.second is None and + self.microsecond is None) + # Compatibility with Python 2.x + __nonzero__ = __bool__ + + def __mul__(self, other): + try: + f = float(other) + except TypeError: + return NotImplemented + + return self.__class__(years=int(self.years * f), + months=int(self.months * f), + days=int(self.days * f), + hours=int(self.hours * f), + minutes=int(self.minutes * f), + seconds=int(self.seconds * f), + microseconds=int(self.microseconds * f), + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + __rmul__ = __mul__ + + def __eq__(self, other): + if not isinstance(other, relativedelta): + return NotImplemented + if self.weekday or other.weekday: + if not self.weekday or not other.weekday: + return False + if self.weekday.weekday != other.weekday.weekday: + return False + n1, n2 = self.weekday.n, other.weekday.n + if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): + return False + return (self.years == other.years and + self.months == other.months and + self.days == other.days and + self.hours == other.hours and + self.minutes == other.minutes and + self.seconds == other.seconds and + self.microseconds == other.microseconds and + self.leapdays == other.leapdays and + self.year == other.year and + self.month == other.month and + self.day == other.day and + self.hour == other.hour and + self.minute == other.minute and + self.second == other.second and + self.microsecond == other.microsecond) + + def __hash__(self): + return hash(( + self.weekday, + self.years, + self.months, + self.days, + self.hours, + self.minutes, + self.seconds, + self.microseconds, + self.leapdays, + self.year, + self.month, + self.day, + self.hour, + self.minute, + self.second, + self.microsecond, + )) + + def __ne__(self, other): + return not self.__eq__(other) + + def __div__(self, other): + try: + reciprocal = 1 / float(other) + except TypeError: + return NotImplemented + + return self.__mul__(reciprocal) + + __truediv__ = __div__ + + def __repr__(self): + l = [] + for attr in ["years", "months", "days", "leapdays", + "hours", "minutes", "seconds", "microseconds"]: + value = getattr(self, attr) + if value: + l.append("{attr}={value:+g}".format(attr=attr, value=value)) + for attr in ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + l.append("{attr}={value}".format(attr=attr, value=repr(value))) + return "{classname}({attrs})".format(classname=self.__class__.__name__, + attrs=", ".join(l)) + + +def _sign(x): + return int(copysign(1, x)) + +# vim:ts=4:sw=4:et diff --git a/venv/lib/python3.6/site-packages/dateutil/rrule.py b/venv/lib/python3.6/site-packages/dateutil/rrule.py new file mode 100644 index 0000000..20a0c4a --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/rrule.py @@ -0,0 +1,1736 @@ +# -*- coding: utf-8 -*- +""" +The rrule module offers a small, complete, and very fast, implementation of +the recurrence rules documented in the +`iCalendar RFC `_, +including support for caching of results. +""" +import itertools +import datetime +import calendar +import re +import sys + +try: + from math import gcd +except ImportError: + from fractions import gcd + +from six import advance_iterator, integer_types +from six.moves import _thread, range +import heapq + +from ._common import weekday as weekdaybase +from .tz import tzutc, tzlocal + +# For warning about deprecation of until and count +from warnings import warn + +__all__ = ["rrule", "rruleset", "rrulestr", + "YEARLY", "MONTHLY", "WEEKLY", "DAILY", + "HOURLY", "MINUTELY", "SECONDLY", + "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + +# Every mask is 7 days longer to handle cross-year weekly periods. +M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 + + [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) +M365MASK = list(M366MASK) +M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32)) +MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +MDAY365MASK = list(MDAY366MASK) +M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0)) +NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +NMDAY365MASK = list(NMDAY366MASK) +M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366) +M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) +WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55 +del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] +MDAY365MASK = tuple(MDAY365MASK) +M365MASK = tuple(M365MASK) + +FREQNAMES = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY', 'HOURLY', 'MINUTELY', 'SECONDLY'] + +(YEARLY, + MONTHLY, + WEEKLY, + DAILY, + HOURLY, + MINUTELY, + SECONDLY) = list(range(7)) + +# Imported on demand. +easter = None +parser = None + + +class weekday(weekdaybase): + """ + This version of weekday does not allow n = 0. + """ + def __init__(self, wkday, n=None): + if n == 0: + raise ValueError("Can't create weekday with n==0") + + super(weekday, self).__init__(wkday, n) + + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) + + +def _invalidates_cache(f): + """ + Decorator for rruleset methods which may invalidate the + cached length. + """ + def inner_func(self, *args, **kwargs): + rv = f(self, *args, **kwargs) + self._invalidate_cache() + return rv + + return inner_func + + +class rrulebase(object): + def __init__(self, cache=False): + if cache: + self._cache = [] + self._cache_lock = _thread.allocate_lock() + self._invalidate_cache() + else: + self._cache = None + self._cache_complete = False + self._len = None + + def __iter__(self): + if self._cache_complete: + return iter(self._cache) + elif self._cache is None: + return self._iter() + else: + return self._iter_cached() + + def _invalidate_cache(self): + if self._cache is not None: + self._cache = [] + self._cache_complete = False + self._cache_gen = self._iter() + + if self._cache_lock.locked(): + self._cache_lock.release() + + self._len = None + + def _iter_cached(self): + i = 0 + gen = self._cache_gen + cache = self._cache + acquire = self._cache_lock.acquire + release = self._cache_lock.release + while gen: + if i == len(cache): + acquire() + if self._cache_complete: + break + try: + for j in range(10): + cache.append(advance_iterator(gen)) + except StopIteration: + self._cache_gen = gen = None + self._cache_complete = True + break + release() + yield cache[i] + i += 1 + while i < self._len: + yield cache[i] + i += 1 + + def __getitem__(self, item): + if self._cache_complete: + return self._cache[item] + elif isinstance(item, slice): + if item.step and item.step < 0: + return list(iter(self))[item] + else: + return list(itertools.islice(self, + item.start or 0, + item.stop or sys.maxsize, + item.step or 1)) + elif item >= 0: + gen = iter(self) + try: + for i in range(item+1): + res = advance_iterator(gen) + except StopIteration: + raise IndexError + return res + else: + return list(iter(self))[item] + + def __contains__(self, item): + if self._cache_complete: + return item in self._cache + else: + for i in self: + if i == item: + return True + elif i > item: + return False + return False + + # __len__() introduces a large performance penality. + def count(self): + """ Returns the number of recurrences in this set. It will have go + trough the whole recurrence, if this hasn't been done before. """ + if self._len is None: + for x in self: + pass + return self._len + + def before(self, dt, inc=False): + """ Returns the last recurrence before the given datetime instance. The + inc keyword defines what happens if dt is an occurrence. With + inc=True, if dt itself is an occurrence, it will be returned. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + last = None + if inc: + for i in gen: + if i > dt: + break + last = i + else: + for i in gen: + if i >= dt: + break + last = i + return last + + def after(self, dt, inc=False): + """ Returns the first recurrence after the given datetime instance. The + inc keyword defines what happens if dt is an occurrence. With + inc=True, if dt itself is an occurrence, it will be returned. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + if inc: + for i in gen: + if i >= dt: + return i + else: + for i in gen: + if i > dt: + return i + return None + + def xafter(self, dt, count=None, inc=False): + """ + Generator which yields up to `count` recurrences after the given + datetime instance, equivalent to `after`. + + :param dt: + The datetime at which to start generating recurrences. + + :param count: + The maximum number of recurrences to generate. If `None` (default), + dates are generated until the recurrence rule is exhausted. + + :param inc: + If `dt` is an instance of the rule and `inc` is `True`, it is + included in the output. + + :yields: Yields a sequence of `datetime` objects. + """ + + if self._cache_complete: + gen = self._cache + else: + gen = self + + # Select the comparison function + if inc: + comp = lambda dc, dtc: dc >= dtc + else: + comp = lambda dc, dtc: dc > dtc + + # Generate dates + n = 0 + for d in gen: + if comp(d, dt): + if count is not None: + n += 1 + if n > count: + break + + yield d + + def between(self, after, before, inc=False, count=1): + """ Returns all the occurrences of the rrule between after and before. + The inc keyword defines what happens if after and/or before are + themselves occurrences. With inc=True, they will be included in the + list, if they are found in the recurrence set. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + started = False + l = [] + if inc: + for i in gen: + if i > before: + break + elif not started: + if i >= after: + started = True + l.append(i) + else: + l.append(i) + else: + for i in gen: + if i >= before: + break + elif not started: + if i > after: + started = True + l.append(i) + else: + l.append(i) + return l + + +class rrule(rrulebase): + """ + That's the base of the rrule operation. It accepts all the keywords + defined in the RFC as its constructor parameters (except byday, + which was renamed to byweekday) and more. The constructor prototype is:: + + rrule(freq) + + Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, + or SECONDLY. + + .. note:: + Per RFC section 3.3.10, recurrence instances falling on invalid dates + and times are ignored rather than coerced: + + Recurrence rules may generate recurrence instances with an invalid + date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM + on a day where the local time is moved forward by an hour at 1:00 + AM). Such recurrence instances MUST be ignored and MUST NOT be + counted as part of the recurrence set. + + This can lead to possibly surprising behavior when, for example, the + start date occurs at the end of the month: + + >>> from dateutil.rrule import rrule, MONTHLY + >>> from datetime import datetime + >>> start_date = datetime(2014, 12, 31) + >>> list(rrule(freq=MONTHLY, count=4, dtstart=start_date)) + ... # doctest: +NORMALIZE_WHITESPACE + [datetime.datetime(2014, 12, 31, 0, 0), + datetime.datetime(2015, 1, 31, 0, 0), + datetime.datetime(2015, 3, 31, 0, 0), + datetime.datetime(2015, 5, 31, 0, 0)] + + Additionally, it supports the following keyword arguments: + + :param dtstart: + The recurrence start. Besides being the base for the recurrence, + missing parameters in the final recurrence instances will also be + extracted from this date. If not given, datetime.now() will be used + instead. + :param interval: + The interval between each freq iteration. For example, when using + YEARLY, an interval of 2 means once every two years, but with HOURLY, + it means once every two hours. The default interval is 1. + :param wkst: + The week start day. Must be one of the MO, TU, WE constants, or an + integer, specifying the first day of the week. This will affect + recurrences based on weekly periods. The default week start is got + from calendar.firstweekday(), and may be modified by + calendar.setfirstweekday(). + :param count: + If given, this determines how many occurrences will be generated. + + .. note:: + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. + :param until: + If given, this must be a datetime instance specifying the upper-bound + limit of the recurrence. The last recurrence in the rule is the greatest + datetime that is less than or equal to the value specified in the + ``until`` parameter. + + .. note:: + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. + :param bysetpos: + If given, it must be either an integer, or a sequence of integers, + positive or negative. Each given integer will specify an occurrence + number, corresponding to the nth occurrence of the rule inside the + frequency period. For example, a bysetpos of -1 if combined with a + MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will + result in the last work day of every month. + :param bymonth: + If given, it must be either an integer, or a sequence of integers, + meaning the months to apply the recurrence to. + :param bymonthday: + If given, it must be either an integer, or a sequence of integers, + meaning the month days to apply the recurrence to. + :param byyearday: + If given, it must be either an integer, or a sequence of integers, + meaning the year days to apply the recurrence to. + :param byeaster: + If given, it must be either an integer, or a sequence of integers, + positive or negative. Each integer will define an offset from the + Easter Sunday. Passing the offset 0 to byeaster will yield the Easter + Sunday itself. This is an extension to the RFC specification. + :param byweekno: + If given, it must be either an integer, or a sequence of integers, + meaning the week numbers to apply the recurrence to. Week numbers + have the meaning described in ISO8601, that is, the first week of + the year is that containing at least four days of the new year. + :param byweekday: + If given, it must be either an integer (0 == MO), a sequence of + integers, one of the weekday constants (MO, TU, etc), or a sequence + of these constants. When given, these variables will define the + weekdays where the recurrence will be applied. It's also possible to + use an argument n for the weekday instances, which will mean the nth + occurrence of this weekday in the period. For example, with MONTHLY, + or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the + first friday of the month where the recurrence happens. Notice that in + the RFC documentation, this is specified as BYDAY, but was renamed to + avoid the ambiguity of that keyword. + :param byhour: + If given, it must be either an integer, or a sequence of integers, + meaning the hours to apply the recurrence to. + :param byminute: + If given, it must be either an integer, or a sequence of integers, + meaning the minutes to apply the recurrence to. + :param bysecond: + If given, it must be either an integer, or a sequence of integers, + meaning the seconds to apply the recurrence to. + :param cache: + If given, it must be a boolean value specifying to enable or disable + caching of results. If you will use the same rrule instance multiple + times, enabling caching will improve the performance considerably. + """ + def __init__(self, freq, dtstart=None, + interval=1, wkst=None, count=None, until=None, bysetpos=None, + bymonth=None, bymonthday=None, byyearday=None, byeaster=None, + byweekno=None, byweekday=None, + byhour=None, byminute=None, bysecond=None, + cache=False): + super(rrule, self).__init__(cache) + global easter + if not dtstart: + if until and until.tzinfo: + dtstart = datetime.datetime.now(tz=until.tzinfo).replace(microsecond=0) + else: + dtstart = datetime.datetime.now().replace(microsecond=0) + elif not isinstance(dtstart, datetime.datetime): + dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) + else: + dtstart = dtstart.replace(microsecond=0) + self._dtstart = dtstart + self._tzinfo = dtstart.tzinfo + self._freq = freq + self._interval = interval + self._count = count + + # Cache the original byxxx rules, if they are provided, as the _byxxx + # attributes do not necessarily map to the inputs, and this can be + # a problem in generating the strings. Only store things if they've + # been supplied (the string retrieval will just use .get()) + self._original_rule = {} + + if until and not isinstance(until, datetime.datetime): + until = datetime.datetime.fromordinal(until.toordinal()) + self._until = until + + if self._dtstart and self._until: + if (self._dtstart.tzinfo is not None) != (self._until.tzinfo is not None): + # According to RFC5545 Section 3.3.10: + # https://tools.ietf.org/html/rfc5545#section-3.3.10 + # + # > If the "DTSTART" property is specified as a date with UTC + # > time or a date with local time and time zone reference, + # > then the UNTIL rule part MUST be specified as a date with + # > UTC time. + raise ValueError( + 'RRULE UNTIL values must be specified in UTC when DTSTART ' + 'is timezone-aware' + ) + + if count is not None and until: + warn("Using both 'count' and 'until' is inconsistent with RFC 5545" + " and has been deprecated in dateutil. Future versions will " + "raise an error.", DeprecationWarning) + + if wkst is None: + self._wkst = calendar.firstweekday() + elif isinstance(wkst, integer_types): + self._wkst = wkst + else: + self._wkst = wkst.weekday + + if bysetpos is None: + self._bysetpos = None + elif isinstance(bysetpos, integer_types): + if bysetpos == 0 or not (-366 <= bysetpos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + self._bysetpos = (bysetpos,) + else: + self._bysetpos = tuple(bysetpos) + for pos in self._bysetpos: + if pos == 0 or not (-366 <= pos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + + if self._bysetpos: + self._original_rule['bysetpos'] = self._bysetpos + + if (byweekno is None and byyearday is None and bymonthday is None and + byweekday is None and byeaster is None): + if freq == YEARLY: + if bymonth is None: + bymonth = dtstart.month + self._original_rule['bymonth'] = None + bymonthday = dtstart.day + self._original_rule['bymonthday'] = None + elif freq == MONTHLY: + bymonthday = dtstart.day + self._original_rule['bymonthday'] = None + elif freq == WEEKLY: + byweekday = dtstart.weekday() + self._original_rule['byweekday'] = None + + # bymonth + if bymonth is None: + self._bymonth = None + else: + if isinstance(bymonth, integer_types): + bymonth = (bymonth,) + + self._bymonth = tuple(sorted(set(bymonth))) + + if 'bymonth' not in self._original_rule: + self._original_rule['bymonth'] = self._bymonth + + # byyearday + if byyearday is None: + self._byyearday = None + else: + if isinstance(byyearday, integer_types): + byyearday = (byyearday,) + + self._byyearday = tuple(sorted(set(byyearday))) + self._original_rule['byyearday'] = self._byyearday + + # byeaster + if byeaster is not None: + if not easter: + from dateutil import easter + if isinstance(byeaster, integer_types): + self._byeaster = (byeaster,) + else: + self._byeaster = tuple(sorted(byeaster)) + + self._original_rule['byeaster'] = self._byeaster + else: + self._byeaster = None + + # bymonthday + if bymonthday is None: + self._bymonthday = () + self._bynmonthday = () + else: + if isinstance(bymonthday, integer_types): + bymonthday = (bymonthday,) + + bymonthday = set(bymonthday) # Ensure it's unique + + self._bymonthday = tuple(sorted(x for x in bymonthday if x > 0)) + self._bynmonthday = tuple(sorted(x for x in bymonthday if x < 0)) + + # Storing positive numbers first, then negative numbers + if 'bymonthday' not in self._original_rule: + self._original_rule['bymonthday'] = tuple( + itertools.chain(self._bymonthday, self._bynmonthday)) + + # byweekno + if byweekno is None: + self._byweekno = None + else: + if isinstance(byweekno, integer_types): + byweekno = (byweekno,) + + self._byweekno = tuple(sorted(set(byweekno))) + + self._original_rule['byweekno'] = self._byweekno + + # byweekday / bynweekday + if byweekday is None: + self._byweekday = None + self._bynweekday = None + else: + # If it's one of the valid non-sequence types, convert to a + # single-element sequence before the iterator that builds the + # byweekday set. + if isinstance(byweekday, integer_types) or hasattr(byweekday, "n"): + byweekday = (byweekday,) + + self._byweekday = set() + self._bynweekday = set() + for wday in byweekday: + if isinstance(wday, integer_types): + self._byweekday.add(wday) + elif not wday.n or freq > MONTHLY: + self._byweekday.add(wday.weekday) + else: + self._bynweekday.add((wday.weekday, wday.n)) + + if not self._byweekday: + self._byweekday = None + elif not self._bynweekday: + self._bynweekday = None + + if self._byweekday is not None: + self._byweekday = tuple(sorted(self._byweekday)) + orig_byweekday = [weekday(x) for x in self._byweekday] + else: + orig_byweekday = () + + if self._bynweekday is not None: + self._bynweekday = tuple(sorted(self._bynweekday)) + orig_bynweekday = [weekday(*x) for x in self._bynweekday] + else: + orig_bynweekday = () + + if 'byweekday' not in self._original_rule: + self._original_rule['byweekday'] = tuple(itertools.chain( + orig_byweekday, orig_bynweekday)) + + # byhour + if byhour is None: + if freq < HOURLY: + self._byhour = {dtstart.hour} + else: + self._byhour = None + else: + if isinstance(byhour, integer_types): + byhour = (byhour,) + + if freq == HOURLY: + self._byhour = self.__construct_byset(start=dtstart.hour, + byxxx=byhour, + base=24) + else: + self._byhour = set(byhour) + + self._byhour = tuple(sorted(self._byhour)) + self._original_rule['byhour'] = self._byhour + + # byminute + if byminute is None: + if freq < MINUTELY: + self._byminute = {dtstart.minute} + else: + self._byminute = None + else: + if isinstance(byminute, integer_types): + byminute = (byminute,) + + if freq == MINUTELY: + self._byminute = self.__construct_byset(start=dtstart.minute, + byxxx=byminute, + base=60) + else: + self._byminute = set(byminute) + + self._byminute = tuple(sorted(self._byminute)) + self._original_rule['byminute'] = self._byminute + + # bysecond + if bysecond is None: + if freq < SECONDLY: + self._bysecond = ((dtstart.second,)) + else: + self._bysecond = None + else: + if isinstance(bysecond, integer_types): + bysecond = (bysecond,) + + self._bysecond = set(bysecond) + + if freq == SECONDLY: + self._bysecond = self.__construct_byset(start=dtstart.second, + byxxx=bysecond, + base=60) + else: + self._bysecond = set(bysecond) + + self._bysecond = tuple(sorted(self._bysecond)) + self._original_rule['bysecond'] = self._bysecond + + if self._freq >= HOURLY: + self._timeset = None + else: + self._timeset = [] + for hour in self._byhour: + for minute in self._byminute: + for second in self._bysecond: + self._timeset.append( + datetime.time(hour, minute, second, + tzinfo=self._tzinfo)) + self._timeset.sort() + self._timeset = tuple(self._timeset) + + def __str__(self): + """ + Output a string that would generate this RRULE if passed to rrulestr. + This is mostly compatible with RFC5545, except for the + dateutil-specific extension BYEASTER. + """ + + output = [] + h, m, s = [None] * 3 + if self._dtstart: + output.append(self._dtstart.strftime('DTSTART:%Y%m%dT%H%M%S')) + h, m, s = self._dtstart.timetuple()[3:6] + + parts = ['FREQ=' + FREQNAMES[self._freq]] + if self._interval != 1: + parts.append('INTERVAL=' + str(self._interval)) + + if self._wkst: + parts.append('WKST=' + repr(weekday(self._wkst))[0:2]) + + if self._count is not None: + parts.append('COUNT=' + str(self._count)) + + if self._until: + parts.append(self._until.strftime('UNTIL=%Y%m%dT%H%M%S')) + + if self._original_rule.get('byweekday') is not None: + # The str() method on weekday objects doesn't generate + # RFC5545-compliant strings, so we should modify that. + original_rule = dict(self._original_rule) + wday_strings = [] + for wday in original_rule['byweekday']: + if wday.n: + wday_strings.append('{n:+d}{wday}'.format( + n=wday.n, + wday=repr(wday)[0:2])) + else: + wday_strings.append(repr(wday)) + + original_rule['byweekday'] = wday_strings + else: + original_rule = self._original_rule + + partfmt = '{name}={vals}' + for name, key in [('BYSETPOS', 'bysetpos'), + ('BYMONTH', 'bymonth'), + ('BYMONTHDAY', 'bymonthday'), + ('BYYEARDAY', 'byyearday'), + ('BYWEEKNO', 'byweekno'), + ('BYDAY', 'byweekday'), + ('BYHOUR', 'byhour'), + ('BYMINUTE', 'byminute'), + ('BYSECOND', 'bysecond'), + ('BYEASTER', 'byeaster')]: + value = original_rule.get(key) + if value: + parts.append(partfmt.format(name=name, vals=(','.join(str(v) + for v in value)))) + + output.append('RRULE:' + ';'.join(parts)) + return '\n'.join(output) + + def replace(self, **kwargs): + """Return new rrule with same attributes except for those attributes given new + values by whichever keyword arguments are specified.""" + new_kwargs = {"interval": self._interval, + "count": self._count, + "dtstart": self._dtstart, + "freq": self._freq, + "until": self._until, + "wkst": self._wkst, + "cache": False if self._cache is None else True } + new_kwargs.update(self._original_rule) + new_kwargs.update(kwargs) + return rrule(**new_kwargs) + + def _iter(self): + year, month, day, hour, minute, second, weekday, yearday, _ = \ + self._dtstart.timetuple() + + # Some local variables to speed things up a bit + freq = self._freq + interval = self._interval + wkst = self._wkst + until = self._until + bymonth = self._bymonth + byweekno = self._byweekno + byyearday = self._byyearday + byweekday = self._byweekday + byeaster = self._byeaster + bymonthday = self._bymonthday + bynmonthday = self._bynmonthday + bysetpos = self._bysetpos + byhour = self._byhour + byminute = self._byminute + bysecond = self._bysecond + + ii = _iterinfo(self) + ii.rebuild(year, month) + + getdayset = {YEARLY: ii.ydayset, + MONTHLY: ii.mdayset, + WEEKLY: ii.wdayset, + DAILY: ii.ddayset, + HOURLY: ii.ddayset, + MINUTELY: ii.ddayset, + SECONDLY: ii.ddayset}[freq] + + if freq < HOURLY: + timeset = self._timeset + else: + gettimeset = {HOURLY: ii.htimeset, + MINUTELY: ii.mtimeset, + SECONDLY: ii.stimeset}[freq] + if ((freq >= HOURLY and + self._byhour and hour not in self._byhour) or + (freq >= MINUTELY and + self._byminute and minute not in self._byminute) or + (freq >= SECONDLY and + self._bysecond and second not in self._bysecond)): + timeset = () + else: + timeset = gettimeset(hour, minute, second) + + total = 0 + count = self._count + while True: + # Get dayset with the right frequency + dayset, start, end = getdayset(year, month, day) + + # Do the "hard" work ;-) + filtered = False + for i in dayset[start:end]: + if ((bymonth and ii.mmask[i] not in bymonth) or + (byweekno and not ii.wnomask[i]) or + (byweekday and ii.wdaymask[i] not in byweekday) or + (ii.nwdaymask and not ii.nwdaymask[i]) or + (byeaster and not ii.eastermask[i]) or + ((bymonthday or bynmonthday) and + ii.mdaymask[i] not in bymonthday and + ii.nmdaymask[i] not in bynmonthday) or + (byyearday and + ((i < ii.yearlen and i+1 not in byyearday and + -ii.yearlen+i not in byyearday) or + (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and + -ii.nextyearlen+i-ii.yearlen not in byyearday)))): + dayset[i] = None + filtered = True + + # Output results + if bysetpos and timeset: + poslist = [] + for pos in bysetpos: + if pos < 0: + daypos, timepos = divmod(pos, len(timeset)) + else: + daypos, timepos = divmod(pos-1, len(timeset)) + try: + i = [x for x in dayset[start:end] + if x is not None][daypos] + time = timeset[timepos] + except IndexError: + pass + else: + date = datetime.date.fromordinal(ii.yearordinal+i) + res = datetime.datetime.combine(date, time) + if res not in poslist: + poslist.append(res) + poslist.sort() + for res in poslist: + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + if count is not None: + count -= 1 + if count < 0: + self._len = total + return + total += 1 + yield res + else: + for i in dayset[start:end]: + if i is not None: + date = datetime.date.fromordinal(ii.yearordinal + i) + for time in timeset: + res = datetime.datetime.combine(date, time) + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + if count is not None: + count -= 1 + if count < 0: + self._len = total + return + + total += 1 + yield res + + # Handle frequency and interval + fixday = False + if freq == YEARLY: + year += interval + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == MONTHLY: + month += interval + if month > 12: + div, mod = divmod(month, 12) + month = mod + year += div + if month == 0: + month = 12 + year -= 1 + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == WEEKLY: + if wkst > weekday: + day += -(weekday+1+(6-wkst))+self._interval*7 + else: + day += -(weekday-wkst)+self._interval*7 + weekday = wkst + fixday = True + elif freq == DAILY: + day += interval + fixday = True + elif freq == HOURLY: + if filtered: + # Jump to one iteration before next day + hour += ((23-hour)//interval)*interval + + if byhour: + ndays, hour = self.__mod_distance(value=hour, + byxxx=self._byhour, + base=24) + else: + ndays, hour = divmod(hour+interval, 24) + + if ndays: + day += ndays + fixday = True + + timeset = gettimeset(hour, minute, second) + elif freq == MINUTELY: + if filtered: + # Jump to one iteration before next day + minute += ((1439-(hour*60+minute))//interval)*interval + + valid = False + rep_rate = (24*60) + for j in range(rep_rate // gcd(interval, rep_rate)): + if byminute: + nhours, minute = \ + self.__mod_distance(value=minute, + byxxx=self._byminute, + base=60) + else: + nhours, minute = divmod(minute+interval, 60) + + div, hour = divmod(hour+nhours, 24) + if div: + day += div + fixday = True + filtered = False + + if not byhour or hour in byhour: + valid = True + break + + if not valid: + raise ValueError('Invalid combination of interval and ' + + 'byhour resulting in empty rule.') + + timeset = gettimeset(hour, minute, second) + elif freq == SECONDLY: + if filtered: + # Jump to one iteration before next day + second += (((86399 - (hour * 3600 + minute * 60 + second)) + // interval) * interval) + + rep_rate = (24 * 3600) + valid = False + for j in range(0, rep_rate // gcd(interval, rep_rate)): + if bysecond: + nminutes, second = \ + self.__mod_distance(value=second, + byxxx=self._bysecond, + base=60) + else: + nminutes, second = divmod(second+interval, 60) + + div, minute = divmod(minute+nminutes, 60) + if div: + hour += div + div, hour = divmod(hour, 24) + if div: + day += div + fixday = True + + if ((not byhour or hour in byhour) and + (not byminute or minute in byminute) and + (not bysecond or second in bysecond)): + valid = True + break + + if not valid: + raise ValueError('Invalid combination of interval, ' + + 'byhour and byminute resulting in empty' + + ' rule.') + + timeset = gettimeset(hour, minute, second) + + if fixday and day > 28: + daysinmonth = calendar.monthrange(year, month)[1] + if day > daysinmonth: + while day > daysinmonth: + day -= daysinmonth + month += 1 + if month == 13: + month = 1 + year += 1 + if year > datetime.MAXYEAR: + self._len = total + return + daysinmonth = calendar.monthrange(year, month)[1] + ii.rebuild(year, month) + + def __construct_byset(self, start, byxxx, base): + """ + If a `BYXXX` sequence is passed to the constructor at the same level as + `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some + specifications which cannot be reached given some starting conditions. + + This occurs whenever the interval is not coprime with the base of a + given unit and the difference between the starting position and the + ending position is not coprime with the greatest common denominator + between the interval and the base. For example, with a FREQ of hourly + starting at 17:00 and an interval of 4, the only valid values for + BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not + coprime. + + :param start: + Specifies the starting position. + :param byxxx: + An iterable containing the list of allowed values. + :param base: + The largest allowable value for the specified frequency (e.g. + 24 hours, 60 minutes). + + This does not preserve the type of the iterable, returning a set, since + the values should be unique and the order is irrelevant, this will + speed up later lookups. + + In the event of an empty set, raises a :exception:`ValueError`, as this + results in an empty rrule. + """ + + cset = set() + + # Support a single byxxx value. + if isinstance(byxxx, integer_types): + byxxx = (byxxx, ) + + for num in byxxx: + i_gcd = gcd(self._interval, base) + # Use divmod rather than % because we need to wrap negative nums. + if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0: + cset.add(num) + + if len(cset) == 0: + raise ValueError("Invalid rrule byxxx generates an empty set.") + + return cset + + def __mod_distance(self, value, byxxx, base): + """ + Calculates the next value in a sequence where the `FREQ` parameter is + specified along with a `BYXXX` parameter at the same "level" + (e.g. `HOURLY` specified with `BYHOUR`). + + :param value: + The old value of the component. + :param byxxx: + The `BYXXX` set, which should have been generated by + `rrule._construct_byset`, or something else which checks that a + valid rule is present. + :param base: + The largest allowable value for the specified frequency (e.g. + 24 hours, 60 minutes). + + If a valid value is not found after `base` iterations (the maximum + number before the sequence would start to repeat), this raises a + :exception:`ValueError`, as no valid values were found. + + This returns a tuple of `divmod(n*interval, base)`, where `n` is the + smallest number of `interval` repetitions until the next specified + value in `byxxx` is found. + """ + accumulator = 0 + for ii in range(1, base + 1): + # Using divmod() over % to account for negative intervals + div, value = divmod(value + self._interval, base) + accumulator += div + if value in byxxx: + return (accumulator, value) + + +class _iterinfo(object): + __slots__ = ["rrule", "lastyear", "lastmonth", + "yearlen", "nextyearlen", "yearordinal", "yearweekday", + "mmask", "mrange", "mdaymask", "nmdaymask", + "wdaymask", "wnomask", "nwdaymask", "eastermask"] + + def __init__(self, rrule): + for attr in self.__slots__: + setattr(self, attr, None) + self.rrule = rrule + + def rebuild(self, year, month): + # Every mask is 7 days longer to handle cross-year weekly periods. + rr = self.rrule + if year != self.lastyear: + self.yearlen = 365 + calendar.isleap(year) + self.nextyearlen = 365 + calendar.isleap(year + 1) + firstyday = datetime.date(year, 1, 1) + self.yearordinal = firstyday.toordinal() + self.yearweekday = firstyday.weekday() + + wday = datetime.date(year, 1, 1).weekday() + if self.yearlen == 365: + self.mmask = M365MASK + self.mdaymask = MDAY365MASK + self.nmdaymask = NMDAY365MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M365RANGE + else: + self.mmask = M366MASK + self.mdaymask = MDAY366MASK + self.nmdaymask = NMDAY366MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M366RANGE + + if not rr._byweekno: + self.wnomask = None + else: + self.wnomask = [0]*(self.yearlen+7) + # no1wkst = firstwkst = self.wdaymask.index(rr._wkst) + no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7 + if no1wkst >= 4: + no1wkst = 0 + # Number of days in the year, plus the days we got + # from last year. + wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7 + else: + # Number of days in the year, minus the days we + # left in last year. + wyearlen = self.yearlen-no1wkst + div, mod = divmod(wyearlen, 7) + numweeks = div+mod//4 + for n in rr._byweekno: + if n < 0: + n += numweeks+1 + if not (0 < n <= numweeks): + continue + if n > 1: + i = no1wkst+(n-1)*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + else: + i = no1wkst + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if 1 in rr._byweekno: + # Check week number 1 of next year as well + # TODO: Check -numweeks for next year. + i = no1wkst+numweeks*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + if i < self.yearlen: + # If week starts in next year, we + # don't care about it. + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if no1wkst: + # Check last week number of last year as + # well. If no1wkst is 0, either the year + # started on week start, or week number 1 + # got days from last year, so there are no + # days from last year's last week number in + # this year. + if -1 not in rr._byweekno: + lyearweekday = datetime.date(year-1, 1, 1).weekday() + lno1wkst = (7-lyearweekday+rr._wkst) % 7 + lyearlen = 365+calendar.isleap(year-1) + if lno1wkst >= 4: + lno1wkst = 0 + lnumweeks = 52+(lyearlen + + (lyearweekday-rr._wkst) % 7) % 7//4 + else: + lnumweeks = 52+(self.yearlen-no1wkst) % 7//4 + else: + lnumweeks = -1 + if lnumweeks in rr._byweekno: + for i in range(no1wkst): + self.wnomask[i] = 1 + + if (rr._bynweekday and (month != self.lastmonth or + year != self.lastyear)): + ranges = [] + if rr._freq == YEARLY: + if rr._bymonth: + for month in rr._bymonth: + ranges.append(self.mrange[month-1:month+1]) + else: + ranges = [(0, self.yearlen)] + elif rr._freq == MONTHLY: + ranges = [self.mrange[month-1:month+1]] + if ranges: + # Weekly frequency won't get here, so we may not + # care about cross-year weekly periods. + self.nwdaymask = [0]*self.yearlen + for first, last in ranges: + last -= 1 + for wday, n in rr._bynweekday: + if n < 0: + i = last+(n+1)*7 + i -= (self.wdaymask[i]-wday) % 7 + else: + i = first+(n-1)*7 + i += (7-self.wdaymask[i]+wday) % 7 + if first <= i <= last: + self.nwdaymask[i] = 1 + + if rr._byeaster: + self.eastermask = [0]*(self.yearlen+7) + eyday = easter.easter(year).toordinal()-self.yearordinal + for offset in rr._byeaster: + self.eastermask[eyday+offset] = 1 + + self.lastyear = year + self.lastmonth = month + + def ydayset(self, year, month, day): + return list(range(self.yearlen)), 0, self.yearlen + + def mdayset(self, year, month, day): + dset = [None]*self.yearlen + start, end = self.mrange[month-1:month+1] + for i in range(start, end): + dset[i] = i + return dset, start, end + + def wdayset(self, year, month, day): + # We need to handle cross-year weeks here. + dset = [None]*(self.yearlen+7) + i = datetime.date(year, month, day).toordinal()-self.yearordinal + start = i + for j in range(7): + dset[i] = i + i += 1 + # if (not (0 <= i < self.yearlen) or + # self.wdaymask[i] == self.rrule._wkst): + # This will cross the year boundary, if necessary. + if self.wdaymask[i] == self.rrule._wkst: + break + return dset, start, i + + def ddayset(self, year, month, day): + dset = [None] * self.yearlen + i = datetime.date(year, month, day).toordinal() - self.yearordinal + dset[i] = i + return dset, i, i + 1 + + def htimeset(self, hour, minute, second): + tset = [] + rr = self.rrule + for minute in rr._byminute: + for second in rr._bysecond: + tset.append(datetime.time(hour, minute, second, + tzinfo=rr._tzinfo)) + tset.sort() + return tset + + def mtimeset(self, hour, minute, second): + tset = [] + rr = self.rrule + for second in rr._bysecond: + tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) + tset.sort() + return tset + + def stimeset(self, hour, minute, second): + return (datetime.time(hour, minute, second, + tzinfo=self.rrule._tzinfo),) + + +class rruleset(rrulebase): + """ The rruleset type allows more complex recurrence setups, mixing + multiple rules, dates, exclusion rules, and exclusion dates. The type + constructor takes the following keyword arguments: + + :param cache: If True, caching of results will be enabled, improving + performance of multiple queries considerably. """ + + class _genitem(object): + def __init__(self, genlist, gen): + try: + self.dt = advance_iterator(gen) + genlist.append(self) + except StopIteration: + pass + self.genlist = genlist + self.gen = gen + + def __next__(self): + try: + self.dt = advance_iterator(self.gen) + except StopIteration: + if self.genlist[0] is self: + heapq.heappop(self.genlist) + else: + self.genlist.remove(self) + heapq.heapify(self.genlist) + + next = __next__ + + def __lt__(self, other): + return self.dt < other.dt + + def __gt__(self, other): + return self.dt > other.dt + + def __eq__(self, other): + return self.dt == other.dt + + def __ne__(self, other): + return self.dt != other.dt + + def __init__(self, cache=False): + super(rruleset, self).__init__(cache) + self._rrule = [] + self._rdate = [] + self._exrule = [] + self._exdate = [] + + @_invalidates_cache + def rrule(self, rrule): + """ Include the given :py:class:`rrule` instance in the recurrence set + generation. """ + self._rrule.append(rrule) + + @_invalidates_cache + def rdate(self, rdate): + """ Include the given :py:class:`datetime` instance in the recurrence + set generation. """ + self._rdate.append(rdate) + + @_invalidates_cache + def exrule(self, exrule): + """ Include the given rrule instance in the recurrence set exclusion + list. Dates which are part of the given recurrence rules will not + be generated, even if some inclusive rrule or rdate matches them. + """ + self._exrule.append(exrule) + + @_invalidates_cache + def exdate(self, exdate): + """ Include the given datetime instance in the recurrence set + exclusion list. Dates included that way will not be generated, + even if some inclusive rrule or rdate matches them. """ + self._exdate.append(exdate) + + def _iter(self): + rlist = [] + self._rdate.sort() + self._genitem(rlist, iter(self._rdate)) + for gen in [iter(x) for x in self._rrule]: + self._genitem(rlist, gen) + exlist = [] + self._exdate.sort() + self._genitem(exlist, iter(self._exdate)) + for gen in [iter(x) for x in self._exrule]: + self._genitem(exlist, gen) + lastdt = None + total = 0 + heapq.heapify(rlist) + heapq.heapify(exlist) + while rlist: + ritem = rlist[0] + if not lastdt or lastdt != ritem.dt: + while exlist and exlist[0] < ritem: + exitem = exlist[0] + advance_iterator(exitem) + if exlist and exlist[0] is exitem: + heapq.heapreplace(exlist, exitem) + if not exlist or ritem != exlist[0]: + total += 1 + yield ritem.dt + lastdt = ritem.dt + advance_iterator(ritem) + if rlist and rlist[0] is ritem: + heapq.heapreplace(rlist, ritem) + self._len = total + + + + +class _rrulestr(object): + """ Parses a string representation of a recurrence rule or set of + recurrence rules. + + :param s: + Required, a string defining one or more recurrence rules. + + :param dtstart: + If given, used as the default recurrence start if not specified in the + rule string. + + :param cache: + If set ``True`` caching of results will be enabled, improving + performance of multiple queries considerably. + + :param unfold: + If set ``True`` indicates that a rule string is split over more + than one line and should be joined before processing. + + :param forceset: + If set ``True`` forces a :class:`dateutil.rrule.rruleset` to + be returned. + + :param compatible: + If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime.datetime` object is returned. + + :param tzids: + If given, a callable or mapping used to retrieve a + :class:`datetime.tzinfo` from a string representation. + Defaults to :func:`dateutil.tz.gettz`. + + :param tzinfos: + Additional time zone names / aliases which may be present in a string + representation. See :func:`dateutil.parser.parse` for more + information. + + :return: + Returns a :class:`dateutil.rrule.rruleset` or + :class:`dateutil.rrule.rrule` + """ + + _freq_map = {"YEARLY": YEARLY, + "MONTHLY": MONTHLY, + "WEEKLY": WEEKLY, + "DAILY": DAILY, + "HOURLY": HOURLY, + "MINUTELY": MINUTELY, + "SECONDLY": SECONDLY} + + _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3, + "FR": 4, "SA": 5, "SU": 6} + + def _handle_int(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = int(value) + + def _handle_int_list(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = [int(x) for x in value.split(',')] + + _handle_INTERVAL = _handle_int + _handle_COUNT = _handle_int + _handle_BYSETPOS = _handle_int_list + _handle_BYMONTH = _handle_int_list + _handle_BYMONTHDAY = _handle_int_list + _handle_BYYEARDAY = _handle_int_list + _handle_BYEASTER = _handle_int_list + _handle_BYWEEKNO = _handle_int_list + _handle_BYHOUR = _handle_int_list + _handle_BYMINUTE = _handle_int_list + _handle_BYSECOND = _handle_int_list + + def _handle_FREQ(self, rrkwargs, name, value, **kwargs): + rrkwargs["freq"] = self._freq_map[value] + + def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): + global parser + if not parser: + from dateutil import parser + try: + rrkwargs["until"] = parser.parse(value, + ignoretz=kwargs.get("ignoretz"), + tzinfos=kwargs.get("tzinfos")) + except ValueError: + raise ValueError("invalid until date") + + def _handle_WKST(self, rrkwargs, name, value, **kwargs): + rrkwargs["wkst"] = self._weekday_map[value] + + def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwargs): + """ + Two ways to specify this: +1MO or MO(+1) + """ + l = [] + for wday in value.split(','): + if '(' in wday: + # If it's of the form TH(+1), etc. + splt = wday.split('(') + w = splt[0] + n = int(splt[1][:-1]) + elif len(wday): + # If it's of the form +1MO + for i in range(len(wday)): + if wday[i] not in '+-0123456789': + break + n = wday[:i] or None + w = wday[i:] + if n: + n = int(n) + else: + raise ValueError("Invalid (empty) BYDAY specification.") + + l.append(weekdays[self._weekday_map[w]](n)) + rrkwargs["byweekday"] = l + + _handle_BYDAY = _handle_BYWEEKDAY + + def _parse_rfc_rrule(self, line, + dtstart=None, + cache=False, + ignoretz=False, + tzinfos=None): + if line.find(':') != -1: + name, value = line.split(':') + if name != "RRULE": + raise ValueError("unknown parameter name") + else: + value = line + rrkwargs = {} + for pair in value.split(';'): + name, value = pair.split('=') + name = name.upper() + value = value.upper() + try: + getattr(self, "_handle_"+name)(rrkwargs, name, value, + ignoretz=ignoretz, + tzinfos=tzinfos) + except AttributeError: + raise ValueError("unknown parameter '%s'" % name) + except (KeyError, ValueError): + raise ValueError("invalid '%s': %s" % (name, value)) + return rrule(dtstart=dtstart, cache=cache, **rrkwargs) + + def _parse_date_value(self, date_value, parms, rule_tzids, + ignoretz, tzids, tzinfos): + global parser + if not parser: + from dateutil import parser + + datevals = [] + value_found = False + TZID = None + + for parm in parms: + if parm.startswith("TZID="): + try: + tzkey = rule_tzids[parm.split('TZID=')[-1]] + except KeyError: + continue + if tzids is None: + from . import tz + tzlookup = tz.gettz + elif callable(tzids): + tzlookup = tzids + else: + tzlookup = getattr(tzids, 'get', None) + if tzlookup is None: + msg = ('tzids must be a callable, mapping, or None, ' + 'not %s' % tzids) + raise ValueError(msg) + + TZID = tzlookup(tzkey) + continue + + # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found + # only once. + if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}: + raise ValueError("unsupported parm: " + parm) + else: + if value_found: + msg = ("Duplicate value parameter found in: " + parm) + raise ValueError(msg) + value_found = True + + for datestr in date_value.split(','): + date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos) + if TZID is not None: + if date.tzinfo is None: + date = date.replace(tzinfo=TZID) + else: + raise ValueError('DTSTART/EXDATE specifies multiple timezone') + datevals.append(date) + + return datevals + + def _parse_rfc(self, s, + dtstart=None, + cache=False, + unfold=False, + forceset=False, + compatible=False, + ignoretz=False, + tzids=None, + tzinfos=None): + global parser + if compatible: + forceset = True + unfold = True + + TZID_NAMES = dict(map( + lambda x: (x.upper(), x), + re.findall('TZID=(?P[^:]+):', s) + )) + s = s.upper() + if not s.strip(): + raise ValueError("empty string") + if unfold: + lines = s.splitlines() + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + else: + lines = s.split() + if (not forceset and len(lines) == 1 and (s.find(':') == -1 or + s.startswith('RRULE:'))): + return self._parse_rfc_rrule(lines[0], cache=cache, + dtstart=dtstart, ignoretz=ignoretz, + tzinfos=tzinfos) + else: + rrulevals = [] + rdatevals = [] + exrulevals = [] + exdatevals = [] + for line in lines: + if not line: + continue + if line.find(':') == -1: + name = "RRULE" + value = line + else: + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError("empty property name") + name = parms[0] + parms = parms[1:] + if name == "RRULE": + for parm in parms: + raise ValueError("unsupported RRULE parm: "+parm) + rrulevals.append(value) + elif name == "RDATE": + for parm in parms: + if parm != "VALUE=DATE-TIME": + raise ValueError("unsupported RDATE parm: "+parm) + rdatevals.append(value) + elif name == "EXRULE": + for parm in parms: + raise ValueError("unsupported EXRULE parm: "+parm) + exrulevals.append(value) + elif name == "EXDATE": + exdatevals.extend( + self._parse_date_value(value, parms, + TZID_NAMES, ignoretz, + tzids, tzinfos) + ) + elif name == "DTSTART": + dtvals = self._parse_date_value(value, parms, TZID_NAMES, + ignoretz, tzids, tzinfos) + if len(dtvals) != 1: + raise ValueError("Multiple DTSTART values specified:" + + value) + dtstart = dtvals[0] + else: + raise ValueError("unsupported property: "+name) + if (forceset or len(rrulevals) > 1 or rdatevals + or exrulevals or exdatevals): + if not parser and (rdatevals or exdatevals): + from dateutil import parser + rset = rruleset(cache=cache) + for value in rrulevals: + rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in rdatevals: + for datestr in value.split(','): + rset.rdate(parser.parse(datestr, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exrulevals: + rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exdatevals: + rset.exdate(value) + if compatible and dtstart: + rset.rdate(dtstart) + return rset + else: + return self._parse_rfc_rrule(rrulevals[0], + dtstart=dtstart, + cache=cache, + ignoretz=ignoretz, + tzinfos=tzinfos) + + def __call__(self, s, **kwargs): + return self._parse_rfc(s, **kwargs) + + +rrulestr = _rrulestr() + +# vim:ts=4:sw=4:et diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/__init__.py b/venv/lib/python3.6/site-packages/dateutil/tz/__init__.py new file mode 100644 index 0000000..5a2d9cd --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/tz/__init__.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from .tz import * +from .tz import __doc__ + +#: Convenience constant providing a :class:`tzutc()` instance +#: +#: .. versionadded:: 2.7.0 +UTC = tzutc() + +__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", + "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz", + "enfold", "datetime_ambiguous", "datetime_exists", + "resolve_imaginary", "UTC", "DeprecatedTzFormatWarning"] + + +class DeprecatedTzFormatWarning(Warning): + """Warning raised when time zones are parsed from deprecated formats.""" diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/__init__.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..e5ce620 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/__init__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/_common.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/_common.cpython-36.pyc new file mode 100644 index 0000000..6c3c849 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/_common.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/_factories.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/_factories.cpython-36.pyc new file mode 100644 index 0000000..6da89f3 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/_factories.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/tz.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/tz.cpython-36.pyc new file mode 100644 index 0000000..562a184 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/tz.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/win.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/win.cpython-36.pyc new file mode 100644 index 0000000..9d3bef7 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/tz/__pycache__/win.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/_common.py b/venv/lib/python3.6/site-packages/dateutil/tz/_common.py new file mode 100644 index 0000000..594e082 --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/tz/_common.py @@ -0,0 +1,419 @@ +from six import PY2 + +from functools import wraps + +from datetime import datetime, timedelta, tzinfo + + +ZERO = timedelta(0) + +__all__ = ['tzname_in_python2', 'enfold'] + + +def tzname_in_python2(namefunc): + """Change unicode output into bytestrings in Python 2 + + tzname() API changed in Python 3. It used to return bytes, but was changed + to unicode strings + """ + if PY2: + @wraps(namefunc) + def adjust_encoding(*args, **kwargs): + name = namefunc(*args, **kwargs) + if name is not None: + name = name.encode() + + return name + + return adjust_encoding + else: + return namefunc + + +# The following is adapted from Alexander Belopolsky's tz library +# https://github.com/abalkin/tz +if hasattr(datetime, 'fold'): + # This is the pre-python 3.6 fold situation + def enfold(dt, fold=1): + """ + Provides a unified interface for assigning the ``fold`` attribute to + datetimes both before and after the implementation of PEP-495. + + :param fold: + The value for the ``fold`` attribute in the returned datetime. This + should be either 0 or 1. + + :return: + Returns an object for which ``getattr(dt, 'fold', 0)`` returns + ``fold`` for all versions of Python. In versions prior to + Python 3.6, this is a ``_DatetimeWithFold`` object, which is a + subclass of :py:class:`datetime.datetime` with the ``fold`` + attribute added, if ``fold`` is 1. + + .. versionadded:: 2.6.0 + """ + return dt.replace(fold=fold) + +else: + class _DatetimeWithFold(datetime): + """ + This is a class designed to provide a PEP 495-compliant interface for + Python versions before 3.6. It is used only for dates in a fold, so + the ``fold`` attribute is fixed at ``1``. + + .. versionadded:: 2.6.0 + """ + __slots__ = () + + def replace(self, *args, **kwargs): + """ + Return a datetime with the same attributes, except for those + attributes given new values by whichever keyword arguments are + specified. Note that tzinfo=None can be specified to create a naive + datetime from an aware datetime with no conversion of date and time + data. + + This is reimplemented in ``_DatetimeWithFold`` because pypy3 will + return a ``datetime.datetime`` even if ``fold`` is unchanged. + """ + argnames = ( + 'year', 'month', 'day', 'hour', 'minute', 'second', + 'microsecond', 'tzinfo' + ) + + for arg, argname in zip(args, argnames): + if argname in kwargs: + raise TypeError('Duplicate argument: {}'.format(argname)) + + kwargs[argname] = arg + + for argname in argnames: + if argname not in kwargs: + kwargs[argname] = getattr(self, argname) + + dt_class = self.__class__ if kwargs.get('fold', 1) else datetime + + return dt_class(**kwargs) + + @property + def fold(self): + return 1 + + def enfold(dt, fold=1): + """ + Provides a unified interface for assigning the ``fold`` attribute to + datetimes both before and after the implementation of PEP-495. + + :param fold: + The value for the ``fold`` attribute in the returned datetime. This + should be either 0 or 1. + + :return: + Returns an object for which ``getattr(dt, 'fold', 0)`` returns + ``fold`` for all versions of Python. In versions prior to + Python 3.6, this is a ``_DatetimeWithFold`` object, which is a + subclass of :py:class:`datetime.datetime` with the ``fold`` + attribute added, if ``fold`` is 1. + + .. versionadded:: 2.6.0 + """ + if getattr(dt, 'fold', 0) == fold: + return dt + + args = dt.timetuple()[:6] + args += (dt.microsecond, dt.tzinfo) + + if fold: + return _DatetimeWithFold(*args) + else: + return datetime(*args) + + +def _validate_fromutc_inputs(f): + """ + The CPython version of ``fromutc`` checks that the input is a ``datetime`` + object and that ``self`` is attached as its ``tzinfo``. + """ + @wraps(f) + def fromutc(self, dt): + if not isinstance(dt, datetime): + raise TypeError("fromutc() requires a datetime argument") + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + return f(self, dt) + + return fromutc + + +class _tzinfo(tzinfo): + """ + Base class for all ``dateutil`` ``tzinfo`` objects. + """ + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + + dt = dt.replace(tzinfo=self) + + wall_0 = enfold(dt, fold=0) + wall_1 = enfold(dt, fold=1) + + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None) + + return same_dt and not same_offset + + def _fold_status(self, dt_utc, dt_wall): + """ + Determine the fold status of a "wall" datetime, given a representation + of the same datetime as a (naive) UTC datetime. This is calculated based + on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all + datetimes, and that this offset is the actual number of hours separating + ``dt_utc`` and ``dt_wall``. + + :param dt_utc: + Representation of the datetime as UTC + + :param dt_wall: + Representation of the datetime as "wall time". This parameter must + either have a `fold` attribute or have a fold-naive + :class:`datetime.tzinfo` attached, otherwise the calculation may + fail. + """ + if self.is_ambiguous(dt_wall): + delta_wall = dt_wall - dt_utc + _fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst())) + else: + _fold = 0 + + return _fold + + def _fold(self, dt): + return getattr(dt, 'fold', 0) + + def _fromutc(self, dt): + """ + Given a timezone-aware datetime in a given timezone, calculates a + timezone-aware datetime in a new timezone. + + Since this is the one time that we *know* we have an unambiguous + datetime object, we take this opportunity to determine whether the + datetime is ambiguous and in a "fold" state (e.g. if it's the first + occurence, chronologically, of the ambiguous datetime). + + :param dt: + A timezone-aware :class:`datetime.datetime` object. + """ + + # Re-implement the algorithm from Python's datetime.py + dtoff = dt.utcoffset() + if dtoff is None: + raise ValueError("fromutc() requires a non-None utcoffset() " + "result") + + # The original datetime.py code assumes that `dst()` defaults to + # zero during ambiguous times. PEP 495 inverts this presumption, so + # for pre-PEP 495 versions of python, we need to tweak the algorithm. + dtdst = dt.dst() + if dtdst is None: + raise ValueError("fromutc() requires a non-None dst() result") + delta = dtoff - dtdst + + dt += delta + # Set fold=1 so we can default to being in the fold for + # ambiguous dates. + dtdst = enfold(dt, fold=1).dst() + if dtdst is None: + raise ValueError("fromutc(): dt.dst gave inconsistent " + "results; cannot convert") + return dt + dtdst + + @_validate_fromutc_inputs + def fromutc(self, dt): + """ + Given a timezone-aware datetime in a given timezone, calculates a + timezone-aware datetime in a new timezone. + + Since this is the one time that we *know* we have an unambiguous + datetime object, we take this opportunity to determine whether the + datetime is ambiguous and in a "fold" state (e.g. if it's the first + occurance, chronologically, of the ambiguous datetime). + + :param dt: + A timezone-aware :class:`datetime.datetime` object. + """ + dt_wall = self._fromutc(dt) + + # Calculate the fold status given the two datetimes. + _fold = self._fold_status(dt, dt_wall) + + # Set the default fold value for ambiguous dates + return enfold(dt_wall, fold=_fold) + + +class tzrangebase(_tzinfo): + """ + This is an abstract base class for time zones represented by an annual + transition into and out of DST. Child classes should implement the following + methods: + + * ``__init__(self, *args, **kwargs)`` + * ``transitions(self, year)`` - this is expected to return a tuple of + datetimes representing the DST on and off transitions in standard + time. + + A fully initialized ``tzrangebase`` subclass should also provide the + following attributes: + * ``hasdst``: Boolean whether or not the zone uses DST. + * ``_dst_offset`` / ``_std_offset``: :class:`datetime.timedelta` objects + representing the respective UTC offsets. + * ``_dst_abbr`` / ``_std_abbr``: Strings representing the timezone short + abbreviations in DST and STD, respectively. + * ``_hasdst``: Whether or not the zone has DST. + + .. versionadded:: 2.6.0 + """ + def __init__(self): + raise NotImplementedError('tzrangebase is an abstract base class') + + def utcoffset(self, dt): + isdst = self._isdst(dt) + + if isdst is None: + return None + elif isdst: + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + isdst = self._isdst(dt) + + if isdst is None: + return None + elif isdst: + return self._dst_base_offset + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + if self._isdst(dt): + return self._dst_abbr + else: + return self._std_abbr + + def fromutc(self, dt): + """ Given a datetime in UTC, return local time """ + if not isinstance(dt, datetime): + raise TypeError("fromutc() requires a datetime argument") + + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + # Get transitions - if there are none, fixed offset + transitions = self.transitions(dt.year) + if transitions is None: + return dt + self.utcoffset(dt) + + # Get the transition times in UTC + dston, dstoff = transitions + + dston -= self._std_offset + dstoff -= self._std_offset + + utc_transitions = (dston, dstoff) + dt_utc = dt.replace(tzinfo=None) + + isdst = self._naive_isdst(dt_utc, utc_transitions) + + if isdst: + dt_wall = dt + self._dst_offset + else: + dt_wall = dt + self._std_offset + + _fold = int(not isdst and self.is_ambiguous(dt_wall)) + + return enfold(dt_wall, fold=_fold) + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + if not self.hasdst: + return False + + start, end = self.transitions(dt.year) + + dt = dt.replace(tzinfo=None) + return (end <= dt < end + self._dst_base_offset) + + def _isdst(self, dt): + if not self.hasdst: + return False + elif dt is None: + return None + + transitions = self.transitions(dt.year) + + if transitions is None: + return False + + dt = dt.replace(tzinfo=None) + + isdst = self._naive_isdst(dt, transitions) + + # Handle ambiguous dates + if not isdst and self.is_ambiguous(dt): + return not self._fold(dt) + else: + return isdst + + def _naive_isdst(self, dt, transitions): + dston, dstoff = transitions + + dt = dt.replace(tzinfo=None) + + if dston < dstoff: + isdst = dston <= dt < dstoff + else: + isdst = not dstoff <= dt < dston + + return isdst + + @property + def _dst_base_offset(self): + return self._dst_offset - self._std_offset + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(...)" % self.__class__.__name__ + + __reduce__ = object.__reduce__ diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/_factories.py b/venv/lib/python3.6/site-packages/dateutil/tz/_factories.py new file mode 100644 index 0000000..d2560eb --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/tz/_factories.py @@ -0,0 +1,73 @@ +from datetime import timedelta +import weakref +from collections import OrderedDict + + +class _TzSingleton(type): + def __init__(cls, *args, **kwargs): + cls.__instance = None + super(_TzSingleton, cls).__init__(*args, **kwargs) + + def __call__(cls): + if cls.__instance is None: + cls.__instance = super(_TzSingleton, cls).__call__() + return cls.__instance + + +class _TzFactory(type): + def instance(cls, *args, **kwargs): + """Alternate constructor that returns a fresh instance""" + return type.__call__(cls, *args, **kwargs) + + +class _TzOffsetFactory(_TzFactory): + def __init__(cls, *args, **kwargs): + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + + def __call__(cls, name, offset): + if isinstance(offset, timedelta): + key = (name, offset.total_seconds()) + else: + key = (name, offset) + + instance = cls.__instances.get(key, None) + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(name, offset)) + + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + # Remove an item if the strong cache is overpopulated + # TODO: Maybe this should be under a lock? + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + + return instance + + +class _TzStrFactory(_TzFactory): + def __init__(cls, *args, **kwargs): + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + + def __call__(cls, s, posix_offset=False): + key = (s, posix_offset) + instance = cls.__instances.get(key, None) + + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(s, posix_offset)) + + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + + # Remove an item if the strong cache is overpopulated + # TODO: Maybe this should be under a lock? + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + + return instance + diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/tz.py b/venv/lib/python3.6/site-packages/dateutil/tz/tz.py new file mode 100644 index 0000000..d05414e --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/tz/tz.py @@ -0,0 +1,1836 @@ +# -*- coding: utf-8 -*- +""" +This module offers timezone implementations subclassing the abstract +:py:class:`datetime.tzinfo` type. There are classes to handle tzfile format +files (usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`, +etc), TZ environment string (in all known formats), given ranges (with help +from relative deltas), local machine timezone, fixed offset timezone, and UTC +timezone. +""" +import datetime +import struct +import time +import sys +import os +import bisect +import weakref +from collections import OrderedDict + +import six +from six import string_types +from six.moves import _thread +from ._common import tzname_in_python2, _tzinfo +from ._common import tzrangebase, enfold +from ._common import _validate_fromutc_inputs + +from ._factories import _TzSingleton, _TzOffsetFactory +from ._factories import _TzStrFactory +try: + from .win import tzwin, tzwinlocal +except ImportError: + tzwin = tzwinlocal = None + +# For warning about rounding tzinfo +from warnings import warn + +ZERO = datetime.timedelta(0) +EPOCH = datetime.datetime.utcfromtimestamp(0) +EPOCHORDINAL = EPOCH.toordinal() + + +@six.add_metaclass(_TzSingleton) +class tzutc(datetime.tzinfo): + """ + This is a tzinfo object that represents the UTC time zone. + + **Examples:** + + .. doctest:: + + >>> from datetime import * + >>> from dateutil.tz import * + + >>> datetime.now() + datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) + + >>> datetime.now(tzutc()) + datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) + + >>> datetime.now(tzutc()).tzname() + 'UTC' + + .. versionchanged:: 2.7.0 + ``tzutc()`` is now a singleton, so the result of ``tzutc()`` will + always return the same object. + + .. doctest:: + + >>> from dateutil.tz import tzutc, UTC + >>> tzutc() is tzutc() + True + >>> tzutc() is UTC + True + """ + def utcoffset(self, dt): + return ZERO + + def dst(self, dt): + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return "UTC" + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + return False + + @_validate_fromutc_inputs + def fromutc(self, dt): + """ + Fast track version of fromutc() returns the original ``dt`` object for + any valid :py:class:`datetime.datetime` object. + """ + return dt + + def __eq__(self, other): + if not isinstance(other, (tzutc, tzoffset)): + return NotImplemented + + return (isinstance(other, tzutc) or + (isinstance(other, tzoffset) and other._offset == ZERO)) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + + +@six.add_metaclass(_TzOffsetFactory) +class tzoffset(datetime.tzinfo): + """ + A simple class for representing a fixed offset from UTC. + + :param name: + The timezone name, to be returned when ``tzname()`` is called. + :param offset: + The time zone offset in seconds, or (since version 2.6.0, represented + as a :py:class:`datetime.timedelta` object). + """ + def __init__(self, name, offset): + self._name = name + + try: + # Allow a timedelta + offset = offset.total_seconds() + except (TypeError, AttributeError): + pass + + self._offset = datetime.timedelta(seconds=_get_supported_offset(offset)) + + def utcoffset(self, dt): + return self._offset + + def dst(self, dt): + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._name + + @_validate_fromutc_inputs + def fromutc(self, dt): + return dt + self._offset + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + return False + + def __eq__(self, other): + if not isinstance(other, tzoffset): + return NotImplemented + + return self._offset == other._offset + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(%s, %s)" % (self.__class__.__name__, + repr(self._name), + int(self._offset.total_seconds())) + + __reduce__ = object.__reduce__ + + +class tzlocal(_tzinfo): + """ + A :class:`tzinfo` subclass built around the ``time`` timezone functions. + """ + def __init__(self): + super(tzlocal, self).__init__() + + self._std_offset = datetime.timedelta(seconds=-time.timezone) + if time.daylight: + self._dst_offset = datetime.timedelta(seconds=-time.altzone) + else: + self._dst_offset = self._std_offset + + self._dst_saved = self._dst_offset - self._std_offset + self._hasdst = bool(self._dst_saved) + self._tznames = tuple(time.tzname) + + def utcoffset(self, dt): + if dt is None and self._hasdst: + return None + + if self._isdst(dt): + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + if dt is None and self._hasdst: + return None + + if self._isdst(dt): + return self._dst_offset - self._std_offset + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._tznames[self._isdst(dt)] + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + naive_dst = self._naive_is_dst(dt) + return (not naive_dst and + (naive_dst != self._naive_is_dst(dt - self._dst_saved))) + + def _naive_is_dst(self, dt): + timestamp = _datetime_to_timestamp(dt) + return time.localtime(timestamp + time.timezone).tm_isdst + + def _isdst(self, dt, fold_naive=True): + # We can't use mktime here. It is unstable when deciding if + # the hour near to a change is DST or not. + # + # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, + # dt.minute, dt.second, dt.weekday(), 0, -1)) + # return time.localtime(timestamp).tm_isdst + # + # The code above yields the following result: + # + # >>> import tz, datetime + # >>> t = tz.tzlocal() + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRDT' + # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() + # 'BRST' + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRST' + # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() + # 'BRDT' + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRDT' + # + # Here is a more stable implementation: + # + if not self._hasdst: + return False + + # Check for ambiguous times: + dstval = self._naive_is_dst(dt) + fold = getattr(dt, 'fold', None) + + if self.is_ambiguous(dt): + if fold is not None: + return not self._fold(dt) + else: + return True + + return dstval + + def __eq__(self, other): + if isinstance(other, tzlocal): + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset) + elif isinstance(other, tzutc): + return (not self._hasdst and + self._tznames[0] in {'UTC', 'GMT'} and + self._std_offset == ZERO) + elif isinstance(other, tzoffset): + return (not self._hasdst and + self._tznames[0] == other._name and + self._std_offset == other._offset) + else: + return NotImplemented + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + + +class _ttinfo(object): + __slots__ = ["offset", "delta", "isdst", "abbr", + "isstd", "isgmt", "dstoffset"] + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def __repr__(self): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) + + def __eq__(self, other): + if not isinstance(other, _ttinfo): + return NotImplemented + + return (self.offset == other.offset and + self.delta == other.delta and + self.isdst == other.isdst and + self.abbr == other.abbr and + self.isstd == other.isstd and + self.isgmt == other.isgmt and + self.dstoffset == other.dstoffset) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __getstate__(self): + state = {} + for name in self.__slots__: + state[name] = getattr(self, name, None) + return state + + def __setstate__(self, state): + for name in self.__slots__: + if name in state: + setattr(self, name, state[name]) + + +class _tzfile(object): + """ + Lightweight class for holding the relevant transition and time zone + information read from binary tzfiles. + """ + attrs = ['trans_list', 'trans_list_utc', 'trans_idx', 'ttinfo_list', + 'ttinfo_std', 'ttinfo_dst', 'ttinfo_before', 'ttinfo_first'] + + def __init__(self, **kwargs): + for attr in self.attrs: + setattr(self, attr, kwargs.get(attr, None)) + + +class tzfile(_tzinfo): + """ + This is a ``tzinfo`` subclass thant allows one to use the ``tzfile(5)`` + format timezone files to extract current and historical zone information. + + :param fileobj: + This can be an opened file stream or a file name that the time zone + information can be read from. + + :param filename: + This is an optional parameter specifying the source of the time zone + information in the event that ``fileobj`` is a file object. If omitted + and ``fileobj`` is a file stream, this parameter will be set either to + ``fileobj``'s ``name`` attribute or to ``repr(fileobj)``. + + See `Sources for Time Zone and Daylight Saving Time Data + `_ for more information. + Time zone files can be compiled from the `IANA Time Zone database files + `_ with the `zic time zone compiler + `_ + + .. note:: + + Only construct a ``tzfile`` directly if you have a specific timezone + file on disk that you want to read into a Python ``tzinfo`` object. + If you want to get a ``tzfile`` representing a specific IANA zone, + (e.g. ``'America/New_York'``), you should call + :func:`dateutil.tz.gettz` with the zone identifier. + + + **Examples:** + + Using the US Eastern time zone as an example, we can see that a ``tzfile`` + provides time zone information for the standard Daylight Saving offsets: + + .. testsetup:: tzfile + + from dateutil.tz import gettz + from datetime import datetime + + .. doctest:: tzfile + + >>> NYC = gettz('America/New_York') + >>> NYC + tzfile('/usr/share/zoneinfo/America/New_York') + + >>> print(datetime(2016, 1, 3, tzinfo=NYC)) # EST + 2016-01-03 00:00:00-05:00 + + >>> print(datetime(2016, 7, 7, tzinfo=NYC)) # EDT + 2016-07-07 00:00:00-04:00 + + + The ``tzfile`` structure contains a fully history of the time zone, + so historical dates will also have the right offsets. For example, before + the adoption of the UTC standards, New York used local solar mean time: + + .. doctest:: tzfile + + >>> print(datetime(1901, 4, 12, tzinfo=NYC)) # LMT + 1901-04-12 00:00:00-04:56 + + And during World War II, New York was on "Eastern War Time", which was a + state of permanent daylight saving time: + + .. doctest:: tzfile + + >>> print(datetime(1944, 2, 7, tzinfo=NYC)) # EWT + 1944-02-07 00:00:00-04:00 + + """ + + def __init__(self, fileobj, filename=None): + super(tzfile, self).__init__() + + file_opened_here = False + if isinstance(fileobj, string_types): + self._filename = fileobj + fileobj = open(fileobj, 'rb') + file_opened_here = True + elif filename is not None: + self._filename = filename + elif hasattr(fileobj, "name"): + self._filename = fileobj.name + else: + self._filename = repr(fileobj) + + if fileobj is not None: + if not file_opened_here: + fileobj = _nullcontext(fileobj) + + with fileobj as file_stream: + tzobj = self._read_tzfile(file_stream) + + self._set_tzdata(tzobj) + + def _set_tzdata(self, tzobj): + """ Set the time zone data of this object from a _tzfile object """ + # Copy the relevant attributes over as private attributes + for attr in _tzfile.attrs: + setattr(self, '_' + attr, getattr(tzobj, attr)) + + def _read_tzfile(self, fileobj): + out = _tzfile() + + # From tzfile(5): + # + # The time zone information files used by tzset(3) + # begin with the magic characters "TZif" to identify + # them as time zone information files, followed by + # sixteen bytes reserved for future use, followed by + # six four-byte values of type long, written in a + # ``standard'' byte order (the high-order byte + # of the value is written first). + if fileobj.read(4).decode() != "TZif": + raise ValueError("magic not found") + + fileobj.read(16) + + ( + # The number of UTC/local indicators stored in the file. + ttisgmtcnt, + + # The number of standard/wall indicators stored in the file. + ttisstdcnt, + + # The number of leap seconds for which data is + # stored in the file. + leapcnt, + + # The number of "transition times" for which data + # is stored in the file. + timecnt, + + # The number of "local time types" for which data + # is stored in the file (must not be zero). + typecnt, + + # The number of characters of "time zone + # abbreviation strings" stored in the file. + charcnt, + + ) = struct.unpack(">6l", fileobj.read(24)) + + # The above header is followed by tzh_timecnt four-byte + # values of type long, sorted in ascending order. + # These values are written in ``standard'' byte order. + # Each is used as a transition time (as returned by + # time(2)) at which the rules for computing local time + # change. + + if timecnt: + out.trans_list_utc = list(struct.unpack(">%dl" % timecnt, + fileobj.read(timecnt*4))) + else: + out.trans_list_utc = [] + + # Next come tzh_timecnt one-byte values of type unsigned + # char; each one tells which of the different types of + # ``local time'' types described in the file is associated + # with the same-indexed transition time. These values + # serve as indices into an array of ttinfo structures that + # appears next in the file. + + if timecnt: + out.trans_idx = struct.unpack(">%dB" % timecnt, + fileobj.read(timecnt)) + else: + out.trans_idx = [] + + # Each ttinfo structure is written as a four-byte value + # for tt_gmtoff of type long, in a standard byte + # order, followed by a one-byte value for tt_isdst + # and a one-byte value for tt_abbrind. In each + # structure, tt_gmtoff gives the number of + # seconds to be added to UTC, tt_isdst tells whether + # tm_isdst should be set by localtime(3), and + # tt_abbrind serves as an index into the array of + # time zone abbreviation characters that follow the + # ttinfo structure(s) in the file. + + ttinfo = [] + + for i in range(typecnt): + ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) + + abbr = fileobj.read(charcnt).decode() + + # Then there are tzh_leapcnt pairs of four-byte + # values, written in standard byte order; the + # first value of each pair gives the time (as + # returned by time(2)) at which a leap second + # occurs; the second gives the total number of + # leap seconds to be applied after the given time. + # The pairs of values are sorted in ascending order + # by time. + + # Not used, for now (but seek for correct file position) + if leapcnt: + fileobj.seek(leapcnt * 8, os.SEEK_CUR) + + # Then there are tzh_ttisstdcnt standard/wall + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as standard + # time or wall clock time, and are used when + # a time zone file is used in handling POSIX-style + # time zone environment variables. + + if ttisstdcnt: + isstd = struct.unpack(">%db" % ttisstdcnt, + fileobj.read(ttisstdcnt)) + + # Finally, there are tzh_ttisgmtcnt UTC/local + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as UTC or + # local time, and are used when a time zone file + # is used in handling POSIX-style time zone envi- + # ronment variables. + + if ttisgmtcnt: + isgmt = struct.unpack(">%db" % ttisgmtcnt, + fileobj.read(ttisgmtcnt)) + + # Build ttinfo list + out.ttinfo_list = [] + for i in range(typecnt): + gmtoff, isdst, abbrind = ttinfo[i] + gmtoff = _get_supported_offset(gmtoff) + tti = _ttinfo() + tti.offset = gmtoff + tti.dstoffset = datetime.timedelta(0) + tti.delta = datetime.timedelta(seconds=gmtoff) + tti.isdst = isdst + tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] + tti.isstd = (ttisstdcnt > i and isstd[i] != 0) + tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) + out.ttinfo_list.append(tti) + + # Replace ttinfo indexes for ttinfo objects. + out.trans_idx = [out.ttinfo_list[idx] for idx in out.trans_idx] + + # Set standard, dst, and before ttinfos. before will be + # used when a given time is before any transitions, + # and will be set to the first non-dst ttinfo, or to + # the first dst, if all of them are dst. + out.ttinfo_std = None + out.ttinfo_dst = None + out.ttinfo_before = None + if out.ttinfo_list: + if not out.trans_list_utc: + out.ttinfo_std = out.ttinfo_first = out.ttinfo_list[0] + else: + for i in range(timecnt-1, -1, -1): + tti = out.trans_idx[i] + if not out.ttinfo_std and not tti.isdst: + out.ttinfo_std = tti + elif not out.ttinfo_dst and tti.isdst: + out.ttinfo_dst = tti + + if out.ttinfo_std and out.ttinfo_dst: + break + else: + if out.ttinfo_dst and not out.ttinfo_std: + out.ttinfo_std = out.ttinfo_dst + + for tti in out.ttinfo_list: + if not tti.isdst: + out.ttinfo_before = tti + break + else: + out.ttinfo_before = out.ttinfo_list[0] + + # Now fix transition times to become relative to wall time. + # + # I'm not sure about this. In my tests, the tz source file + # is setup to wall time, and in the binary file isstd and + # isgmt are off, so it should be in wall time. OTOH, it's + # always in gmt time. Let me know if you have comments + # about this. + lastdst = None + lastoffset = None + lastdstoffset = None + lastbaseoffset = None + out.trans_list = [] + + for i, tti in enumerate(out.trans_idx): + offset = tti.offset + dstoffset = 0 + + if lastdst is not None: + if tti.isdst: + if not lastdst: + dstoffset = offset - lastoffset + + if not dstoffset and lastdstoffset: + dstoffset = lastdstoffset + + tti.dstoffset = datetime.timedelta(seconds=dstoffset) + lastdstoffset = dstoffset + + # If a time zone changes its base offset during a DST transition, + # then you need to adjust by the previous base offset to get the + # transition time in local time. Otherwise you use the current + # base offset. Ideally, I would have some mathematical proof of + # why this is true, but I haven't really thought about it enough. + baseoffset = offset - dstoffset + adjustment = baseoffset + if (lastbaseoffset is not None and baseoffset != lastbaseoffset + and tti.isdst != lastdst): + # The base DST has changed + adjustment = lastbaseoffset + + lastdst = tti.isdst + lastoffset = offset + lastbaseoffset = baseoffset + + out.trans_list.append(out.trans_list_utc[i] + adjustment) + + out.trans_idx = tuple(out.trans_idx) + out.trans_list = tuple(out.trans_list) + out.trans_list_utc = tuple(out.trans_list_utc) + + return out + + def _find_last_transition(self, dt, in_utc=False): + # If there's no list, there are no transitions to find + if not self._trans_list: + return None + + timestamp = _datetime_to_timestamp(dt) + + # Find where the timestamp fits in the transition list - if the + # timestamp is a transition time, it's part of the "after" period. + trans_list = self._trans_list_utc if in_utc else self._trans_list + idx = bisect.bisect_right(trans_list, timestamp) + + # We want to know when the previous transition was, so subtract off 1 + return idx - 1 + + def _get_ttinfo(self, idx): + # For no list or after the last transition, default to _ttinfo_std + if idx is None or (idx + 1) >= len(self._trans_list): + return self._ttinfo_std + + # If there is a list and the time is before it, return _ttinfo_before + if idx < 0: + return self._ttinfo_before + + return self._trans_idx[idx] + + def _find_ttinfo(self, dt): + idx = self._resolve_ambiguous_time(dt) + + return self._get_ttinfo(idx) + + def fromutc(self, dt): + """ + The ``tzfile`` implementation of :py:func:`datetime.tzinfo.fromutc`. + + :param dt: + A :py:class:`datetime.datetime` object. + + :raises TypeError: + Raised if ``dt`` is not a :py:class:`datetime.datetime` object. + + :raises ValueError: + Raised if this is called with a ``dt`` which does not have this + ``tzinfo`` attached. + + :return: + Returns a :py:class:`datetime.datetime` object representing the + wall time in ``self``'s time zone. + """ + # These isinstance checks are in datetime.tzinfo, so we'll preserve + # them, even if we don't care about duck typing. + if not isinstance(dt, datetime.datetime): + raise TypeError("fromutc() requires a datetime argument") + + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + # First treat UTC as wall time and get the transition we're in. + idx = self._find_last_transition(dt, in_utc=True) + tti = self._get_ttinfo(idx) + + dt_out = dt + datetime.timedelta(seconds=tti.offset) + + fold = self.is_ambiguous(dt_out, idx=idx) + + return enfold(dt_out, fold=int(fold)) + + def is_ambiguous(self, dt, idx=None): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + if idx is None: + idx = self._find_last_transition(dt) + + # Calculate the difference in offsets from current to previous + timestamp = _datetime_to_timestamp(dt) + tti = self._get_ttinfo(idx) + + if idx is None or idx <= 0: + return False + + od = self._get_ttinfo(idx - 1).offset - tti.offset + tt = self._trans_list[idx] # Transition time + + return timestamp < tt + od + + def _resolve_ambiguous_time(self, dt): + idx = self._find_last_transition(dt) + + # If we have no transitions, return the index + _fold = self._fold(dt) + if idx is None or idx == 0: + return idx + + # If it's ambiguous and we're in a fold, shift to a different index. + idx_offset = int(not _fold and self.is_ambiguous(dt, idx)) + + return idx - idx_offset + + def utcoffset(self, dt): + if dt is None: + return None + + if not self._ttinfo_std: + return ZERO + + return self._find_ttinfo(dt).delta + + def dst(self, dt): + if dt is None: + return None + + if not self._ttinfo_dst: + return ZERO + + tti = self._find_ttinfo(dt) + + if not tti.isdst: + return ZERO + + # The documentation says that utcoffset()-dst() must + # be constant for every dt. + return tti.dstoffset + + @tzname_in_python2 + def tzname(self, dt): + if not self._ttinfo_std or dt is None: + return None + return self._find_ttinfo(dt).abbr + + def __eq__(self, other): + if not isinstance(other, tzfile): + return NotImplemented + return (self._trans_list == other._trans_list and + self._trans_idx == other._trans_idx and + self._ttinfo_list == other._ttinfo_list) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._filename)) + + def __reduce__(self): + return self.__reduce_ex__(None) + + def __reduce_ex__(self, protocol): + return (self.__class__, (None, self._filename), self.__dict__) + + +class tzrange(tzrangebase): + """ + The ``tzrange`` object is a time zone specified by a set of offsets and + abbreviations, equivalent to the way the ``TZ`` variable can be specified + in POSIX-like systems, but using Python delta objects to specify DST + start, end and offsets. + + :param stdabbr: + The abbreviation for standard time (e.g. ``'EST'``). + + :param stdoffset: + An integer or :class:`datetime.timedelta` object or equivalent + specifying the base offset from UTC. + + If unspecified, +00:00 is used. + + :param dstabbr: + The abbreviation for DST / "Summer" time (e.g. ``'EDT'``). + + If specified, with no other DST information, DST is assumed to occur + and the default behavior or ``dstoffset``, ``start`` and ``end`` is + used. If unspecified and no other DST information is specified, it + is assumed that this zone has no DST. + + If this is unspecified and other DST information is *is* specified, + DST occurs in the zone but the time zone abbreviation is left + unchanged. + + :param dstoffset: + A an integer or :class:`datetime.timedelta` object or equivalent + specifying the UTC offset during DST. If unspecified and any other DST + information is specified, it is assumed to be the STD offset +1 hour. + + :param start: + A :class:`relativedelta.relativedelta` object or equivalent specifying + the time and time of year that daylight savings time starts. To + specify, for example, that DST starts at 2AM on the 2nd Sunday in + March, pass: + + ``relativedelta(hours=2, month=3, day=1, weekday=SU(+2))`` + + If unspecified and any other DST information is specified, the default + value is 2 AM on the first Sunday in April. + + :param end: + A :class:`relativedelta.relativedelta` object or equivalent + representing the time and time of year that daylight savings time + ends, with the same specification method as in ``start``. One note is + that this should point to the first time in the *standard* zone, so if + a transition occurs at 2AM in the DST zone and the clocks are set back + 1 hour to 1AM, set the ``hours`` parameter to +1. + + + **Examples:** + + .. testsetup:: tzrange + + from dateutil.tz import tzrange, tzstr + + .. doctest:: tzrange + + >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") + True + + >>> from dateutil.relativedelta import * + >>> range1 = tzrange("EST", -18000, "EDT") + >>> range2 = tzrange("EST", -18000, "EDT", -14400, + ... relativedelta(hours=+2, month=4, day=1, + ... weekday=SU(+1)), + ... relativedelta(hours=+1, month=10, day=31, + ... weekday=SU(-1))) + >>> tzstr('EST5EDT') == range1 == range2 + True + + """ + def __init__(self, stdabbr, stdoffset=None, + dstabbr=None, dstoffset=None, + start=None, end=None): + + global relativedelta + from dateutil import relativedelta + + self._std_abbr = stdabbr + self._dst_abbr = dstabbr + + try: + stdoffset = stdoffset.total_seconds() + except (TypeError, AttributeError): + pass + + try: + dstoffset = dstoffset.total_seconds() + except (TypeError, AttributeError): + pass + + if stdoffset is not None: + self._std_offset = datetime.timedelta(seconds=stdoffset) + else: + self._std_offset = ZERO + + if dstoffset is not None: + self._dst_offset = datetime.timedelta(seconds=dstoffset) + elif dstabbr and stdoffset is not None: + self._dst_offset = self._std_offset + datetime.timedelta(hours=+1) + else: + self._dst_offset = ZERO + + if dstabbr and start is None: + self._start_delta = relativedelta.relativedelta( + hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) + else: + self._start_delta = start + + if dstabbr and end is None: + self._end_delta = relativedelta.relativedelta( + hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) + else: + self._end_delta = end + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = bool(self._start_delta) + + def transitions(self, year): + """ + For a given year, get the DST on and off transition times, expressed + always on the standard time side. For zones with no transitions, this + function returns ``None``. + + :param year: + The year whose transitions you would like to query. + + :return: + Returns a :class:`tuple` of :class:`datetime.datetime` objects, + ``(dston, dstoff)`` for zones with an annual DST transition, or + ``None`` for fixed offset zones. + """ + if not self.hasdst: + return None + + base_year = datetime.datetime(year, 1, 1) + + start = base_year + self._start_delta + end = base_year + self._end_delta + + return (start, end) + + def __eq__(self, other): + if not isinstance(other, tzrange): + return NotImplemented + + return (self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr and + self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._start_delta == other._start_delta and + self._end_delta == other._end_delta) + + @property + def _dst_base_offset(self): + return self._dst_base_offset_ + + +@six.add_metaclass(_TzStrFactory) +class tzstr(tzrange): + """ + ``tzstr`` objects are time zone objects specified by a time-zone string as + it would be passed to a ``TZ`` variable on POSIX-style systems (see + the `GNU C Library: TZ Variable`_ for more details). + + There is one notable exception, which is that POSIX-style time zones use an + inverted offset format, so normally ``GMT+3`` would be parsed as an offset + 3 hours *behind* GMT. The ``tzstr`` time zone object will parse this as an + offset 3 hours *ahead* of GMT. If you would like to maintain the POSIX + behavior, pass a ``True`` value to ``posix_offset``. + + The :class:`tzrange` object provides the same functionality, but is + specified using :class:`relativedelta.relativedelta` objects. rather than + strings. + + :param s: + A time zone string in ``TZ`` variable format. This can be a + :class:`bytes` (2.x: :class:`str`), :class:`str` (2.x: + :class:`unicode`) or a stream emitting unicode characters + (e.g. :class:`StringIO`). + + :param posix_offset: + Optional. If set to ``True``, interpret strings such as ``GMT+3`` or + ``UTC+3`` as being 3 hours *behind* UTC rather than ahead, per the + POSIX standard. + + .. caution:: + + Prior to version 2.7.0, this function also supported time zones + in the format: + + * ``EST5EDT,4,0,6,7200,10,0,26,7200,3600`` + * ``EST5EDT,4,1,0,7200,10,-1,0,7200,3600`` + + This format is non-standard and has been deprecated; this function + will raise a :class:`DeprecatedTZFormatWarning` until + support is removed in a future version. + + .. _`GNU C Library: TZ Variable`: + https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + """ + def __init__(self, s, posix_offset=False): + global parser + from dateutil.parser import _parser as parser + + self._s = s + + res = parser._parsetz(s) + if res is None or res.any_unused_tokens: + raise ValueError("unknown string format") + + # Here we break the compatibility with the TZ variable handling. + # GMT-3 actually *means* the timezone -3. + if res.stdabbr in ("GMT", "UTC") and not posix_offset: + res.stdoffset *= -1 + + # We must initialize it first, since _delta() needs + # _std_offset and _dst_offset set. Use False in start/end + # to avoid building it two times. + tzrange.__init__(self, res.stdabbr, res.stdoffset, + res.dstabbr, res.dstoffset, + start=False, end=False) + + if not res.dstabbr: + self._start_delta = None + self._end_delta = None + else: + self._start_delta = self._delta(res.start) + if self._start_delta: + self._end_delta = self._delta(res.end, isend=1) + + self.hasdst = bool(self._start_delta) + + def _delta(self, x, isend=0): + from dateutil import relativedelta + kwargs = {} + if x.month is not None: + kwargs["month"] = x.month + if x.weekday is not None: + kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) + if x.week > 0: + kwargs["day"] = 1 + else: + kwargs["day"] = 31 + elif x.day: + kwargs["day"] = x.day + elif x.yday is not None: + kwargs["yearday"] = x.yday + elif x.jyday is not None: + kwargs["nlyearday"] = x.jyday + if not kwargs: + # Default is to start on first sunday of april, and end + # on last sunday of october. + if not isend: + kwargs["month"] = 4 + kwargs["day"] = 1 + kwargs["weekday"] = relativedelta.SU(+1) + else: + kwargs["month"] = 10 + kwargs["day"] = 31 + kwargs["weekday"] = relativedelta.SU(-1) + if x.time is not None: + kwargs["seconds"] = x.time + else: + # Default is 2AM. + kwargs["seconds"] = 7200 + if isend: + # Convert to standard time, to follow the documented way + # of working with the extra hour. See the documentation + # of the tzinfo class. + delta = self._dst_offset - self._std_offset + kwargs["seconds"] -= delta.seconds + delta.days * 86400 + return relativedelta.relativedelta(**kwargs) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._s)) + + +class _tzicalvtzcomp(object): + def __init__(self, tzoffsetfrom, tzoffsetto, isdst, + tzname=None, rrule=None): + self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) + self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) + self.tzoffsetdiff = self.tzoffsetto - self.tzoffsetfrom + self.isdst = isdst + self.tzname = tzname + self.rrule = rrule + + +class _tzicalvtz(_tzinfo): + def __init__(self, tzid, comps=[]): + super(_tzicalvtz, self).__init__() + + self._tzid = tzid + self._comps = comps + self._cachedate = [] + self._cachecomp = [] + self._cache_lock = _thread.allocate_lock() + + def _find_comp(self, dt): + if len(self._comps) == 1: + return self._comps[0] + + dt = dt.replace(tzinfo=None) + + try: + with self._cache_lock: + return self._cachecomp[self._cachedate.index( + (dt, self._fold(dt)))] + except ValueError: + pass + + lastcompdt = None + lastcomp = None + + for comp in self._comps: + compdt = self._find_compdt(comp, dt) + + if compdt and (not lastcompdt or lastcompdt < compdt): + lastcompdt = compdt + lastcomp = comp + + if not lastcomp: + # RFC says nothing about what to do when a given + # time is before the first onset date. We'll look for the + # first standard component, or the first component, if + # none is found. + for comp in self._comps: + if not comp.isdst: + lastcomp = comp + break + else: + lastcomp = comp[0] + + with self._cache_lock: + self._cachedate.insert(0, (dt, self._fold(dt))) + self._cachecomp.insert(0, lastcomp) + + if len(self._cachedate) > 10: + self._cachedate.pop() + self._cachecomp.pop() + + return lastcomp + + def _find_compdt(self, comp, dt): + if comp.tzoffsetdiff < ZERO and self._fold(dt): + dt -= comp.tzoffsetdiff + + compdt = comp.rrule.before(dt, inc=True) + + return compdt + + def utcoffset(self, dt): + if dt is None: + return None + + return self._find_comp(dt).tzoffsetto + + def dst(self, dt): + comp = self._find_comp(dt) + if comp.isdst: + return comp.tzoffsetdiff + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._find_comp(dt).tzname + + def __repr__(self): + return "" % repr(self._tzid) + + __reduce__ = object.__reduce__ + + +class tzical(object): + """ + This object is designed to parse an iCalendar-style ``VTIMEZONE`` structure + as set out in `RFC 5545`_ Section 4.6.5 into one or more `tzinfo` objects. + + :param `fileobj`: + A file or stream in iCalendar format, which should be UTF-8 encoded + with CRLF endings. + + .. _`RFC 5545`: https://tools.ietf.org/html/rfc5545 + """ + def __init__(self, fileobj): + global rrule + from dateutil import rrule + + if isinstance(fileobj, string_types): + self._s = fileobj + # ical should be encoded in UTF-8 with CRLF + fileobj = open(fileobj, 'r') + else: + self._s = getattr(fileobj, 'name', repr(fileobj)) + fileobj = _nullcontext(fileobj) + + self._vtz = {} + + with fileobj as fobj: + self._parse_rfc(fobj.read()) + + def keys(self): + """ + Retrieves the available time zones as a list. + """ + return list(self._vtz.keys()) + + def get(self, tzid=None): + """ + Retrieve a :py:class:`datetime.tzinfo` object by its ``tzid``. + + :param tzid: + If there is exactly one time zone available, omitting ``tzid`` + or passing :py:const:`None` value returns it. Otherwise a valid + key (which can be retrieved from :func:`keys`) is required. + + :raises ValueError: + Raised if ``tzid`` is not specified but there are either more + or fewer than 1 zone defined. + + :returns: + Returns either a :py:class:`datetime.tzinfo` object representing + the relevant time zone or :py:const:`None` if the ``tzid`` was + not found. + """ + if tzid is None: + if len(self._vtz) == 0: + raise ValueError("no timezones defined") + elif len(self._vtz) > 1: + raise ValueError("more than one timezone available") + tzid = next(iter(self._vtz)) + + return self._vtz.get(tzid) + + def _parse_offset(self, s): + s = s.strip() + if not s: + raise ValueError("empty offset") + if s[0] in ('+', '-'): + signal = (-1, +1)[s[0] == '+'] + s = s[1:] + else: + signal = +1 + if len(s) == 4: + return (int(s[:2]) * 3600 + int(s[2:]) * 60) * signal + elif len(s) == 6: + return (int(s[:2]) * 3600 + int(s[2:4]) * 60 + int(s[4:])) * signal + else: + raise ValueError("invalid offset: " + s) + + def _parse_rfc(self, s): + lines = s.splitlines() + if not lines: + raise ValueError("empty string") + + # Unfold + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + + tzid = None + comps = [] + invtz = False + comptype = None + for line in lines: + if not line: + continue + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError("empty property name") + name = parms[0].upper() + parms = parms[1:] + if invtz: + if name == "BEGIN": + if value in ("STANDARD", "DAYLIGHT"): + # Process component + pass + else: + raise ValueError("unknown component: "+value) + comptype = value + founddtstart = False + tzoffsetfrom = None + tzoffsetto = None + rrulelines = [] + tzname = None + elif name == "END": + if value == "VTIMEZONE": + if comptype: + raise ValueError("component not closed: "+comptype) + if not tzid: + raise ValueError("mandatory TZID not found") + if not comps: + raise ValueError( + "at least one component is needed") + # Process vtimezone + self._vtz[tzid] = _tzicalvtz(tzid, comps) + invtz = False + elif value == comptype: + if not founddtstart: + raise ValueError("mandatory DTSTART not found") + if tzoffsetfrom is None: + raise ValueError( + "mandatory TZOFFSETFROM not found") + if tzoffsetto is None: + raise ValueError( + "mandatory TZOFFSETFROM not found") + # Process component + rr = None + if rrulelines: + rr = rrule.rrulestr("\n".join(rrulelines), + compatible=True, + ignoretz=True, + cache=True) + comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, + (comptype == "DAYLIGHT"), + tzname, rr) + comps.append(comp) + comptype = None + else: + raise ValueError("invalid component end: "+value) + elif comptype: + if name == "DTSTART": + # DTSTART in VTIMEZONE takes a subset of valid RRULE + # values under RFC 5545. + for parm in parms: + if parm != 'VALUE=DATE-TIME': + msg = ('Unsupported DTSTART param in ' + + 'VTIMEZONE: ' + parm) + raise ValueError(msg) + rrulelines.append(line) + founddtstart = True + elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): + rrulelines.append(line) + elif name == "TZOFFSETFROM": + if parms: + raise ValueError( + "unsupported %s parm: %s " % (name, parms[0])) + tzoffsetfrom = self._parse_offset(value) + elif name == "TZOFFSETTO": + if parms: + raise ValueError( + "unsupported TZOFFSETTO parm: "+parms[0]) + tzoffsetto = self._parse_offset(value) + elif name == "TZNAME": + if parms: + raise ValueError( + "unsupported TZNAME parm: "+parms[0]) + tzname = value + elif name == "COMMENT": + pass + else: + raise ValueError("unsupported property: "+name) + else: + if name == "TZID": + if parms: + raise ValueError( + "unsupported TZID parm: "+parms[0]) + tzid = value + elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): + pass + else: + raise ValueError("unsupported property: "+name) + elif name == "BEGIN" and value == "VTIMEZONE": + tzid = None + comps = [] + invtz = True + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._s)) + + +if sys.platform != "win32": + TZFILES = ["/etc/localtime", "localtime"] + TZPATHS = ["/usr/share/zoneinfo", + "/usr/lib/zoneinfo", + "/usr/share/lib/zoneinfo", + "/etc/zoneinfo"] +else: + TZFILES = [] + TZPATHS = [] + + +def __get_gettz(): + tzlocal_classes = (tzlocal,) + if tzwinlocal is not None: + tzlocal_classes += (tzwinlocal,) + + class GettzFunc(object): + """ + Retrieve a time zone object from a string representation + + This function is intended to retrieve the :py:class:`tzinfo` subclass + that best represents the time zone that would be used if a POSIX + `TZ variable`_ were set to the same value. + + If no argument or an empty string is passed to ``gettz``, local time + is returned: + + .. code-block:: python3 + + >>> gettz() + tzfile('/etc/localtime') + + This function is also the preferred way to map IANA tz database keys + to :class:`tzfile` objects: + + .. code-block:: python3 + + >>> gettz('Pacific/Kiritimati') + tzfile('/usr/share/zoneinfo/Pacific/Kiritimati') + + On Windows, the standard is extended to include the Windows-specific + zone names provided by the operating system: + + .. code-block:: python3 + + >>> gettz('Egypt Standard Time') + tzwin('Egypt Standard Time') + + Passing a GNU ``TZ`` style string time zone specification returns a + :class:`tzstr` object: + + .. code-block:: python3 + + >>> gettz('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') + tzstr('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') + + :param name: + A time zone name (IANA, or, on Windows, Windows keys), location of + a ``tzfile(5)`` zoneinfo file or ``TZ`` variable style time zone + specifier. An empty string, no argument or ``None`` is interpreted + as local time. + + :return: + Returns an instance of one of ``dateutil``'s :py:class:`tzinfo` + subclasses. + + .. versionchanged:: 2.7.0 + + After version 2.7.0, any two calls to ``gettz`` using the same + input strings will return the same object: + + .. code-block:: python3 + + >>> tz.gettz('America/Chicago') is tz.gettz('America/Chicago') + True + + In addition to improving performance, this ensures that + `"same zone" semantics`_ are used for datetimes in the same zone. + + + .. _`TZ variable`: + https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + + .. _`"same zone" semantics`: + https://blog.ganssle.io/articles/2018/02/aware-datetime-arithmetic.html + """ + def __init__(self): + + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache_size = 8 + self.__strong_cache = OrderedDict() + self._cache_lock = _thread.allocate_lock() + + def __call__(self, name=None): + with self._cache_lock: + rv = self.__instances.get(name, None) + + if rv is None: + rv = self.nocache(name=name) + if not (name is None + or isinstance(rv, tzlocal_classes) + or rv is None): + # tzlocal is slightly more complicated than the other + # time zone providers because it depends on environment + # at construction time, so don't cache that. + # + # We also cannot store weak references to None, so we + # will also not store that. + self.__instances[name] = rv + else: + # No need for strong caching, return immediately + return rv + + self.__strong_cache[name] = self.__strong_cache.pop(name, rv) + + if len(self.__strong_cache) > self.__strong_cache_size: + self.__strong_cache.popitem(last=False) + + return rv + + def set_cache_size(self, size): + with self._cache_lock: + self.__strong_cache_size = size + while len(self.__strong_cache) > size: + self.__strong_cache.popitem(last=False) + + def cache_clear(self): + with self._cache_lock: + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache.clear() + + @staticmethod + def nocache(name=None): + """A non-cached version of gettz""" + tz = None + if not name: + try: + name = os.environ["TZ"] + except KeyError: + pass + if name is None or name == ":": + for filepath in TZFILES: + if not os.path.isabs(filepath): + filename = filepath + for path in TZPATHS: + filepath = os.path.join(path, filename) + if os.path.isfile(filepath): + break + else: + continue + if os.path.isfile(filepath): + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = tzlocal() + else: + if name.startswith(":"): + name = name[1:] + if os.path.isabs(name): + if os.path.isfile(name): + tz = tzfile(name) + else: + tz = None + else: + for path in TZPATHS: + filepath = os.path.join(path, name) + if not os.path.isfile(filepath): + filepath = filepath.replace(' ', '_') + if not os.path.isfile(filepath): + continue + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = None + if tzwin is not None: + try: + tz = tzwin(name) + except (WindowsError, UnicodeEncodeError): + # UnicodeEncodeError is for Python 2.7 compat + tz = None + + if not tz: + from dateutil.zoneinfo import get_zonefile_instance + tz = get_zonefile_instance().get(name) + + if not tz: + for c in name: + # name is not a tzstr unless it has at least + # one offset. For short values of "name", an + # explicit for loop seems to be the fastest way + # To determine if a string contains a digit + if c in "0123456789": + try: + tz = tzstr(name) + except ValueError: + pass + break + else: + if name in ("GMT", "UTC"): + tz = tzutc() + elif name in time.tzname: + tz = tzlocal() + return tz + + return GettzFunc() + + +gettz = __get_gettz() +del __get_gettz + + +def datetime_exists(dt, tz=None): + """ + Given a datetime and a time zone, determine whether or not a given datetime + would fall in a gap. + + :param dt: + A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` + is provided.) + + :param tz: + A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If + ``None`` or not provided, the datetime's own time zone will be used. + + :return: + Returns a boolean value whether or not the "wall time" exists in + ``tz``. + + .. versionadded:: 2.7.0 + """ + if tz is None: + if dt.tzinfo is None: + raise ValueError('Datetime is naive and no time zone provided.') + tz = dt.tzinfo + + dt = dt.replace(tzinfo=None) + + # This is essentially a test of whether or not the datetime can survive + # a round trip to UTC. + dt_rt = dt.replace(tzinfo=tz).astimezone(tzutc()).astimezone(tz) + dt_rt = dt_rt.replace(tzinfo=None) + + return dt == dt_rt + + +def datetime_ambiguous(dt, tz=None): + """ + Given a datetime and a time zone, determine whether or not a given datetime + is ambiguous (i.e if there are two times differentiated only by their DST + status). + + :param dt: + A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` + is provided.) + + :param tz: + A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If + ``None`` or not provided, the datetime's own time zone will be used. + + :return: + Returns a boolean value whether or not the "wall time" is ambiguous in + ``tz``. + + .. versionadded:: 2.6.0 + """ + if tz is None: + if dt.tzinfo is None: + raise ValueError('Datetime is naive and no time zone provided.') + + tz = dt.tzinfo + + # If a time zone defines its own "is_ambiguous" function, we'll use that. + is_ambiguous_fn = getattr(tz, 'is_ambiguous', None) + if is_ambiguous_fn is not None: + try: + return tz.is_ambiguous(dt) + except Exception: + pass + + # If it doesn't come out and tell us it's ambiguous, we'll just check if + # the fold attribute has any effect on this particular date and time. + dt = dt.replace(tzinfo=tz) + wall_0 = enfold(dt, fold=0) + wall_1 = enfold(dt, fold=1) + + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + same_dst = wall_0.dst() == wall_1.dst() + + return not (same_offset and same_dst) + + +def resolve_imaginary(dt): + """ + Given a datetime that may be imaginary, return an existing datetime. + + This function assumes that an imaginary datetime represents what the + wall time would be in a zone had the offset transition not occurred, so + it will always fall forward by the transition's change in offset. + + .. doctest:: + + >>> from dateutil import tz + >>> from datetime import datetime + >>> NYC = tz.gettz('America/New_York') + >>> print(tz.resolve_imaginary(datetime(2017, 3, 12, 2, 30, tzinfo=NYC))) + 2017-03-12 03:30:00-04:00 + + >>> KIR = tz.gettz('Pacific/Kiritimati') + >>> print(tz.resolve_imaginary(datetime(1995, 1, 1, 12, 30, tzinfo=KIR))) + 1995-01-02 12:30:00+14:00 + + As a note, :func:`datetime.astimezone` is guaranteed to produce a valid, + existing datetime, so a round-trip to and from UTC is sufficient to get + an extant datetime, however, this generally "falls back" to an earlier time + rather than falling forward to the STD side (though no guarantees are made + about this behavior). + + :param dt: + A :class:`datetime.datetime` which may or may not exist. + + :return: + Returns an existing :class:`datetime.datetime`. If ``dt`` was not + imaginary, the datetime returned is guaranteed to be the same object + passed to the function. + + .. versionadded:: 2.7.0 + """ + if dt.tzinfo is not None and not datetime_exists(dt): + + curr_offset = (dt + datetime.timedelta(hours=24)).utcoffset() + old_offset = (dt - datetime.timedelta(hours=24)).utcoffset() + + dt += curr_offset - old_offset + + return dt + + +def _datetime_to_timestamp(dt): + """ + Convert a :class:`datetime.datetime` object to an epoch timestamp in + seconds since January 1, 1970, ignoring the time zone. + """ + return (dt.replace(tzinfo=None) - EPOCH).total_seconds() + + +if sys.version_info >= (3, 6): + def _get_supported_offset(second_offset): + return second_offset +else: + def _get_supported_offset(second_offset): + # For python pre-3.6, round to full-minutes if that's not the case. + # Python's datetime doesn't accept sub-minute timezones. Check + # http://python.org/sf/1447945 or https://bugs.python.org/issue5288 + # for some information. + old_offset = second_offset + calculated_offset = 60 * ((second_offset + 30) // 60) + return calculated_offset + + +try: + # Python 3.7 feature + from contextmanager import nullcontext as _nullcontext +except ImportError: + class _nullcontext(object): + """ + Class for wrapping contexts so that they are passed through in a + with statement. + """ + def __init__(self, context): + self.context = context + + def __enter__(self): + return self.context + + def __exit__(*args, **kwargs): + pass + +# vim:ts=4:sw=4:et diff --git a/venv/lib/python3.6/site-packages/dateutil/tz/win.py b/venv/lib/python3.6/site-packages/dateutil/tz/win.py new file mode 100644 index 0000000..cde07ba --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/tz/win.py @@ -0,0 +1,370 @@ +# -*- coding: utf-8 -*- +""" +This module provides an interface to the native time zone data on Windows, +including :py:class:`datetime.tzinfo` implementations. + +Attempting to import this module on a non-Windows platform will raise an +:py:obj:`ImportError`. +""" +# This code was originally contributed by Jeffrey Harris. +import datetime +import struct + +from six.moves import winreg +from six import text_type + +try: + import ctypes + from ctypes import wintypes +except ValueError: + # ValueError is raised on non-Windows systems for some horrible reason. + raise ImportError("Running tzwin on non-Windows system") + +from ._common import tzrangebase + +__all__ = ["tzwin", "tzwinlocal", "tzres"] + +ONEWEEK = datetime.timedelta(7) + +TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" +TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" +TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" + + +def _settzkeyname(): + handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + winreg.OpenKey(handle, TZKEYNAMENT).Close() + TZKEYNAME = TZKEYNAMENT + except WindowsError: + TZKEYNAME = TZKEYNAME9X + handle.Close() + return TZKEYNAME + + +TZKEYNAME = _settzkeyname() + + +class tzres(object): + """ + Class for accessing ``tzres.dll``, which contains timezone name related + resources. + + .. versionadded:: 2.5.0 + """ + p_wchar = ctypes.POINTER(wintypes.WCHAR) # Pointer to a wide char + + def __init__(self, tzres_loc='tzres.dll'): + # Load the user32 DLL so we can load strings from tzres + user32 = ctypes.WinDLL('user32') + + # Specify the LoadStringW function + user32.LoadStringW.argtypes = (wintypes.HINSTANCE, + wintypes.UINT, + wintypes.LPWSTR, + ctypes.c_int) + + self.LoadStringW = user32.LoadStringW + self._tzres = ctypes.WinDLL(tzres_loc) + self.tzres_loc = tzres_loc + + def load_name(self, offset): + """ + Load a timezone name from a DLL offset (integer). + + >>> from dateutil.tzwin import tzres + >>> tzr = tzres() + >>> print(tzr.load_name(112)) + 'Eastern Standard Time' + + :param offset: + A positive integer value referring to a string from the tzres dll. + + .. note:: + + Offsets found in the registry are generally of the form + ``@tzres.dll,-114``. The offset in this case is 114, not -114. + + """ + resource = self.p_wchar() + lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR) + nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0) + return resource[:nchar] + + def name_from_string(self, tzname_str): + """ + Parse strings as returned from the Windows registry into the time zone + name as defined in the registry. + + >>> from dateutil.tzwin import tzres + >>> tzr = tzres() + >>> print(tzr.name_from_string('@tzres.dll,-251')) + 'Dateline Daylight Time' + >>> print(tzr.name_from_string('Eastern Standard Time')) + 'Eastern Standard Time' + + :param tzname_str: + A timezone name string as returned from a Windows registry key. + + :return: + Returns the localized timezone string from tzres.dll if the string + is of the form `@tzres.dll,-offset`, else returns the input string. + """ + if not tzname_str.startswith('@'): + return tzname_str + + name_splt = tzname_str.split(',-') + try: + offset = int(name_splt[1]) + except: + raise ValueError("Malformed timezone string.") + + return self.load_name(offset) + + +class tzwinbase(tzrangebase): + """tzinfo class based on win32's timezones available in the registry.""" + def __init__(self): + raise NotImplementedError('tzwinbase is an abstract base class') + + def __eq__(self, other): + # Compare on all relevant dimensions, including name. + if not isinstance(other, tzwinbase): + return NotImplemented + + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._stddayofweek == other._stddayofweek and + self._dstdayofweek == other._dstdayofweek and + self._stdweeknumber == other._stdweeknumber and + self._dstweeknumber == other._dstweeknumber and + self._stdhour == other._stdhour and + self._dsthour == other._dsthour and + self._stdminute == other._stdminute and + self._dstminute == other._dstminute and + self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr) + + @staticmethod + def list(): + """Return a list of all time zones known to the system.""" + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + with winreg.OpenKey(handle, TZKEYNAME) as tzkey: + result = [winreg.EnumKey(tzkey, i) + for i in range(winreg.QueryInfoKey(tzkey)[0])] + return result + + def display(self): + """ + Return the display name of the time zone. + """ + return self._display + + def transitions(self, year): + """ + For a given year, get the DST on and off transition times, expressed + always on the standard time side. For zones with no transitions, this + function returns ``None``. + + :param year: + The year whose transitions you would like to query. + + :return: + Returns a :class:`tuple` of :class:`datetime.datetime` objects, + ``(dston, dstoff)`` for zones with an annual DST transition, or + ``None`` for fixed offset zones. + """ + + if not self.hasdst: + return None + + dston = picknthweekday(year, self._dstmonth, self._dstdayofweek, + self._dsthour, self._dstminute, + self._dstweeknumber) + + dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek, + self._stdhour, self._stdminute, + self._stdweeknumber) + + # Ambiguous dates default to the STD side + dstoff -= self._dst_base_offset + + return dston, dstoff + + def _get_hasdst(self): + return self._dstmonth != 0 + + @property + def _dst_base_offset(self): + return self._dst_base_offset_ + + +class tzwin(tzwinbase): + """ + Time zone object created from the zone info in the Windows registry + + These are similar to :py:class:`dateutil.tz.tzrange` objects in that + the time zone data is provided in the format of a single offset rule + for either 0 or 2 time zone transitions per year. + + :param: name + The name of a Windows time zone key, e.g. "Eastern Standard Time". + The full list of keys can be retrieved with :func:`tzwin.list`. + """ + + def __init__(self, name): + self._name = name + + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + tzkeyname = text_type("{kn}\\{name}").format(kn=TZKEYNAME, name=name) + with winreg.OpenKey(handle, tzkeyname) as tzkey: + keydict = valuestodict(tzkey) + + self._std_abbr = keydict["Std"] + self._dst_abbr = keydict["Dlt"] + + self._display = keydict["Display"] + + # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm + tup = struct.unpack("=3l16h", keydict["TZI"]) + stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 + dstoffset = stdoffset-tup[2] # + DaylightBias * -1 + self._std_offset = datetime.timedelta(minutes=stdoffset) + self._dst_offset = datetime.timedelta(minutes=dstoffset) + + # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx + (self._stdmonth, + self._stddayofweek, # Sunday = 0 + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[4:9] + + (self._dstmonth, + self._dstdayofweek, # Sunday = 0 + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[12:17] + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = self._get_hasdst() + + def __repr__(self): + return "tzwin(%s)" % repr(self._name) + + def __reduce__(self): + return (self.__class__, (self._name,)) + + +class tzwinlocal(tzwinbase): + """ + Class representing the local time zone information in the Windows registry + + While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time` + module) to retrieve time zone information, ``tzwinlocal`` retrieves the + rules directly from the Windows registry and creates an object like + :class:`dateutil.tz.tzwin`. + + Because Windows does not have an equivalent of :func:`time.tzset`, on + Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the + time zone settings *at the time that the process was started*, meaning + changes to the machine's time zone settings during the run of a program + on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`. + Because ``tzwinlocal`` reads the registry directly, it is unaffected by + this issue. + """ + def __init__(self): + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: + keydict = valuestodict(tzlocalkey) + + self._std_abbr = keydict["StandardName"] + self._dst_abbr = keydict["DaylightName"] + + try: + tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME, + sn=self._std_abbr) + with winreg.OpenKey(handle, tzkeyname) as tzkey: + _keydict = valuestodict(tzkey) + self._display = _keydict["Display"] + except OSError: + self._display = None + + stdoffset = -keydict["Bias"]-keydict["StandardBias"] + dstoffset = stdoffset-keydict["DaylightBias"] + + self._std_offset = datetime.timedelta(minutes=stdoffset) + self._dst_offset = datetime.timedelta(minutes=dstoffset) + + # For reasons unclear, in this particular key, the day of week has been + # moved to the END of the SYSTEMTIME structure. + tup = struct.unpack("=8h", keydict["StandardStart"]) + + (self._stdmonth, + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[1:5] + + self._stddayofweek = tup[7] + + tup = struct.unpack("=8h", keydict["DaylightStart"]) + + (self._dstmonth, + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[1:5] + + self._dstdayofweek = tup[7] + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = self._get_hasdst() + + def __repr__(self): + return "tzwinlocal()" + + def __str__(self): + # str will return the standard name, not the daylight name. + return "tzwinlocal(%s)" % repr(self._std_abbr) + + def __reduce__(self): + return (self.__class__, ()) + + +def picknthweekday(year, month, dayofweek, hour, minute, whichweek): + """ dayofweek == 0 means Sunday, whichweek 5 means last instance """ + first = datetime.datetime(year, month, 1, hour, minute) + + # This will work if dayofweek is ISO weekday (1-7) or Microsoft-style (0-6), + # Because 7 % 7 = 0 + weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7) + 1) + wd = weekdayone + ((whichweek - 1) * ONEWEEK) + if (wd.month != month): + wd -= ONEWEEK + + return wd + + +def valuestodict(key): + """Convert a registry key's values to a dictionary.""" + dout = {} + size = winreg.QueryInfoKey(key)[1] + tz_res = None + + for i in range(size): + key_name, value, dtype = winreg.EnumValue(key, i) + if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN: + # If it's a DWORD (32-bit integer), it's stored as unsigned - convert + # that to a proper signed integer + if value & (1 << 31): + value = value - (1 << 32) + elif dtype == winreg.REG_SZ: + # If it's a reference to the tzres DLL, load the actual string + if value.startswith('@tzres'): + tz_res = tz_res or tzres() + value = tz_res.name_from_string(value) + + value = value.rstrip('\x00') # Remove trailing nulls + + dout[key_name] = value + + return dout diff --git a/venv/lib/python3.6/site-packages/dateutil/tzwin.py b/venv/lib/python3.6/site-packages/dateutil/tzwin.py new file mode 100644 index 0000000..cebc673 --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/tzwin.py @@ -0,0 +1,2 @@ +# tzwin has moved to dateutil.tz.win +from .tz.win import * diff --git a/venv/lib/python3.6/site-packages/dateutil/utils.py b/venv/lib/python3.6/site-packages/dateutil/utils.py new file mode 100644 index 0000000..ebcce6a --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/utils.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" +This module offers general convenience and utility functions for dealing with +datetimes. + +.. versionadded:: 2.7.0 +""" +from __future__ import unicode_literals + +from datetime import datetime, time + + +def today(tzinfo=None): + """ + Returns a :py:class:`datetime` representing the current day at midnight + + :param tzinfo: + The time zone to attach (also used to determine the current day). + + :return: + A :py:class:`datetime.datetime` object representing the current day + at midnight. + """ + + dt = datetime.now(tzinfo) + return datetime.combine(dt.date(), time(0, tzinfo=tzinfo)) + + +def default_tzinfo(dt, tzinfo): + """ + Sets the the ``tzinfo`` parameter on naive datetimes only + + This is useful for example when you are provided a datetime that may have + either an implicit or explicit time zone, such as when parsing a time zone + string. + + .. doctest:: + + >>> from dateutil.tz import tzoffset + >>> from dateutil.parser import parse + >>> from dateutil.utils import default_tzinfo + >>> dflt_tz = tzoffset("EST", -18000) + >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz)) + 2014-01-01 12:30:00+00:00 + >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz)) + 2014-01-01 12:30:00-05:00 + + :param dt: + The datetime on which to replace the time zone + + :param tzinfo: + The :py:class:`datetime.tzinfo` subclass instance to assign to + ``dt`` if (and only if) it is naive. + + :return: + Returns an aware :py:class:`datetime.datetime`. + """ + if dt.tzinfo is not None: + return dt + else: + return dt.replace(tzinfo=tzinfo) + + +def within_delta(dt1, dt2, delta): + """ + Useful for comparing two datetimes that may a negilible difference + to be considered equal. + """ + delta = abs(delta) + difference = dt1 - dt2 + return -delta <= difference <= delta diff --git a/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__init__.py b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__init__.py new file mode 100644 index 0000000..34f11ad --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__init__.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +import warnings +import json + +from tarfile import TarFile +from pkgutil import get_data +from io import BytesIO + +from dateutil.tz import tzfile as _tzfile + +__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata"] + +ZONEFILENAME = "dateutil-zoneinfo.tar.gz" +METADATA_FN = 'METADATA' + + +class tzfile(_tzfile): + def __reduce__(self): + return (gettz, (self._filename,)) + + +def getzoneinfofile_stream(): + try: + return BytesIO(get_data(__name__, ZONEFILENAME)) + except IOError as e: # TODO switch to FileNotFoundError? + warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) + return None + + +class ZoneInfoFile(object): + def __init__(self, zonefile_stream=None): + if zonefile_stream is not None: + with TarFile.open(fileobj=zonefile_stream) as tf: + self.zones = {zf.name: tzfile(tf.extractfile(zf), filename=zf.name) + for zf in tf.getmembers() + if zf.isfile() and zf.name != METADATA_FN} + # deal with links: They'll point to their parent object. Less + # waste of memory + links = {zl.name: self.zones[zl.linkname] + for zl in tf.getmembers() if + zl.islnk() or zl.issym()} + self.zones.update(links) + try: + metadata_json = tf.extractfile(tf.getmember(METADATA_FN)) + metadata_str = metadata_json.read().decode('UTF-8') + self.metadata = json.loads(metadata_str) + except KeyError: + # no metadata in tar file + self.metadata = None + else: + self.zones = {} + self.metadata = None + + def get(self, name, default=None): + """ + Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method + for retrieving zones from the zone dictionary. + + :param name: + The name of the zone to retrieve. (Generally IANA zone names) + + :param default: + The value to return in the event of a missing key. + + .. versionadded:: 2.6.0 + + """ + return self.zones.get(name, default) + + +# The current API has gettz as a module function, although in fact it taps into +# a stateful class. So as a workaround for now, without changing the API, we +# will create a new "global" class instance the first time a user requests a +# timezone. Ugly, but adheres to the api. +# +# TODO: Remove after deprecation period. +_CLASS_ZONE_INSTANCE = [] + + +def get_zonefile_instance(new_instance=False): + """ + This is a convenience function which provides a :class:`ZoneInfoFile` + instance using the data provided by the ``dateutil`` package. By default, it + caches a single instance of the ZoneInfoFile object and returns that. + + :param new_instance: + If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and + used as the cached instance for the next call. Otherwise, new instances + are created only as necessary. + + :return: + Returns a :class:`ZoneInfoFile` object. + + .. versionadded:: 2.6 + """ + if new_instance: + zif = None + else: + zif = getattr(get_zonefile_instance, '_cached_instance', None) + + if zif is None: + zif = ZoneInfoFile(getzoneinfofile_stream()) + + get_zonefile_instance._cached_instance = zif + + return zif + + +def gettz(name): + """ + This retrieves a time zone from the local zoneinfo tarball that is packaged + with dateutil. + + :param name: + An IANA-style time zone name, as found in the zoneinfo file. + + :return: + Returns a :class:`dateutil.tz.tzfile` time zone object. + + .. warning:: + It is generally inadvisable to use this function, and it is only + provided for API compatibility with earlier versions. This is *not* + equivalent to ``dateutil.tz.gettz()``, which selects an appropriate + time zone based on the inputs, favoring system zoneinfo. This is ONLY + for accessing the dateutil-specific zoneinfo (which may be out of + date compared to the system zoneinfo). + + .. deprecated:: 2.6 + If you need to use a specific zoneinfofile over the system zoneinfo, + instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call + :func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead. + + Use :func:`get_zonefile_instance` to retrieve an instance of the + dateutil-provided zoneinfo. + """ + warnings.warn("zoneinfo.gettz() will be removed in future versions, " + "to use the dateutil-provided zoneinfo files, instantiate a " + "ZoneInfoFile object and use ZoneInfoFile.zones.get() " + "instead. See the documentation for details.", + DeprecationWarning) + + if len(_CLASS_ZONE_INSTANCE) == 0: + _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) + return _CLASS_ZONE_INSTANCE[0].zones.get(name) + + +def gettz_db_metadata(): + """ Get the zonefile metadata + + See `zonefile_metadata`_ + + :returns: + A dictionary with the database metadata + + .. deprecated:: 2.6 + See deprecation warning in :func:`zoneinfo.gettz`. To get metadata, + query the attribute ``zoneinfo.ZoneInfoFile.metadata``. + """ + warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future " + "versions, to use the dateutil-provided zoneinfo files, " + "ZoneInfoFile object and query the 'metadata' attribute " + "instead. See the documentation for details.", + DeprecationWarning) + + if len(_CLASS_ZONE_INSTANCE) == 0: + _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) + return _CLASS_ZONE_INSTANCE[0].metadata diff --git a/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..130d942 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__pycache__/rebuild.cpython-36.pyc b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__pycache__/rebuild.cpython-36.pyc new file mode 100644 index 0000000..b4f7fd6 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/__pycache__/rebuild.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz new file mode 100644 index 0000000..124f3e1 Binary files /dev/null and b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz differ diff --git a/venv/lib/python3.6/site-packages/dateutil/zoneinfo/rebuild.py b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/rebuild.py new file mode 100644 index 0000000..78f0d1a --- /dev/null +++ b/venv/lib/python3.6/site-packages/dateutil/zoneinfo/rebuild.py @@ -0,0 +1,53 @@ +import logging +import os +import tempfile +import shutil +import json +from subprocess import check_call +from tarfile import TarFile + +from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME + + +def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): + """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar* + + filename is the timezone tarball from ``ftp.iana.org/tz``. + + """ + tmpdir = tempfile.mkdtemp() + zonedir = os.path.join(tmpdir, "zoneinfo") + moduledir = os.path.dirname(__file__) + try: + with TarFile.open(filename) as tf: + for name in zonegroups: + tf.extract(name, tmpdir) + filepaths = [os.path.join(tmpdir, n) for n in zonegroups] + try: + check_call(["zic", "-d", zonedir] + filepaths) + except OSError as e: + _print_on_nosuchfile(e) + raise + # write metadata file + with open(os.path.join(zonedir, METADATA_FN), 'w') as f: + json.dump(metadata, f, indent=4, sort_keys=True) + target = os.path.join(moduledir, ZONEFILENAME) + with TarFile.open(target, "w:%s" % format) as tf: + for entry in os.listdir(zonedir): + entrypath = os.path.join(zonedir, entry) + tf.add(entrypath, entry) + finally: + shutil.rmtree(tmpdir) + + +def _print_on_nosuchfile(e): + """Print helpful troubleshooting message + + e is an exception raised by subprocess.check_call() + + """ + if e.errno == 2: + logging.error( + "Could not find zic. Perhaps you need to install " + "libc-bin or some other package that provides it, " + "or it's not in your PATH?") diff --git a/venv/lib/python3.6/site-packages/easy_install.py b/venv/lib/python3.6/site-packages/easy_install.py new file mode 100644 index 0000000..d87e984 --- /dev/null +++ b/venv/lib/python3.6/site-packages/easy_install.py @@ -0,0 +1,5 @@ +"""Run the EasyInstall command""" + +if __name__ == '__main__': + from setuptools.command.easy_install import main + main() diff --git a/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/INSTALLER b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/METADATA b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/METADATA new file mode 100644 index 0000000..6c363ca --- /dev/null +++ b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/METADATA @@ -0,0 +1,42 @@ +Metadata-Version: 2.1 +Name: kiwisolver +Version: 1.1.0 +Summary: A fast implementation of the Cassowary constraint solver +Home-page: https://github.com/nucleic/kiwi +Author: The Nucleic Development Team +Author-email: sccolbert@gmail.com +License: BSD +Platform: UNKNOWN +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Requires-Dist: setuptools + +Welcome to Kiwi +=============== + +.. image:: https://travis-ci.org/nucleic/kiwi.svg?branch=master + :target: https://travis-ci.org/nucleic/kiwi +.. image:: https://codecov.io/gh/nucleic/kiwi/branch/master/graph/badge.svg + :target: https://codecov.io/gh/nucleic/kiwi +.. image:: https://readthedocs.org/projects/kiwisolver/badge/?version=latest + :target: https://kiwisolver.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +Kiwi is an efficient C++ implementation of the Cassowary constraint solving +algorithm. Kiwi is an implementation of the algorithm based on the seminal +Cassowary paper. It is *not* a refactoring of the original C++ solver. Kiwi +has been designed from the ground up to be lightweight and fast. Kiwi ranges +from 10x to 500x faster than the original Cassowary solver with typical use +cases gaining a 40x improvement. Memory savings are consistently > 5x. + +In addition to the C++ solver, Kiwi ships with hand-rolled Python bindings. + + diff --git a/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/RECORD b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/RECORD new file mode 100644 index 0000000..7f72cfe --- /dev/null +++ b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/RECORD @@ -0,0 +1,6 @@ +kiwisolver-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +kiwisolver-1.1.0.dist-info/METADATA,sha256=nNIX_Qo2CTCeL6nPZLrhr-TNSrYMzYp_Krcdf9U2noQ,1789 +kiwisolver-1.1.0.dist-info/RECORD,, +kiwisolver-1.1.0.dist-info/WHEEL,sha256=d2ILPScH-y2UwGxsW1PeA2TT-KW0Git4AJ6LeOK8sQo,109 +kiwisolver-1.1.0.dist-info/top_level.txt,sha256=xqwWj7oSHlpIjcw2QMJb8puTFPdjDBO78AZp9gjTh9c,11 +kiwisolver.cpython-36m-x86_64-linux-gnu.so,sha256=2YtEotfSpKnW2baxO0dH2UbDhSTijkB8UKW6IyWm-Yc,255336 diff --git a/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/WHEEL b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/WHEEL new file mode 100644 index 0000000..92946fe --- /dev/null +++ b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.31.1) +Root-Is-Purelib: false +Tag: cp36-cp36m-manylinux1_x86_64 + diff --git a/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/top_level.txt b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/top_level.txt new file mode 100644 index 0000000..9b85884 --- /dev/null +++ b/venv/lib/python3.6/site-packages/kiwisolver-1.1.0.dist-info/top_level.txt @@ -0,0 +1 @@ +kiwisolver diff --git a/venv/lib/python3.6/site-packages/kiwisolver.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/kiwisolver.cpython-36m-x86_64-linux-gnu.so new file mode 100755 index 0000000..9c54aab Binary files /dev/null and b/venv/lib/python3.6/site-packages/kiwisolver.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1-py3.6-nspkg.pth b/venv/lib/python3.6/site-packages/matplotlib-3.1.1-py3.6-nspkg.pth new file mode 100644 index 0000000..2137841 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1-py3.6-nspkg.pth @@ -0,0 +1 @@ +import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('mpl_toolkits',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('mpl_toolkits', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('mpl_toolkits', [os.path.dirname(p)])));m = m or sys.modules.setdefault('mpl_toolkits', types.ModuleType('mpl_toolkits'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/INSTALLER b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/METADATA b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/METADATA new file mode 100644 index 0000000..313e5ac --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/METADATA @@ -0,0 +1,35 @@ +Metadata-Version: 2.1 +Name: matplotlib +Version: 3.1.1 +Summary: Python plotting package +Home-page: https://matplotlib.org +Author: John D. Hunter, Michael Droettboom +Author-email: matplotlib-users@python.org +License: PSF +Download-URL: https://matplotlib.org/users/installing.html +Project-URL: Bug Tracker, https://github.com/matplotlib/matplotlib/issues +Project-URL: Documentation, https://matplotlib.org/contents.html +Project-URL: Source Code, https://github.com/matplotlib/matplotlib +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: Python Software Foundation License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Scientific/Engineering :: Visualization +Requires-Python: >=3.6 +Requires-Dist: cycler (>=0.10) +Requires-Dist: kiwisolver (>=1.0.1) +Requires-Dist: pyparsing (!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1) +Requires-Dist: python-dateutil (>=2.1) +Requires-Dist: numpy (>=1.11) + + +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. + + diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/RECORD b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/RECORD new file mode 100644 index 0000000..e5e4fed --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/RECORD @@ -0,0 +1,927 @@ +__pycache__/pylab.cpython-36.pyc,, +matplotlib-3.1.1-py3.6-nspkg.pth,sha256=FgO_3ug071EXEKT8mgOPBUhyrswPtPCYjOpUCyau7UU,569 +matplotlib-3.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +matplotlib-3.1.1.dist-info/METADATA,sha256=80CxmAUjX1KOBpnnSNbM2zEdMGJDytKupTa_bqAwR30,1382 +matplotlib-3.1.1.dist-info/RECORD,, +matplotlib-3.1.1.dist-info/WHEEL,sha256=d2ILPScH-y2UwGxsW1PeA2TT-KW0Git4AJ6LeOK8sQo,109 +matplotlib-3.1.1.dist-info/namespace_packages.txt,sha256=A2PHFg9NKYOU4pEQ1h97U0Qd-rB-65W34XqC-56ZN9g,13 +matplotlib-3.1.1.dist-info/top_level.txt,sha256=9tEw2ni8DdgX8CceoYHqSH1s50vrJ9SDfgtLIG8e3Y4,30 +matplotlib/.libs/libpng16-cfdb1654.so.16.21.0,sha256=Fo8LBDWTuCclLkpSng_KP5pI7wcQtuXA9opT1FFkXl0,275648 +matplotlib/.libs/libz-a147dcb0.so.1.2.3,sha256=VwXH3AM7bnoa793tKDw_H0pW-VZos08-FEtM_g_VWVM,87848 +matplotlib/__init__.py,sha256=ku0DuQReLHh080zyCe1AOi2GQ6UlsM2dDv9olEJSj8w,56344 +matplotlib/__pycache__/__init__.cpython-36.pyc,, +matplotlib/__pycache__/_animation_data.cpython-36.pyc,, +matplotlib/__pycache__/_cm.cpython-36.pyc,, +matplotlib/__pycache__/_cm_listed.cpython-36.pyc,, +matplotlib/__pycache__/_color_data.cpython-36.pyc,, +matplotlib/__pycache__/_constrained_layout.cpython-36.pyc,, +matplotlib/__pycache__/_layoutbox.cpython-36.pyc,, +matplotlib/__pycache__/_mathtext_data.cpython-36.pyc,, +matplotlib/__pycache__/_pylab_helpers.cpython-36.pyc,, +matplotlib/__pycache__/_version.cpython-36.pyc,, +matplotlib/__pycache__/afm.cpython-36.pyc,, +matplotlib/__pycache__/animation.cpython-36.pyc,, +matplotlib/__pycache__/artist.cpython-36.pyc,, +matplotlib/__pycache__/axis.cpython-36.pyc,, +matplotlib/__pycache__/backend_bases.cpython-36.pyc,, +matplotlib/__pycache__/backend_managers.cpython-36.pyc,, +matplotlib/__pycache__/backend_tools.cpython-36.pyc,, +matplotlib/__pycache__/bezier.cpython-36.pyc,, +matplotlib/__pycache__/blocking_input.cpython-36.pyc,, +matplotlib/__pycache__/category.cpython-36.pyc,, +matplotlib/__pycache__/cm.cpython-36.pyc,, +matplotlib/__pycache__/collections.cpython-36.pyc,, +matplotlib/__pycache__/colorbar.cpython-36.pyc,, +matplotlib/__pycache__/colors.cpython-36.pyc,, +matplotlib/__pycache__/container.cpython-36.pyc,, +matplotlib/__pycache__/contour.cpython-36.pyc,, +matplotlib/__pycache__/dates.cpython-36.pyc,, +matplotlib/__pycache__/docstring.cpython-36.pyc,, +matplotlib/__pycache__/dviread.cpython-36.pyc,, +matplotlib/__pycache__/figure.cpython-36.pyc,, +matplotlib/__pycache__/font_manager.cpython-36.pyc,, +matplotlib/__pycache__/fontconfig_pattern.cpython-36.pyc,, +matplotlib/__pycache__/gridspec.cpython-36.pyc,, +matplotlib/__pycache__/hatch.cpython-36.pyc,, +matplotlib/__pycache__/image.cpython-36.pyc,, +matplotlib/__pycache__/legend.cpython-36.pyc,, +matplotlib/__pycache__/legend_handler.cpython-36.pyc,, +matplotlib/__pycache__/lines.cpython-36.pyc,, +matplotlib/__pycache__/markers.cpython-36.pyc,, +matplotlib/__pycache__/mathtext.cpython-36.pyc,, +matplotlib/__pycache__/mlab.cpython-36.pyc,, +matplotlib/__pycache__/offsetbox.cpython-36.pyc,, +matplotlib/__pycache__/patches.cpython-36.pyc,, +matplotlib/__pycache__/path.cpython-36.pyc,, +matplotlib/__pycache__/patheffects.cpython-36.pyc,, +matplotlib/__pycache__/pylab.cpython-36.pyc,, +matplotlib/__pycache__/pyplot.cpython-36.pyc,, +matplotlib/__pycache__/quiver.cpython-36.pyc,, +matplotlib/__pycache__/rcsetup.cpython-36.pyc,, +matplotlib/__pycache__/sankey.cpython-36.pyc,, +matplotlib/__pycache__/scale.cpython-36.pyc,, +matplotlib/__pycache__/spines.cpython-36.pyc,, +matplotlib/__pycache__/stackplot.cpython-36.pyc,, +matplotlib/__pycache__/streamplot.cpython-36.pyc,, +matplotlib/__pycache__/table.cpython-36.pyc,, +matplotlib/__pycache__/texmanager.cpython-36.pyc,, +matplotlib/__pycache__/text.cpython-36.pyc,, +matplotlib/__pycache__/textpath.cpython-36.pyc,, +matplotlib/__pycache__/ticker.cpython-36.pyc,, +matplotlib/__pycache__/tight_bbox.cpython-36.pyc,, +matplotlib/__pycache__/tight_layout.cpython-36.pyc,, +matplotlib/__pycache__/transforms.cpython-36.pyc,, +matplotlib/__pycache__/type1font.cpython-36.pyc,, +matplotlib/__pycache__/units.cpython-36.pyc,, +matplotlib/__pycache__/widgets.cpython-36.pyc,, +matplotlib/_animation_data.py,sha256=yClmMx6K-y6pjG3FdHancRyRhyneFuBEbQZ_lhezVys,7499 +matplotlib/_cm.py,sha256=QXe4aTlOoE0dphzUD-yRTI2LiwjXLajO6ORplHSlDL0,66617 +matplotlib/_cm_listed.py,sha256=EpTjQ6pZ9E_UeY4kDa6fU9za_VHBvhuOmCG6fwNRvlk,98362 +matplotlib/_color_data.py,sha256=tbElcmqb3UvQzMAN3ThiODfFUdxK2hMB2kddXnXdCy4,34777 +matplotlib/_constrained_layout.py,sha256=Zy5F6YS7GT4w_prRa6Q0ZIv93R4UKruk1KZ-B8PXqLY,30043 +matplotlib/_contour.cpython-36m-x86_64-linux-gnu.so,sha256=Win3WVCSFAc2lgyLciYvAYU-W1CD2TxtWxcipq7FmFk,95144 +matplotlib/_image.cpython-36m-x86_64-linux-gnu.so,sha256=kQM6e3_wEnoHK_rghjLbFsaXrbg1R5268-ih6TX16-M,242496 +matplotlib/_layoutbox.py,sha256=daKACOWkdrfWq474LJGEl6eBrMYn-5buG_l8BUs_STo,24283 +matplotlib/_mathtext_data.py,sha256=CmKFRW6mXCJqgZSQaiNOSG_VUn9WiSx5Hrg-4qKIn14,89371 +matplotlib/_path.cpython-36m-x86_64-linux-gnu.so,sha256=l_b-DmJSmcl3QMZLR0rHY0OD0Qv9hursgLFosylr2vk,190280 +matplotlib/_png.cpython-36m-x86_64-linux-gnu.so,sha256=-FsjoHFJ6ibRSjOgujxkiCk98j2Fb6oV_HycFoj-tBA,48232 +matplotlib/_pylab_helpers.py,sha256=t5iyTlFNczfZdwizeNg5jT_ADtPAF1VrdTZZRFBLK9Y,3455 +matplotlib/_qhull.cpython-36m-x86_64-linux-gnu.so,sha256=sosg8UH2AEtm7P1kD6FdEj5AelUed88kEjc_UCTTczI,382672 +matplotlib/_tri.cpython-36m-x86_64-linux-gnu.so,sha256=gp0KG75tU9L-iWhE6UEph8iBhyA132DJ6YSrLRVf9RY,128616 +matplotlib/_version.py,sha256=4ThFwZDrum_EB2YgUiCk1L5_5mZsYK-y1rue9EMHiu0,471 +matplotlib/afm.py,sha256=ot_qN9D42DFMwPc8qHnVQD_y_RN0NhUaSLL2B47fYq8,17598 +matplotlib/animation.py,sha256=1Cb7BrTMSXGcoVwBZ3PDaNcnFARxYOuqR1TZMalzCUQ,67703 +matplotlib/artist.py,sha256=TF8IxC4pTI6ZWW-izavBYlEpWpyosSllLro6eN0Eww0,51915 +matplotlib/axes/__init__.py,sha256=npQuBvs_xEBEGUP2-BBZzCrelsAQYgB1U96kSZTSWIs,46 +matplotlib/axes/__pycache__/__init__.cpython-36.pyc,, +matplotlib/axes/__pycache__/_axes.cpython-36.pyc,, +matplotlib/axes/__pycache__/_base.cpython-36.pyc,, +matplotlib/axes/__pycache__/_secondary_axes.cpython-36.pyc,, +matplotlib/axes/__pycache__/_subplots.cpython-36.pyc,, +matplotlib/axes/_axes.py,sha256=f2CX7R5VYVN9aO5kZdJDozfBA4HlgB0wBkQ9q6FTltY,314569 +matplotlib/axes/_base.py,sha256=cC8nhBYwC9V9RjEphLCa5UyZOhp3pOy1mNl0gNY8qbs,158972 +matplotlib/axes/_secondary_axes.py,sha256=z2F2hBVHqspZbGq6OGu--ij49X5qf-nSu_W6DeJuEKM,15730 +matplotlib/axes/_subplots.py,sha256=bO0OHbAOfySyAGGfa3Drv9pBvdRauQJzspelG8SSQF4,9569 +matplotlib/axis.py,sha256=06pVhUlg6ckGMQLGuL2a_JVP0oj2Xla-hxX617860rE,89759 +matplotlib/backend_bases.py,sha256=Zgb9O_GeDPIVx2jJjcoVTmFAIwvib27WTfMmla0tH5k,114574 +matplotlib/backend_managers.py,sha256=bJ5nQeMWA4kYaW2xYQFJXoK5bwpJr7Wf3Szu9fDulbc,12851 +matplotlib/backend_tools.py,sha256=w5gq3pyuFWlJ3PJyO28rgRrTTEbdIapHdOVyXF5POZI,36281 +matplotlib/backends/__init__.py,sha256=rA4YyK6cq3LHtbPYXsUJKgNQ4fIqeVScNz4aS5SxOTE,3522 +matplotlib/backends/__pycache__/__init__.cpython-36.pyc,, +matplotlib/backends/__pycache__/_backend_pdf_ps.cpython-36.pyc,, +matplotlib/backends/__pycache__/_backend_tk.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_agg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_cairo.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_gtk3.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_gtk3agg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_gtk3cairo.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_macosx.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_mixed.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_nbagg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_pdf.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_pgf.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_ps.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_qt4.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_qt4agg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_qt4cairo.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_qt5.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_qt5agg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_qt5cairo.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_svg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_template.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_tkagg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_tkcairo.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_webagg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_webagg_core.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_wx.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_wxagg.cpython-36.pyc,, +matplotlib/backends/__pycache__/backend_wxcairo.cpython-36.pyc,, +matplotlib/backends/__pycache__/qt_compat.cpython-36.pyc,, +matplotlib/backends/__pycache__/tkagg.cpython-36.pyc,, +matplotlib/backends/__pycache__/windowing.cpython-36.pyc,, +matplotlib/backends/__pycache__/wx_compat.cpython-36.pyc,, +matplotlib/backends/_backend_agg.cpython-36m-x86_64-linux-gnu.so,sha256=26jbTqVSciPcbmRqWOUDUL4Ej4gWkjkZb21lt_NC_3Y,354224 +matplotlib/backends/_backend_pdf_ps.py,sha256=T8x_NWAo9_Wvnpw6HnsneRI9AyAxcp80TDe-z2eosbM,2709 +matplotlib/backends/_backend_tk.py,sha256=7ysrzE0nKM0TBXWInRTA71je3LhlYVHVEqu1n6o9-lM,35445 +matplotlib/backends/_tkagg.cpython-36m-x86_64-linux-gnu.so,sha256=90tXD4wEY9enxidz9Jh1mRpIMd0o09Z8bslTf9Dx278,29440 +matplotlib/backends/backend_agg.py,sha256=PeIUQHicz5keVfsF4G-rIcj12fA2ytiEJv9YjOMCmOE,22339 +matplotlib/backends/backend_cairo.py,sha256=wmplcjn0-06WsCJPTpFYKhZSzW3afGXvhFp89DwJVVM,17472 +matplotlib/backends/backend_gtk3.py,sha256=UzRc3Kr78Aid3WP-TSSJgUgudkqGKFwCkirE-hhu1P8,34276 +matplotlib/backends/backend_gtk3agg.py,sha256=wyyHAe5ZaZX1oqcIbeS1GZd8DDUm3tBezicXGcFEE9s,2997 +matplotlib/backends/backend_gtk3cairo.py,sha256=RKQQ98HyXrU8JCSP0rpP58wPuTJi4SYcPWdZDKa8GR8,1546 +matplotlib/backends/backend_macosx.py,sha256=m_GI_WAkulM9KdJa0rRpmI2QL-rZgPQ_q20D67OYmqI,6105 +matplotlib/backends/backend_mixed.py,sha256=fA7CGIMyqPko0LnTyNvL1q7anGQ5ca4-N9gGdtcAVRo,5288 +matplotlib/backends/backend_nbagg.py,sha256=ypFZW0An4Vf2gQ5dF-EPsdQaQ70UlmToURTS2OiW-Ic,8958 +matplotlib/backends/backend_pdf.py,sha256=LpQhsa7GePIrIQTWtzvy0zpkUEbFWEihmVQuEjVgog0,95012 +matplotlib/backends/backend_pgf.py,sha256=YBQDULT7uObs17fXonNVDAZvMvzqtzgMOQFarmavBKM,42252 +matplotlib/backends/backend_ps.py,sha256=rDxuGCltL3IyXcTKF1z3UGhP-pg8_ZuuTPkyHUrIGyM,56453 +matplotlib/backends/backend_qt4.py,sha256=x9KHRXMxJfmlJ-6lMdmKrw9cGe5RlZAAGjk1Ga1xX2c,410 +matplotlib/backends/backend_qt4agg.py,sha256=xTZMUL161hqcsOKSeU4sEs9kYloQrC7_OJjfyuYUAp0,245 +matplotlib/backends/backend_qt4cairo.py,sha256=B-LD_AECxVVsZA6Zb-oxoN39iM-GUNl81LR7nVaJ8q4,159 +matplotlib/backends/backend_qt5.py,sha256=r_hPPAhKd3hk7RaMCJC2zC-hTXB7kvLiW02yDI3uizE,40230 +matplotlib/backends/backend_qt5agg.py,sha256=Im-PIGy6gIpl2v3zq9Z32Yb3Wrlst6NrMBd9GxZESb0,3181 +matplotlib/backends/backend_qt5cairo.py,sha256=YzXN1Ckr6JLS2r50LPxeypajdWccXaHoXC5QZ4VWrEY,1892 +matplotlib/backends/backend_svg.py,sha256=wxAdczfj3B1cnN-_5fEhiaxAvI9KoADthJDQM_ixLEY,43696 +matplotlib/backends/backend_template.py,sha256=A0YC5DI5txrRuNST4vuc5DQ6xiwDiNOURM81IJbpAtE,9242 +matplotlib/backends/backend_tkagg.py,sha256=WMslLWYmtxlmAaBH4tx4HjmRDWMKiSV91KHF9yeMRng,676 +matplotlib/backends/backend_tkcairo.py,sha256=dVCh7ZD_2OR0DBQ0N3icD8cDV1SeEzCsRja446wWhPw,1069 +matplotlib/backends/backend_webagg.py,sha256=vKVC76QCHrpsy22p4Z_Vx2UZRfiAPU3Qr7fwdrf-sxM,11191 +matplotlib/backends/backend_webagg_core.py,sha256=5Ln-CpJ65S8grBHEW3gUqe_PcMmCKgM-dn2dLultFQc,17533 +matplotlib/backends/backend_wx.py,sha256=WT57kcfl7Xagg0PErB_Rt5cf5u6XI6kxqHBLtqgR98Y,68489 +matplotlib/backends/backend_wxagg.py,sha256=h8JqEqAtEzILMG61QXxhqEHBfIv6GS20-ybhNHeWO_E,3158 +matplotlib/backends/backend_wxcairo.py,sha256=VC5TyJaX8TPLSgHv5ckAreoGrY_KiNRMQjVInMLlcFk,1843 +matplotlib/backends/qt_compat.py,sha256=eMamsy7UoQMQeGyb-oTf5mQYxAHWctdYLTh_nRaFXkQ,6181 +matplotlib/backends/qt_editor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +matplotlib/backends/qt_editor/__pycache__/__init__.cpython-36.pyc,, +matplotlib/backends/qt_editor/__pycache__/_formlayout.cpython-36.pyc,, +matplotlib/backends/qt_editor/__pycache__/figureoptions.cpython-36.pyc,, +matplotlib/backends/qt_editor/__pycache__/formlayout.cpython-36.pyc,, +matplotlib/backends/qt_editor/__pycache__/formsubplottool.cpython-36.pyc,, +matplotlib/backends/qt_editor/_formlayout.py,sha256=Y6iflN1ECLQTD4VwZs5zUZ7iujk9PbcN1NCh4nZ2h-4,20583 +matplotlib/backends/qt_editor/figureoptions.py,sha256=eJVDlfPJVe31bW663ciiCbcMT9S-iMzRFaGAO5bZDdg,9606 +matplotlib/backends/qt_editor/formlayout.py,sha256=ERfmFwpvhl168PWNTJ0SFhQmPuSrmjzFNOe_puUCoSE,177 +matplotlib/backends/qt_editor/formsubplottool.py,sha256=HiiXkwCotra_hI9JU208KOs8Q9JuGH1uAW3mV5l3Evg,1934 +matplotlib/backends/tkagg.py,sha256=6-JtCBp9RKkv9xEumuWh-IMaSKny1AJCRE3K7DNcGsA,1304 +matplotlib/backends/web_backend/all_figures.html,sha256=m20aQIhuI4GBdrgZg_j02zSVjAcTRUufPOMSe4i7ayc,1525 +matplotlib/backends/web_backend/css/boilerplate.css,sha256=qui16QXRnQFNJDbcMasfH6KtN9hLjv8883U9cJmsVCE,2310 +matplotlib/backends/web_backend/css/fbm.css,sha256=Us0osu_rK8EUAdp_GXrh89tN_hUNCN-r7N1T1NvmmwI,1473 +matplotlib/backends/web_backend/css/page.css,sha256=Djf6ZNMFaM6_hVaizSkDFoqk-jn81qgduwles4AroGk,1599 +matplotlib/backends/web_backend/ipython_inline_figure.html,sha256=mzi-yWg4fcO6PdtTBCfiNuvcv04T53lcRQi-8hphwuE,1305 +matplotlib/backends/web_backend/jquery-ui-1.12.1/AUTHORS.txt,sha256=W2Lh1mbGo3Owc0oXX9U1-TFVSZYaC72KvSRrrRp3UII,12660 +matplotlib/backends/web_backend/jquery-ui-1.12.1/LICENSE.txt,sha256=3jP7aViA0LB2FdS4b3jNQ3lpBpWa3l_f73CWiCeg23g,1817 +matplotlib/backends/web_backend/jquery-ui-1.12.1/external/jquery/jquery.js,sha256=Qw82-bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU,293430 +matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_444444_256x240.png,sha256=6vfH7idHJ13abFPnMaENsaexX0-7RuG2nWuyBWvJ_YE,7006 +matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_555555_256x240.png,sha256=XQQFHf2dLXQDVUBPmKaD0ewP6y_KfXblM8Gm5c6S3S4,7074 +matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_777620_256x240.png,sha256=nb5KDQP-7W9l6yVgoKi0ukJkVF7o_THBdjo7IZ0DKNY,4676 +matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_777777_256x240.png,sha256=51snIR4W_PlHFRaAAbtwVco3bUb5KBELo9CCUjJFLlo,7013 +matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_cc0000_256x240.png,sha256=AokVddQ1jp7d4-QtlAV_jp-CqdZDdvce6GzvFJ0wU34,4632 +matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_ffffff_256x240.png,sha256=trBt7vK5JMw4NdY_SIPUeIJzSjPnGyEtkXpozt47jp0,6313 +matplotlib/backends/web_backend/jquery-ui-1.12.1/index.html,sha256=5g7_MLZlkh92FXWOR0q02My8knssXq20DXz-BkiYiP4,32588 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.css,sha256=p6xU9YulB7E2Ic62_PX-h59ayb3PBJ0WFTEQxq0EjHw,37326 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.js,sha256=T0Vest3yCU7pafRw9r-settMBX6JkKN06dqBnpQ8d30,520714 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.min.css,sha256=rByPlHULObEjJ6XQxW_flG2r-22R5dKiAoef-aXWfik,32076 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.min.js,sha256=KM512VNnjElC30ehFwehXjx1YCHPiQkOPmqnrWtpccM,253669 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.structure.css,sha256=E1uqV-d412nbSI-oqDMIQsTSttP-FS7Bxwc7mQdQYOo,18705 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.structure.min.css,sha256=rxais37anKUnpL5QzSYte-JnIsmkGmLG-ZhKSkZkwVM,15548 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.theme.css,sha256=mEMD30TTg-vIEGUmHHgcgSOgm0FBfLipyQ97Jr0TTH8,18671 +matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.theme.min.css,sha256=AjyoyaRtnGVTywKH_Isxxu5PXI0s4CcE0BzPAX83Ppc,13849 +matplotlib/backends/web_backend/jquery-ui-1.12.1/package.json,sha256=kjEW8xMYuqRSwEE58KqTDNLgkx_6YL7tb1M9vlMK98w,1847 +matplotlib/backends/web_backend/jquery/js/jquery.js,sha256=kaIBSZlozqJ4IeqPwOlDOi97qhNHWTchpUedwo5-gMU,284395 +matplotlib/backends/web_backend/jquery/js/jquery.min.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957 +matplotlib/backends/web_backend/js/mpl.js,sha256=xrBOaet7K2P2iq7wgIexceDdc9T_WFb4TPJXDX55JuU,16991 +matplotlib/backends/web_backend/js/mpl_tornado.js,sha256=lSxC7-yqF1GYY-6SheaHanx6SujMdcG7Vx2_3qbi-9Q,272 +matplotlib/backends/web_backend/js/nbagg_mpl.js,sha256=cfv0V27jN3oP7mgN1zwoB1mzqQH1W4Wt4myI-ZzPlT4,7468 +matplotlib/backends/web_backend/nbagg_uat.ipynb,sha256=y1N8hQzBJ05rJ2hZla2_Mw6tOUfNP1UHKo636W1e098,15933 +matplotlib/backends/web_backend/single_figure.html,sha256=-iFrlIsaY1rOK9bNiDxcX8fdc0WP7DXXq-MEuLYfOvM,1216 +matplotlib/backends/windowing.py,sha256=LmRBUwGp5pHBhw6DTQMIKyMATXJacbQ-lLJwDAPluF4,908 +matplotlib/backends/wx_compat.py,sha256=QPwM6dmnMHtQr82PtfowzPLE9MRj1QAEgxvnOhdmD5Y,964 +matplotlib/bezier.py,sha256=wVGi7-mV5sn1dGBXhtjuD9SLit24N4c8lDJRyVUwcPA,15332 +matplotlib/blocking_input.py,sha256=cLcis0sLH30HzSP6ljCPJuNdEEic1a2dgxTjNNKGpjI,11138 +matplotlib/category.py,sha256=_R_eBzzJFzcMHLS3NTECyVYnBFRGbPBOkMLeobgvBZw,7237 +matplotlib/cbook/__init__.py,sha256=MTqeFgEIhHgP0mqFGpqxmzQlTPC5jzd9PzzlOy6y8H4,68983 +matplotlib/cbook/__pycache__/__init__.cpython-36.pyc,, +matplotlib/cbook/__pycache__/deprecation.cpython-36.pyc,, +matplotlib/cbook/deprecation.py,sha256=6oP_a5YzuNDgMlxHKoVCbiVL1kiKSjozD_0KnxXcpH0,15386 +matplotlib/cm.py,sha256=k3R6-M6YttaMoyeF-w6Gir7cgO4eSRKBIOs_jSfk0Sw,13290 +matplotlib/collections.py,sha256=4z1Yw2z5oTU6lAlVTXatMMCIG6cekq8EdPviVkOQzYg,72181 +matplotlib/colorbar.py,sha256=iRxNPxPVYpHUH1XeifXQzLKMRh5KaG4YcAdqeXMcWYg,61551 +matplotlib/colors.py,sha256=d7qpB62Idn0TdsfYh2lP-r7DwrdEYN09qfMvAGZ5s7w,72737 +matplotlib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +matplotlib/compat/__pycache__/__init__.cpython-36.pyc,, +matplotlib/compat/__pycache__/subprocess.cpython-36.pyc,, +matplotlib/compat/subprocess.py,sha256=-K36IW-t5SjjWcP4nL80GAE-y7v0HZE6nQ-hscwmkvg,1562 +matplotlib/container.py,sha256=61H8LgCuxf4LdG2ZQ7EGMkmlTAgspyKeuhpuD9JKkaw,5631 +matplotlib/contour.py,sha256=u5Bus1vKPfYHxP2ERW8wfV-5RYaJK9SpIX0GPR1Vn7c,69725 +matplotlib/dates.py,sha256=bZG5tZAXBAeBnvdWjppr_Qr5HeekvoSem2mvnc6azTA,71394 +matplotlib/docstring.py,sha256=4gR4xKlMvrNqVovy0xDYQ3BzTy5OkgPNQLTVpom2iNc,3985 +matplotlib/dviread.py,sha256=s7GQjouGQU9wHed6W4fa0LXrodXUMyEe_rqDSnpDcC4,39176 +matplotlib/figure.py,sha256=UPTIIrfCAvuF2masgz5iWDWSMW5AV0021DhwtqQlLqY,99788 +matplotlib/font_manager.py,sha256=dTmJF9Pvn2A1X1zVd6kp_l7TI1PGGEfL-aEIXs58XpM,45793 +matplotlib/fontconfig_pattern.py,sha256=I3cwVMsMS8xqV19BT2cxNnNv8lklkqNy83LghWxt0kc,6483 +matplotlib/ft2font.cpython-36m-x86_64-linux-gnu.so,sha256=8uOOmAMqSi-nUNH1SlGlc6Lwc6KEFQcW_Lqbf2ig7tM,898136 +matplotlib/gridspec.py,sha256=qtMJLyHmh6lziQmyyFVb2IAG6SUwJGaaMPN40p4N_cE,20947 +matplotlib/hatch.py,sha256=KR7ezvCHUfVjKB9aDPQjKSAJvVmAKbB-ooPL9dCoSgY,7047 +matplotlib/image.py,sha256=alGU3q3MmN6mpDMqs2SUHj6jhbs5t6JOD9xlFbkrIsw,58235 +matplotlib/legend.py,sha256=pFNDkCXdRHFiaBleIlRJxAyslXdzEzz8vKu1HpnOTis,49005 +matplotlib/legend_handler.py,sha256=nGqIqlxSTD3kmnH1KVDSGDwPdrgWtL3X2KjBBc7XUGY,26509 +matplotlib/lines.py,sha256=MAZ3JYZRMReoyA27ARvXj7tempSuisfb9kPURmxOXqA,51164 +matplotlib/markers.py,sha256=TJycw9nyz5Id4Yi5uvTQiWqj0qaY0EDze1hKpvzFfrY,34177 +matplotlib/mathtext.py,sha256=WSGMgLSJAVcE6P5guZSQrXW0b0qFx6bIaa6AlQ1Rm1Y,121367 +matplotlib/mlab.py,sha256=r5G9yncf0F2-L8iNQHYWnXAFgXrkOHmtaPtZDdbGHFk,49479 +matplotlib/mpl-data/fonts/afm/cmex10.afm,sha256=blR3ERmrVBV5XKkAnDCj4NMeYVgzH7cXtJ3u59u9GuE,12070 +matplotlib/mpl-data/fonts/afm/cmmi10.afm,sha256=5qwEOpedEo76bDUahyuuF1q0cD84tRrX-VQ4p3MlfBo,10416 +matplotlib/mpl-data/fonts/afm/cmr10.afm,sha256=WDvgC_D3UkGJg9u-J0U6RaT02lF4oz3lQxHtg1r3lYw,10101 +matplotlib/mpl-data/fonts/afm/cmsy10.afm,sha256=AbmzvCVWBceHRfmRfeJ9E6xzOQTFLk0U1zDfpf3_MaM,8295 +matplotlib/mpl-data/fonts/afm/cmtt10.afm,sha256=4ji7_mTpeWMa93o_UHBWPKCnqsBfhJJNllat1lJArP4,6501 +matplotlib/mpl-data/fonts/afm/pagd8a.afm,sha256=jjFrigwkTpYLqa26cpzZvKQNBo-PuF4bmDVqaM4pMWw,17183 +matplotlib/mpl-data/fonts/afm/pagdo8a.afm,sha256=sgNQdeYyx8J-itGw9h31y95aMBiTCRvmNSPTXwwS7xg,17255 +matplotlib/mpl-data/fonts/afm/pagk8a.afm,sha256=ZUtfHPloNqcvGMHMxaKDSlshhOcjwheUx143RwpGdIU,17241 +matplotlib/mpl-data/fonts/afm/pagko8a.afm,sha256=Yj1wBg6Jsqqz1KBfhRoJ3ACR-CMQol8Fj_ZM5NZ1gDk,17346 +matplotlib/mpl-data/fonts/afm/pbkd8a.afm,sha256=Zl5o6J_di9Y5j2EpHtjew-_sfg7-WoeVmO9PzOYSTUc,15157 +matplotlib/mpl-data/fonts/afm/pbkdi8a.afm,sha256=JAOno930iTyfZILMf11vWtiaTgrJcPpP6FRTRhEMMD4,15278 +matplotlib/mpl-data/fonts/afm/pbkl8a.afm,sha256=UJqJjOJ6xQDgDBLX157mKpohIJFVmHM-N6x2-DiGv14,15000 +matplotlib/mpl-data/fonts/afm/pbkli8a.afm,sha256=AWislZ2hDbs0ox_qOWREugsbS8_8lpL48LPMR40qpi0,15181 +matplotlib/mpl-data/fonts/afm/pcrb8a.afm,sha256=6j1TS2Uc7DWSc-8l42TGDc1u0Fg8JspeWfxFayjUwi8,15352 +matplotlib/mpl-data/fonts/afm/pcrbo8a.afm,sha256=smg3mjl9QaBDtQIt06ko5GvaxLsO9QtTvYANuE5hfG0,15422 +matplotlib/mpl-data/fonts/afm/pcrr8a.afm,sha256=7nxFr0Ehz4E5KG_zSE5SZOhxRH8MyfnCbw-7x5wu7tw,15339 +matplotlib/mpl-data/fonts/afm/pcrro8a.afm,sha256=NKEz7XtdFkh9cA8MvY-S3UOZlV2Y_J3tMEWFFxj7QSg,15443 +matplotlib/mpl-data/fonts/afm/phvb8a.afm,sha256=NAx4M4HjL7vANCJbc-tk04Vkol-T0oaXeQ3T2h-XUvM,17155 +matplotlib/mpl-data/fonts/afm/phvb8an.afm,sha256=8e_myD-AQkNF7q9XNLb2m76_lX2TUr3a5wog_LIE1sk,17086 +matplotlib/mpl-data/fonts/afm/phvbo8a.afm,sha256=8fkBRmJ-SWY2YrBg8fFyjJyrJp8daQ6JPO6LvhM8xPI,17230 +matplotlib/mpl-data/fonts/afm/phvbo8an.afm,sha256=aeVRvV4r15BBvxuRJ0MG8ZHuH2HViuIiCYkvuapmkmM,17195 +matplotlib/mpl-data/fonts/afm/phvl8a.afm,sha256=IyMYM-bgl-gI6rG0EuZZ2OLzlxJfGeSh8xqsh0t-eJQ,15627 +matplotlib/mpl-data/fonts/afm/phvlo8a.afm,sha256=s12C-eNnIDHJ_UVbuiprjxBjCiHIbS3Y8ORTC-qTpuI,15729 +matplotlib/mpl-data/fonts/afm/phvr8a.afm,sha256=Kt8KaRidts89EBIK29X2JomDUEDxvroeaJz_RNTi6r4,17839 +matplotlib/mpl-data/fonts/afm/phvr8an.afm,sha256=lL5fAHTRwODl-sB5mH7IfsD1tnnea4yRUK-_Ca2bQHM,17781 +matplotlib/mpl-data/fonts/afm/phvro8a.afm,sha256=3KqK3eejiR4hIFBUynuSX_4lMdE2V2T58xOF8lX-fwc,17919 +matplotlib/mpl-data/fonts/afm/phvro8an.afm,sha256=Vx9rRf3YfasMY7tz-njSxz67xHKk-fNkN7yBi0X2IP0,17877 +matplotlib/mpl-data/fonts/afm/pncb8a.afm,sha256=aoXepTcDQtQa_mspflMJkEFKefzXHoyjz6ioJVI0YNc,16028 +matplotlib/mpl-data/fonts/afm/pncbi8a.afm,sha256=pCWW1MYgy0EmvwaYsaYJaAI_LfrsKmDANHu7Pk0RaiU,17496 +matplotlib/mpl-data/fonts/afm/pncr8a.afm,sha256=0CIB2BLe9r-6_Wl5ObRTTf98UOrezmGQ8ZOuBX5kLks,16665 +matplotlib/mpl-data/fonts/afm/pncri8a.afm,sha256=5R-pLZOnaHNG8pjV6MP3Ai-d2OTQYR_cYCb5zQhzfSU,16920 +matplotlib/mpl-data/fonts/afm/pplb8a.afm,sha256=3EzUbNnXr5Ft5eFLY00W9oWu59rHORgDXUuJaOoKN58,15662 +matplotlib/mpl-data/fonts/afm/pplbi8a.afm,sha256=X_9tVspvrcMer3OS8qvdwjFFqpAXYZneyCL2NHA902g,15810 +matplotlib/mpl-data/fonts/afm/pplr8a.afm,sha256=ijMb497FDJ9nVdVMb21F7W3-cu9sb_9nF0oriFpSn8k,15752 +matplotlib/mpl-data/fonts/afm/pplri8a.afm,sha256=8KITbarcUUMi_hdoRLLmNHtlqs0TtOSKqtPFft7X5nY,15733 +matplotlib/mpl-data/fonts/afm/psyr.afm,sha256=Iyt8ajE4B2Tm34oBj2pKtctIf9kPfq05suQefq8p3Ro,9644 +matplotlib/mpl-data/fonts/afm/ptmb8a.afm,sha256=bL1fA1NC4_nW14Zrnxz4nHlXJb4dzELJPvodqKnYeMg,17983 +matplotlib/mpl-data/fonts/afm/ptmbi8a.afm,sha256=-_Ui6XlKaFTHEnkoS_-1GtIr5VtGa3gFQ2ezLOYHs08,18070 +matplotlib/mpl-data/fonts/afm/ptmr8a.afm,sha256=IEcsWcmzJyjCwkgsw4o6hIMmzlyXUglJat9s1PZNnEU,17942 +matplotlib/mpl-data/fonts/afm/ptmri8a.afm,sha256=49fQMg5fIGguZ7rgc_2styMK55Pv5bPTs7wCzqpcGpk,18068 +matplotlib/mpl-data/fonts/afm/putb8a.afm,sha256=qMaHTdpkrNL-m4DWhjpxJCSmgYkCv1qIzLlFfM0rl40,21532 +matplotlib/mpl-data/fonts/afm/putbi8a.afm,sha256=g7AVJyiTxeMpNk_1cSfmYgM09uNUfPlZyWGv3D1vcAk,21931 +matplotlib/mpl-data/fonts/afm/putr8a.afm,sha256=XYmNC5GQgSVAZKTIYdYeNksE6znNm9GF_0SmQlriqx0,22148 +matplotlib/mpl-data/fonts/afm/putri8a.afm,sha256=i7fVe-iLyLtQxCfAa4IxdxH-ufcHmMk7hbCGG5TxAY4,21891 +matplotlib/mpl-data/fonts/afm/pzcmi8a.afm,sha256=wyuoIWEZOcoXrSl1tPzLkEahik7kGi91JJj-tkFRG4A,16250 +matplotlib/mpl-data/fonts/afm/pzdr.afm,sha256=MyjLAnzKYRdQBfof1W3k_hf30MvqOkqL__G22mQ5xww,9467 +matplotlib/mpl-data/fonts/pdfcorefonts/Courier-Bold.afm,sha256=sIDDI-B82VZ3C0mI_mHFITCZ7PVn37AIYMv1CrHX4sE,15333 +matplotlib/mpl-data/fonts/pdfcorefonts/Courier-BoldOblique.afm,sha256=zg61QobD3YU9UBfCXmvmhBNaFKno-xj8sY0b2RpgfLw,15399 +matplotlib/mpl-data/fonts/pdfcorefonts/Courier-Oblique.afm,sha256=vRQm5j1sTUN4hicT1PcVZ9P9DTTUHhEzfPXqUUzVZhE,15441 +matplotlib/mpl-data/fonts/pdfcorefonts/Courier.afm,sha256=Mdcq2teZEBJrIqVXnsnhee7oZnTs6-P8_292kWGTrw4,15335 +matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-Bold.afm,sha256=i2l4gcjuYXoXf28uK7yIVwuf0rnw6J7PwPVQeHj5iPw,69269 +matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-BoldOblique.afm,sha256=Um5O6qK11DXLt8uj_0IoWkc84TKqHK3bObSKUswQqvY,69365 +matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-Oblique.afm,sha256=hVYDg2b52kqtbVeCzmiv25bW1yYdpkZS-LXlGREN2Rs,74392 +matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica.afm,sha256=23cvKDD7bQAJB3kdjSahJSTZaUOppznlIO6FXGslyW8,74292 +matplotlib/mpl-data/fonts/pdfcorefonts/Symbol.afm,sha256=P5UaoXr4y0qh4SiMa5uqijDT6ZDr2-jPmj1ayry593E,9740 +matplotlib/mpl-data/fonts/pdfcorefonts/Times-Bold.afm,sha256=cQTmr2LFPwKQE_sGQageMcmFicjye16mKJslsJLHQyE,64251 +matplotlib/mpl-data/fonts/pdfcorefonts/Times-BoldItalic.afm,sha256=pzWOdycm6RqocBWgAVY5Jq0z3Fp7LuqWgLNMx4q6OFw,59642 +matplotlib/mpl-data/fonts/pdfcorefonts/Times-Italic.afm,sha256=bK5puSMpGT_YUILwyJrXoxjfj7XJOdfv5TQ_iKsJRzw,66328 +matplotlib/mpl-data/fonts/pdfcorefonts/Times-Roman.afm,sha256=hhNrUnpazuDDKD1WpraPxqPWCYLrO7D7bMVOg-zI13o,60460 +matplotlib/mpl-data/fonts/pdfcorefonts/ZapfDingbats.afm,sha256=ZuOmt9GcKofjdOq8kqhPhtAIhOwkL2rTJTmZxAjFakA,9527 +matplotlib/mpl-data/fonts/pdfcorefonts/readme.txt,sha256=MRv8ppSITYYAb7lt5EOw9DWWNZIblfxsFhu5TQE7cpI,828 +matplotlib/mpl-data/fonts/ttf/DejaVuSans-Bold.ttf,sha256=sYS4njwQdfIva3FXW2_CDUlys8_TsjMiym_Vltyu8Wc,704128 +matplotlib/mpl-data/fonts/ttf/DejaVuSans-BoldOblique.ttf,sha256=bt8CgxYBhq9FHL7nHnuEXy5Mq_Jku5ks5mjIPCVGXm8,641720 +matplotlib/mpl-data/fonts/ttf/DejaVuSans-Oblique.ttf,sha256=zN90s1DxH9PdV3TeUOXmNGoaXaH1t9X7g1kGZel6UhM,633840 +matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf,sha256=P99pyr8GBJ6nCgC1kZNA4s4ebQKwzDxLRPtoAb0eDSI,756072 +matplotlib/mpl-data/fonts/ttf/DejaVuSansDisplay.ttf,sha256=ggmdz7paqGjN_CdFGYlSX-MpL3N_s8ngMozpzvWWUvY,25712 +matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Bold.ttf,sha256=uq2ppRcv4giGJRr_BDP8OEYZEtXa8HKH577lZiCo2pY,331536 +matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-BoldOblique.ttf,sha256=ppCBwVx2yCfgonpaf1x0thNchDSZlVSV_6jCDTqYKIs,253116 +matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Oblique.ttf,sha256=KAUoE_enCfyJ9S0ZLcmV708P3Fw9e3OknWhJsZFtDNA,251472 +matplotlib/mpl-data/fonts/ttf/DejaVuSansMono.ttf,sha256=YC7Ia4lIz82VZIL-ZPlMNshndwFJ7y95HUYT9EO87LM,340240 +matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf,sha256=w3U_Lta8Zz8VhG3EWt2-s7nIcvMvsY_VOiHxvvHtdnY,355692 +matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf,sha256=2T7-x6nS6CZ2jRou6VuVhw4V4pWZqE80hK8d4c7C4YE,347064 +matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Italic.ttf,sha256=PnmU-8VPoQzjNSpC1Uj63X2crbacsRCbydlg9trFfwQ,345612 +matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf,sha256=EHJElW6ZYrnpb6zNxVGCXgrgiYrhNzcTPhuSGi_TX_o,379740 +matplotlib/mpl-data/fonts/ttf/DejaVuSerifDisplay.ttf,sha256=KRTzLkfHd8J75Wd6-ufbTeefnkXeb8kJfZlJwjwU99U,14300 +matplotlib/mpl-data/fonts/ttf/LICENSE_DEJAVU,sha256=11k43sCY8G8Kw8AIUwZdlPAgvhw8Yu8dwpdboVtNmw4,4816 +matplotlib/mpl-data/fonts/ttf/LICENSE_STIX,sha256=cxFOZdp1AxNhXR6XxCzf5iJpNcu-APm-geOHhD-s0h8,5475 +matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf,sha256=FnN4Ax4t3cYhbWeBnJJg6aBv_ExHjk4jy5im_USxg8I,448228 +matplotlib/mpl-data/fonts/ttf/STIXGeneralBol.ttf,sha256=6FM9xwg_o0a9oZM9YOpKg7Z9CUW86vGzVB-CtKDixqA,237360 +matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf,sha256=mHiP1LpI37sr0CbA4gokeosGxzcoeWKLemuw1bsJc2w,181152 +matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf,sha256=bPyzM9IrfDxiO9_UAXTxTIXD1nMcphZsHtyAFA6uhSc,175040 +matplotlib/mpl-data/fonts/ttf/STIXNonUni.ttf,sha256=Ulb34CEzWsSFTRgPDovxmJZOwvyCAXYnbhaqvGU3u1c,59108 +matplotlib/mpl-data/fonts/ttf/STIXNonUniBol.ttf,sha256=XRBqW3jR_8MBdFU0ObhiV7-kXwiBIMs7QVClHcT5tgs,30512 +matplotlib/mpl-data/fonts/ttf/STIXNonUniBolIta.ttf,sha256=pb22DnbDf2yQqizotc3wBDqFGC_g27YcCGJivH9-Le8,41272 +matplotlib/mpl-data/fonts/ttf/STIXNonUniIta.ttf,sha256=BMr9pWiBv2YIZdq04X4c3CgL6NPLUPrl64aV1N4w9Ug,46752 +matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf,sha256=wYuH1gYUpCuusqItRH5kf9p_s6mUD-9X3L5RvRtKSxs,13656 +matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf,sha256=yNdvjUoSmsZCULmD7SVq9HabndG9P4dPhboL1JpAf0s,12228 +matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf,sha256=-9xVMYL4_1rcO8FiCKrCfR4PaSmKtA42ddLGqwtei1w,15972 +matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf,sha256=cYexyo8rZcdqMlpa9fNF5a2IoXLUTZuIvh0JD1Qp0i4,12556 +matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf,sha256=0lbHzpndzJmO8S42mlkhsz5NbvJLQCaH5Mcc7QZRDzc,19760 +matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf,sha256=3eBc-VtYbhQU3BnxiypfO6eAzEu8BdDvtIJSFbkS2oY,12192 +matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf,sha256=XFSKCptbESM8uxHtUFSAV2cybwxhSjd8dWVByq6f3w0,15836 +matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf,sha256=MUCYHrA0ZqFiSE_PjIGlJZgMuv79aUgQqE7Dtu3kuo0,12116 +matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf,sha256=_sdxDuEwBDtADpu9CyIXQxV7sIqA2TZVBCUiUjq5UCk,15704 +matplotlib/mpl-data/fonts/ttf/cmb10.ttf,sha256=B0SXtQxD6ldZcYFZH5iT04_BKofpUQT1ZX_CSB9hojo,25680 +matplotlib/mpl-data/fonts/ttf/cmex10.ttf,sha256=ryjwwXByOsd2pxv6WVrKCemNFa5cPVTOGa_VYZyWqQU,21092 +matplotlib/mpl-data/fonts/ttf/cmmi10.ttf,sha256=MJKWW4gR_WpnZXmWZIRRgfwd0TMLk3-RWAjEhdMWI00,32560 +matplotlib/mpl-data/fonts/ttf/cmr10.ttf,sha256=Tdl2GwWMAJ25shRfVe5mF9CTwnPdPWxbPkP_YRD6m_Y,26348 +matplotlib/mpl-data/fonts/ttf/cmss10.ttf,sha256=ffkag9BbLkcexjjLC0NaNgo8eSsJ_EKn2mfpHy55EVo,20376 +matplotlib/mpl-data/fonts/ttf/cmsy10.ttf,sha256=uyJu2TLz8QDNDlL15JEu5VO0G2nnv9uNOFTbDrZgUjI,29396 +matplotlib/mpl-data/fonts/ttf/cmtt10.ttf,sha256=YhHwmuk1mZka_alwwkZp2tGnfiU9kVYk-_IS9wLwcdc,28136 +matplotlib/mpl-data/images/back.gif,sha256=sdkxFRAh-Mgs44DTvruO5OxcI3Av9CS1g5MqMA_DDkQ,608 +matplotlib/mpl-data/images/back.pdf,sha256=ZR7CJo_dAeCM-KlaGvskgtHQyRtrPIolc8REOmcoqJk,1623 +matplotlib/mpl-data/images/back.png,sha256=E4dGf4Gnz1xJ1v2tMygHV0YNQgShreDeVApaMb-74mU,380 +matplotlib/mpl-data/images/back.svg,sha256=yRdMiKsa-awUm2x_JE_rEV20rNTa7FInbFBEoMo-6ik,1512 +matplotlib/mpl-data/images/back_large.gif,sha256=tqCtecrxNrPuDCUj7FGs8UXWftljKcwgp5cSBBhXwiQ,799 +matplotlib/mpl-data/images/back_large.png,sha256=9A6hUSQeszhYONE4ZuH3kvOItM0JfDVu6tkfromCbsQ,620 +matplotlib/mpl-data/images/filesave.gif,sha256=wAyNwOPd9c-EIPwcUAlqHSfLmxq167nhDVppOWPy9UA,723 +matplotlib/mpl-data/images/filesave.pdf,sha256=P1EPPV2g50WTt8UaX-6kFoTZM1xVqo6S2H6FJ6Zd1ec,1734 +matplotlib/mpl-data/images/filesave.png,sha256=b7ctucrM_F2mG-DycTedG_a_y4pHkx3F-zM7l18GLhk,458 +matplotlib/mpl-data/images/filesave.svg,sha256=oxPVbLS9Pzelz71C1GCJWB34DZ0sx_pUVPRHBrCZrGs,2029 +matplotlib/mpl-data/images/filesave_large.gif,sha256=IXrenlwu3wwO8WTRvxHt_q62NF6ZWyqk3jZhm6GE-G8,1498 +matplotlib/mpl-data/images/filesave_large.png,sha256=LNbRD5KZ3Kf7nbp-stx_a1_6XfGBSWUfDdpgmnzoRvk,720 +matplotlib/mpl-data/images/forward.gif,sha256=VNL9R-dECOX7wUAYPtU_DWn5hwi3SwLR17DhmBvUIxE,590 +matplotlib/mpl-data/images/forward.pdf,sha256=KIqIL4YId43LkcOxV_TT5uvz1SP8k5iUNUeJmAElMV8,1630 +matplotlib/mpl-data/images/forward.png,sha256=pKbLepgGiGeyY2TCBl8svjvm7Z4CS3iysFxcq4GR-wk,357 +matplotlib/mpl-data/images/forward.svg,sha256=NnQDOenfjsn-o0aJMUfErrP320Zcx9XHZkLh0cjMHsk,1531 +matplotlib/mpl-data/images/forward_large.gif,sha256=H6Jbcc7qJwHJAE294YqI5Bm-5irofX40cKRvYdrG_Ig,786 +matplotlib/mpl-data/images/forward_large.png,sha256=36h7m7DZDHql6kkdpNPckyi2LKCe_xhhyavWARz_2kQ,593 +matplotlib/mpl-data/images/hand.gif,sha256=3lRfmAqQU7A2t1YXXsB9IbwzK7FaRh-IZO84D5-xCrw,1267 +matplotlib/mpl-data/images/hand.pdf,sha256=hspwkNY915KPD7AMWnVQs7LFPOtlcj0VUiLu76dMabQ,4172 +matplotlib/mpl-data/images/hand.png,sha256=2cchRETGKa0hYNKUxnJABwkyYXEBPqJy_VqSPlT0W2Q,979 +matplotlib/mpl-data/images/hand.svg,sha256=tsVIES_nINrAbH4FqdsCGOx0SVE37vcofSYBhnnaOP0,4888 +matplotlib/mpl-data/images/hand_large.gif,sha256=H5IHmVTvOqHQb9FZ_7g7AlPt9gv-zRq0L5_Q9B7OuvU,973 +matplotlib/mpl-data/images/help.pdf,sha256=CeE978IMi0YWznWKjIT1R8IrP4KhZ0S7usPUvreSgcA,1813 +matplotlib/mpl-data/images/help.png,sha256=s4pQrqaQ0py8I7vc9hv3BI3DO_tky-7YBMpaHuBDCBY,472 +matplotlib/mpl-data/images/help.ppm,sha256=mVPvgwcddzCM-nGZd8Lnl_CorzDkRIXQE17b7qo8vlU,1741 +matplotlib/mpl-data/images/help.svg,sha256=KXabvQhqIWen_t2SvZuddFYa3S0iI3W8cAKm3s1fI8Q,1870 +matplotlib/mpl-data/images/help_large.png,sha256=1IwEyWfGRgnoCWM-r9CJHEogTJVD5n1c8LXTK4AJ4RE,747 +matplotlib/mpl-data/images/help_large.ppm,sha256=MiCSKp1Su88FXOi9MTtkQDA2srwbX3w5navi6cneAi4,6925 +matplotlib/mpl-data/images/home.gif,sha256=NKuFM7tTtFngdfsOpJ4AxYTL8PYS5GWKAoiJjBMwLlU,666 +matplotlib/mpl-data/images/home.pdf,sha256=e0e0pI-XRtPmvUCW2VTKL1DeYu1pvPmUUeRSgEbWmik,1737 +matplotlib/mpl-data/images/home.png,sha256=IcFdAAUa6_A0qt8IO3I8p4rpXpQgAlJ8ndBECCh7C1w,468 +matplotlib/mpl-data/images/home.svg,sha256=n_AosjJVXET3McymFuHgXbUr5vMLdXK2PDgghX8Cch4,1891 +matplotlib/mpl-data/images/home_large.gif,sha256=k86PJCgED46sCFkOlUYHA0s5U7OjRsc517bpAtU2JSw,1422 +matplotlib/mpl-data/images/home_large.png,sha256=uxS2O3tWOHh1iau7CaVV4ermIJaZ007ibm5Z3i8kXYg,790 +matplotlib/mpl-data/images/matplotlib.pdf,sha256=BkSUf-2xoij-eXfpV2t7y1JFKG1zD1gtV6aAg3Xi_wE,22852 +matplotlib/mpl-data/images/matplotlib.png,sha256=w8KLRYVa-voUZXa41hgJauQuoois23f3NFfdc72pUYY,1283 +matplotlib/mpl-data/images/matplotlib.ppm,sha256=voTyfqUGvirNbkrsJGMwJT0z0g_KFWAnO8Hn8J4XXh8,1741 +matplotlib/mpl-data/images/matplotlib.svg,sha256=QiTIcqlQwGaVPtHsEk-vtmJk1wxwZSvijhqBe_b9VCI,62087 +matplotlib/mpl-data/images/matplotlib_large.png,sha256=ElRoue9grUqkZXJngk-nvh4GKfpvJ4gE69WryjCbX5U,3088 +matplotlib/mpl-data/images/move.gif,sha256=FN52MptH4FZiwmV2rQgYCO2FvO3m5LtqYv8jk6Xbeyk,679 +matplotlib/mpl-data/images/move.pdf,sha256=CXk3PGK9WL5t-5J-G2X5Tl-nb6lcErTBS5oUj2St6aU,1867 +matplotlib/mpl-data/images/move.png,sha256=TmjR41IzSzxGbhiUcV64X0zx2BjrxbWH3cSKvnG2vzc,481 +matplotlib/mpl-data/images/move.svg,sha256=_ZKpcwGD6DMTkZlbyj0nQbT8Ygt5vslEZ0OqXaXGd4E,2509 +matplotlib/mpl-data/images/move_large.gif,sha256=RMIAr-G9OOY7vWC04oN6qv5TAHJxhQGhLsw_bNsvWbg,951 +matplotlib/mpl-data/images/move_large.png,sha256=Skjz2nW_RTA5s_0g88gdq2hrVbm6DOcfYW4Fu42Fn9U,767 +matplotlib/mpl-data/images/qt4_editor_options.pdf,sha256=2qu6GVyBrJvVHxychQoJUiXPYxBylbH2j90QnytXs_w,1568 +matplotlib/mpl-data/images/qt4_editor_options.png,sha256=EryQjQ5hh2dwmIxtzCFiMN1U6Tnd11p1CDfgH5ZHjNM,380 +matplotlib/mpl-data/images/qt4_editor_options.svg,sha256=E00YoX7u4NrxMHm_L1TM8PDJ88bX5qRdCrO-Uj59CEA,1244 +matplotlib/mpl-data/images/qt4_editor_options_large.png,sha256=-Pd-9Vh5aIr3PZa8O6Ge_BLo41kiEnpmkdDj8a11JkY,619 +matplotlib/mpl-data/images/subplots.gif,sha256=QfhmUdcrko08-WtrzCJUjrVFDTvUZCJEXpARNtzEwkg,691 +matplotlib/mpl-data/images/subplots.pdf,sha256=Q0syPMI5EvtgM-CE-YXKOkL9eFUAZnj_X2Ihoj6R4p4,1714 +matplotlib/mpl-data/images/subplots.png,sha256=MUfCItq3_yzb9yRieGOglpn0Y74h8IA7m5i70B63iRc,445 +matplotlib/mpl-data/images/subplots.svg,sha256=8acBogXIr9OWGn1iD6mUkgahdFZgDybww385zLCLoIs,2130 +matplotlib/mpl-data/images/subplots_large.gif,sha256=Ff3ERmtVAaGP9i1QGUNnIIKac6LGuSW2Qf4DrockZSI,1350 +matplotlib/mpl-data/images/subplots_large.png,sha256=Edu9SwVMQEXJZ5ogU5cyW7VLcwXJdhdf-EtxxmxdkIs,662 +matplotlib/mpl-data/images/zoom_to_rect.gif,sha256=mTX6h9fh2W9zmvUYqeibK0TZ7qIMKOB1nAXMpD_jDys,696 +matplotlib/mpl-data/images/zoom_to_rect.pdf,sha256=SEvPc24gfZRpl-dHv7nx8KkxPyU66Kq4zgQTvGFm9KA,1609 +matplotlib/mpl-data/images/zoom_to_rect.png,sha256=aNz3QZBrIgxu9E-fFfaQweCVNitGuDUFoC27e5NU2L4,530 +matplotlib/mpl-data/images/zoom_to_rect.svg,sha256=1vRxr3cl8QTwTuRlQzD1jxu0fXZofTJ2PMgG97E7Bco,1479 +matplotlib/mpl-data/images/zoom_to_rect_large.gif,sha256=nx5LUpTAH6ZynM3ZfZDS-wR87jbMUsUnyQ27NGkV0_c,1456 +matplotlib/mpl-data/images/zoom_to_rect_large.png,sha256=V6pkxmm6VwFExdg_PEJWdK37HB7k3cE_corLa7RbUMk,1016 +matplotlib/mpl-data/matplotlibrc,sha256=_dzr3DPPXNGUyFoC4U40Q-uPwXZjBy9RTM5wlj2rx8c,33492 +matplotlib/mpl-data/sample_data/Minduka_Present_Blue_Pack.png,sha256=XnKGiCanpDKalQ5anvo5NZSAeDP7fyflzQAaivuc0IE,13634 +matplotlib/mpl-data/sample_data/None_vs_nearest-pdf.png,sha256=5CPvcG3SDNfOXx39CMKHCNS9JKZ-fmOUwIfpppNXsQ0,106228 +matplotlib/mpl-data/sample_data/README.txt,sha256=ABz19VBKfGewdY39QInG9Qccgn1MTYV3bT5Ph7TCy2Y,128 +matplotlib/mpl-data/sample_data/aapl.npz,sha256=GssVYka_EccteiXbNRJJ5GsuqU7G8F597qX7srYXZsw,107503 +matplotlib/mpl-data/sample_data/ada.png,sha256=X1hjJK1_1Nc8DN-EEhey3G7Sq8jBwQDKNSl4cCAE0uY,308313 +matplotlib/mpl-data/sample_data/axes_grid/bivariate_normal.npy,sha256=DpWZ9udAh6ospYqneEa27D6EkRgORFwHosacZXVu98U,1880 +matplotlib/mpl-data/sample_data/ct.raw.gz,sha256=LDvvgH-mycRQF2D29-w5MW94ZI0opvwKUoFI8euNpMk,256159 +matplotlib/mpl-data/sample_data/data_x_x2_x3.csv,sha256=A0SU3buOUGhT-NI_6LQ6p70fFSIU3iLFdgzvzrKR6SE,132 +matplotlib/mpl-data/sample_data/demodata.csv,sha256=MRybziqnyrqMCH9qG7Mr6BwcohIhftVG5dejXV2AX2M,659 +matplotlib/mpl-data/sample_data/eeg.dat,sha256=KGVjFt8ABKz7p6XZirNfcxSTOpGGNuyA8JYErRKLRBc,25600 +matplotlib/mpl-data/sample_data/embedding_in_wx3.xrc,sha256=cUqVw5vDHNSZoaO4J0ebZUf5SrJP36775abs7R9Bclg,2186 +matplotlib/mpl-data/sample_data/goog.npz,sha256=QAkXzzDmtmT3sNqT18dFhg06qQCNqLfxYNLdEuajGLE,22845 +matplotlib/mpl-data/sample_data/grace_hopper.jpg,sha256=qMptc0dlcDsJcoq0f-WfRz2Trjln_CTHwCiMPHrbcTA,61306 +matplotlib/mpl-data/sample_data/grace_hopper.png,sha256=MCf0ju2kpC40srQ0xw4HEyOoKhLL4khP3jHfU9_dR7s,628280 +matplotlib/mpl-data/sample_data/jacksboro_fault_dem.npz,sha256=1JP1CjPoKkQgSUxU0fyhU50Xe9wnqxkLxf5ukvYvtjc,174061 +matplotlib/mpl-data/sample_data/logo2.png,sha256=ITxkJUsan2oqXgJDy6DJvwJ4aHviKeWGnxPkTjXUt7A,33541 +matplotlib/mpl-data/sample_data/membrane.dat,sha256=q3lbQpIBpbtXXGNw1eFwkN_PwxdDGqk4L46IE2b0M1c,48000 +matplotlib/mpl-data/sample_data/msft.csv,sha256=GArKb0O3DgKZRsKdJf6lX3rMSf-PCekIiBoLNdgF7Mk,3211 +matplotlib/mpl-data/sample_data/percent_bachelors_degrees_women_usa.csv,sha256=TzoqamsV_N3d3lW7SKmj14zZVX4FOOg9jJcsC5U9pbA,5681 +matplotlib/mpl-data/sample_data/s1045.ima.gz,sha256=MrQk1k9it-ccsk0p_VOTitVmTWCAVaZ6srKvQ2n4uJ4,33229 +matplotlib/mpl-data/sample_data/topobathy.npz,sha256=AkTgMpFwLfRQJNy1ysvE89TLMNct-n_TccSsYcQrT78,45224 +matplotlib/mpl-data/stylelib/Solarize_Light2.mplstyle,sha256=PECeO60wwJe2sSDvxapBJRuKGek0qLcoaN8qOX6tgNQ,1255 +matplotlib/mpl-data/stylelib/_classic_test.mplstyle,sha256=5W84_yy5EBXn7A7g1_ky_iLurRQmCGf9fdHaD_gQ2ws,24330 +matplotlib/mpl-data/stylelib/bmh.mplstyle,sha256=-KbhaI859BITHIoyUZIfpQDjfckgLAlDAS_ydKsm6mc,712 +matplotlib/mpl-data/stylelib/classic.mplstyle,sha256=0RjtrDi0vZOzWGnt9cme_At_9GqMwHzwEBCAH9OQZ7I,24511 +matplotlib/mpl-data/stylelib/dark_background.mplstyle,sha256=-EGmoFm_35Zk7oRp29UalT56HsOSuJbYMeQGdAATnz4,477 +matplotlib/mpl-data/stylelib/fast.mplstyle,sha256=yTa2YEIIP9xi5V_G0p2vSlxghuhNwjRi9gPECMxyRiM,288 +matplotlib/mpl-data/stylelib/fivethirtyeight.mplstyle,sha256=WNUmAFuBPcqQPVgt6AS1ldy8Be2XO01N-1YQL__Q6ZY,832 +matplotlib/mpl-data/stylelib/ggplot.mplstyle,sha256=xhjLwr8hiikEXKy8APMy0Bmvtz1g0WnG84gX7e9lArs,957 +matplotlib/mpl-data/stylelib/grayscale.mplstyle,sha256=KCLg-pXpns9cnKDXKN2WH6mV41OH-6cbT-5zKQotSdw,526 +matplotlib/mpl-data/stylelib/seaborn-bright.mplstyle,sha256=pDqn3-NUyVLvlfkYs8n8HzNZvmslVMChkeH-HtZuJIc,144 +matplotlib/mpl-data/stylelib/seaborn-colorblind.mplstyle,sha256=eCSzFj5_2vR6n5qu1rHE46wvSVGZcdVqz85ov40ZsH8,148 +matplotlib/mpl-data/stylelib/seaborn-dark-palette.mplstyle,sha256=p5ABKNQHRG7bk4HXqMQrRBjDlxGAo3RCXHdQmP7g-Ng,142 +matplotlib/mpl-data/stylelib/seaborn-dark.mplstyle,sha256=I4xQ75vE5_9X4k0cNDiqhhnF3OcrZ2xlPX8Ll7OCkoE,667 +matplotlib/mpl-data/stylelib/seaborn-darkgrid.mplstyle,sha256=2bXOSzS5gmPzRBrRmzVWyhg_7ZaBRQ6t_-O-cRuyZoA,670 +matplotlib/mpl-data/stylelib/seaborn-deep.mplstyle,sha256=44dLcXjjRgR-6yaopgGRInaVgz3jk8VJVQTbBIcxRB0,142 +matplotlib/mpl-data/stylelib/seaborn-muted.mplstyle,sha256=T4o3jvqKD_ImXDkp66XFOV_xrBVFUolJU34JDFk1Xkk,143 +matplotlib/mpl-data/stylelib/seaborn-notebook.mplstyle,sha256=PcvZQbYrDdducrNlavBPmQ1g2minio_9GkUUFRdgtoM,382 +matplotlib/mpl-data/stylelib/seaborn-paper.mplstyle,sha256=n0mboUp2C4Usq2j6tNWcu4TZ_YT4-kKgrYO0t-rz1yw,393 +matplotlib/mpl-data/stylelib/seaborn-pastel.mplstyle,sha256=8nV8qRpbUrnFZeyE6VcQ1oRuZPLil2W74M2U37DNMOE,144 +matplotlib/mpl-data/stylelib/seaborn-poster.mplstyle,sha256=dUaKqTE4MRfUq2rWVXbbou7kzD7Z9PE9Ko8aXLza8JA,403 +matplotlib/mpl-data/stylelib/seaborn-talk.mplstyle,sha256=7FnBaBEdWBbncTm6_ER-EQVa_bZgU7dncgez-ez8R74,403 +matplotlib/mpl-data/stylelib/seaborn-ticks.mplstyle,sha256=CITZmZFUFp40MK2Oz8tI8a7WRoCizQU9Z4J172YWfWw,665 +matplotlib/mpl-data/stylelib/seaborn-white.mplstyle,sha256=WjJ6LEU6rlCwUugToawciAbKP9oERFHr9rfFlUrdTx0,665 +matplotlib/mpl-data/stylelib/seaborn-whitegrid.mplstyle,sha256=ec4BjsNzmOvHptcJ3mdPxULF3S1_U1EUocuqfIpw-Nk,664 +matplotlib/mpl-data/stylelib/seaborn.mplstyle,sha256=_Xu6qXKzi4b3GymCOB1b1-ykKTQ8xhDliZ8ezHGTiAs,1130 +matplotlib/mpl-data/stylelib/tableau-colorblind10.mplstyle,sha256=BsirZVd1LmPWT4tBIz6loZPjZcInoQrIGfC7rvzqmJw,190 +matplotlib/offsetbox.py,sha256=AMXlJ1_GHO3LP3YkNs99lLPR421QPQWDDV-DCTdF6Mc,54203 +matplotlib/patches.py,sha256=qqKqvsdhC7yO1M9pPPQACnK11Uv1pcKqU4ydEkn_H1A,152021 +matplotlib/path.py,sha256=GXkMzxaZrJemhGPImtkGVRqZ5czP1VA5l35kNXD3iCM,36298 +matplotlib/patheffects.py,sha256=sHAw4WFMrl3TkW1u71STyjyHjbsjLtHBi6df7PEDJiw,13804 +matplotlib/projections/__init__.py,sha256=R9NzSCA9ex2PI7gcBH6JNN83gJFYXOANVjViiJ8GZ1I,1828 +matplotlib/projections/__pycache__/__init__.cpython-36.pyc,, +matplotlib/projections/__pycache__/geo.cpython-36.pyc,, +matplotlib/projections/__pycache__/polar.cpython-36.pyc,, +matplotlib/projections/geo.py,sha256=MbpiBUmj2R_w6xr7SnZwNYm59CbqGipoIf5DNqrqC-o,17960 +matplotlib/projections/polar.py,sha256=7GJd0y4mk5UStm2j-MwGurPLTpjSPafbQvwJHZrn7d8,52193 +matplotlib/pylab.py,sha256=J_MQJT79VBIR8j6KSGmkiTe6_gH5ghVLzuERIft4NUQ,9613 +matplotlib/pyplot.py,sha256=uDdHX-gXmW-LVBMUHeKJyV8v-joy3tBH5vJVboBRSug,111125 +matplotlib/quiver.py,sha256=kI1yv4WX14s_jaS889ngra5tAV0J1hRwMxHHjQkPClU,46760 +matplotlib/rcsetup.py,sha256=q7gnVs0m4PQRpdhZvhb2_NrvPn7fRxTcGQtMgNx9Zf0,58610 +matplotlib/sankey.py,sha256=k1_QKTlsJ3hCuhiGrE08SVTHn-keVGBxgSN9AP23koA,36994 +matplotlib/scale.py,sha256=Qgagfhr3PY38v2J7ACDVNCe2kEo-8jAiMGH_8c-9c78,24265 +matplotlib/sphinxext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +matplotlib/sphinxext/__pycache__/__init__.cpython-36.pyc,, +matplotlib/sphinxext/__pycache__/mathmpl.cpython-36.pyc,, +matplotlib/sphinxext/__pycache__/plot_directive.cpython-36.pyc,, +matplotlib/sphinxext/mathmpl.py,sha256=jTqwBfxLLGjx-4TwEzwYvi2WdCoJpqHfDcbLKrgcKss,4276 +matplotlib/sphinxext/plot_directive.py,sha256=AYTbhda6HSwwvANnBU4oKV8rXZKEdlpmQJbd19jvFgw,27583 +matplotlib/sphinxext/tests/__init__.py,sha256=gTnBimTaMh3t3WC49SvyeSH0rsbWxQgjAsr5H8HRDig,23 +matplotlib/sphinxext/tests/__pycache__/__init__.cpython-36.pyc,, +matplotlib/sphinxext/tests/__pycache__/conftest.cpython-36.pyc,, +matplotlib/sphinxext/tests/__pycache__/test_tinypages.cpython-36.pyc,, +matplotlib/sphinxext/tests/conftest.py,sha256=Ph6QZKdfAnkPwU52StddC-uwtCHfANKX1dDXgtX122g,213 +matplotlib/sphinxext/tests/test_tinypages.py,sha256=VfFfCq5T3jaVN0Ut67SHpilUOzl-_zaJDnGxfGEtrgA,2022 +matplotlib/sphinxext/tests/tinypages/__pycache__/conf.cpython-36.pyc,, +matplotlib/sphinxext/tests/tinypages/__pycache__/range4.cpython-36.pyc,, +matplotlib/sphinxext/tests/tinypages/__pycache__/range6.cpython-36.pyc,, +matplotlib/sphinxext/tests/tinypages/_static/README.txt,sha256=1nnoizmUuHn5GKx8RL6MwJPlkyGmu_KHhYIMTDSWUNM,303 +matplotlib/sphinxext/tests/tinypages/conf.py,sha256=0_a4wyqPA9oaOFpLLpSEzkZI-hwtyRbqLWBx9nf0sLA,8432 +matplotlib/sphinxext/tests/tinypages/index.rst,sha256=kLSy7c3SoIAVsKOFkbzB4zFVzk3HW3d_rJHlHcNGBAg,446 +matplotlib/sphinxext/tests/tinypages/range4.py,sha256=fs2krzi9sY9ysmJRQCdGs_Jh1L9vDXDrNse7c0aX_Rw,81 +matplotlib/sphinxext/tests/tinypages/range6.py,sha256=a2EaHrNwXz4GJqhRuc7luqRpt7sqLKhTKeid9Drt2QQ,281 +matplotlib/sphinxext/tests/tinypages/some_plots.rst,sha256=C9rwV9UVlhFvxm8VqV6PoAP1AQ8Kk0LGZI9va4joif0,2156 +matplotlib/spines.py,sha256=AQQD9gNGdiIot781Mim4ZyWWvgLCYKVqj-ww9C616sk,23073 +matplotlib/stackplot.py,sha256=Xh_uFaOq4CB170_Y1dW0MONbCOyiiNnF_Rf8WKvoHaQ,3952 +matplotlib/streamplot.py,sha256=FYalqlVMTopl0KmqNaJJ8msNolPPQ58zNI8xf6GYUpU,22252 +matplotlib/style/__init__.py,sha256=EExOAUAq3u_rscUwkfKtZoEgLA5npmltCrYZOP9ftjw,67 +matplotlib/style/__pycache__/__init__.cpython-36.pyc,, +matplotlib/style/__pycache__/core.cpython-36.pyc,, +matplotlib/style/core.py,sha256=NZWf_B9uKgLHUbwqgxSWI4fsVehuUVnV5FOduIldZWU,7820 +matplotlib/table.py,sha256=2vm4FxGe9BHCC3CXvd100MoPYvGOwHLF8LzKSzsFJ0o,26743 +matplotlib/testing/__init__.py,sha256=uLOEIbWI6J62ZVGlhhKVEwKPH4IsIftXsRXH4yuX0ZY,1450 +matplotlib/testing/__pycache__/__init__.cpython-36.pyc,, +matplotlib/testing/__pycache__/compare.cpython-36.pyc,, +matplotlib/testing/__pycache__/conftest.cpython-36.pyc,, +matplotlib/testing/__pycache__/decorators.cpython-36.pyc,, +matplotlib/testing/__pycache__/determinism.cpython-36.pyc,, +matplotlib/testing/__pycache__/disable_internet.cpython-36.pyc,, +matplotlib/testing/__pycache__/exceptions.cpython-36.pyc,, +matplotlib/testing/compare.py,sha256=skna_3nIabji3tRtIE0PGg7NnKpFTXvm9xmBk9zJbh8,18516 +matplotlib/testing/conftest.py,sha256=6-91kiLK4nhUsCKaJ2WQe6pn5mIAh8KBtIhuHVvtV5g,3311 +matplotlib/testing/decorators.py,sha256=yhyMJ99GfGFfp8XsQGRHmg5G7ApRh1Ue8t1qC3lVfXY,19621 +matplotlib/testing/determinism.py,sha256=GM-4kW3Qc0GNdzqKjm6qncK-RWY9ougjQACGXJyxVMw,4379 +matplotlib/testing/disable_internet.py,sha256=prxLEWAtV4HR1Jy9lleh5Q5KgWWAeJ7eJIrhlLX9NRo,4777 +matplotlib/testing/exceptions.py,sha256=72QmjiHG7DwxSvlJf8mei-hRit5AH3NKh0-osBo4YbY,138 +matplotlib/testing/jpl_units/Duration.py,sha256=Qv9ImFIv6fZMu-fimFTrlwPUa2hOcxF2cUhCVv9eFZc,5094 +matplotlib/testing/jpl_units/Epoch.py,sha256=oluM2cU43QDmBV6BfglZIbu9gU3thGOMZLZMjJf36gc,6426 +matplotlib/testing/jpl_units/EpochConverter.py,sha256=mOk4H0fnUIStuo_ofpjGFA-GPPqAcCiWEdenyJLeewE,4467 +matplotlib/testing/jpl_units/StrConverter.py,sha256=tISoIplCkBQjZGzCSD2n61bHK79_yhF6wPLc7CLAhMg,4565 +matplotlib/testing/jpl_units/UnitDbl.py,sha256=c4IaywqWi721P2S017p71jQLW5p5jk_17aeRymR3HuI,7791 +matplotlib/testing/jpl_units/UnitDblConverter.py,sha256=dtANG332ygFdqzx_t6CUxVNaCbNfBKFoPVDAWNcEYJU,4584 +matplotlib/testing/jpl_units/UnitDblFormatter.py,sha256=TOGtaP4AoWzTNT_mziajOfEwT0x_LwF6IAbo_WnTTy0,937 +matplotlib/testing/jpl_units/__init__.py,sha256=Bp4Lz_eqRuxNWO_l3VvhuurFZaUmZIlvcF3N0UBmzHc,2692 +matplotlib/testing/jpl_units/__pycache__/Duration.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/Epoch.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/EpochConverter.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/StrConverter.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/UnitDbl.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/UnitDblConverter.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/UnitDblFormatter.cpython-36.pyc,, +matplotlib/testing/jpl_units/__pycache__/__init__.cpython-36.pyc,, +matplotlib/tests/__init__.py,sha256=ns6SIKdszYNXD5h5PqKRCR06Z45H-sXrUX2VwujSRIM,366 +matplotlib/tests/__pycache__/__init__.cpython-36.pyc,, +matplotlib/tests/__pycache__/conftest.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_afm.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_agg.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_agg_filter.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_animation.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_arrow_patches.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_artist.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_axes.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_bases.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_cairo.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_nbagg.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_pdf.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_pgf.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_ps.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_qt.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_svg.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backend_tools.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_backends_interactive.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_basic.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_bbox_tight.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_category.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_cbook.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_collections.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_colorbar.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_colors.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_compare_images.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_constrainedlayout.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_container.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_contour.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_cycles.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_dates.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_dviread.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_figure.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_font_manager.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_gridspec.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_image.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_legend.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_lines.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_marker.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_mathtext.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_matplotlib.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_mlab.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_offsetbox.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_patches.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_path.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_patheffects.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_pickle.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_png.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_preprocess_data.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_pyplot.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_quiver.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_rcparams.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_sankey.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_scale.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_simplification.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_skew.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_spines.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_streamplot.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_style.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_subplots.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_table.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_texmanager.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_text.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_ticker.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_tightlayout.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_transforms.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_triangulation.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_ttconv.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_type1font.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_units.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_usetex.cpython-36.pyc,, +matplotlib/tests/__pycache__/test_widgets.cpython-36.pyc,, +matplotlib/tests/cmr10.pfb,sha256=_c7eh5QBjfXytY8JBfsgorQY7Y9ntz7hJEWFXfvlsb4,35752 +matplotlib/tests/conftest.py,sha256=QtpdWPUoXL_9F8WIytDc3--h0nPjbo8PToig7svIT1Y,258 +matplotlib/tests/mpltest.ttf,sha256=Jwb2O5KRVk_2CMqnhL0igeI3iGQCY3eChyS16N589zE,2264 +matplotlib/tests/test_afm.py,sha256=M8TSB0eNOgcLteDJwSSc1GSa6fYcvC0HQd60djKMhKs,2632 +matplotlib/tests/test_agg.py,sha256=wg04wxnUWOvfoUw_x1oObhiAkI2Ta4UBh0gCq_Xqm8s,8041 +matplotlib/tests/test_agg_filter.py,sha256=sfntvGVUuCaGqU3DdOnTRXqq0P1afVqWuaV_ZEYh8kQ,969 +matplotlib/tests/test_animation.py,sha256=Lph8VbnnecSzIQVQ4WFagp1hwdYs28UIg6vSywFNXPw,9657 +matplotlib/tests/test_arrow_patches.py,sha256=Q1cqQJh6NAr-JHJo3aPPJCIo8eV8_R4f3LnQHdWGzMY,5944 +matplotlib/tests/test_artist.py,sha256=M0_TIj7k0gNVhdDkLb2j36fs-9fRGtr_2SBwiXE_sfs,9431 +matplotlib/tests/test_axes.py,sha256=UuVQekUA-rOEIJoXRyBAYQLQDOg-k9o80K1N1D323SI,210869 +matplotlib/tests/test_backend_bases.py,sha256=I3Oiqk6Fm-fctj-aOxq5Av8Kqe3QLjlY-oTwTbdO6dw,3811 +matplotlib/tests/test_backend_cairo.py,sha256=UwvpWDEMU0ClH9OB4QrfDEVx1Waw40r7L4Q6Wx-bymY,1961 +matplotlib/tests/test_backend_nbagg.py,sha256=VfZtCWJ43uk87pKdNu5U5i0JBp4MLVr78MT3kre7q1Y,1021 +matplotlib/tests/test_backend_pdf.py,sha256=-S1l7M4d-c-RccvhgWmZv7YhIMkC73v-Yvx0c8ctOr8,7939 +matplotlib/tests/test_backend_pgf.py,sha256=GEYeAku09gn3erePaZMHRWVUBAFwuzdAXmrnFl5a4mc,8157 +matplotlib/tests/test_backend_ps.py,sha256=kA3wU7_nT29L9GKazE5ejTlj7L_tzDctOatlLgrpyyo,4564 +matplotlib/tests/test_backend_qt.py,sha256=Q8s1LA1DwKO_rcryVKKHi--nhOLNYXdDkPfu0uFOkoc,9645 +matplotlib/tests/test_backend_svg.py,sha256=BnDG5OnTp7V7BbbA_dKe8fbbSlgUcnqzTNu6vBIT5MQ,5854 +matplotlib/tests/test_backend_tools.py,sha256=C-B7NCkyWsQ5KzQEnI5Be16DsAHHZJU9P5v9--wsF-o,501 +matplotlib/tests/test_backends_interactive.py,sha256=QsdZhWATJPh3ZYM2F90MRQCyoW3ROUOGXYgrM0XUxsc,5018 +matplotlib/tests/test_basic.py,sha256=IQI1prekIUiqbPVEiVfR9gxpB8B97glTkIvdiuKSJpw,1216 +matplotlib/tests/test_bbox_tight.py,sha256=Jfy0JvhSlSaH9NMl--AEpT2kXxuBownLc9X-t5BxA_0,3997 +matplotlib/tests/test_category.py,sha256=HJ1oBEZD0A6wHUnrz49kymv93UX0fkkdFCclIBrI09w,10303 +matplotlib/tests/test_cbook.py,sha256=HUJtyEg9qW6Bjfg5Y9xCgNdRvC7giqElgMDruBYri1g,18807 +matplotlib/tests/test_collections.py,sha256=q1yd5k4SfzAUxOQocBY4az1O94oVLKZ-CntwVOBeVJo,23910 +matplotlib/tests/test_colorbar.py,sha256=b8r2M_MPRL0KRPd-WLFAu8mL_okOEzI6m3dg3J3h0-s,21345 +matplotlib/tests/test_colors.py,sha256=9_0NGS8xYRGXg6NV8fiiVBX02sSWlE9HZtw_XyJvlTI,29456 +matplotlib/tests/test_compare_images.py,sha256=n3Uoukid0GcjyQpd6ZrqIY9u3RLNE2XAPWwtcHIsqto,3155 +matplotlib/tests/test_constrainedlayout.py,sha256=EXT4HsqVcIsncAAplHaMiDLyf5UtjckwvMRsCgUvSSE,13211 +matplotlib/tests/test_container.py,sha256=ijZ2QDT_GLdMwKW393K4WU6R7A5jJNaH1uhLRDwoXXI,550 +matplotlib/tests/test_contour.py,sha256=HydLrcjlRvqWQjmI7vJvgrK0NWKZGrbKUDU30whCJPA,12980 +matplotlib/tests/test_cycles.py,sha256=mhofUWZPXHTjj3EtwU_dqqm3MzqZcnMq31geTVZwhDo,7474 +matplotlib/tests/test_dates.py,sha256=Pu7B_muQW0ZK8obhelgyNGFrNdkrk2BWy92f5nUrSLU,33273 +matplotlib/tests/test_dviread.py,sha256=kTk9Qv6q9Kk3fJcDAEWm35HF-sKsP6Ybec6N8jEHasE,2342 +matplotlib/tests/test_figure.py,sha256=TN9Fl8Ievtkb-gjOM0PeUqi4Kaz6zaGifG2tGOGJabw,14054 +matplotlib/tests/test_font_manager.py,sha256=7zPeJpzN_fwes7uYsZwqAYOsnYlZW3-KOr3j-rUUlAs,7163 +matplotlib/tests/test_gridspec.py,sha256=zahj5Rd4pB0xtAc_3KX7fQWyBys0P-IQk-Cq0cs8VgY,626 +matplotlib/tests/test_image.py,sha256=0hAVfnF02tMg9LRkv8uOrGnVcrWz1KfSZRheSx4dLRk,30934 +matplotlib/tests/test_legend.py,sha256=r6ejU9Vn-gxXxiqqtDLPPhccnEV65hbtCdsvvTo5F1Y,20073 +matplotlib/tests/test_lines.py,sha256=VTgCoKIXunTGi76DCbbMXhSs98hJ8xSK0qa_u1LwUmY,6198 +matplotlib/tests/test_marker.py,sha256=fhHHW93wCl5KbrZRL2iEVziv2BLBZU6zSt66hgsI5jY,739 +matplotlib/tests/test_mathtext.py,sha256=XbrtJ0_PcG13DVIUyMK4TuzWYF9QfZzdqTcxN3XqTkw,13063 +matplotlib/tests/test_matplotlib.py,sha256=DIBqISzUIYanSxNWJL9n2oob1dRLOOAr6TIz2BTWK1I,706 +matplotlib/tests/test_mlab.py,sha256=KZvV7S24Qc8hR6WG40nnFFdgPJbRvAOxIk2SXrAJwXo,90295 +matplotlib/tests/test_offsetbox.py,sha256=u_VCL-lWvQ66IGTzuotzRxq23ySzcB86Gjvmeib-S3w,4198 +matplotlib/tests/test_patches.py,sha256=pgQDb92u4Rz8ONRVJcWdJLiqVxZuy3Jx2dVhcRTwJEc,16862 +matplotlib/tests/test_path.py,sha256=-Jt3IU4DY_yL-f5T6e2JiO61fJOK0L5uAlxiQCBTLpM,12115 +matplotlib/tests/test_patheffects.py,sha256=Sl90AY4wri37bEvRuS3QEthE_GV5i5drh0Yk2oGJjc0,5372 +matplotlib/tests/test_pickle.py,sha256=luHci_HlSaH6IDh-889uMX66I7uq_GKUEpgLR2AH5lE,5481 +matplotlib/tests/test_png.py,sha256=3TieTdSRvSL9mS7bhxpozw1CClQxKYunK83TLPU4bnA,1786 +matplotlib/tests/test_preprocess_data.py,sha256=3UGFRtQGoBxM4MsxsVUCqfZgh0elEG6oQ1C8NGzB8AA,10027 +matplotlib/tests/test_pyplot.py,sha256=9KEPaGTyHduk7vi40kbva03HFk7bm8KrGlWjkBGMoQ0,1662 +matplotlib/tests/test_quiver.py,sha256=CggxfJ6RkNj1CtM-ZvzcKccpnIb41AujAiSmJa1iOXw,7184 +matplotlib/tests/test_rcparams.py,sha256=_pNDlC7PrCHPXS28eBJmlFuRD2cr0EwLp_MU5HjOuIM,19593 +matplotlib/tests/test_rcparams.rc,sha256=zwPbYzajd7FTIYURvpwTBAn8i060Do3OVDGZ2xHZeLw,74 +matplotlib/tests/test_sankey.py,sha256=KdWhgZpEiCJ8o7yuFjnCgqFeodwKSCuuhV_mhIc04dM,310 +matplotlib/tests/test_scale.py,sha256=z1-lHkTpXkpe4spHOTILGr9aSSbMHMAI5-3bXJyjsU8,5632 +matplotlib/tests/test_simplification.py,sha256=d8FXKuaiFnYZKJKzMRWzsYkjD5_3nLEMwCcZPAEAUYk,10889 +matplotlib/tests/test_skew.py,sha256=sY_LEdtoNPY3KAepaXhIngQ3_dSUNWL-5jmv4O8x0yo,6342 +matplotlib/tests/test_spines.py,sha256=1cN5KequShVG83DggeUxt5QWE9uIkfmyONaoVNJOojw,2326 +matplotlib/tests/test_streamplot.py,sha256=5p8PH0WvT5f3UNmcVSFRyiFKhhJ5T7-ytDMU_JrXvuA,3495 +matplotlib/tests/test_style.py,sha256=BRL-_OH6E-VTwzMQRPuFzXW8ZUIkaZSyNEyNJ3DIuL0,5309 +matplotlib/tests/test_subplots.py,sha256=yMzfFiUpZBcBt2FpLFySHzxmoj2B4jevjLviFWkPouo,5551 +matplotlib/tests/test_table.py,sha256=1Ksl98_jzSuJFpRBKGmLh5Q4YX7NiC9u3WJdlCPcZe8,5905 +matplotlib/tests/test_texmanager.py,sha256=zCtJ3JnZNfP2AQNy7q2LQAgaflSe7S5htJkJNylQSGE,459 +matplotlib/tests/test_text.py,sha256=t3t-s9EReWNcGIFqHXfeHoKo0Y3qpRoT-JBmPd6O5og,18473 +matplotlib/tests/test_ticker.py,sha256=F_kHe9zKgypli_WGwXdCZbBtJY_kqDTfFhexfISGKJk,38272 +matplotlib/tests/test_tightlayout.py,sha256=S9D9MBbZYlyA2YWzE1_0bC8ylsfau2AUYy0j32DrEog,10376 +matplotlib/tests/test_transforms.py,sha256=i1EfTglebgAmNgrUzdGUSlx4ODuFCYnwxBiK-BZJ3aM,24705 +matplotlib/tests/test_triangulation.py,sha256=MvICjPsFt1whjQCX8F7UaaQ9UHY9KgMHckfZKiJzJL8,45654 +matplotlib/tests/test_ttconv.py,sha256=xilgvzZpTpHSnumaUlHvQ_zdIQ7U7xBD1Aflx34I-xU,641 +matplotlib/tests/test_type1font.py,sha256=C0pCPBGOv49SR2xxDOq6LSXAEH_ZNvIWvr_jG-23Gmc,2097 +matplotlib/tests/test_units.py,sha256=sKmHGFKJOQ_Vjlzq6wkMSJHKq67R3CAxyLXG15RQSIE,5549 +matplotlib/tests/test_usetex.py,sha256=ea0JMvk-zd_sVtJ4Ku7PlC0SqKg3gvWYSjoZVg9EioI,1077 +matplotlib/tests/test_utf32_be_rcparams.rc,sha256=K66jcKehDKcG1yTXJCOSsmp1iteU9Kvsd_eobV5wNW4,56 +matplotlib/tests/test_widgets.py,sha256=BoaOqayjM2imF3usdtirD0wrq0_X75ShkIFlLV04D5M,17617 +matplotlib/texmanager.py,sha256=jpDBr6bvnlhUnLw8OXX1qtpU7wkh2jNzxIDnDtzAlG8,16639 +matplotlib/text.py,sha256=wF6sXYH59pIL9ZhAqL2S9Q6Y2fBCDyfC01TKh7mGjDo,81000 +matplotlib/textpath.py,sha256=DaW0UIZddHcvJrwwPbIQCRiPvvXgEgfcozC1jBCr3xU,17932 +matplotlib/ticker.py,sha256=J9RSb8T5VRBBROhmimnVhIDiPDtDlBYTEnVGyLl-d2Q,93130 +matplotlib/tight_bbox.py,sha256=bQAOXPKfVWoBkGZbC0ckRcldgLJ8eBUe2IsT8UQpgaY,2590 +matplotlib/tight_layout.py,sha256=L2k1a7i4k3bp_Hoes6SYhkTl5b9DJGn6eO-eLc60yCI,14656 +matplotlib/transforms.py,sha256=1feN91_7mlnutbiMzDwhoubWj8HRWDwTFtv6YyWzLVw,97557 +matplotlib/tri/__init__.py,sha256=XMaejh88uov7Neu7MuYMyaNQqaxg49nXaiJfvjifrRM,256 +matplotlib/tri/__pycache__/__init__.cpython-36.pyc,, +matplotlib/tri/__pycache__/triangulation.cpython-36.pyc,, +matplotlib/tri/__pycache__/tricontour.cpython-36.pyc,, +matplotlib/tri/__pycache__/trifinder.cpython-36.pyc,, +matplotlib/tri/__pycache__/triinterpolate.cpython-36.pyc,, +matplotlib/tri/__pycache__/tripcolor.cpython-36.pyc,, +matplotlib/tri/__pycache__/triplot.cpython-36.pyc,, +matplotlib/tri/__pycache__/trirefine.cpython-36.pyc,, +matplotlib/tri/__pycache__/tritools.cpython-36.pyc,, +matplotlib/tri/triangulation.py,sha256=jhyKbeNgAhhA84oML-ygtKOQ3AwOf_HTD7TX4Z5lk6E,8415 +matplotlib/tri/tricontour.py,sha256=JGmjZ1uQcKiDxs6crme17mnxTmBMMTjYUmspCwAlhnk,9788 +matplotlib/tri/trifinder.py,sha256=g0q96yL7CKowfGI_3mtQX9U7OLDpg-lppGQVnWRmocA,3510 +matplotlib/tri/triinterpolate.py,sha256=KvMgcygsBJJfx1fIvKk4-mR8QmFL1QzRKpxsvfKCuHo,65020 +matplotlib/tri/tripcolor.py,sha256=SVcG8nPfHcjkWm_DEL68rcy6RDB6SaXsRymTuYkGeYM,5242 +matplotlib/tri/triplot.py,sha256=aZ9O_VVLH0AOne31u11ltLlyVyhqKtyzec7WH3b3pkk,2857 +matplotlib/tri/trirefine.py,sha256=5ntGB8rcY_LkcSgMl2lD-7TOjbKaRNtWSY8inegn7g4,13828 +matplotlib/tri/tritools.py,sha256=MontOCHIx0QSysOB9TtQlf9lZbPUVkbXFk14TzWHRCM,12422 +matplotlib/ttconv.cpython-36m-x86_64-linux-gnu.so,sha256=DhFx2UOow2EkHvRhRhsIYL-lCKzlfCA9nAKyB8_lZpA,83888 +matplotlib/type1font.py,sha256=aBak-e5VKpZpH_LyYqNUyAX4vgRisZq4sfeEcV45-j4,12173 +matplotlib/units.py,sha256=ax1Nv_are42KiqXfAplJsIjb4WPSpILVt7nxJM15irk,5637 +matplotlib/widgets.py,sha256=tCUhJKAmwG03F6GDAWn44NIcdNgZjuqMNqi6ZeFR-nA,95461 +mpl_toolkits/axes_grid/__init__.py,sha256=d0j8ET68OmR22G59uzWO4BQ3Jv2kCmJC15nZRAf227M,559 +mpl_toolkits/axes_grid/__pycache__/__init__.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/anchored_artists.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/angle_helper.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axes_divider.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axes_grid.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axes_rgb.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axes_size.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axis_artist.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axisline_style.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/axislines.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/clip_path.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/colorbar.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/floating_axes.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/grid_finder.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/grid_helper_curvelinear.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/inset_locator.cpython-36.pyc,, +mpl_toolkits/axes_grid/__pycache__/parasite_axes.cpython-36.pyc,, +mpl_toolkits/axes_grid/anchored_artists.py,sha256=_F6-9iacZidb5JpJ8jCOZ9PdiZaR5qpfBjf-3VjTzNc,291 +mpl_toolkits/axes_grid/angle_helper.py,sha256=Tb4Mb_NGkUdkisebe2dqfBdFmUZiSmGyUnftiSeSIls,51 +mpl_toolkits/axes_grid/axes_divider.py,sha256=Q1NvDXXtKVuX7iUoKFFRw11Wg1eHEGt3-qDWG7DOVxg,269 +mpl_toolkits/axes_grid/axes_grid.py,sha256=t2Fc8fM-_qINumuDxctOEYhMI3M1ZfqEVc3th-cnz5g,152 +mpl_toolkits/axes_grid/axes_rgb.py,sha256=d3h2tImoPxvVtl8i4IBA_i1vBQykZDYizcNDGdjRltE,201 +mpl_toolkits/axes_grid/axes_size.py,sha256=v4Nhxe7DVp1FkKX03DqJJ1aevDanDvgKT9r0ouDzTxw,48 +mpl_toolkits/axes_grid/axis_artist.py,sha256=zUlJFUHueDsMtzLi_mK2_Wf-nSBQgiTsMOFpo_SngZ0,50 +mpl_toolkits/axes_grid/axisline_style.py,sha256=lNVHXkFWhSWPXOOfF-wlVkDPzmzuStJyJzF-NS5Wf_g,53 +mpl_toolkits/axes_grid/axislines.py,sha256=kVyhb6laiImmuNE53QTQh3kgxz0sO1mcSMpnqIdjylA,48 +mpl_toolkits/axes_grid/clip_path.py,sha256=s-d36hUiy9I9BSr9wpxjgoAACCQrczHjw072JvArNvE,48 +mpl_toolkits/axes_grid/colorbar.py,sha256=DckRf6tadLeTNjx-Zk1u3agnSGZgizDjd0Dxw1-GRdw,171 +mpl_toolkits/axes_grid/floating_axes.py,sha256=i35OfV1ZMF-DkLo4bKmzFZP6LgCwXfdDKxYlGqjyKOM,52 +mpl_toolkits/axes_grid/grid_finder.py,sha256=Y221c-Jh_AFd3Oolzvr0B1Zrz9MoXPatUABQdLsFdpw,50 +mpl_toolkits/axes_grid/grid_helper_curvelinear.py,sha256=nRl_B-755X7UpVqqdwkqc_IwiTmM48z3eOMHuvJT5HI,62 +mpl_toolkits/axes_grid/inset_locator.py,sha256=qqXlT8JWokP0kV-8NHknZDINtK-jbXfkutH_1tcRe_o,216 +mpl_toolkits/axes_grid/parasite_axes.py,sha256=kCFtaRTd0O8ePL78GOYvhEKqn8rE9bk61v0kVgMb6UE,469 +mpl_toolkits/axes_grid1/__init__.py,sha256=SEWPa2ggZnKkFVX4yaJOPN7KgyV_T-cyjr8UjIjjhPs,272 +mpl_toolkits/axes_grid1/__pycache__/__init__.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/anchored_artists.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/axes_divider.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/axes_grid.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/axes_rgb.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/axes_size.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/colorbar.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/inset_locator.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/mpl_axes.cpython-36.pyc,, +mpl_toolkits/axes_grid1/__pycache__/parasite_axes.cpython-36.pyc,, +mpl_toolkits/axes_grid1/anchored_artists.py,sha256=0wZQvCKuWwuhFN8TY9hSQeO3ijbr8mBOWPnNQEIXuOM,21042 +mpl_toolkits/axes_grid1/axes_divider.py,sha256=_heH2djdTbeYSomi2e-szYp9ht-C9oqHK_FDmx_YhV8,29673 +mpl_toolkits/axes_grid1/axes_grid.py,sha256=lobcv7sjoWENowW16X9Jsogfkdan0M3QkP-2jfPFtJk,27404 +mpl_toolkits/axes_grid1/axes_rgb.py,sha256=H1M8P6lJbaGXPboE1U3tWXP7LAbZ3Zm1PLSkDN0mJVc,6660 +mpl_toolkits/axes_grid1/axes_size.py,sha256=UbYK3RSlnGsiejIm0a8bIjLGF2KF5G65k826SKPd66k,8638 +mpl_toolkits/axes_grid1/colorbar.py,sha256=iK_XOIjlqfkGfFBKc2lvX8ZaTPjjBbl_BzMZ9r4PkfU,27099 +mpl_toolkits/axes_grid1/inset_locator.py,sha256=b39j5q99G9o09qp9wSmuvyB0no8GM4M91IrhAutgn0Y,23680 +mpl_toolkits/axes_grid1/mpl_axes.py,sha256=f8wQcCTuQldh2cdk5g2DGXwQfwis8_56yUO6cm7ek_k,4387 +mpl_toolkits/axes_grid1/parasite_axes.py,sha256=ug0YRJiTtA3YVikdKMGj-qjoeOFnqNw2QnRab0Qp7wI,13570 +mpl_toolkits/axisartist/__init__.py,sha256=2zsgjqTtP_NXv78MEaKabmfmkjA7yhy77pIcaR57YWs,748 +mpl_toolkits/axisartist/__pycache__/__init__.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/angle_helper.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/axes_divider.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/axes_grid.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/axes_rgb.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/axis_artist.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/axisline_style.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/axislines.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/clip_path.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/floating_axes.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/grid_finder.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/grid_helper_curvelinear.cpython-36.pyc,, +mpl_toolkits/axisartist/__pycache__/parasite_axes.cpython-36.pyc,, +mpl_toolkits/axisartist/angle_helper.py,sha256=nXbshd8AutGEmpAmnAo2z1yzvvEsYVy6vhBxGOnDy-g,12633 +mpl_toolkits/axisartist/axes_divider.py,sha256=FqYC72nAYkmU9oaawDb7TjMxb1NSjhbYocD1vxwCrvM,509 +mpl_toolkits/axisartist/axes_grid.py,sha256=vfd_EXHuYQ7iIVK2FOm6inLhb7huZxtOSvFyOVW2GmU,610 +mpl_toolkits/axisartist/axes_rgb.py,sha256=TpJCB8eA0wHZVXOxxfFoy1Tk_KFj68sZvo74doDeHYE,179 +mpl_toolkits/axisartist/axis_artist.py,sha256=1io56PlZIyWrkFUai9WOvCjuT8Ux_7P5k_JfWddyD2g,44162 +mpl_toolkits/axisartist/axisline_style.py,sha256=1YU7NMRDol7eMV1SGL76al74N93d5vRpByOJX6hR7cY,5104 +mpl_toolkits/axisartist/axislines.py,sha256=MZTlK87Qp4EquI1kDgXe2NHUaVlY-vlUnohHn6-xkCk,21415 +mpl_toolkits/axisartist/clip_path.py,sha256=CEW9HRQXkBGpW4KQTqE-APyZRzOdt88FjQMx2HmbDa8,3780 +mpl_toolkits/axisartist/floating_axes.py,sha256=j0kMaapcLLUxb6ZFXp-8puMPScop8pOXP1CZavbBHRw,16007 +mpl_toolkits/axisartist/grid_finder.py,sha256=UWQVUhoW1JNqERTES2SispPpmAWmVryxKfBIu-Oatc8,11376 +mpl_toolkits/axisartist/grid_helper_curvelinear.py,sha256=9NCYT8WbNxnFO7Quu6hXNQv0FhmXkmkN7PJfwn3W8dw,14881 +mpl_toolkits/axisartist/parasite_axes.py,sha256=1sQwBEYuXHpaEeObb7cXh0I1xWroYtcvFiEmwrzqK3w,447 +mpl_toolkits/mplot3d/__init__.py,sha256=V2iPIP9VyRhoJsFWnQf5AkfyI1GSSP9H6hICEe9edJo,27 +mpl_toolkits/mplot3d/__pycache__/__init__.cpython-36.pyc,, +mpl_toolkits/mplot3d/__pycache__/art3d.cpython-36.pyc,, +mpl_toolkits/mplot3d/__pycache__/axes3d.cpython-36.pyc,, +mpl_toolkits/mplot3d/__pycache__/axis3d.cpython-36.pyc,, +mpl_toolkits/mplot3d/__pycache__/proj3d.cpython-36.pyc,, +mpl_toolkits/mplot3d/art3d.py,sha256=UsVdjuOdebSpZ9hIit2LXpNyqKyQFZ1XXTblyBFYg4U,27021 +mpl_toolkits/mplot3d/axes3d.py,sha256=jcgeBpJBl83Caqz1Yz7-qHcEIqgBr3mjDCQl41_F_kU,103965 +mpl_toolkits/mplot3d/axis3d.py,sha256=f5twzlpZI8vdKHuf7EMvdHmSTz-Afd51_S5eP5SsbRA,18050 +mpl_toolkits/mplot3d/proj3d.py,sha256=LVjwKrQf24NBOKQDMFrWEVoBf0tC3NBabF3DY8bN7jo,5488 +mpl_toolkits/tests/__init__.py,sha256=iPdasxJf0vpIi11tQ98OVSQgS0UaPUyOEGGfAryAhIA,381 +mpl_toolkits/tests/__pycache__/__init__.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/conftest.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axes_grid.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axes_grid1.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_angle_helper.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_axis_artist.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_axislines.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_clip_path.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_floating_axes.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_grid_finder.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_axisartist_grid_helper_curvelinear.cpython-36.pyc,, +mpl_toolkits/tests/__pycache__/test_mplot3d.cpython-36.pyc,, +mpl_toolkits/tests/baseline_images/test_axes_grid/imagegrid_cbar_mode.png,sha256=yvo6erXXc3Z9aO0rrEezBooCc6KhAw7wKv4WngOQmFA,87393 +mpl_toolkits/tests/baseline_images/test_axes_grid1/anchored_direction_arrows.png,sha256=XMZGgG7_9k96bKhI2G--XBVKpct5O5psbGH2Wvj5YA0,10784 +mpl_toolkits/tests/baseline_images/test_axes_grid1/anchored_direction_arrows_many_args.png,sha256=fkPsdmhd4S1g-QxMb55M63iAgWmC2G4ytcLOT9tMAD0,11039 +mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.pdf,sha256=eW2CuM_T4d95dC-DU0PmmQD7gqRQIO0rcQpvp-zu1i4,25446 +mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.png,sha256=VfRfs6p4akgjGxxNm6Bu83Pg0v1KmU7WPu97_-kzNFc,48825 +mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.svg,sha256=usfsa3y-s-N2KMOzsOZHTq-PZXgAPXsSM-lkxJ3ZUi0,172812 +mpl_toolkits/tests/baseline_images/test_axes_grid1/fill_facecolor.png,sha256=Tkrylxebxm8SuWZjQK0qXSX8m9QsQU6kYm7L2dgt4yg,14845 +mpl_toolkits/tests/baseline_images/test_axes_grid1/image_grid.png,sha256=HIg43mbdOUyEWY-jQ1DEpG7DMqCcWbX1Xf2itmW1YL4,3786 +mpl_toolkits/tests/baseline_images/test_axes_grid1/inset_axes.png,sha256=RQmR39E6Vskvl7G4LInHibW9E1VK0QgCvI-hBlb-E2E,9928 +mpl_toolkits/tests/baseline_images/test_axes_grid1/inset_locator.png,sha256=bQKKKUuoU_EZwZT_9FzzeVKsKwUUBOZV55g4vVUbnCU,9490 +mpl_toolkits/tests/baseline_images/test_axes_grid1/inverted_zoomed_axes.png,sha256=rvglsLg8Kl9jE_JukTJ5B3EHozsIYJsaYA0JIOicZL8,25997 +mpl_toolkits/tests/baseline_images/test_axes_grid1/twin_axes_empty_and_removed.png,sha256=0YzkFhxs4SBG_FEmnWB10bXIxl9aq7WJveQAqHm0JrQ,37701 +mpl_toolkits/tests/baseline_images/test_axes_grid1/zoomed_axes.png,sha256=mUu8zJtz8FMb7h5l4Cfp3oBi9jaNR5OoyaDgwqpAZp4,25893 +mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist.png,sha256=qdlk9UPScCAN9RBOhoNqLmJvmkXt8pCuwuQtrz5E8Bs,10151 +mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_labelbase.png,sha256=An5lovtvAiNA1NZI-E8kOj6eYTruQMqwf3J7pXwdk4A,10598 +mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_ticklabels.png,sha256=7vuAKkIqcpgJrc2AF7oslf-E_sDfSlCoymyc87u4AWs,5696 +mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_ticks.png,sha256=CkVtCWG13ViW0w2DsbzfXSvoFWHYaaqQYeEYpbKbOg8,5695 +mpl_toolkits/tests/baseline_images/test_axisartist_axislines/ParasiteAxesAuxTrans_meshplot.png,sha256=FOgl-Glmzhdp6V8mz4StofTsFXGysFkEcUeaWtmJDZs,34354 +mpl_toolkits/tests/baseline_images/test_axisartist_axislines/Subplot.png,sha256=tRpYCjR5zUkafA85DVmY3duTEouwCZq6jDwSF4UsBS8,26919 +mpl_toolkits/tests/baseline_images/test_axisartist_axislines/SubplotZero.png,sha256=3kCrz7HQMYrK3iDgYgf8kyigxRtIGFBbcUzJPtiXh_E,28682 +mpl_toolkits/tests/baseline_images/test_axisartist_clip_path/clip_path.png,sha256=BtMyb7ZawcgId9jl1_qW72lU_ZyxLN780uQ9bCLjbHA,25701 +mpl_toolkits/tests/baseline_images/test_axisartist_floating_axes/curvelinear3.png,sha256=4th7Y74_9YV6X25RqJW0Op9WDzGRCcxF1kfNogkgozE,52835 +mpl_toolkits/tests/baseline_images/test_axisartist_floating_axes/curvelinear4.png,sha256=cYjrSiH6Mvor-VhmwNUgX7Le3_k1rurpd8L5vhTf16s,29374 +mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/axis_direction.png,sha256=3fue92dg-ntYI0XX0nB31IFpgRT2V3izqjrmLvEdYN4,40536 +mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/custom_transform.png,sha256=4cQhIFK1z8oPUVyvkHNZ_m-GCbikmUbTvkvYVGy6U4o,15118 +mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/polar_box.png,sha256=wWaPM3I7_435SkVQqIggb8BHrWBMWrsSVyMZQQJ6fE4,62526 +mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_cla.png,sha256=htnP1CA8dd85KqdnOsHVlsehT90MUoQD8kFTyra0AuE,51409 +mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_labelpad.png,sha256=zrLsk8t7s970yaY3cqj6SOMbI6UY8Loe0Zbp0WqFtwQ,66817 +mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_ortho.pdf,sha256=zkfSOR2bJYC_X425qnXHMmGJPSlLSpFs53YB_R760Gw,6603 +mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_ortho.png,sha256=SoyN30SsuvEECZyB_ReGP3ZKGZJazOp05dXa3YUn7Jc,47796 +mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_ortho.svg,sha256=Kb_zdIzZG6JKnztMcmOUG4esPsuteljB_A2sxrhIA3Y,18046 +mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d.pdf,sha256=YI5gzs8NK6fWo6JB0wf8xeZ-FrHlS3P8DSCccsLU4fE,7197 +mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d.png,sha256=Qw909B4nDmV9DlMuo1DKk7y5ndjtvni5d_DcysmG9VA,100466 +mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d.svg,sha256=iU1Pk60SDC89km6bwz9Li9mXdNdZ_Vn15bkbAUG2iKo,30591 +mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d_notshaded.png,sha256=soaHKytaVZHmPvHIEcPFQDJDqhEEuNO_JIVCZyjacxM,66294 +mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d_shaded.png,sha256=laBssZyuviouRe3seffJWOz45OLunXC0dFHi-lYge1w,115939 +mpl_toolkits/tests/baseline_images/test_mplot3d/contour3d.pdf,sha256=CtzH5MJNMY_hZGAyp9py9PLI0a8kJ-jNnpQKQYtoQEE,25170 +mpl_toolkits/tests/baseline_images/test_mplot3d/contour3d.png,sha256=tii1IakS8MC_Vuwd95HhcyM0iq4zGN5DxgRFfB9mKu8,83161 +mpl_toolkits/tests/baseline_images/test_mplot3d/contour3d.svg,sha256=3VjmHaN5hRXJ-HH9duS1M6nR8gkgBOCtb3zruWcSujU,67618 +mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d.pdf,sha256=H7FyZjuiA12CzP8FDDnVNf42HxGfMlg_8rA57HA1sIo,52812 +mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d.png,sha256=Jb-fhAcgogE8jn9DSsaqInUfWC7D_5Pf3QRf7XWAX2Q,42575 +mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d.svg,sha256=cz9TicdIGJ_8UdHTKQZ76n2rAv6Rx2EELPg8AyAEgMU,173077 +mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d_fill.pdf,sha256=raTRNOdfYPFJvZiM7BbRbdWRPElQe0sn6jsKH63TTyA,3950 +mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d_fill.png,sha256=dE8eHoj43eePB44F1nLM2RLj8iqw8rCYI3D0VD3gUg0,39694 +mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d_fill.svg,sha256=BM-PcmZJ-8iyB4wUWQxcMuskmDXemrsX52LKPYEz850,11093 +mpl_toolkits/tests/baseline_images/test_mplot3d/lines3d.pdf,sha256=6pKrI8lUIPxRwi3ofm8DK8UqNeZsBYprXwX51vwFv1Y,4354 +mpl_toolkits/tests/baseline_images/test_mplot3d/lines3d.png,sha256=DQT-NruHCeG5LKpjG-dlLln3aCoPKhua5PQnHTafBGU,60217 +mpl_toolkits/tests/baseline_images/test_mplot3d/lines3d.svg,sha256=c32m_X6tFYlY5PCVYJ0cPzvZDTbgRA-GIwzDUVTNKYA,12919 +mpl_toolkits/tests/baseline_images/test_mplot3d/mixedsubplot.pdf,sha256=knDLOPbYAI0WPLwXaVuH_vlVODceOPIIzEI_Q3Q1dUU,53964 +mpl_toolkits/tests/baseline_images/test_mplot3d/mixedsubplot.png,sha256=iHxYbxRflxIpjoAtWo9KAvgK4CS-k4N03p0SX_xF4DA,39674 +mpl_toolkits/tests/baseline_images/test_mplot3d/mixedsubplot.svg,sha256=TQ9KQlKC0BU4lnayB2S8ArbsfAh87qKjFEh5WKjWbvk,286241 +mpl_toolkits/tests/baseline_images/test_mplot3d/plot_3d_from_2d.png,sha256=AWos5EJWMerD0tgVZyvBofz-5hnCq6fhGHKmQi-izAg,56593 +mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_alpha.png,sha256=AnZJbnnBnF_fny5FBTlSWblkNMlPI1dcQRlCfGPIjWI,52046 +mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_closed.pdf,sha256=mJYYIj01eM9ouCPpoeWu-KDrXe3_o2um4_JddGAzWGg,2680 +mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_closed.png,sha256=ePzSA-iFaQbmH603vw1jhs9vyIt45xXnbpIuUF3a1l8,52065 +mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_closed.svg,sha256=K-D9vp-jB8KFTilVotfIQvuhG3qTMT04XZ6LUIfpZ60,8594 +mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_axes_cube.png,sha256=AJ0EoayvdBoywpOUWcxbMQ0oB7cTzcoWGgGyx2qgQMU,23182 +mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_axes_cube_ortho.png,sha256=5Phz7BclSciZpg4SDu-eUQ-v_ikHbEqReQWCdeHywQk,16210 +mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_lines_dists.png,sha256=XCd4hX2ckc5GCxcgenkRJ8MT7pX-3iMLylD2rCjNl-4,18898 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.pdf,sha256=T4nKDMCEi2zKpoq5FOsdyMQJd0igS9yBeyUL84a0oso,18589 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.png,sha256=PBllNI1kHf1rz-oPK507OwsPNE9DPwivXAVJM9DemBI,104755 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.svg,sha256=_cwXN4aH-mQx5ADarZtXsY-vaeRFg4dPuVmP6S9NZbM,128623 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_empty.pdf,sha256=DSFSucOBU22R3zmG8eKlWWtLy5Wb7L7wqZ1B7CMybKc,7405 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_empty.png,sha256=98D3k5QIL7KugUwzqJhdLtp9dgDGgx8hGa9_u8cvX6o,37954 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_empty.svg,sha256=H_b_HtjccyLTNDjIqUek6DwQugfsyb88nVBepBzFdTo,7745 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_masked.pdf,sha256=_VIBNh32vX_K9QrH-0o4z13FAE0JZQuOzOfkCTsSe7c,10939 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_masked.png,sha256=67yp7-6f-vDiYTmCqMFfuIEGly5UHCCUOV84YJtLsX8,80392 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_masked.svg,sha256=JO8n2RUeQANeCpq_PmtyjmVPqMmuqvZQg7vk_3hsv8I,68796 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_pivot_middle.png,sha256=N4o26wMzfnyxndPbZ2VnsjIAiNYrFN9Aa40ficwO9AM,104735 +mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_pivot_tail.png,sha256=Ff_UrWxD-VIMQLN1uXy5u_Yd5e1P427YfGM05nvU2kE,104951 +mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d.pdf,sha256=93umAGrsz8bYekxMETAlU67eCTY3tzycxpVmm2M7eEE,5847 +mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d.png,sha256=MDaocusHz6Itinjm2j6fnDh-rl1fqVjnqM89nP8bwZs,43155 +mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d.svg,sha256=yc-PIx36-DdoCE1Vd8JRih45GoBR7eVtdi6wMZVZUXU,12494 +mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d_color.png,sha256=Y7De9BIFLp0Ova4fk9IcXloNjiwmifTrFA1IfVJA3aE,41598 +mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d.pdf,sha256=OSvMZiGJzmVdtv_e0XHIBw4bLSY7DLtWGDAYgh6vNuo,48096 +mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d.png,sha256=Ok0UmO2DELze2yK8mRx0CifmRAgvjyS1IvERsBRvFlU,54712 +mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d.svg,sha256=CaqTIT-jdKSKfCqp8GC_QAc_3Dxwgr97uvDR-a4xdcw,270325 +mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d_shaded.png,sha256=kWYGPWgG1ZrQVgd389xmIZ1cc59tAkKKiikKaJzHKkw,43474 +mpl_toolkits/tests/baseline_images/test_mplot3d/text3d.pdf,sha256=5yX0OZojv0yDLP5pWAPr9q_H2Rr6Y6zA1rJHlmoCcuA,13747 +mpl_toolkits/tests/baseline_images/test_mplot3d/text3d.png,sha256=sO68K3cti2YsPkkjEIAvc7_pd8JaHpc_a78UVx4Htu4,78758 +mpl_toolkits/tests/baseline_images/test_mplot3d/text3d.svg,sha256=h9yzYfY7Idnab8Rx-qri2fOrAg0fq6kMZOhUrge_CKQ,36533 +mpl_toolkits/tests/baseline_images/test_mplot3d/tricontour.png,sha256=8IjYmJP6cBhnPGLz-WDyn7UUMYZ10Kz2MpjOFwDUVow,71328 +mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d.pdf,sha256=OVbK3ausYMApR7_UJPx0pf3bt4A3CpZumhAVhzQMbs0,169155 +mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d.png,sha256=nO0gJBIluLEX3mlxXY3C6bx-9Jf_xJyXAnTXKnqrIkQ,99103 +mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d.svg,sha256=PFUTTF34KiJcol6J5JmRjkaillzRWAgsbfxgEhpWxmA,103333 +mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d_shaded.png,sha256=LSVF3lI7JnYXmCBAcn410k3JRE-3ssp84Dmgg3zr0FA,94328 +mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-alpha.png,sha256=LELjsQnfvfzLF8rNSh5azv9BdwF8TlCMn2wbBJNTtyQ,178141 +mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-edge-style.png,sha256=UJXpFMSWIFgUH2rLEv1nxDvHrnshlSz4d5ZB34upa3g,65759 +mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-named-colors.png,sha256=J8m66Bc5NoeZxGRwbBThV06_aybNvMeTtwUnmCRzNak,93580 +mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-rgb-data.png,sha256=5s02No0RWv8NYV_ccFUnDdBaUHQ8DTO90qddKBnN6mw,131458 +mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-simple.png,sha256=7VCcyzKKKz8E7txQV4wi-jEbtftaFW_ekWmA9E1qx3Y,60304 +mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-xyz.png,sha256=KwDmkuK7FMtl0Q2ank7wcph9uTncUr7UdTh2hUYdZP8,121446 +mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3d.pdf,sha256=3gYea_CtpNg1UmurOhyWt3vHZSkLX1-trEY779yrxbc,36169 +mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3d.png,sha256=epmsR4rWGzh7prW3RL_t8ZcUEsphM5bc0t5j__iauOY,108371 +mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3d.svg,sha256=-hjWYF-WSE3aDuCSpHYztjeV_yktEqatDK2yZyn_rhE,85892 +mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3dzerocstride.png,sha256=WaO_3NcaZPFzlui5SQYJ-TbUylHkSbieneCYPffNgAA,81117 +mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3dzerorstride.png,sha256=y1JvfuVOBiNhJoJ2HdOXyBYBBkQm-oaPcoekfT-cMso,84284 +mpl_toolkits/tests/conftest.py,sha256=Ph6QZKdfAnkPwU52StddC-uwtCHfANKX1dDXgtX122g,213 +mpl_toolkits/tests/test_axes_grid.py,sha256=UCQFk5p-9sbTMCS6RKk7BfyCiTb9yRnsarH23eUem0o,1638 +mpl_toolkits/tests/test_axes_grid1.py,sha256=-xuTd5WRqNx1fXO6qNT6Z5C2LaUinjJNfWie7zVAtfM,17534 +mpl_toolkits/tests/test_axisartist_angle_helper.py,sha256=PwhJwBm2kk4uMyhdO5arQs8IlqSX2vN0hvUzI7YHqrw,5670 +mpl_toolkits/tests/test_axisartist_axis_artist.py,sha256=h8UXVxnt-fsfvjEOLxnyrwA4z0b7Lf-1UtvIh_SNaI4,2893 +mpl_toolkits/tests/test_axisartist_axislines.py,sha256=WHLuvnqIChl8D8NqUFryq-f9MCKfejXL61olpn59gdA,2271 +mpl_toolkits/tests/test_axisartist_clip_path.py,sha256=7K1Y-2DPbDdyvpAHq3XEDaXfsikw-u8v7olwaqwZ53o,1054 +mpl_toolkits/tests/test_axisartist_floating_axes.py,sha256=_ykVuVnTyZ_zrBe3g_R7JmhBs2mQJnK05zRZZA-nzwA,4122 +mpl_toolkits/tests/test_axisartist_grid_finder.py,sha256=e65sLudWFIXeU08Sis3_SI1JEI6eq8YqKj-80F_Nohk,325 +mpl_toolkits/tests/test_axisartist_grid_helper_curvelinear.py,sha256=TpV3ShQOPAk57KV-97dWfpULRws0zyAOQwn3JpejTe4,7487 +mpl_toolkits/tests/test_mplot3d.py,sha256=WDEFiPVru7oW7z5W3J-ESBnuIVfZw5oU-oK_L4mEuPM,30075 +pylab.py,sha256=u_By3CHla-rBMg57egFXIxZ3P_J6zEkSu_dNpBcH5pw,90 diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/WHEEL b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/WHEEL new file mode 100644 index 0000000..92946fe --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.31.1) +Root-Is-Purelib: false +Tag: cp36-cp36m-manylinux1_x86_64 + diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/namespace_packages.txt b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/namespace_packages.txt new file mode 100644 index 0000000..ba2e3ed --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/namespace_packages.txt @@ -0,0 +1 @@ +mpl_toolkits diff --git a/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/top_level.txt b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/top_level.txt new file mode 100644 index 0000000..0eb77e4 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib-3.1.1.dist-info/top_level.txt @@ -0,0 +1,3 @@ +matplotlib +mpl_toolkits +pylab diff --git a/venv/lib/python3.6/site-packages/matplotlib/.libs/libpng16-cfdb1654.so.16.21.0 b/venv/lib/python3.6/site-packages/matplotlib/.libs/libpng16-cfdb1654.so.16.21.0 new file mode 100644 index 0000000..bb94afb Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/.libs/libpng16-cfdb1654.so.16.21.0 differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/.libs/libz-a147dcb0.so.1.2.3 b/venv/lib/python3.6/site-packages/matplotlib/.libs/libz-a147dcb0.so.1.2.3 new file mode 100644 index 0000000..1ce02c2 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/.libs/libz-a147dcb0.so.1.2.3 differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__init__.py b/venv/lib/python3.6/site-packages/matplotlib/__init__.py new file mode 100644 index 0000000..350d4c5 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/__init__.py @@ -0,0 +1,1649 @@ +""" +This is an object-oriented plotting library. + +A procedural interface is provided by the companion pyplot module, +which may be imported directly, e.g.:: + + import matplotlib.pyplot as plt + +or using ipython:: + + ipython + +at your terminal, followed by:: + + In [1]: %matplotlib + In [2]: import matplotlib.pyplot as plt + +at the ipython shell prompt. + +For the most part, direct use of the object-oriented library is +encouraged when programming; pyplot is primarily for working +interactively. The +exceptions are the pyplot commands :func:`~matplotlib.pyplot.figure`, +:func:`~matplotlib.pyplot.subplot`, +:func:`~matplotlib.pyplot.subplots`, and +:func:`~pyplot.savefig`, which can greatly simplify scripting. + +Modules include: + + :mod:`matplotlib.axes` + defines the :class:`~matplotlib.axes.Axes` class. Most pyplot + commands are wrappers for :class:`~matplotlib.axes.Axes` + methods. The axes module is the highest level of OO access to + the library. + + :mod:`matplotlib.figure` + defines the :class:`~matplotlib.figure.Figure` class. + + :mod:`matplotlib.artist` + defines the :class:`~matplotlib.artist.Artist` base class for + all classes that draw things. + + :mod:`matplotlib.lines` + defines the :class:`~matplotlib.lines.Line2D` class for + drawing lines and markers + + :mod:`matplotlib.patches` + defines classes for drawing polygons + + :mod:`matplotlib.text` + defines the :class:`~matplotlib.text.Text`, + :class:`~matplotlib.text.TextWithDash`, and + :class:`~matplotlib.text.Annotate` classes + + :mod:`matplotlib.image` + defines the :class:`~matplotlib.image.AxesImage` and + :class:`~matplotlib.image.FigureImage` classes + + :mod:`matplotlib.collections` + classes for efficient drawing of groups of lines or polygons + + :mod:`matplotlib.colors` + classes for interpreting color specifications and for making + colormaps + + :mod:`matplotlib.cm` + colormaps and the :class:`~matplotlib.image.ScalarMappable` + mixin class for providing color mapping functionality to other + classes + + :mod:`matplotlib.ticker` + classes for calculating tick mark locations and for formatting + tick labels + + :mod:`matplotlib.backends` + a subpackage with modules for various gui libraries and output + formats + +The base matplotlib namespace includes: + + :data:`~matplotlib.rcParams` + a global dictionary of default configuration settings. It is + initialized by code which may be overridden by a matplotlibrc + file. + + :func:`~matplotlib.rc` + a function for setting groups of rcParams values + + :func:`~matplotlib.use` + a function for setting the matplotlib backend. If used, this + function must be called immediately after importing matplotlib + for the first time. In particular, it must be called + **before** importing pyplot (if pyplot is imported). + +matplotlib was initially written by John D. Hunter (1968-2012) and is now +developed and maintained by a host of others. + +Occasionally the internal documentation (python docstrings) will refer +to MATLAB®, a registered trademark of The MathWorks, Inc. + +""" +# NOTE: This file must remain Python 2 compatible for the foreseeable future, +# to ensure that we error out properly for existing editable installs. + +import sys +if sys.version_info < (3, 5): # noqa: E402 + raise ImportError(""" +Matplotlib 3.0+ does not support Python 2.x, 3.0, 3.1, 3.2, 3.3, or 3.4. +Beginning with Matplotlib 3.0, Python 3.5 and above is required. + +See Matplotlib `INSTALL.rst` file for more information: + + https://github.com/matplotlib/matplotlib/blob/master/INSTALL.rst + +""") + +import atexit +from collections import namedtuple +from collections.abc import MutableMapping +import contextlib +from distutils.version import LooseVersion +import functools +import importlib +import inspect +from inspect import Parameter +import locale +import logging +import os +from pathlib import Path +import pprint +import re +import shutil +import subprocess +import tempfile + +# cbook must import matplotlib only within function +# definitions, so it is safe to import from it here. +from . import cbook, rcsetup +from matplotlib.cbook import ( + MatplotlibDeprecationWarning, dedent, get_label, sanitize_sequence) +from matplotlib.cbook import mplDeprecation # deprecated +from matplotlib.rcsetup import defaultParams, validate_backend, cycler + +import numpy + +# Get the version from the _version.py versioneer file. For a git checkout, +# this is computed based on the number of commits since the last tag. +from ._version import get_versions +__version__ = str(get_versions()['version']) +del get_versions + +_log = logging.getLogger(__name__) + +__bibtex__ = r"""@Article{Hunter:2007, + Author = {Hunter, J. D.}, + Title = {Matplotlib: A 2D graphics environment}, + Journal = {Computing in Science \& Engineering}, + Volume = {9}, + Number = {3}, + Pages = {90--95}, + abstract = {Matplotlib is a 2D graphics package used for Python + for application development, interactive scripting, and + publication-quality image generation across user + interfaces and operating systems.}, + publisher = {IEEE COMPUTER SOC}, + year = 2007 +}""" + + +def compare_versions(a, b): + "Return whether version *a* is greater than or equal to version *b*." + if isinstance(a, bytes): + cbook.warn_deprecated( + "3.0", message="compare_versions arguments should be strs.") + a = a.decode('ascii') + if isinstance(b, bytes): + cbook.warn_deprecated( + "3.0", message="compare_versions arguments should be strs.") + b = b.decode('ascii') + if a: + return LooseVersion(a) >= LooseVersion(b) + else: + return False + + +def _check_versions(): + + # Quickfix to ensure Microsoft Visual C++ redistributable + # DLLs are loaded before importing kiwisolver + from . import ft2font + + for modname, minver in [ + ("cycler", "0.10"), + ("dateutil", "2.1"), + ("kiwisolver", "1.0.1"), + ("numpy", "1.11"), + ("pyparsing", "2.0.1"), + ]: + module = importlib.import_module(modname) + if LooseVersion(module.__version__) < minver: + raise ImportError("Matplotlib requires {}>={}; you have {}" + .format(modname, minver, module.__version__)) + + +_check_versions() + + +if not hasattr(sys, 'argv'): # for modpython + sys.argv = ['modpython'] + + +# The decorator ensures this always returns the same handler (and it is only +# attached once). +@functools.lru_cache() +def _ensure_handler(): + """ + The first time this function is called, attach a `StreamHandler` using the + same format as `logging.basicConfig` to the Matplotlib root logger. + + Return this handler every time this function is called. + """ + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT)) + _log.addHandler(handler) + return handler + + +def set_loglevel(level): + """ + Sets the Matplotlib's root logger and root logger handler level, creating + the handler if it does not exist yet. + + Typically, one should call ``set_loglevel("info")`` or + ``set_loglevel("debug")`` to get additional debugging information. + + Parameters + ---------- + level : {"notset", "debug", "info", "warning", "error", "critical"} + The log level of the handler. + + Notes + ----- + The first time this function is called, an additional handler is attached + to Matplotlib's root handler; this handler is reused every time and this + function simply manipulates the logger and handler's level. + """ + _log.setLevel(level.upper()) + _ensure_handler().setLevel(level.upper()) + + +def _logged_cached(fmt, func=None): + """ + Decorator that logs a function's return value, and memoizes that value. + + After :: + + @_logged_cached(fmt) + def func(): ... + + the first call to *func* will log its return value at the DEBUG level using + %-format string *fmt*, and memoize it; later calls to *func* will directly + return that value. + """ + if func is None: # Return the actual decorator. + return functools.partial(_logged_cached, fmt) + + called = False + ret = None + + @functools.wraps(func) + def wrapper(): + nonlocal called, ret + if not called: + ret = func() + called = True + _log.debug(fmt, ret) + return ret + + return wrapper + + +_ExecInfo = namedtuple("_ExecInfo", "executable version") + + +@functools.lru_cache() +def _get_executable_info(name): + """ + Get the version of some executable that Matplotlib optionally depends on. + + .. warning: + The list of executables that this function supports is set according to + Matplotlib's internal needs, and may change without notice. + + Parameters + ---------- + name : str + The executable to query. The following values are currently supported: + "dvipng", "gs", "inkscape", "magick", "pdftops". This list is subject + to change without notice. + + Returns + ------- + If the executable is found, a namedtuple with fields ``executable`` (`str`) + and ``version`` (`distutils.version.LooseVersion`, or ``None`` if the + version cannot be determined). + + Raises + ------ + FileNotFoundError + If the executable is not found or older than the oldest version + supported by Matplotlib. + ValueError + If the executable is not one that we know how to query. + """ + + def impl(args, regex, min_ver=None, ignore_exit_code=False): + # Execute the subprocess specified by args; capture stdout and stderr. + # Search for a regex match in the output; if the match succeeds, the + # first group of the match is the version. + # Return an _ExecInfo if the executable exists, and has a version of + # at least min_ver (if set); else, raise FileNotFoundError. + try: + output = subprocess.check_output( + args, stderr=subprocess.STDOUT, universal_newlines=True) + except subprocess.CalledProcessError as _cpe: + if ignore_exit_code: + output = _cpe.output + else: + raise _cpe + match = re.search(regex, output) + if match: + version = LooseVersion(match.group(1)) + if min_ver is not None and version < min_ver: + raise FileNotFoundError( + f"You have {args[0]} version {version} but the minimum " + f"version supported by Matplotlib is {min_ver}.") + return _ExecInfo(args[0], version) + else: + raise FileNotFoundError( + f"Failed to determine the version of {args[0]} from " + f"{' '.join(args)}, which output {output}") + + if name == "dvipng": + return impl(["dvipng", "-version"], "(?m)^dvipng(?: .*)? (.+)", "1.6") + elif name == "gs": + execs = (["gswin32c", "gswin64c", "mgs", "gs"] # "mgs" for miktex. + if sys.platform == "win32" else + ["gs"]) + for e in execs: + try: + return impl([e, "--version"], "(.*)", "9") + except FileNotFoundError: + pass + raise FileNotFoundError("Failed to find a Ghostscript installation") + elif name == "inkscape": + return impl(["inkscape", "-V"], "^Inkscape ([^ ]*)") + elif name == "magick": + path = None + if sys.platform == "win32": + # Check the registry to avoid confusing ImageMagick's convert with + # Windows's builtin convert.exe. + import winreg + binpath = "" + for flag in [0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY]: + try: + with winreg.OpenKeyEx( + winreg.HKEY_LOCAL_MACHINE, + r"Software\Imagemagick\Current", + 0, winreg.KEY_QUERY_VALUE | flag) as hkey: + binpath = winreg.QueryValueEx(hkey, "BinPath")[0] + except OSError: + pass + if binpath: + for name in ["convert.exe", "magick.exe"]: + candidate = Path(binpath, name) + if candidate.exists(): + path = str(candidate) + break + else: + path = "convert" + if path is None: + raise FileNotFoundError( + "Failed to find an ImageMagick installation") + return impl([path, "--version"], r"^Version: ImageMagick (\S*)") + elif name == "pdftops": + info = impl(["pdftops", "-v"], "^pdftops version (.*)", + ignore_exit_code=True) + if info and not ("3.0" <= info.version + # poppler version numbers. + or "0.9" <= info.version <= "1.0"): + raise FileNotFoundError( + f"You have pdftops version {info.version} but the minimum " + f"version supported by Matplotlib is 3.0.") + return info + else: + raise ValueError("Unknown executable: {!r}".format(name)) + + +@cbook.deprecated("3.1") +def checkdep_dvipng(): + try: + s = subprocess.Popen(['dvipng', '-version'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + line = stdout.decode('ascii').split('\n')[1] + v = line.split()[-1] + return v + except (IndexError, ValueError, OSError): + return None + + +@cbook.deprecated("3.1") +def checkdep_ghostscript(): + if checkdep_ghostscript.executable is None: + if sys.platform == 'win32': + # mgs is the name in miktex + gs_execs = ['gswin32c', 'gswin64c', 'mgs', 'gs'] + else: + gs_execs = ['gs'] + for gs_exec in gs_execs: + try: + s = subprocess.Popen( + [gs_exec, '--version'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + if s.returncode == 0: + v = stdout[:-1].decode('ascii') + if compare_versions(v, '9.0'): + checkdep_ghostscript.executable = gs_exec + checkdep_ghostscript.version = v + except (IndexError, ValueError, OSError): + pass + return checkdep_ghostscript.executable, checkdep_ghostscript.version +checkdep_ghostscript.executable = None +checkdep_ghostscript.version = None + + +@cbook.deprecated("3.1") +def checkdep_pdftops(): + try: + s = subprocess.Popen(['pdftops', '-v'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + lines = stderr.decode('ascii').split('\n') + for line in lines: + if 'version' in line: + v = line.split()[-1] + return v + except (IndexError, ValueError, UnboundLocalError, OSError): + return None + + +@cbook.deprecated("3.1") +def checkdep_inkscape(): + if checkdep_inkscape.version is None: + try: + s = subprocess.Popen(['inkscape', '-V'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + lines = stdout.decode('ascii').split('\n') + for line in lines: + if 'Inkscape' in line: + v = line.split()[1] + break + checkdep_inkscape.version = v + except (IndexError, ValueError, UnboundLocalError, OSError): + pass + return checkdep_inkscape.version +checkdep_inkscape.version = None + + +def checkdep_ps_distiller(s): + if not s: + return False + try: + _get_executable_info("gs") + except FileNotFoundError: + _log.warning( + "Setting rcParams['ps.usedistiller'] requires ghostscript.") + return False + if s == "xpdf": + try: + _get_executable_info("pdftops") + except FileNotFoundError: + _log.warning( + "Setting rcParams['ps.usedistiller'] to 'xpdf' requires xpdf.") + return False + return s + + +def checkdep_usetex(s): + if not s: + return False + if not shutil.which("tex"): + _log.warning("usetex mode requires TeX.") + return False + try: + _get_executable_info("dvipng") + except FileNotFoundError: + _log.warning("usetex mode requires dvipng.") + return False + try: + _get_executable_info("gs") + except FileNotFoundError: + _log.warning("usetex mode requires ghostscript.") + return False + return True + + +@_logged_cached('$HOME=%s') +def get_home(): + """ + Return the user's home directory. + + If the user's home directory cannot be found, return None. + """ + try: + return str(Path.home()) + except Exception: + return None + + +def _create_tmp_config_or_cache_dir(): + """ + If the config or cache directory cannot be created, create a temporary one. + """ + configdir = os.environ['MPLCONFIGDIR'] = ( + tempfile.mkdtemp(prefix='matplotlib-')) + atexit.register(shutil.rmtree, configdir) + return configdir + + +def _get_xdg_config_dir(): + """ + Return the XDG configuration directory, according to the `XDG + base directory spec + `_. + """ + return (os.environ.get('XDG_CONFIG_HOME') + or (str(Path(get_home(), ".config")) + if get_home() + else None)) + + +def _get_xdg_cache_dir(): + """ + Return the XDG cache directory, according to the `XDG + base directory spec + `_. + """ + return (os.environ.get('XDG_CACHE_HOME') + or (str(Path(get_home(), ".cache")) + if get_home() + else None)) + + +def _get_config_or_cache_dir(xdg_base): + configdir = os.environ.get('MPLCONFIGDIR') + if configdir: + configdir = Path(configdir).resolve() + elif sys.platform.startswith(('linux', 'freebsd')) and xdg_base: + configdir = Path(xdg_base, "matplotlib") + elif get_home(): + configdir = Path(get_home(), ".matplotlib") + else: + configdir = None + + if configdir: + try: + configdir.mkdir(parents=True, exist_ok=True) + except OSError: + pass + else: + if os.access(str(configdir), os.W_OK) and configdir.is_dir(): + return str(configdir) + + return _create_tmp_config_or_cache_dir() + + +@_logged_cached('CONFIGDIR=%s') +def get_configdir(): + """ + Return the string representing the configuration directory. + + The directory is chosen as follows: + + 1. If the MPLCONFIGDIR environment variable is supplied, choose that. + 2a. On Linux, follow the XDG specification and look first in + `$XDG_CONFIG_HOME`, if defined, or `$HOME/.config`. + 2b. On other platforms, choose `$HOME/.matplotlib`. + 3. If the chosen directory exists and is writable, use that as the + configuration directory. + 4. If possible, create a temporary directory, and use it as the + configuration directory. + 5. A writable directory could not be found or created; return None. + """ + return _get_config_or_cache_dir(_get_xdg_config_dir()) + + +@_logged_cached('CACHEDIR=%s') +def get_cachedir(): + """ + Return the location of the cache directory. + + The procedure used to find the directory is the same as for + _get_config_dir, except using `$XDG_CACHE_HOME`/`~/.cache` instead. + """ + return _get_config_or_cache_dir(_get_xdg_cache_dir()) + + +def _get_data_path(): + 'get the path to matplotlib data' + + if 'MATPLOTLIBDATA' in os.environ: + path = os.environ['MATPLOTLIBDATA'] + if not os.path.isdir(path): + raise RuntimeError('Path in environment MATPLOTLIBDATA not a ' + 'directory') + cbook.warn_deprecated( + "3.1", name="MATPLOTLIBDATA", obj_type="environment variable") + return path + + def get_candidate_paths(): + yield Path(__file__).with_name('mpl-data') + # setuptools' namespace_packages may hijack this init file + # so need to try something known to be in Matplotlib, not basemap. + import matplotlib.afm + yield Path(matplotlib.afm.__file__).with_name('mpl-data') + # py2exe zips pure python, so still need special check. + if getattr(sys, 'frozen', None): + yield Path(sys.executable).with_name('mpl-data') + # Try again assuming we need to step up one more directory. + yield Path(sys.executable).parent.with_name('mpl-data') + # Try again assuming sys.path[0] is a dir not a exe. + yield Path(sys.path[0]) / 'mpl-data' + + for path in get_candidate_paths(): + if path.is_dir(): + return str(path) + + raise RuntimeError('Could not find the matplotlib data files') + + +@_logged_cached('matplotlib data path: %s') +def get_data_path(): + if defaultParams['datapath'][0] is None: + defaultParams['datapath'][0] = _get_data_path() + return defaultParams['datapath'][0] + + +@cbook.deprecated("3.1") +def get_py2exe_datafiles(): + data_path = Path(get_data_path()) + d = {} + for path in filter(Path.is_file, data_path.glob("**/*")): + (d.setdefault(str(path.parent.relative_to(data_path.parent)), []) + .append(str(path))) + return list(d.items()) + + +def matplotlib_fname(): + """ + Get the location of the config file. + + The file location is determined in the following order + + - ``$PWD/matplotlibrc`` + - ``$MATPLOTLIBRC`` if it is not a directory + - ``$MATPLOTLIBRC/matplotlibrc`` + - ``$MPLCONFIGDIR/matplotlibrc`` + - On Linux, + - ``$XDG_CONFIG_HOME/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME`` + is defined) + - or ``$HOME/.config/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME`` + is not defined) + - On other platforms, + - ``$HOME/.matplotlib/matplotlibrc`` if ``$HOME`` is defined + - Lastly, it looks in ``$MATPLOTLIBDATA/matplotlibrc``, which should always + exist. + """ + + def gen_candidates(): + yield os.path.join(os.getcwd(), 'matplotlibrc') + try: + matplotlibrc = os.environ['MATPLOTLIBRC'] + except KeyError: + pass + else: + yield matplotlibrc + yield os.path.join(matplotlibrc, 'matplotlibrc') + yield os.path.join(get_configdir(), 'matplotlibrc') + yield os.path.join(get_data_path(), 'matplotlibrc') + + for fname in gen_candidates(): + if os.path.exists(fname) and not os.path.isdir(fname): + return fname + + raise RuntimeError("Could not find matplotlibrc file; your Matplotlib " + "install is broken") + + +# rcParams deprecated and automatically mapped to another key. +# Values are tuples of (version, new_name, f_old2new, f_new2old). +_deprecated_map = {} + +# rcParams deprecated; some can manually be mapped to another key. +# Values are tuples of (version, new_name_or_None). +_deprecated_ignore_map = { + 'pgf.debug': ('3.0', None), +} + +# rcParams deprecated; can use None to suppress warnings; remain actually +# listed in the rcParams (not included in _all_deprecated). +# Values are tuples of (version,) +_deprecated_remain_as_none = { + 'text.latex.unicode': ('3.0',), + 'savefig.frameon': ('3.1',), + 'verbose.fileo': ('3.1',), + 'verbose.level': ('3.1',), +} + + +_all_deprecated = {*_deprecated_map, *_deprecated_ignore_map} + + +class RcParams(MutableMapping, dict): + + """ + A dictionary object including validation + + validating functions are defined and associated with rc parameters in + :mod:`matplotlib.rcsetup` + """ + + validate = {key: converter + for key, (default, converter) in defaultParams.items() + if key not in _all_deprecated} + + @cbook.deprecated("3.0") + @property + def msg_depr(self): + return "%s is deprecated and replaced with %s; please use the latter." + + @cbook.deprecated("3.0") + @property + def msg_depr_ignore(self): + return "%s is deprecated and ignored. Use %s instead." + + @cbook.deprecated("3.0") + @property + def msg_depr_set(self): + return ("%s is deprecated. Please remove it from your matplotlibrc " + "and/or style files.") + + @cbook.deprecated("3.0") + @property + def msg_obsolete(self): + return ("%s is obsolete. Please remove it from your matplotlibrc " + "and/or style files.") + + @cbook.deprecated("3.0") + @property + def msg_backend_obsolete(self): + return ("The {} rcParam was deprecated in version 2.2. In order to " + "force the use of a specific Qt binding, either import that " + "binding first, or set the QT_API environment variable.") + + # validate values on the way in + def __init__(self, *args, **kwargs): + self.update(*args, **kwargs) + + def __setitem__(self, key, val): + try: + if key in _deprecated_map: + version, alt_key, alt_val, inverse_alt = _deprecated_map[key] + cbook.warn_deprecated( + version, name=key, obj_type="rcparam", alternative=alt_key) + key = alt_key + val = alt_val(val) + elif key in _deprecated_remain_as_none and val is not None: + version, = _deprecated_remain_as_none[key] + cbook.warn_deprecated( + version, name=key, obj_type="rcparam") + elif key in _deprecated_ignore_map: + version, alt_key = _deprecated_ignore_map[key] + cbook.warn_deprecated( + version, name=key, obj_type="rcparam", alternative=alt_key) + return + elif key == 'examples.directory': + cbook.warn_deprecated( + "3.0", name=key, obj_type="rcparam", addendum="In the " + "future, examples will be found relative to the " + "'datapath' directory.") + elif key == 'backend': + if val is rcsetup._auto_backend_sentinel: + if 'backend' in self: + return + try: + cval = self.validate[key](val) + except ValueError as ve: + raise ValueError("Key %s: %s" % (key, str(ve))) + dict.__setitem__(self, key, cval) + except KeyError: + raise KeyError( + f"{key} is not a valid rc parameter (see rcParams.keys() for " + f"a list of valid parameters)") + + def __getitem__(self, key): + if key in _deprecated_map: + version, alt_key, alt_val, inverse_alt = _deprecated_map[key] + cbook.warn_deprecated( + version, name=key, obj_type="rcparam", alternative=alt_key) + return inverse_alt(dict.__getitem__(self, alt_key)) + + elif key in _deprecated_ignore_map: + version, alt_key = _deprecated_ignore_map[key] + cbook.warn_deprecated( + version, name=key, obj_type="rcparam", alternative=alt_key) + return dict.__getitem__(self, alt_key) if alt_key else None + + elif key == 'examples.directory': + cbook.warn_deprecated( + "3.0", name=key, obj_type="rcparam", addendum="In the future, " + "examples will be found relative to the 'datapath' directory.") + + elif key == "backend": + val = dict.__getitem__(self, key) + if val is rcsetup._auto_backend_sentinel: + from matplotlib import pyplot as plt + plt.switch_backend(rcsetup._auto_backend_sentinel) + + return dict.__getitem__(self, key) + + def __repr__(self): + class_name = self.__class__.__name__ + indent = len(class_name) + 1 + repr_split = pprint.pformat(dict(self), indent=1, + width=80 - indent).split('\n') + repr_indented = ('\n' + ' ' * indent).join(repr_split) + return '{}({})'.format(class_name, repr_indented) + + def __str__(self): + return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self.items()))) + + def __iter__(self): + """Yield sorted list of keys.""" + with cbook._suppress_matplotlib_deprecation_warning(): + yield from sorted(dict.__iter__(self)) + + def __len__(self): + return dict.__len__(self) + + def find_all(self, pattern): + """ + Return the subset of this RcParams dictionary whose keys match, + using :func:`re.search`, the given ``pattern``. + + .. note:: + + Changes to the returned dictionary are *not* propagated to + the parent RcParams dictionary. + + """ + pattern_re = re.compile(pattern) + return RcParams((key, value) + for key, value in self.items() + if pattern_re.search(key)) + + def copy(self): + return {k: dict.__getitem__(self, k) for k in self} + + +def rc_params(fail_on_error=False): + """Return a :class:`matplotlib.RcParams` instance from the + default matplotlib rc file. + """ + return rc_params_from_file(matplotlib_fname(), fail_on_error) + + +URL_REGEX = re.compile(r'http://|https://|ftp://|file://|file:\\') + + +def is_url(filename): + """Return True if string is an http, ftp, or file URL path.""" + return URL_REGEX.match(filename) is not None + + +@contextlib.contextmanager +def _open_file_or_url(fname): + if is_url(fname): + import urllib.request + with urllib.request.urlopen(fname) as f: + yield (line.decode('utf-8') for line in f) + else: + fname = os.path.expanduser(fname) + encoding = locale.getpreferredencoding(do_setlocale=False) + if encoding is None: + encoding = "utf-8" + with open(fname, encoding=encoding) as f: + yield f + + +_error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"' + + +def _rc_params_in_file(fname, fail_on_error=False): + """Return :class:`matplotlib.RcParams` from the contents of the given file. + + Unlike `rc_params_from_file`, the configuration class only contains the + parameters specified in the file (i.e. default values are not filled in). + """ + cnt = 0 + rc_temp = {} + with _open_file_or_url(fname) as fd: + try: + for line in fd: + cnt += 1 + strippedline = line.split('#', 1)[0].strip() + if not strippedline: + continue + tup = strippedline.split(':', 1) + if len(tup) != 2: + error_details = _error_details_fmt % (cnt, line, fname) + _log.warning('Illegal %s', error_details) + continue + key, val = tup + key = key.strip() + val = val.strip() + if key in rc_temp: + _log.warning('Duplicate key in file %r line #%d.', + fname, cnt) + rc_temp[key] = (val, line, cnt) + except UnicodeDecodeError: + _log.warning('Cannot decode configuration file %s with encoding ' + '%s, check LANG and LC_* variables.', + fname, + locale.getpreferredencoding(do_setlocale=False) + or 'utf-8 (default)') + raise + + config = RcParams() + + for key, (val, line, cnt) in rc_temp.items(): + if key in defaultParams: + if fail_on_error: + config[key] = val # try to convert to proper type or raise + else: + try: + config[key] = val # try to convert to proper type or skip + except Exception as msg: + error_details = _error_details_fmt % (cnt, line, fname) + _log.warning('Bad val %r on %s\n\t%s', + val, error_details, msg) + elif key in _deprecated_ignore_map: + version, alt_key = _deprecated_ignore_map[key] + cbook.warn_deprecated( + version, name=key, alternative=alt_key, + addendum="Please update your matplotlibrc.") + else: + print(""" +Bad key "%s" on line %d in +%s. +You probably need to get an updated matplotlibrc file from +http://github.com/matplotlib/matplotlib/blob/master/matplotlibrc.template +or from the matplotlib source distribution""" % (key, cnt, fname), + file=sys.stderr) + + return config + + +def rc_params_from_file(fname, fail_on_error=False, use_default_template=True): + """Return :class:`matplotlib.RcParams` from the contents of the given file. + + Parameters + ---------- + fname : str + Name of file parsed for matplotlib settings. + fail_on_error : bool + If True, raise an error when the parser fails to convert a parameter. + use_default_template : bool + If True, initialize with default parameters before updating with those + in the given file. If False, the configuration class only contains the + parameters specified in the file. (Useful for updating dicts.) + """ + config_from_file = _rc_params_in_file(fname, fail_on_error) + + if not use_default_template: + return config_from_file + + iter_params = defaultParams.items() + with cbook._suppress_matplotlib_deprecation_warning(): + config = RcParams([(key, default) for key, (default, _) in iter_params + if key not in _all_deprecated]) + config.update(config_from_file) + + if config['datapath'] is None: + config['datapath'] = get_data_path() + + if "".join(config['text.latex.preamble']): + _log.info(""" +***************************************************************** +You have the following UNSUPPORTED LaTeX preamble customizations: +%s +Please do not ask for support with these customizations active. +***************************************************************** +""", '\n'.join(config['text.latex.preamble'])) + _log.debug('loaded rc file %s', fname) + + return config + + +# this is the instance used by the matplotlib classes +rcParams = rc_params() + +# Don't trigger deprecation warning when just fetching. +if dict.__getitem__(rcParams, 'examples.directory'): + # paths that are intended to be relative to matplotlib_fname() + # are allowed for the examples.directory parameter. + # However, we will need to fully qualify the path because + # Sphinx requires absolute paths. + if not os.path.isabs(rcParams['examples.directory']): + _basedir, _fname = os.path.split(matplotlib_fname()) + # Sometimes matplotlib_fname() can return relative paths, + # Also, using realpath() guarantees that Sphinx will use + # the same path that matplotlib sees (in case of weird symlinks). + _basedir = os.path.realpath(_basedir) + _fullpath = os.path.join(_basedir, rcParams['examples.directory']) + rcParams['examples.directory'] = _fullpath + + +with cbook._suppress_matplotlib_deprecation_warning(): + rcParamsOrig = RcParams(rcParams.copy()) + rcParamsDefault = RcParams([(key, default) for key, (default, converter) in + defaultParams.items() + if key not in _all_deprecated]) + +rcParams['ps.usedistiller'] = checkdep_ps_distiller( + rcParams['ps.usedistiller']) + +if rcParams['axes.formatter.use_locale']: + locale.setlocale(locale.LC_ALL, '') + + +def rc(group, **kwargs): + """ + Set the current rc params. *group* is the grouping for the rc, e.g., + for ``lines.linewidth`` the group is ``lines``, for + ``axes.facecolor``, the group is ``axes``, and so on. Group may + also be a list or tuple of group names, e.g., (*xtick*, *ytick*). + *kwargs* is a dictionary attribute name/value pairs, e.g.,:: + + rc('lines', linewidth=2, color='r') + + sets the current rc params and is equivalent to:: + + rcParams['lines.linewidth'] = 2 + rcParams['lines.color'] = 'r' + + The following aliases are available to save typing for interactive + users: + + ===== ================= + Alias Property + ===== ================= + 'lw' 'linewidth' + 'ls' 'linestyle' + 'c' 'color' + 'fc' 'facecolor' + 'ec' 'edgecolor' + 'mew' 'markeredgewidth' + 'aa' 'antialiased' + ===== ================= + + Thus you could abbreviate the above rc command as:: + + rc('lines', lw=2, c='r') + + + Note you can use python's kwargs dictionary facility to store + dictionaries of default parameters. e.g., you can customize the + font rc as follows:: + + font = {'family' : 'monospace', + 'weight' : 'bold', + 'size' : 'larger'} + + rc('font', **font) # pass in the font dict as kwargs + + This enables you to easily switch between several configurations. Use + ``matplotlib.style.use('default')`` or :func:`~matplotlib.rcdefaults` to + restore the default rc params after changes. + """ + + aliases = { + 'lw': 'linewidth', + 'ls': 'linestyle', + 'c': 'color', + 'fc': 'facecolor', + 'ec': 'edgecolor', + 'mew': 'markeredgewidth', + 'aa': 'antialiased', + } + + if isinstance(group, str): + group = (group,) + for g in group: + for k, v in kwargs.items(): + name = aliases.get(k) or k + key = '%s.%s' % (g, name) + try: + rcParams[key] = v + except KeyError: + raise KeyError(('Unrecognized key "%s" for group "%s" and ' + 'name "%s"') % (key, g, name)) + + +def rcdefaults(): + """ + Restore the rc params from Matplotlib's internal default style. + + Style-blacklisted rc params (defined in + `matplotlib.style.core.STYLE_BLACKLIST`) are not updated. + + See Also + -------- + rc_file_defaults + Restore the rc params from the rc file originally loaded by Matplotlib. + matplotlib.style.use : + Use a specific style file. Call ``style.use('default')`` to restore + the default style. + """ + # Deprecation warnings were already handled when creating rcParamsDefault, + # no need to reemit them here. + with cbook._suppress_matplotlib_deprecation_warning(): + from .style.core import STYLE_BLACKLIST + rcParams.clear() + rcParams.update({k: v for k, v in rcParamsDefault.items() + if k not in STYLE_BLACKLIST}) + + +def rc_file_defaults(): + """ + Restore the rc params from the original rc file loaded by Matplotlib. + + Style-blacklisted rc params (defined in + `matplotlib.style.core.STYLE_BLACKLIST`) are not updated. + """ + # Deprecation warnings were already handled when creating rcParamsOrig, no + # need to reemit them here. + with cbook._suppress_matplotlib_deprecation_warning(): + from .style.core import STYLE_BLACKLIST + rcParams.update({k: rcParamsOrig[k] for k in rcParamsOrig + if k not in STYLE_BLACKLIST}) + + +def rc_file(fname, *, use_default_template=True): + """ + Update rc params from file. + + Style-blacklisted rc params (defined in + `matplotlib.style.core.STYLE_BLACKLIST`) are not updated. + + Parameters + ---------- + fname : str + Name of file parsed for matplotlib settings. + + use_default_template : bool + If True, initialize with default parameters before updating with those + in the given file. If False, the current configuration persists + and only the parameters specified in the file are updated. + + """ + # Deprecation warnings were already handled in rc_params_from_file, no need + # to reemit them here. + with cbook._suppress_matplotlib_deprecation_warning(): + from .style.core import STYLE_BLACKLIST + rc_from_file = rc_params_from_file( + fname, use_default_template=use_default_template) + rcParams.update({k: rc_from_file[k] for k in rc_from_file + if k not in STYLE_BLACKLIST}) + + +class rc_context: + """ + Return a context manager for managing rc settings. + + This allows one to do:: + + with mpl.rc_context(fname='screen.rc'): + plt.plot(x, a) + with mpl.rc_context(fname='print.rc'): + plt.plot(x, b) + plt.plot(x, c) + + The 'a' vs 'x' and 'c' vs 'x' plots would have settings from + 'screen.rc', while the 'b' vs 'x' plot would have settings from + 'print.rc'. + + A dictionary can also be passed to the context manager:: + + with mpl.rc_context(rc={'text.usetex': True}, fname='screen.rc'): + plt.plot(x, a) + + The 'rc' dictionary takes precedence over the settings loaded from + 'fname'. Passing a dictionary only is also valid. For example a + common usage is:: + + with mpl.rc_context(rc={'interactive': False}): + fig, ax = plt.subplots() + ax.plot(range(3), range(3)) + fig.savefig('A.png', format='png') + plt.close(fig) + """ + # While it may seem natural to implement rc_context using + # contextlib.contextmanager, that would entail always calling the finally: + # clause of the contextmanager (which restores the original rcs) including + # during garbage collection; as a result, something like `plt.xkcd(); + # gc.collect()` would result in the style being lost (as `xkcd()` is + # implemented on top of rc_context, and nothing is holding onto context + # manager except possibly circular references. + + def __init__(self, rc=None, fname=None): + self._orig = rcParams.copy() + try: + if fname: + rc_file(fname) + if rc: + rcParams.update(rc) + except Exception: + self.__fallback() + raise + + def __fallback(self): + # If anything goes wrong, revert to the original rcs. + updated_backend = self._orig['backend'] + dict.update(rcParams, self._orig) + # except for the backend. If the context block triggered resolving + # the auto backend resolution keep that value around + if self._orig['backend'] is rcsetup._auto_backend_sentinel: + rcParams['backend'] = updated_backend + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, exc_tb): + self.__fallback() + + +@cbook._rename_parameter("3.1", "arg", "backend") +def use(backend, warn=False, force=True): + """ + Select the backend used for rendering and GUI integration. + + Parameters + ---------- + backend : str + The backend to switch to. This can either be one of the standard + backend names, which are case-insensitive: + + - interactive backends: + GTK3Agg, GTK3Cairo, MacOSX, nbAgg, + Qt4Agg, Qt4Cairo, Qt5Agg, Qt5Cairo, + TkAgg, TkCairo, WebAgg, WX, WXAgg, WXCairo + + - non-interactive backends: + agg, cairo, pdf, pgf, ps, svg, template + + or a string of the form: ``module://my.module.name``. + + warn : bool, optional, default: False + If True and not *force*, warn that the call will have no effect if + this is called after pyplot has been imported and a backend is set up. + + + force : bool, optional, default: True + If True, attempt to switch the backend. An ImportError is raised if + an interactive backend is selected, but another interactive + backend has already started. + + See Also + -------- + :ref:`backends` + matplotlib.get_backend + """ + name = validate_backend(backend) + + if dict.__getitem__(rcParams, 'backend') == name: + # Nothing to do if the requested backend is already set + pass + elif 'matplotlib.pyplot' in sys.modules: + # pyplot has already been imported (which triggered backend selection) + # and the requested backend is different from the current one. + + # If we are going to force the switch, never warn, else, if warn + # is True, then direct users to `plt.switch_backend` + if (not force) and warn: + cbook._warn_external( + "matplotlib.pyplot has already been imported, " + "this call will have no effect.") + + # if we are going to force switching the backend, pull in + # `switch_backend` from pyplot. This will only happen if + # pyplot is already imported. + if force: + from matplotlib.pyplot import switch_backend + switch_backend(name) + else: + # Finally if pyplot is not imported update both rcParams and + # rcDefaults so restoring the defaults later with rcdefaults + # won't change the backend. This is a bit of overkill as 'backend' + # is already in style.core.STYLE_BLACKLIST, but better to be safe. + rcParams['backend'] = rcParamsDefault['backend'] = name + + +if os.environ.get('MPLBACKEND'): + rcParams['backend'] = os.environ.get('MPLBACKEND') + + +def get_backend(): + """ + Return the name of the current backend. + + See Also + -------- + matplotlib.use + """ + return rcParams['backend'] + + +def interactive(b): + """ + Set interactive mode to boolean b. + + If b is True, then draw after every plotting command, e.g., after xlabel + """ + rcParams['interactive'] = b + + +def is_interactive(): + 'Return true if plot mode is interactive' + return rcParams['interactive'] + + +@cbook.deprecated("3.1", alternative="rcParams['tk.window_focus']") +def tk_window_focus(): + """Return true if focus maintenance under TkAgg on win32 is on. + This currently works only for python.exe and IPython.exe. + Both IDLE and Pythonwin.exe fail badly when tk_window_focus is on.""" + if rcParams['backend'] != 'TkAgg': + return False + return rcParams['tk.window_focus'] + + +default_test_modules = [ + 'matplotlib.tests', + 'matplotlib.sphinxext.tests', + 'mpl_toolkits.tests', +] + + +def _init_tests(): + # CPython's faulthandler since v3.6 handles exceptions on Windows + # https://bugs.python.org/issue23848 but until v3.6.4 it was printing + # non-fatal exceptions https://bugs.python.org/issue30557 + import platform + if not (sys.platform == 'win32' and + (3, 6) < sys.version_info < (3, 6, 4) and + platform.python_implementation() == 'CPython'): + import faulthandler + faulthandler.enable() + + # The version of FreeType to install locally for running the + # tests. This must match the value in `setupext.py` + LOCAL_FREETYPE_VERSION = '2.6.1' + + from matplotlib import ft2font + if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or + ft2font.__freetype_build_type__ != 'local'): + _log.warning( + "Matplotlib is not built with the correct FreeType version to run " + "tests. Set local_freetype=True in setup.cfg and rebuild. " + "Expect many image comparison failures below. " + "Expected freetype version {0}. " + "Found freetype version {1}. " + "Freetype build type is {2}local".format( + LOCAL_FREETYPE_VERSION, + ft2font.__freetype_version__, + "" if ft2font.__freetype_build_type__ == 'local' else "not ")) + + try: + import pytest + except ImportError: + print("matplotlib.test requires pytest to run.") + raise + + +def test(verbosity=None, coverage=False, switch_backend_warn=True, + recursionlimit=0, **kwargs): + """Run the matplotlib test suite.""" + _init_tests() + if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')): + raise ImportError("Matplotlib test data is not installed") + + old_backend = get_backend() + old_recursionlimit = sys.getrecursionlimit() + try: + use('agg') + if recursionlimit: + sys.setrecursionlimit(recursionlimit) + import pytest + + args = kwargs.pop('argv', []) + provide_default_modules = True + use_pyargs = True + for arg in args: + if any(arg.startswith(module_path) + for module_path in default_test_modules): + provide_default_modules = False + break + if os.path.exists(arg): + provide_default_modules = False + use_pyargs = False + break + if use_pyargs: + args += ['--pyargs'] + if provide_default_modules: + args += default_test_modules + + if coverage: + args += ['--cov'] + + if verbosity: + args += ['-' + 'v' * verbosity] + + retcode = pytest.main(args, **kwargs) + finally: + if old_backend.lower() != 'agg': + use(old_backend, warn=switch_backend_warn) + if recursionlimit: + sys.setrecursionlimit(old_recursionlimit) + + return retcode + + +test.__test__ = False # pytest: this function is not a test + + +def _replacer(data, value): + """ + Either returns ``data[value]`` or passes ``data`` back, converts either to + a sequence. + """ + try: + # if key isn't a string don't bother + if isinstance(value, str): + # try to use __getitem__ + value = data[value] + except Exception: + # key does not exist, silently fall back to key + pass + return sanitize_sequence(value) + + +def _label_from_arg(y, default_name): + try: + return y.name + except AttributeError: + if isinstance(default_name, str): + return default_name + return None + + +_DATA_DOC_TITLE = """ + +Notes +----- +""" + +_DATA_DOC_APPENDIX = """ + +.. note:: + In addition to the above described arguments, this function can take a + **data** keyword argument. If such a **data** argument is given, the + following arguments are replaced by **data[]**: + + {replaced} + + Objects passed as **data** must support item access (``data[]``) and + membership test (`` in data``). +""" + + +def _add_data_doc(docstring, replace_names): + """Add documentation for a *data* field to the given docstring. + + Parameters + ---------- + docstring : str + The input docstring. + replace_names : list of str or None + The list of parameter names which arguments should be replaced by + ``data[name]`` (if ``data[name]`` does not throw an exception). If + None, replacement is attempted for all arguments. + + Returns + ------- + The augmented docstring. + """ + docstring = inspect.cleandoc(docstring) if docstring is not None else "" + repl = ("* All positional and all keyword arguments." + if replace_names is None else + "" + if len(replace_names) == 0 else + "* All arguments with the following names: {}.".format( + ", ".join(map(repr, sorted(replace_names))))) + addendum = _DATA_DOC_APPENDIX.format(replaced=repl) + if _DATA_DOC_TITLE not in docstring: + addendum = _DATA_DOC_TITLE + addendum + return docstring + addendum + + +def _preprocess_data(func=None, *, replace_names=None, label_namer=None): + """ + A decorator to add a 'data' kwarg to a function. + + :: + @_preprocess_data() + def func(ax, *args, **kwargs): ... + + is a function with signature ``decorated(ax, *args, data=None, **kwargs)`` + with the following behavior: + + - if called with ``data=None``, forward the other arguments to ``func``; + - otherwise, *data* must be a mapping; for any argument passed in as a + string ``name``, replace the argument by ``data[name]`` (if this does not + throw an exception), then forward the arguments to ``func``. + + In either case, any argument that is a `MappingView` is also converted to a + list. + + Parameters + ---------- + replace_names : list of str or None, optional, default: None + The list of parameter names for which lookup into *data* should be + attempted. If None, replacement is attempted for all arguments. + label_namer : string, optional, default: None + If set e.g. to "namer" (which must be a kwarg in the function's + signature -- not as ``**kwargs``), if the *namer* argument passed in is + a (string) key of *data* and no *label* kwarg is passed, then use the + (string) value of the *namer* as *label*. :: + + @_preprocess_data(label_namer="foo") + def func(foo, label=None): ... + + func("key", data={"key": value}) + # is equivalent to + func.__wrapped__(value, label="key") + """ + + if func is None: # Return the actual decorator. + return functools.partial( + _preprocess_data, + replace_names=replace_names, label_namer=label_namer) + + sig = inspect.signature(func) + varargs_name = None + varkwargs_name = None + arg_names = [] + params = list(sig.parameters.values()) + for p in params: + if p.kind is Parameter.VAR_POSITIONAL: + varargs_name = p.name + elif p.kind is Parameter.VAR_KEYWORD: + varkwargs_name = p.name + else: + arg_names.append(p.name) + data_param = Parameter("data", Parameter.KEYWORD_ONLY, default=None) + if varkwargs_name: + params.insert(-1, data_param) + else: + params.append(data_param) + new_sig = sig.replace(parameters=params) + arg_names = arg_names[1:] # remove the first "ax" / self arg + + if replace_names is not None: + replace_names = set(replace_names) + + assert (replace_names or set()) <= set(arg_names) or varkwargs_name, ( + "Matplotlib internal error: invalid replace_names ({!r}) for {!r}" + .format(replace_names, func.__name__)) + assert label_namer is None or label_namer in arg_names, ( + "Matplotlib internal error: invalid label_namer ({!r}) for {!r}" + .format(label_namer, func.__name__)) + + @functools.wraps(func) + def inner(ax, *args, data=None, **kwargs): + if data is None: + return func(ax, *map(sanitize_sequence, args), **kwargs) + + bound = new_sig.bind(ax, *args, **kwargs) + needs_label = (label_namer + and "label" not in bound.arguments + and "label" not in bound.kwargs) + auto_label = (bound.arguments.get(label_namer) + or bound.kwargs.get(label_namer)) + + for k, v in bound.arguments.items(): + if k == varkwargs_name: + for k1, v1 in v.items(): + if replace_names is None or k1 in replace_names: + v[k1] = _replacer(data, v1) + elif k == varargs_name: + if replace_names is None: + bound.arguments[k] = tuple(_replacer(data, v1) for v1 in v) + else: + if replace_names is None or k in replace_names: + bound.arguments[k] = _replacer(data, v) + + bound.apply_defaults() + del bound.arguments["data"] + + if needs_label: + all_kwargs = {**bound.arguments, **bound.kwargs} + # label_namer will be in all_kwargs as we asserted above that + # `label_namer is None or label_namer in arg_names`. + label = _label_from_arg(all_kwargs[label_namer], auto_label) + if "label" in arg_names: + bound.arguments["label"] = label + try: + bound.arguments.move_to_end(varkwargs_name) + except KeyError: + pass + else: + bound.arguments.setdefault(varkwargs_name, {})["label"] = label + + return func(*bound.args, **bound.kwargs) + + inner.__doc__ = _add_data_doc(inner.__doc__, replace_names) + inner.__signature__ = new_sig + return inner + + +_log.debug('matplotlib version %s', __version__) +_log.debug('interactive is %s', is_interactive()) +_log.debug('platform is %s', sys.platform) +_log.debug('loaded modules: %s', list(sys.modules)) diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/__init__.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..f33d323 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/__init__.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_animation_data.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_animation_data.cpython-36.pyc new file mode 100644 index 0000000..b16e775 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_animation_data.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_cm.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_cm.cpython-36.pyc new file mode 100644 index 0000000..dbbc45b Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_cm.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_cm_listed.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_cm_listed.cpython-36.pyc new file mode 100644 index 0000000..8fc588c Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_cm_listed.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_color_data.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_color_data.cpython-36.pyc new file mode 100644 index 0000000..a301968 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_color_data.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_constrained_layout.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_constrained_layout.cpython-36.pyc new file mode 100644 index 0000000..2caeb58 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_constrained_layout.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_layoutbox.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_layoutbox.cpython-36.pyc new file mode 100644 index 0000000..819096c Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_layoutbox.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_mathtext_data.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_mathtext_data.cpython-36.pyc new file mode 100644 index 0000000..64c1cce Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_mathtext_data.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_pylab_helpers.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_pylab_helpers.cpython-36.pyc new file mode 100644 index 0000000..fda3250 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_pylab_helpers.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_version.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_version.cpython-36.pyc new file mode 100644 index 0000000..5654578 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/_version.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/afm.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/afm.cpython-36.pyc new file mode 100644 index 0000000..9da274d Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/afm.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/animation.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/animation.cpython-36.pyc new file mode 100644 index 0000000..1141150 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/animation.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/artist.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/artist.cpython-36.pyc new file mode 100644 index 0000000..f08602f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/artist.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/axis.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/axis.cpython-36.pyc new file mode 100644 index 0000000..79d7bb2 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/axis.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_bases.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_bases.cpython-36.pyc new file mode 100644 index 0000000..1ef76a9 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_bases.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_managers.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_managers.cpython-36.pyc new file mode 100644 index 0000000..f6fb535 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_managers.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_tools.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_tools.cpython-36.pyc new file mode 100644 index 0000000..9663ee1 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/backend_tools.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/bezier.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/bezier.cpython-36.pyc new file mode 100644 index 0000000..9d2d17f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/bezier.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/blocking_input.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/blocking_input.cpython-36.pyc new file mode 100644 index 0000000..89edd91 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/blocking_input.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/category.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/category.cpython-36.pyc new file mode 100644 index 0000000..1ae01bd Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/category.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/cm.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/cm.cpython-36.pyc new file mode 100644 index 0000000..7bff44f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/cm.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/collections.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/collections.cpython-36.pyc new file mode 100644 index 0000000..13b9e9e Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/collections.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/colorbar.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/colorbar.cpython-36.pyc new file mode 100644 index 0000000..886b708 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/colorbar.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/colors.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/colors.cpython-36.pyc new file mode 100644 index 0000000..4df3ac8 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/colors.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/container.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/container.cpython-36.pyc new file mode 100644 index 0000000..4f6719f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/container.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/contour.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/contour.cpython-36.pyc new file mode 100644 index 0000000..fec0c0b Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/contour.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/dates.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/dates.cpython-36.pyc new file mode 100644 index 0000000..26fa5cf Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/dates.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/docstring.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/docstring.cpython-36.pyc new file mode 100644 index 0000000..7821f79 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/docstring.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/dviread.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/dviread.cpython-36.pyc new file mode 100644 index 0000000..c34570b Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/dviread.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/figure.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/figure.cpython-36.pyc new file mode 100644 index 0000000..e0f27bc Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/figure.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/font_manager.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/font_manager.cpython-36.pyc new file mode 100644 index 0000000..ad0a4bb Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/font_manager.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/fontconfig_pattern.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/fontconfig_pattern.cpython-36.pyc new file mode 100644 index 0000000..39e585e Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/fontconfig_pattern.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/gridspec.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/gridspec.cpython-36.pyc new file mode 100644 index 0000000..6a16d56 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/gridspec.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/hatch.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/hatch.cpython-36.pyc new file mode 100644 index 0000000..5142dc0 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/hatch.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/image.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/image.cpython-36.pyc new file mode 100644 index 0000000..a2d3a85 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/image.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/legend.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/legend.cpython-36.pyc new file mode 100644 index 0000000..c87afe6 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/legend.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/legend_handler.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/legend_handler.cpython-36.pyc new file mode 100644 index 0000000..b31f42e Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/legend_handler.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/lines.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/lines.cpython-36.pyc new file mode 100644 index 0000000..b6afd84 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/lines.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/markers.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/markers.cpython-36.pyc new file mode 100644 index 0000000..55639e2 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/markers.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/mathtext.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/mathtext.cpython-36.pyc new file mode 100644 index 0000000..af2b21f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/mathtext.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/mlab.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/mlab.cpython-36.pyc new file mode 100644 index 0000000..7dbb841 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/mlab.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/offsetbox.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/offsetbox.cpython-36.pyc new file mode 100644 index 0000000..4832854 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/offsetbox.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/patches.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/patches.cpython-36.pyc new file mode 100644 index 0000000..bf6812f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/patches.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/path.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/path.cpython-36.pyc new file mode 100644 index 0000000..e151b97 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/path.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/patheffects.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/patheffects.cpython-36.pyc new file mode 100644 index 0000000..818f188 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/patheffects.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/pylab.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/pylab.cpython-36.pyc new file mode 100644 index 0000000..b5c011b Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/pylab.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/pyplot.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/pyplot.cpython-36.pyc new file mode 100644 index 0000000..6d48378 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/pyplot.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/quiver.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/quiver.cpython-36.pyc new file mode 100644 index 0000000..bdfd362 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/quiver.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/rcsetup.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/rcsetup.cpython-36.pyc new file mode 100644 index 0000000..23ba74d Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/rcsetup.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/sankey.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/sankey.cpython-36.pyc new file mode 100644 index 0000000..d6a2e43 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/sankey.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/scale.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/scale.cpython-36.pyc new file mode 100644 index 0000000..1d48412 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/scale.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/spines.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/spines.cpython-36.pyc new file mode 100644 index 0000000..d86e146 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/spines.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/stackplot.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/stackplot.cpython-36.pyc new file mode 100644 index 0000000..4937595 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/stackplot.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/streamplot.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/streamplot.cpython-36.pyc new file mode 100644 index 0000000..ac7d2a0 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/streamplot.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/table.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/table.cpython-36.pyc new file mode 100644 index 0000000..b27b3dc Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/table.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/texmanager.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/texmanager.cpython-36.pyc new file mode 100644 index 0000000..93f555d Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/texmanager.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/text.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/text.cpython-36.pyc new file mode 100644 index 0000000..9efc356 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/text.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/textpath.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/textpath.cpython-36.pyc new file mode 100644 index 0000000..23277fe Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/textpath.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/ticker.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/ticker.cpython-36.pyc new file mode 100644 index 0000000..6cb0743 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/ticker.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/tight_bbox.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/tight_bbox.cpython-36.pyc new file mode 100644 index 0000000..5f35b99 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/tight_bbox.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/tight_layout.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/tight_layout.cpython-36.pyc new file mode 100644 index 0000000..3ff40a1 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/tight_layout.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/transforms.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/transforms.cpython-36.pyc new file mode 100644 index 0000000..ae0ad9d Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/transforms.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/type1font.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/type1font.cpython-36.pyc new file mode 100644 index 0000000..7b3a938 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/type1font.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/units.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/units.cpython-36.pyc new file mode 100644 index 0000000..5a9630f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/units.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/__pycache__/widgets.cpython-36.pyc b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/widgets.cpython-36.pyc new file mode 100644 index 0000000..3085378 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/__pycache__/widgets.cpython-36.pyc differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_animation_data.py b/venv/lib/python3.6/site-packages/matplotlib/_animation_data.py new file mode 100644 index 0000000..6045bd7 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_animation_data.py @@ -0,0 +1,260 @@ +# Javascript template for HTMLWriter +JS_INCLUDE = """ + + +""" + + +# Style definitions for the HTML template +STYLE_INCLUDE = """ + +""" + + +# HTML template for HTMLWriter +DISPLAY_TEMPLATE = """ +
+ +
+ +
+ + + + + + + + + +
+
+ + + + + + +
+
+
+ + + +""" + + +INCLUDED_FRAMES = """ + for (var i=0; i<{Nframes}; i++){{ + frames[i] = "{frame_dir}/frame" + ("0000000" + i).slice(-7) + + ".{frame_format}"; + }} +""" diff --git a/venv/lib/python3.6/site-packages/matplotlib/_cm.py b/venv/lib/python3.6/site-packages/matplotlib/_cm.py new file mode 100644 index 0000000..4de5e7c --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_cm.py @@ -0,0 +1,1426 @@ +""" +Nothing here but dictionaries for generating LinearSegmentedColormaps, +and a dictionary of these dictionaries. + +Documentation for each is in pyplot.colormaps(). Please update this +with the purpose and type of your colormap if you add data for one here. +""" + +from functools import partial + +import numpy as np + +_binary_data = { + 'red': ((0., 1., 1.), (1., 0., 0.)), + 'green': ((0., 1., 1.), (1., 0., 0.)), + 'blue': ((0., 1., 1.), (1., 0., 0.)) + } + +_autumn_data = {'red': ((0., 1.0, 1.0), (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), (1.0, 0., 0.))} + +_bone_data = {'red': ((0., 0., 0.), + (0.746032, 0.652778, 0.652778), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (0.365079, 0.319444, 0.319444), + (0.746032, 0.777778, 0.777778), + (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), + (0.365079, 0.444444, 0.444444), + (1.0, 1.0, 1.0))} + +_cool_data = {'red': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'green': ((0., 1., 1.), (1.0, 0., 0.)), + 'blue': ((0., 1., 1.), (1.0, 1., 1.))} + +_copper_data = {'red': ((0., 0., 0.), + (0.809524, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (1.0, 0.7812, 0.7812)), + 'blue': ((0., 0., 0.), + (1.0, 0.4975, 0.4975))} + +def _flag_red(x): return 0.75 * np.sin((x * 31.5 + 0.25) * np.pi) + 0.5 +def _flag_green(x): return np.sin(x * 31.5 * np.pi) +def _flag_blue(x): return 0.75 * np.sin((x * 31.5 - 0.25) * np.pi) + 0.5 +_flag_data = {'red': _flag_red, 'green': _flag_green, 'blue': _flag_blue} + +def _prism_red(x): return 0.75 * np.sin((x * 20.9 + 0.25) * np.pi) + 0.67 +def _prism_green(x): return 0.75 * np.sin((x * 20.9 - 0.25) * np.pi) + 0.33 +def _prism_blue(x): return -1.1 * np.sin((x * 20.9) * np.pi) +_prism_data = {'red': _prism_red, 'green': _prism_green, 'blue': _prism_blue} + +def _ch_helper(gamma, s, r, h, p0, p1, x): + """Helper function for generating picklable cubehelix color maps.""" + # Apply gamma factor to emphasise low or high intensity values + xg = x ** gamma + # Calculate amplitude and angle of deviation from the black to white + # diagonal in the plane of constant perceived intensity. + a = h * xg * (1 - xg) / 2 + phi = 2 * np.pi * (s / 3 + r * x) + return xg + a * (p0 * np.cos(phi) + p1 * np.sin(phi)) + +def cubehelix(gamma=1.0, s=0.5, r=-1.5, h=1.0): + """ + Return custom data dictionary of (r,g,b) conversion functions, which can be + used with :func:`register_cmap`, for the cubehelix color scheme. + + Unlike most other color schemes cubehelix was designed by D.A. Green to + be monotonically increasing in terms of perceived brightness. + Also, when printed on a black and white postscript printer, the scheme + results in a greyscale with monotonically increasing brightness. + This color scheme is named cubehelix because the r,g,b values produced + can be visualised as a squashed helix around the diagonal in the + r,g,b color cube. + + For a unit color cube (i.e. 3-D coordinates for r,g,b each in the + range 0 to 1) the color scheme starts at (r,g,b) = (0,0,0), i.e. black, + and finishes at (r,g,b) = (1,1,1), i.e. white. For some fraction *x*, + between 0 and 1, the color is the corresponding grey value at that + fraction along the black to white diagonal (x,x,x) plus a color + element. This color element is calculated in a plane of constant + perceived intensity and controlled by the following parameters. + + Optional keyword arguments: + + ========= ======================================================= + Keyword Description + ========= ======================================================= + gamma gamma factor to emphasise either low intensity values + (gamma < 1), or high intensity values (gamma > 1); + defaults to 1.0. + s the start color; defaults to 0.5 (i.e. purple). + r the number of r,g,b rotations in color that are made + from the start to the end of the color scheme; defaults + to -1.5 (i.e. -> B -> G -> R -> B). + h the hue parameter which controls how saturated the + colors are. If this parameter is zero then the color + scheme is purely a greyscale; defaults to 1.0. + ========= ======================================================= + """ + return {'red': partial(_ch_helper, gamma, s, r, h, -0.14861, 1.78277), + 'green': partial(_ch_helper, gamma, s, r, h, -0.29227, -0.90649), + 'blue': partial(_ch_helper, gamma, s, r, h, 1.97294, 0.0)} + +_cubehelix_data = cubehelix() + +_bwr_data = ((0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0)) +_brg_data = ((0.0, 0.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)) + +# Gnuplot palette functions +def _g0(x): return 0 +def _g1(x): return 0.5 +def _g2(x): return 1 +def _g3(x): return x +def _g4(x): return x ** 2 +def _g5(x): return x ** 3 +def _g6(x): return x ** 4 +def _g7(x): return np.sqrt(x) +def _g8(x): return np.sqrt(np.sqrt(x)) +def _g9(x): return np.sin(x * np.pi / 2) +def _g10(x): return np.cos(x * np.pi / 2) +def _g11(x): return np.abs(x - 0.5) +def _g12(x): return (2 * x - 1) ** 2 +def _g13(x): return np.sin(x * np.pi) +def _g14(x): return np.abs(np.cos(x * np.pi)) +def _g15(x): return np.sin(x * 2 * np.pi) +def _g16(x): return np.cos(x * 2 * np.pi) +def _g17(x): return np.abs(np.sin(x * 2 * np.pi)) +def _g18(x): return np.abs(np.cos(x * 2 * np.pi)) +def _g19(x): return np.abs(np.sin(x * 4 * np.pi)) +def _g20(x): return np.abs(np.cos(x * 4 * np.pi)) +def _g21(x): return 3 * x +def _g22(x): return 3 * x - 1 +def _g23(x): return 3 * x - 2 +def _g24(x): return np.abs(3 * x - 1) +def _g25(x): return np.abs(3 * x - 2) +def _g26(x): return (3 * x - 1) / 2 +def _g27(x): return (3 * x - 2) / 2 +def _g28(x): return np.abs((3 * x - 1) / 2) +def _g29(x): return np.abs((3 * x - 2) / 2) +def _g30(x): return x / 0.32 - 0.78125 +def _g31(x): return 2 * x - 0.84 +def _g32(x): + ret = np.zeros(len(x)) + m = (x < 0.25) + ret[m] = 4 * x[m] + m = (x >= 0.25) & (x < 0.92) + ret[m] = -2 * x[m] + 1.84 + m = (x >= 0.92) + ret[m] = x[m] / 0.08 - 11.5 + return ret +def _g33(x): return np.abs(2 * x - 0.5) +def _g34(x): return 2 * x +def _g35(x): return 2 * x - 0.5 +def _g36(x): return 2 * x - 1 + +gfunc = {i: globals()["_g{}".format(i)] for i in range(37)} + +_gnuplot_data = { + 'red': gfunc[7], + 'green': gfunc[5], + 'blue': gfunc[15], +} + +_gnuplot2_data = { + 'red': gfunc[30], + 'green': gfunc[31], + 'blue': gfunc[32], +} + +_ocean_data = { + 'red': gfunc[23], + 'green': gfunc[28], + 'blue': gfunc[3], +} + +_afmhot_data = { + 'red': gfunc[34], + 'green': gfunc[35], + 'blue': gfunc[36], +} + +_rainbow_data = { + 'red': gfunc[33], + 'green': gfunc[13], + 'blue': gfunc[10], +} + +_seismic_data = ( + (0.0, 0.0, 0.3), (0.0, 0.0, 1.0), + (1.0, 1.0, 1.0), (1.0, 0.0, 0.0), + (0.5, 0.0, 0.0)) + +_terrain_data = ( + (0.00, (0.2, 0.2, 0.6)), + (0.15, (0.0, 0.6, 1.0)), + (0.25, (0.0, 0.8, 0.4)), + (0.50, (1.0, 1.0, 0.6)), + (0.75, (0.5, 0.36, 0.33)), + (1.00, (1.0, 1.0, 1.0))) + +_gray_data = {'red': ((0., 0, 0), (1., 1, 1)), + 'green': ((0., 0, 0), (1., 1, 1)), + 'blue': ((0., 0, 0), (1., 1, 1))} + +_hot_data = {'red': ((0., 0.0416, 0.0416), + (0.365079, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (0.365079, 0.000000, 0.000000), + (0.746032, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), + (0.746032, 0.000000, 0.000000), + (1.0, 1.0, 1.0))} + +_hsv_data = {'red': ((0., 1., 1.), + (0.158730, 1.000000, 1.000000), + (0.174603, 0.968750, 0.968750), + (0.333333, 0.031250, 0.031250), + (0.349206, 0.000000, 0.000000), + (0.666667, 0.000000, 0.000000), + (0.682540, 0.031250, 0.031250), + (0.841270, 0.968750, 0.968750), + (0.857143, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (0.158730, 0.937500, 0.937500), + (0.174603, 1.000000, 1.000000), + (0.507937, 1.000000, 1.000000), + (0.666667, 0.062500, 0.062500), + (0.682540, 0.000000, 0.000000), + (1.0, 0., 0.)), + 'blue': ((0., 0., 0.), + (0.333333, 0.000000, 0.000000), + (0.349206, 0.062500, 0.062500), + (0.507937, 1.000000, 1.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 0.937500, 0.937500), + (1.0, 0.09375, 0.09375))} + +_jet_data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1), + (1, 0.5, 0.5)), + 'green': ((0., 0, 0), (0.125, 0, 0), (0.375, 1, 1), (0.64, 1, 1), + (0.91, 0, 0), (1, 0, 0)), + 'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), + (0.65, 0, 0), (1, 0, 0))} + +_pink_data = {'red': ((0., 0.1178, 0.1178), (0.015873, 0.195857, 0.195857), + (0.031746, 0.250661, 0.250661), + (0.047619, 0.295468, 0.295468), + (0.063492, 0.334324, 0.334324), + (0.079365, 0.369112, 0.369112), + (0.095238, 0.400892, 0.400892), + (0.111111, 0.430331, 0.430331), + (0.126984, 0.457882, 0.457882), + (0.142857, 0.483867, 0.483867), + (0.158730, 0.508525, 0.508525), + (0.174603, 0.532042, 0.532042), + (0.190476, 0.554563, 0.554563), + (0.206349, 0.576204, 0.576204), + (0.222222, 0.597061, 0.597061), + (0.238095, 0.617213, 0.617213), + (0.253968, 0.636729, 0.636729), + (0.269841, 0.655663, 0.655663), + (0.285714, 0.674066, 0.674066), + (0.301587, 0.691980, 0.691980), + (0.317460, 0.709441, 0.709441), + (0.333333, 0.726483, 0.726483), + (0.349206, 0.743134, 0.743134), + (0.365079, 0.759421, 0.759421), + (0.380952, 0.766356, 0.766356), + (0.396825, 0.773229, 0.773229), + (0.412698, 0.780042, 0.780042), + (0.428571, 0.786796, 0.786796), + (0.444444, 0.793492, 0.793492), + (0.460317, 0.800132, 0.800132), + (0.476190, 0.806718, 0.806718), + (0.492063, 0.813250, 0.813250), + (0.507937, 0.819730, 0.819730), + (0.523810, 0.826160, 0.826160), + (0.539683, 0.832539, 0.832539), + (0.555556, 0.838870, 0.838870), + (0.571429, 0.845154, 0.845154), + (0.587302, 0.851392, 0.851392), + (0.603175, 0.857584, 0.857584), + (0.619048, 0.863731, 0.863731), + (0.634921, 0.869835, 0.869835), + (0.650794, 0.875897, 0.875897), + (0.666667, 0.881917, 0.881917), + (0.682540, 0.887896, 0.887896), + (0.698413, 0.893835, 0.893835), + (0.714286, 0.899735, 0.899735), + (0.730159, 0.905597, 0.905597), + (0.746032, 0.911421, 0.911421), + (0.761905, 0.917208, 0.917208), + (0.777778, 0.922958, 0.922958), + (0.793651, 0.928673, 0.928673), + (0.809524, 0.934353, 0.934353), + (0.825397, 0.939999, 0.939999), + (0.841270, 0.945611, 0.945611), + (0.857143, 0.951190, 0.951190), + (0.873016, 0.956736, 0.956736), + (0.888889, 0.962250, 0.962250), + (0.904762, 0.967733, 0.967733), + (0.920635, 0.973185, 0.973185), + (0.936508, 0.978607, 0.978607), + (0.952381, 0.983999, 0.983999), + (0.968254, 0.989361, 0.989361), + (0.984127, 0.994695, 0.994695), (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), (0.015873, 0.102869, 0.102869), + (0.031746, 0.145479, 0.145479), + (0.047619, 0.178174, 0.178174), + (0.063492, 0.205738, 0.205738), + (0.079365, 0.230022, 0.230022), + (0.095238, 0.251976, 0.251976), + (0.111111, 0.272166, 0.272166), + (0.126984, 0.290957, 0.290957), + (0.142857, 0.308607, 0.308607), + (0.158730, 0.325300, 0.325300), + (0.174603, 0.341178, 0.341178), + (0.190476, 0.356348, 0.356348), + (0.206349, 0.370899, 0.370899), + (0.222222, 0.384900, 0.384900), + (0.238095, 0.398410, 0.398410), + (0.253968, 0.411476, 0.411476), + (0.269841, 0.424139, 0.424139), + (0.285714, 0.436436, 0.436436), + (0.301587, 0.448395, 0.448395), + (0.317460, 0.460044, 0.460044), + (0.333333, 0.471405, 0.471405), + (0.349206, 0.482498, 0.482498), + (0.365079, 0.493342, 0.493342), + (0.380952, 0.517549, 0.517549), + (0.396825, 0.540674, 0.540674), + (0.412698, 0.562849, 0.562849), + (0.428571, 0.584183, 0.584183), + (0.444444, 0.604765, 0.604765), + (0.460317, 0.624669, 0.624669), + (0.476190, 0.643958, 0.643958), + (0.492063, 0.662687, 0.662687), + (0.507937, 0.680900, 0.680900), + (0.523810, 0.698638, 0.698638), + (0.539683, 0.715937, 0.715937), + (0.555556, 0.732828, 0.732828), + (0.571429, 0.749338, 0.749338), + (0.587302, 0.765493, 0.765493), + (0.603175, 0.781313, 0.781313), + (0.619048, 0.796819, 0.796819), + (0.634921, 0.812029, 0.812029), + (0.650794, 0.826960, 0.826960), + (0.666667, 0.841625, 0.841625), + (0.682540, 0.856040, 0.856040), + (0.698413, 0.870216, 0.870216), + (0.714286, 0.884164, 0.884164), + (0.730159, 0.897896, 0.897896), + (0.746032, 0.911421, 0.911421), + (0.761905, 0.917208, 0.917208), + (0.777778, 0.922958, 0.922958), + (0.793651, 0.928673, 0.928673), + (0.809524, 0.934353, 0.934353), + (0.825397, 0.939999, 0.939999), + (0.841270, 0.945611, 0.945611), + (0.857143, 0.951190, 0.951190), + (0.873016, 0.956736, 0.956736), + (0.888889, 0.962250, 0.962250), + (0.904762, 0.967733, 0.967733), + (0.920635, 0.973185, 0.973185), + (0.936508, 0.978607, 0.978607), + (0.952381, 0.983999, 0.983999), + (0.968254, 0.989361, 0.989361), + (0.984127, 0.994695, 0.994695), (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), (0.015873, 0.102869, 0.102869), + (0.031746, 0.145479, 0.145479), + (0.047619, 0.178174, 0.178174), + (0.063492, 0.205738, 0.205738), + (0.079365, 0.230022, 0.230022), + (0.095238, 0.251976, 0.251976), + (0.111111, 0.272166, 0.272166), + (0.126984, 0.290957, 0.290957), + (0.142857, 0.308607, 0.308607), + (0.158730, 0.325300, 0.325300), + (0.174603, 0.341178, 0.341178), + (0.190476, 0.356348, 0.356348), + (0.206349, 0.370899, 0.370899), + (0.222222, 0.384900, 0.384900), + (0.238095, 0.398410, 0.398410), + (0.253968, 0.411476, 0.411476), + (0.269841, 0.424139, 0.424139), + (0.285714, 0.436436, 0.436436), + (0.301587, 0.448395, 0.448395), + (0.317460, 0.460044, 0.460044), + (0.333333, 0.471405, 0.471405), + (0.349206, 0.482498, 0.482498), + (0.365079, 0.493342, 0.493342), + (0.380952, 0.503953, 0.503953), + (0.396825, 0.514344, 0.514344), + (0.412698, 0.524531, 0.524531), + (0.428571, 0.534522, 0.534522), + (0.444444, 0.544331, 0.544331), + (0.460317, 0.553966, 0.553966), + (0.476190, 0.563436, 0.563436), + (0.492063, 0.572750, 0.572750), + (0.507937, 0.581914, 0.581914), + (0.523810, 0.590937, 0.590937), + (0.539683, 0.599824, 0.599824), + (0.555556, 0.608581, 0.608581), + (0.571429, 0.617213, 0.617213), + (0.587302, 0.625727, 0.625727), + (0.603175, 0.634126, 0.634126), + (0.619048, 0.642416, 0.642416), + (0.634921, 0.650600, 0.650600), + (0.650794, 0.658682, 0.658682), + (0.666667, 0.666667, 0.666667), + (0.682540, 0.674556, 0.674556), + (0.698413, 0.682355, 0.682355), + (0.714286, 0.690066, 0.690066), + (0.730159, 0.697691, 0.697691), + (0.746032, 0.705234, 0.705234), + (0.761905, 0.727166, 0.727166), + (0.777778, 0.748455, 0.748455), + (0.793651, 0.769156, 0.769156), + (0.809524, 0.789314, 0.789314), + (0.825397, 0.808969, 0.808969), + (0.841270, 0.828159, 0.828159), + (0.857143, 0.846913, 0.846913), + (0.873016, 0.865261, 0.865261), + (0.888889, 0.883229, 0.883229), + (0.904762, 0.900837, 0.900837), + (0.920635, 0.918109, 0.918109), + (0.936508, 0.935061, 0.935061), + (0.952381, 0.951711, 0.951711), + (0.968254, 0.968075, 0.968075), + (0.984127, 0.984167, 0.984167), (1.0, 1.0, 1.0))} + +_spring_data = {'red': ((0., 1., 1.), (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'blue': ((0., 1., 1.), (1.0, 0.0, 0.0))} + + +_summer_data = {'red': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'green': ((0., 0.5, 0.5), (1.0, 1.0, 1.0)), + 'blue': ((0., 0.4, 0.4), (1.0, 0.4, 0.4))} + + +_winter_data = {'red': ((0., 0., 0.), (1.0, 0.0, 0.0)), + 'green': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'blue': ((0., 1., 1.), (1.0, 0.5, 0.5))} + +_nipy_spectral_data = { + 'red': [(0.0, 0.0, 0.0), (0.05, 0.4667, 0.4667), + (0.10, 0.5333, 0.5333), (0.15, 0.0, 0.0), + (0.20, 0.0, 0.0), (0.25, 0.0, 0.0), + (0.30, 0.0, 0.0), (0.35, 0.0, 0.0), + (0.40, 0.0, 0.0), (0.45, 0.0, 0.0), + (0.50, 0.0, 0.0), (0.55, 0.0, 0.0), + (0.60, 0.0, 0.0), (0.65, 0.7333, 0.7333), + (0.70, 0.9333, 0.9333), (0.75, 1.0, 1.0), + (0.80, 1.0, 1.0), (0.85, 1.0, 1.0), + (0.90, 0.8667, 0.8667), (0.95, 0.80, 0.80), + (1.0, 0.80, 0.80)], + 'green': [(0.0, 0.0, 0.0), (0.05, 0.0, 0.0), + (0.10, 0.0, 0.0), (0.15, 0.0, 0.0), + (0.20, 0.0, 0.0), (0.25, 0.4667, 0.4667), + (0.30, 0.6000, 0.6000), (0.35, 0.6667, 0.6667), + (0.40, 0.6667, 0.6667), (0.45, 0.6000, 0.6000), + (0.50, 0.7333, 0.7333), (0.55, 0.8667, 0.8667), + (0.60, 1.0, 1.0), (0.65, 1.0, 1.0), + (0.70, 0.9333, 0.9333), (0.75, 0.8000, 0.8000), + (0.80, 0.6000, 0.6000), (0.85, 0.0, 0.0), + (0.90, 0.0, 0.0), (0.95, 0.0, 0.0), + (1.0, 0.80, 0.80)], + 'blue': [(0.0, 0.0, 0.0), (0.05, 0.5333, 0.5333), + (0.10, 0.6000, 0.6000), (0.15, 0.6667, 0.6667), + (0.20, 0.8667, 0.8667), (0.25, 0.8667, 0.8667), + (0.30, 0.8667, 0.8667), (0.35, 0.6667, 0.6667), + (0.40, 0.5333, 0.5333), (0.45, 0.0, 0.0), + (0.5, 0.0, 0.0), (0.55, 0.0, 0.0), + (0.60, 0.0, 0.0), (0.65, 0.0, 0.0), + (0.70, 0.0, 0.0), (0.75, 0.0, 0.0), + (0.80, 0.0, 0.0), (0.85, 0.0, 0.0), + (0.90, 0.0, 0.0), (0.95, 0.0, 0.0), + (1.0, 0.80, 0.80)], +} + + +# 34 colormaps based on color specifications and designs +# developed by Cynthia Brewer (http://colorbrewer.org). +# The ColorBrewer palettes have been included under the terms +# of an Apache-stype license (for details, see the file +# LICENSE_COLORBREWER in the license directory of the matplotlib +# source distribution). + +# RGB values taken from Brewer's Excel sheet, divided by 255 + +_Blues_data = ( + (0.96862745098039216, 0.98431372549019602, 1.0 ), + (0.87058823529411766, 0.92156862745098034, 0.96862745098039216), + (0.77647058823529413, 0.85882352941176465, 0.93725490196078431), + (0.61960784313725492, 0.792156862745098 , 0.88235294117647056), + (0.41960784313725491, 0.68235294117647061, 0.83921568627450982), + (0.25882352941176473, 0.5725490196078431 , 0.77647058823529413), + (0.12941176470588237, 0.44313725490196076, 0.70980392156862748), + (0.03137254901960784, 0.31764705882352939, 0.61176470588235299), + (0.03137254901960784, 0.18823529411764706, 0.41960784313725491) + ) + +_BrBG_data = ( + (0.32941176470588235, 0.18823529411764706, 0.0196078431372549 ), + (0.5490196078431373 , 0.31764705882352939, 0.0392156862745098 ), + (0.74901960784313726, 0.50588235294117645, 0.17647058823529413), + (0.87450980392156863, 0.76078431372549016, 0.49019607843137253), + (0.96470588235294119, 0.90980392156862744, 0.76470588235294112), + (0.96078431372549022, 0.96078431372549022, 0.96078431372549022), + (0.7803921568627451 , 0.91764705882352937, 0.89803921568627454), + (0.50196078431372548, 0.80392156862745101, 0.75686274509803919), + (0.20784313725490197, 0.59215686274509804, 0.5607843137254902 ), + (0.00392156862745098, 0.4 , 0.36862745098039218), + (0.0 , 0.23529411764705882, 0.18823529411764706) + ) + +_BuGn_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.99215686274509807), + (0.89803921568627454, 0.96078431372549022, 0.97647058823529409), + (0.8 , 0.92549019607843142, 0.90196078431372551), + (0.6 , 0.84705882352941175, 0.78823529411764703), + (0.4 , 0.76078431372549016, 0.64313725490196083), + (0.25490196078431371, 0.68235294117647061, 0.46274509803921571), + (0.13725490196078433, 0.54509803921568623, 0.27058823529411763), + (0.0 , 0.42745098039215684, 0.17254901960784313), + (0.0 , 0.26666666666666666, 0.10588235294117647) + ) + +_BuPu_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.99215686274509807), + (0.8784313725490196 , 0.92549019607843142, 0.95686274509803926), + (0.74901960784313726, 0.82745098039215681, 0.90196078431372551), + (0.61960784313725492, 0.73725490196078436, 0.85490196078431369), + (0.5490196078431373 , 0.58823529411764708, 0.77647058823529413), + (0.5490196078431373 , 0.41960784313725491, 0.69411764705882351), + (0.53333333333333333, 0.25490196078431371, 0.61568627450980395), + (0.50588235294117645, 0.05882352941176471, 0.48627450980392156), + (0.30196078431372547, 0.0 , 0.29411764705882354) + ) + +_GnBu_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.94117647058823528), + (0.8784313725490196 , 0.95294117647058818, 0.85882352941176465), + (0.8 , 0.92156862745098034, 0.77254901960784317), + (0.6588235294117647 , 0.8666666666666667 , 0.70980392156862748), + (0.4823529411764706 , 0.8 , 0.7686274509803922 ), + (0.30588235294117649, 0.70196078431372544, 0.82745098039215681), + (0.16862745098039217, 0.5490196078431373 , 0.74509803921568629), + (0.03137254901960784, 0.40784313725490196, 0.67450980392156867), + (0.03137254901960784, 0.25098039215686274, 0.50588235294117645) + ) + +_Greens_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.96078431372549022), + (0.89803921568627454, 0.96078431372549022, 0.8784313725490196 ), + (0.7803921568627451 , 0.9137254901960784 , 0.75294117647058822), + (0.63137254901960782, 0.85098039215686272, 0.60784313725490191), + (0.45490196078431372, 0.7686274509803922 , 0.46274509803921571), + (0.25490196078431371, 0.6705882352941176 , 0.36470588235294116), + (0.13725490196078433, 0.54509803921568623, 0.27058823529411763), + (0.0 , 0.42745098039215684, 0.17254901960784313), + (0.0 , 0.26666666666666666, 0.10588235294117647) + ) + +_Greys_data = ( + (1.0 , 1.0 , 1.0 ), + (0.94117647058823528, 0.94117647058823528, 0.94117647058823528), + (0.85098039215686272, 0.85098039215686272, 0.85098039215686272), + (0.74117647058823533, 0.74117647058823533, 0.74117647058823533), + (0.58823529411764708, 0.58823529411764708, 0.58823529411764708), + (0.45098039215686275, 0.45098039215686275, 0.45098039215686275), + (0.32156862745098042, 0.32156862745098042, 0.32156862745098042), + (0.14509803921568629, 0.14509803921568629, 0.14509803921568629), + (0.0 , 0.0 , 0.0 ) + ) + +_Oranges_data = ( + (1.0 , 0.96078431372549022, 0.92156862745098034), + (0.99607843137254903, 0.90196078431372551, 0.80784313725490198), + (0.99215686274509807, 0.81568627450980391, 0.63529411764705879), + (0.99215686274509807, 0.68235294117647061, 0.41960784313725491), + (0.99215686274509807, 0.55294117647058827, 0.23529411764705882), + (0.94509803921568625, 0.41176470588235292, 0.07450980392156863), + (0.85098039215686272, 0.28235294117647058, 0.00392156862745098), + (0.65098039215686276, 0.21176470588235294, 0.01176470588235294), + (0.49803921568627452, 0.15294117647058825, 0.01568627450980392) + ) + +_OrRd_data = ( + (1.0 , 0.96862745098039216, 0.92549019607843142), + (0.99607843137254903, 0.90980392156862744, 0.78431372549019607), + (0.99215686274509807, 0.83137254901960789, 0.61960784313725492), + (0.99215686274509807, 0.73333333333333328, 0.51764705882352946), + (0.9882352941176471 , 0.55294117647058827, 0.34901960784313724), + (0.93725490196078431, 0.396078431372549 , 0.28235294117647058), + (0.84313725490196079, 0.18823529411764706, 0.12156862745098039), + (0.70196078431372544, 0.0 , 0.0 ), + (0.49803921568627452, 0.0 , 0.0 ) + ) + +_PiYG_data = ( + (0.55686274509803924, 0.00392156862745098, 0.32156862745098042), + (0.77254901960784317, 0.10588235294117647, 0.49019607843137253), + (0.87058823529411766, 0.46666666666666667, 0.68235294117647061), + (0.94509803921568625, 0.71372549019607845, 0.85490196078431369), + (0.99215686274509807, 0.8784313725490196 , 0.93725490196078431), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.90196078431372551, 0.96078431372549022, 0.81568627450980391), + (0.72156862745098038, 0.88235294117647056, 0.52549019607843139), + (0.49803921568627452, 0.73725490196078436, 0.25490196078431371), + (0.30196078431372547, 0.5725490196078431 , 0.12941176470588237), + (0.15294117647058825, 0.39215686274509803, 0.09803921568627451) + ) + +_PRGn_data = ( + (0.25098039215686274, 0.0 , 0.29411764705882354), + (0.46274509803921571, 0.16470588235294117, 0.51372549019607838), + (0.6 , 0.4392156862745098 , 0.6705882352941176 ), + (0.76078431372549016, 0.6470588235294118 , 0.81176470588235294), + (0.90588235294117647, 0.83137254901960789, 0.90980392156862744), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.85098039215686272, 0.94117647058823528, 0.82745098039215681), + (0.65098039215686276, 0.85882352941176465, 0.62745098039215685), + (0.35294117647058826, 0.68235294117647061, 0.38039215686274508), + (0.10588235294117647, 0.47058823529411764, 0.21568627450980393), + (0.0 , 0.26666666666666666, 0.10588235294117647) + ) + +_PuBu_data = ( + (1.0 , 0.96862745098039216, 0.98431372549019602), + (0.92549019607843142, 0.90588235294117647, 0.94901960784313721), + (0.81568627450980391, 0.81960784313725488, 0.90196078431372551), + (0.65098039215686276, 0.74117647058823533, 0.85882352941176465), + (0.45490196078431372, 0.66274509803921566, 0.81176470588235294), + (0.21176470588235294, 0.56470588235294117, 0.75294117647058822), + (0.0196078431372549 , 0.4392156862745098 , 0.69019607843137254), + (0.01568627450980392, 0.35294117647058826, 0.55294117647058827), + (0.00784313725490196, 0.2196078431372549 , 0.34509803921568627) + ) + +_PuBuGn_data = ( + (1.0 , 0.96862745098039216, 0.98431372549019602), + (0.92549019607843142, 0.88627450980392153, 0.94117647058823528), + (0.81568627450980391, 0.81960784313725488, 0.90196078431372551), + (0.65098039215686276, 0.74117647058823533, 0.85882352941176465), + (0.40392156862745099, 0.66274509803921566, 0.81176470588235294), + (0.21176470588235294, 0.56470588235294117, 0.75294117647058822), + (0.00784313725490196, 0.50588235294117645, 0.54117647058823526), + (0.00392156862745098, 0.42352941176470588, 0.34901960784313724), + (0.00392156862745098, 0.27450980392156865, 0.21176470588235294) + ) + +_PuOr_data = ( + (0.49803921568627452, 0.23137254901960785, 0.03137254901960784), + (0.70196078431372544, 0.34509803921568627, 0.02352941176470588), + (0.8784313725490196 , 0.50980392156862742, 0.07843137254901961), + (0.99215686274509807, 0.72156862745098038, 0.38823529411764707), + (0.99607843137254903, 0.8784313725490196 , 0.71372549019607845), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.84705882352941175, 0.85490196078431369, 0.92156862745098034), + (0.69803921568627447, 0.6705882352941176 , 0.82352941176470584), + (0.50196078431372548, 0.45098039215686275, 0.67450980392156867), + (0.32941176470588235, 0.15294117647058825, 0.53333333333333333), + (0.17647058823529413, 0.0 , 0.29411764705882354) + ) + +_PuRd_data = ( + (0.96862745098039216, 0.95686274509803926, 0.97647058823529409), + (0.90588235294117647, 0.88235294117647056, 0.93725490196078431), + (0.83137254901960789, 0.72549019607843135, 0.85490196078431369), + (0.78823529411764703, 0.58039215686274515, 0.7803921568627451 ), + (0.87450980392156863, 0.396078431372549 , 0.69019607843137254), + (0.90588235294117647, 0.16078431372549021, 0.54117647058823526), + (0.80784313725490198, 0.07058823529411765, 0.33725490196078434), + (0.59607843137254901, 0.0 , 0.2627450980392157 ), + (0.40392156862745099, 0.0 , 0.12156862745098039) + ) + +_Purples_data = ( + (0.9882352941176471 , 0.98431372549019602, 0.99215686274509807), + (0.93725490196078431, 0.92941176470588238, 0.96078431372549022), + (0.85490196078431369, 0.85490196078431369, 0.92156862745098034), + (0.73725490196078436, 0.74117647058823533, 0.86274509803921573), + (0.61960784313725492, 0.60392156862745094, 0.78431372549019607), + (0.50196078431372548, 0.49019607843137253, 0.72941176470588232), + (0.41568627450980394, 0.31764705882352939, 0.63921568627450975), + (0.32941176470588235, 0.15294117647058825, 0.5607843137254902 ), + (0.24705882352941178, 0.0 , 0.49019607843137253) + ) + +_RdBu_data = ( + (0.40392156862745099, 0.0 , 0.12156862745098039), + (0.69803921568627447, 0.09411764705882353, 0.16862745098039217), + (0.83921568627450982, 0.37647058823529411, 0.30196078431372547), + (0.95686274509803926, 0.6470588235294118 , 0.50980392156862742), + (0.99215686274509807, 0.85882352941176465, 0.7803921568627451 ), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.81960784313725488, 0.89803921568627454, 0.94117647058823528), + (0.5725490196078431 , 0.77254901960784317, 0.87058823529411766), + (0.2627450980392157 , 0.57647058823529407, 0.76470588235294112), + (0.12941176470588237, 0.4 , 0.67450980392156867), + (0.0196078431372549 , 0.18823529411764706, 0.38039215686274508) + ) + +_RdGy_data = ( + (0.40392156862745099, 0.0 , 0.12156862745098039), + (0.69803921568627447, 0.09411764705882353, 0.16862745098039217), + (0.83921568627450982, 0.37647058823529411, 0.30196078431372547), + (0.95686274509803926, 0.6470588235294118 , 0.50980392156862742), + (0.99215686274509807, 0.85882352941176465, 0.7803921568627451 ), + (1.0 , 1.0 , 1.0 ), + (0.8784313725490196 , 0.8784313725490196 , 0.8784313725490196 ), + (0.72941176470588232, 0.72941176470588232, 0.72941176470588232), + (0.52941176470588236, 0.52941176470588236, 0.52941176470588236), + (0.30196078431372547, 0.30196078431372547, 0.30196078431372547), + (0.10196078431372549, 0.10196078431372549, 0.10196078431372549) + ) + +_RdPu_data = ( + (1.0 , 0.96862745098039216, 0.95294117647058818), + (0.99215686274509807, 0.8784313725490196 , 0.86666666666666667), + (0.9882352941176471 , 0.77254901960784317, 0.75294117647058822), + (0.98039215686274506, 0.62352941176470589, 0.70980392156862748), + (0.96862745098039216, 0.40784313725490196, 0.63137254901960782), + (0.86666666666666667, 0.20392156862745098, 0.59215686274509804), + (0.68235294117647061, 0.00392156862745098, 0.49411764705882355), + (0.47843137254901963, 0.00392156862745098, 0.46666666666666667), + (0.28627450980392155, 0.0 , 0.41568627450980394) + ) + +_RdYlBu_data = ( + (0.6470588235294118 , 0.0 , 0.14901960784313725), + (0.84313725490196079, 0.18823529411764706 , 0.15294117647058825), + (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ), + (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508), + (0.99607843137254903, 0.8784313725490196 , 0.56470588235294117), + (1.0 , 1.0 , 0.74901960784313726), + (0.8784313725490196 , 0.95294117647058818 , 0.97254901960784312), + (0.6705882352941176 , 0.85098039215686272 , 0.9137254901960784 ), + (0.45490196078431372, 0.67843137254901964 , 0.81960784313725488), + (0.27058823529411763, 0.45882352941176469 , 0.70588235294117652), + (0.19215686274509805, 0.21176470588235294 , 0.58431372549019611) + ) + +_RdYlGn_data = ( + (0.6470588235294118 , 0.0 , 0.14901960784313725), + (0.84313725490196079, 0.18823529411764706 , 0.15294117647058825), + (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ), + (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508), + (0.99607843137254903, 0.8784313725490196 , 0.54509803921568623), + (1.0 , 1.0 , 0.74901960784313726), + (0.85098039215686272, 0.93725490196078431 , 0.54509803921568623), + (0.65098039215686276, 0.85098039215686272 , 0.41568627450980394), + (0.4 , 0.74117647058823533 , 0.38823529411764707), + (0.10196078431372549, 0.59607843137254901 , 0.31372549019607843), + (0.0 , 0.40784313725490196 , 0.21568627450980393) + ) + +_Reds_data = ( + (1.0 , 0.96078431372549022 , 0.94117647058823528), + (0.99607843137254903, 0.8784313725490196 , 0.82352941176470584), + (0.9882352941176471 , 0.73333333333333328 , 0.63137254901960782), + (0.9882352941176471 , 0.5725490196078431 , 0.44705882352941179), + (0.98431372549019602, 0.41568627450980394 , 0.29019607843137257), + (0.93725490196078431, 0.23137254901960785 , 0.17254901960784313), + (0.79607843137254897, 0.094117647058823528, 0.11372549019607843), + (0.6470588235294118 , 0.058823529411764705, 0.08235294117647058), + (0.40392156862745099, 0.0 , 0.05098039215686274) + ) + +_Spectral_data = ( + (0.61960784313725492, 0.003921568627450980, 0.25882352941176473), + (0.83529411764705885, 0.24313725490196078 , 0.30980392156862746), + (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ), + (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508), + (0.99607843137254903, 0.8784313725490196 , 0.54509803921568623), + (1.0 , 1.0 , 0.74901960784313726), + (0.90196078431372551, 0.96078431372549022 , 0.59607843137254901), + (0.6705882352941176 , 0.8666666666666667 , 0.64313725490196083), + (0.4 , 0.76078431372549016 , 0.6470588235294118 ), + (0.19607843137254902, 0.53333333333333333 , 0.74117647058823533), + (0.36862745098039218, 0.30980392156862746 , 0.63529411764705879) + ) + +_YlGn_data = ( + (1.0 , 1.0 , 0.89803921568627454), + (0.96862745098039216, 0.9882352941176471 , 0.72549019607843135), + (0.85098039215686272, 0.94117647058823528 , 0.63921568627450975), + (0.67843137254901964, 0.8666666666666667 , 0.55686274509803924), + (0.47058823529411764, 0.77647058823529413 , 0.47450980392156861), + (0.25490196078431371, 0.6705882352941176 , 0.36470588235294116), + (0.13725490196078433, 0.51764705882352946 , 0.2627450980392157 ), + (0.0 , 0.40784313725490196 , 0.21568627450980393), + (0.0 , 0.27058823529411763 , 0.16078431372549021) + ) + +_YlGnBu_data = ( + (1.0 , 1.0 , 0.85098039215686272), + (0.92941176470588238, 0.97254901960784312 , 0.69411764705882351), + (0.7803921568627451 , 0.9137254901960784 , 0.70588235294117652), + (0.49803921568627452, 0.80392156862745101 , 0.73333333333333328), + (0.25490196078431371, 0.71372549019607845 , 0.7686274509803922 ), + (0.11372549019607843, 0.56862745098039214 , 0.75294117647058822), + (0.13333333333333333, 0.36862745098039218 , 0.6588235294117647 ), + (0.14509803921568629, 0.20392156862745098 , 0.58039215686274515), + (0.03137254901960784, 0.11372549019607843 , 0.34509803921568627) + ) + +_YlOrBr_data = ( + (1.0 , 1.0 , 0.89803921568627454), + (1.0 , 0.96862745098039216 , 0.73725490196078436), + (0.99607843137254903, 0.8901960784313725 , 0.56862745098039214), + (0.99607843137254903, 0.7686274509803922 , 0.30980392156862746), + (0.99607843137254903, 0.6 , 0.16078431372549021), + (0.92549019607843142, 0.4392156862745098 , 0.07843137254901961), + (0.8 , 0.29803921568627451 , 0.00784313725490196), + (0.6 , 0.20392156862745098 , 0.01568627450980392), + (0.4 , 0.14509803921568629 , 0.02352941176470588) + ) + +_YlOrRd_data = ( + (1.0 , 1.0 , 0.8 ), + (1.0 , 0.92941176470588238 , 0.62745098039215685), + (0.99607843137254903, 0.85098039215686272 , 0.46274509803921571), + (0.99607843137254903, 0.69803921568627447 , 0.29803921568627451), + (0.99215686274509807, 0.55294117647058827 , 0.23529411764705882), + (0.9882352941176471 , 0.30588235294117649 , 0.16470588235294117), + (0.8901960784313725 , 0.10196078431372549 , 0.10980392156862745), + (0.74117647058823533, 0.0 , 0.14901960784313725), + (0.50196078431372548, 0.0 , 0.14901960784313725) + ) + + +# ColorBrewer's qualitative maps, implemented using ListedColormap +# for use with mpl.colors.NoNorm + +_Accent_data = ( + (0.49803921568627452, 0.78823529411764703, 0.49803921568627452), + (0.74509803921568629, 0.68235294117647061, 0.83137254901960789), + (0.99215686274509807, 0.75294117647058822, 0.52549019607843139), + (1.0, 1.0, 0.6 ), + (0.2196078431372549, 0.42352941176470588, 0.69019607843137254), + (0.94117647058823528, 0.00784313725490196, 0.49803921568627452), + (0.74901960784313726, 0.35686274509803922, 0.09019607843137254), + (0.4, 0.4, 0.4 ), + ) + +_Dark2_data = ( + (0.10588235294117647, 0.61960784313725492, 0.46666666666666667), + (0.85098039215686272, 0.37254901960784315, 0.00784313725490196), + (0.45882352941176469, 0.4392156862745098, 0.70196078431372544), + (0.90588235294117647, 0.16078431372549021, 0.54117647058823526), + (0.4, 0.65098039215686276, 0.11764705882352941), + (0.90196078431372551, 0.6705882352941176, 0.00784313725490196), + (0.65098039215686276, 0.46274509803921571, 0.11372549019607843), + (0.4, 0.4, 0.4 ), + ) + +_Paired_data = ( + (0.65098039215686276, 0.80784313725490198, 0.8901960784313725 ), + (0.12156862745098039, 0.47058823529411764, 0.70588235294117652), + (0.69803921568627447, 0.87450980392156863, 0.54117647058823526), + (0.2, 0.62745098039215685, 0.17254901960784313), + (0.98431372549019602, 0.60392156862745094, 0.6 ), + (0.8901960784313725, 0.10196078431372549, 0.10980392156862745), + (0.99215686274509807, 0.74901960784313726, 0.43529411764705883), + (1.0, 0.49803921568627452, 0.0 ), + (0.792156862745098, 0.69803921568627447, 0.83921568627450982), + (0.41568627450980394, 0.23921568627450981, 0.60392156862745094), + (1.0, 1.0, 0.6 ), + (0.69411764705882351, 0.34901960784313724, 0.15686274509803921), + ) + +_Pastel1_data = ( + (0.98431372549019602, 0.70588235294117652, 0.68235294117647061), + (0.70196078431372544, 0.80392156862745101, 0.8901960784313725 ), + (0.8, 0.92156862745098034, 0.77254901960784317), + (0.87058823529411766, 0.79607843137254897, 0.89411764705882357), + (0.99607843137254903, 0.85098039215686272, 0.65098039215686276), + (1.0, 1.0, 0.8 ), + (0.89803921568627454, 0.84705882352941175, 0.74117647058823533), + (0.99215686274509807, 0.85490196078431369, 0.92549019607843142), + (0.94901960784313721, 0.94901960784313721, 0.94901960784313721), + ) + +_Pastel2_data = ( + (0.70196078431372544, 0.88627450980392153, 0.80392156862745101), + (0.99215686274509807, 0.80392156862745101, 0.67450980392156867), + (0.79607843137254897, 0.83529411764705885, 0.90980392156862744), + (0.95686274509803926, 0.792156862745098, 0.89411764705882357), + (0.90196078431372551, 0.96078431372549022, 0.78823529411764703), + (1.0, 0.94901960784313721, 0.68235294117647061), + (0.94509803921568625, 0.88627450980392153, 0.8 ), + (0.8, 0.8, 0.8 ), + ) + +_Set1_data = ( + (0.89411764705882357, 0.10196078431372549, 0.10980392156862745), + (0.21568627450980393, 0.49411764705882355, 0.72156862745098038), + (0.30196078431372547, 0.68627450980392157, 0.29019607843137257), + (0.59607843137254901, 0.30588235294117649, 0.63921568627450975), + (1.0, 0.49803921568627452, 0.0 ), + (1.0, 1.0, 0.2 ), + (0.65098039215686276, 0.33725490196078434, 0.15686274509803921), + (0.96862745098039216, 0.50588235294117645, 0.74901960784313726), + (0.6, 0.6, 0.6), + ) + +_Set2_data = ( + (0.4, 0.76078431372549016, 0.6470588235294118 ), + (0.9882352941176471, 0.55294117647058827, 0.3843137254901961 ), + (0.55294117647058827, 0.62745098039215685, 0.79607843137254897), + (0.90588235294117647, 0.54117647058823526, 0.76470588235294112), + (0.65098039215686276, 0.84705882352941175, 0.32941176470588235), + (1.0, 0.85098039215686272, 0.18431372549019609), + (0.89803921568627454, 0.7686274509803922, 0.58039215686274515), + (0.70196078431372544, 0.70196078431372544, 0.70196078431372544), + ) + +_Set3_data = ( + (0.55294117647058827, 0.82745098039215681, 0.7803921568627451 ), + (1.0, 1.0, 0.70196078431372544), + (0.74509803921568629, 0.72941176470588232, 0.85490196078431369), + (0.98431372549019602, 0.50196078431372548, 0.44705882352941179), + (0.50196078431372548, 0.69411764705882351, 0.82745098039215681), + (0.99215686274509807, 0.70588235294117652, 0.3843137254901961 ), + (0.70196078431372544, 0.87058823529411766, 0.41176470588235292), + (0.9882352941176471, 0.80392156862745101, 0.89803921568627454), + (0.85098039215686272, 0.85098039215686272, 0.85098039215686272), + (0.73725490196078436, 0.50196078431372548, 0.74117647058823533), + (0.8, 0.92156862745098034, 0.77254901960784317), + (1.0, 0.92941176470588238, 0.43529411764705883), + ) + + +# The next 7 palettes are from the Yorick scientific visualization package, +# an evolution of the GIST package, both by David H. Munro. +# They are released under a BSD-like license (see LICENSE_YORICK in +# the license directory of the matplotlib source distribution). +# +# Most palette functions have been reduced to simple function descriptions +# by Reinier Heeres, since the rgb components were mostly straight lines. +# gist_earth_data and gist_ncar_data were simplified by a script and some +# manual effort. + +_gist_earth_data = \ +{'red': ( +(0.0, 0.0, 0.0000), +(0.2824, 0.1882, 0.1882), +(0.4588, 0.2714, 0.2714), +(0.5490, 0.4719, 0.4719), +(0.6980, 0.7176, 0.7176), +(0.7882, 0.7553, 0.7553), +(1.0000, 0.9922, 0.9922), +), 'green': ( +(0.0, 0.0, 0.0000), +(0.0275, 0.0000, 0.0000), +(0.1098, 0.1893, 0.1893), +(0.1647, 0.3035, 0.3035), +(0.2078, 0.3841, 0.3841), +(0.2824, 0.5020, 0.5020), +(0.5216, 0.6397, 0.6397), +(0.6980, 0.7171, 0.7171), +(0.7882, 0.6392, 0.6392), +(0.7922, 0.6413, 0.6413), +(0.8000, 0.6447, 0.6447), +(0.8078, 0.6481, 0.6481), +(0.8157, 0.6549, 0.6549), +(0.8667, 0.6991, 0.6991), +(0.8745, 0.7103, 0.7103), +(0.8824, 0.7216, 0.7216), +(0.8902, 0.7323, 0.7323), +(0.8980, 0.7430, 0.7430), +(0.9412, 0.8275, 0.8275), +(0.9569, 0.8635, 0.8635), +(0.9647, 0.8816, 0.8816), +(0.9961, 0.9733, 0.9733), +(1.0000, 0.9843, 0.9843), +), 'blue': ( +(0.0, 0.0, 0.0000), +(0.0039, 0.1684, 0.1684), +(0.0078, 0.2212, 0.2212), +(0.0275, 0.4329, 0.4329), +(0.0314, 0.4549, 0.4549), +(0.2824, 0.5004, 0.5004), +(0.4667, 0.2748, 0.2748), +(0.5451, 0.3205, 0.3205), +(0.7843, 0.3961, 0.3961), +(0.8941, 0.6651, 0.6651), +(1.0000, 0.9843, 0.9843), +)} + +_gist_gray_data = { + 'red': gfunc[3], + 'green': gfunc[3], + 'blue': gfunc[3], +} + +def _gist_heat_red(x): return 1.5 * x +def _gist_heat_green(x): return 2 * x - 1 +def _gist_heat_blue(x): return 4 * x - 3 +_gist_heat_data = { + 'red': _gist_heat_red, 'green': _gist_heat_green, 'blue': _gist_heat_blue} + +_gist_ncar_data = \ +{'red': ( +(0.0, 0.0, 0.0000), +(0.3098, 0.0000, 0.0000), +(0.3725, 0.3993, 0.3993), +(0.4235, 0.5003, 0.5003), +(0.5333, 1.0000, 1.0000), +(0.7922, 1.0000, 1.0000), +(0.8471, 0.6218, 0.6218), +(0.8980, 0.9235, 0.9235), +(1.0000, 0.9961, 0.9961), +), 'green': ( +(0.0, 0.0, 0.0000), +(0.0510, 0.3722, 0.3722), +(0.1059, 0.0000, 0.0000), +(0.1569, 0.7202, 0.7202), +(0.1608, 0.7537, 0.7537), +(0.1647, 0.7752, 0.7752), +(0.2157, 1.0000, 1.0000), +(0.2588, 0.9804, 0.9804), +(0.2706, 0.9804, 0.9804), +(0.3176, 1.0000, 1.0000), +(0.3686, 0.8081, 0.8081), +(0.4275, 1.0000, 1.0000), +(0.5216, 1.0000, 1.0000), +(0.6314, 0.7292, 0.7292), +(0.6863, 0.2796, 0.2796), +(0.7451, 0.0000, 0.0000), +(0.7922, 0.0000, 0.0000), +(0.8431, 0.1753, 0.1753), +(0.8980, 0.5000, 0.5000), +(1.0000, 0.9725, 0.9725), +), 'blue': ( +(0.0, 0.5020, 0.5020), +(0.0510, 0.0222, 0.0222), +(0.1098, 1.0000, 1.0000), +(0.2039, 1.0000, 1.0000), +(0.2627, 0.6145, 0.6145), +(0.3216, 0.0000, 0.0000), +(0.4157, 0.0000, 0.0000), +(0.4745, 0.2342, 0.2342), +(0.5333, 0.0000, 0.0000), +(0.5804, 0.0000, 0.0000), +(0.6314, 0.0549, 0.0549), +(0.6902, 0.0000, 0.0000), +(0.7373, 0.0000, 0.0000), +(0.7922, 0.9738, 0.9738), +(0.8000, 1.0000, 1.0000), +(0.8431, 1.0000, 1.0000), +(0.8980, 0.9341, 0.9341), +(1.0000, 0.9961, 0.9961), +)} + +_gist_rainbow_data = ( + (0.000, (1.00, 0.00, 0.16)), + (0.030, (1.00, 0.00, 0.00)), + (0.215, (1.00, 1.00, 0.00)), + (0.400, (0.00, 1.00, 0.00)), + (0.586, (0.00, 1.00, 1.00)), + (0.770, (0.00, 0.00, 1.00)), + (0.954, (1.00, 0.00, 1.00)), + (1.000, (1.00, 0.00, 0.75)) +) + +_gist_stern_data = { + 'red': ( + (0.000, 0.000, 0.000), (0.0547, 1.000, 1.000), + (0.250, 0.027, 0.250), # (0.2500, 0.250, 0.250), + (1.000, 1.000, 1.000)), + 'green': ((0, 0, 0), (1, 1, 1)), + 'blue': ( + (0.000, 0.000, 0.000), (0.500, 1.000, 1.000), + (0.735, 0.000, 0.000), (1.000, 1.000, 1.000)) +} + +def _gist_yarg(x): return 1 - x +_gist_yarg_data = {'red': _gist_yarg, 'green': _gist_yarg, 'blue': _gist_yarg} + +# This bipolar color map was generated from CoolWarmFloat33.csv of +# "Diverging Color Maps for Scientific Visualization" by Kenneth Moreland. +# +_coolwarm_data = { + 'red': [ + (0.0, 0.2298057, 0.2298057), + (0.03125, 0.26623388, 0.26623388), + (0.0625, 0.30386891, 0.30386891), + (0.09375, 0.342804478, 0.342804478), + (0.125, 0.38301334, 0.38301334), + (0.15625, 0.424369608, 0.424369608), + (0.1875, 0.46666708, 0.46666708), + (0.21875, 0.509635204, 0.509635204), + (0.25, 0.552953156, 0.552953156), + (0.28125, 0.596262162, 0.596262162), + (0.3125, 0.639176211, 0.639176211), + (0.34375, 0.681291281, 0.681291281), + (0.375, 0.722193294, 0.722193294), + (0.40625, 0.761464949, 0.761464949), + (0.4375, 0.798691636, 0.798691636), + (0.46875, 0.833466556, 0.833466556), + (0.5, 0.865395197, 0.865395197), + (0.53125, 0.897787179, 0.897787179), + (0.5625, 0.924127593, 0.924127593), + (0.59375, 0.944468518, 0.944468518), + (0.625, 0.958852946, 0.958852946), + (0.65625, 0.96732803, 0.96732803), + (0.6875, 0.969954137, 0.969954137), + (0.71875, 0.966811177, 0.966811177), + (0.75, 0.958003065, 0.958003065), + (0.78125, 0.943660866, 0.943660866), + (0.8125, 0.923944917, 0.923944917), + (0.84375, 0.89904617, 0.89904617), + (0.875, 0.869186849, 0.869186849), + (0.90625, 0.834620542, 0.834620542), + (0.9375, 0.795631745, 0.795631745), + (0.96875, 0.752534934, 0.752534934), + (1.0, 0.705673158, 0.705673158)], + 'green': [ + (0.0, 0.298717966, 0.298717966), + (0.03125, 0.353094838, 0.353094838), + (0.0625, 0.406535296, 0.406535296), + (0.09375, 0.458757618, 0.458757618), + (0.125, 0.50941904, 0.50941904), + (0.15625, 0.558148092, 0.558148092), + (0.1875, 0.604562568, 0.604562568), + (0.21875, 0.648280772, 0.648280772), + (0.25, 0.688929332, 0.688929332), + (0.28125, 0.726149107, 0.726149107), + (0.3125, 0.759599947, 0.759599947), + (0.34375, 0.788964712, 0.788964712), + (0.375, 0.813952739, 0.813952739), + (0.40625, 0.834302879, 0.834302879), + (0.4375, 0.849786142, 0.849786142), + (0.46875, 0.860207984, 0.860207984), + (0.5, 0.86541021, 0.86541021), + (0.53125, 0.848937047, 0.848937047), + (0.5625, 0.827384882, 0.827384882), + (0.59375, 0.800927443, 0.800927443), + (0.625, 0.769767752, 0.769767752), + (0.65625, 0.734132809, 0.734132809), + (0.6875, 0.694266682, 0.694266682), + (0.71875, 0.650421156, 0.650421156), + (0.75, 0.602842431, 0.602842431), + (0.78125, 0.551750968, 0.551750968), + (0.8125, 0.49730856, 0.49730856), + (0.84375, 0.439559467, 0.439559467), + (0.875, 0.378313092, 0.378313092), + (0.90625, 0.312874446, 0.312874446), + (0.9375, 0.24128379, 0.24128379), + (0.96875, 0.157246067, 0.157246067), + (1.0, 0.01555616, 0.01555616)], + 'blue': [ + (0.0, 0.753683153, 0.753683153), + (0.03125, 0.801466763, 0.801466763), + (0.0625, 0.84495867, 0.84495867), + (0.09375, 0.883725899, 0.883725899), + (0.125, 0.917387822, 0.917387822), + (0.15625, 0.945619588, 0.945619588), + (0.1875, 0.968154911, 0.968154911), + (0.21875, 0.98478814, 0.98478814), + (0.25, 0.995375608, 0.995375608), + (0.28125, 0.999836203, 0.999836203), + (0.3125, 0.998151185, 0.998151185), + (0.34375, 0.990363227, 0.990363227), + (0.375, 0.976574709, 0.976574709), + (0.40625, 0.956945269, 0.956945269), + (0.4375, 0.931688648, 0.931688648), + (0.46875, 0.901068838, 0.901068838), + (0.5, 0.865395561, 0.865395561), + (0.53125, 0.820880546, 0.820880546), + (0.5625, 0.774508472, 0.774508472), + (0.59375, 0.726736146, 0.726736146), + (0.625, 0.678007945, 0.678007945), + (0.65625, 0.628751763, 0.628751763), + (0.6875, 0.579375448, 0.579375448), + (0.71875, 0.530263762, 0.530263762), + (0.75, 0.481775914, 0.481775914), + (0.78125, 0.434243684, 0.434243684), + (0.8125, 0.387970225, 0.387970225), + (0.84375, 0.343229596, 0.343229596), + (0.875, 0.300267182, 0.300267182), + (0.90625, 0.259301199, 0.259301199), + (0.9375, 0.220525627, 0.220525627), + (0.96875, 0.184115123, 0.184115123), + (1.0, 0.150232812, 0.150232812)] + } + +# Implementation of Carey Rappaport's CMRmap. +# See `A Color Map for Effective Black-and-White Rendering of Color-Scale +# Images' by Carey Rappaport +# http://www.mathworks.com/matlabcentral/fileexchange/2662-cmrmap-m +_CMRmap_data = {'red': ((0.000, 0.00, 0.00), + (0.125, 0.15, 0.15), + (0.250, 0.30, 0.30), + (0.375, 0.60, 0.60), + (0.500, 1.00, 1.00), + (0.625, 0.90, 0.90), + (0.750, 0.90, 0.90), + (0.875, 0.90, 0.90), + (1.000, 1.00, 1.00)), + 'green': ((0.000, 0.00, 0.00), + (0.125, 0.15, 0.15), + (0.250, 0.15, 0.15), + (0.375, 0.20, 0.20), + (0.500, 0.25, 0.25), + (0.625, 0.50, 0.50), + (0.750, 0.75, 0.75), + (0.875, 0.90, 0.90), + (1.000, 1.00, 1.00)), + 'blue': ((0.000, 0.00, 0.00), + (0.125, 0.50, 0.50), + (0.250, 0.75, 0.75), + (0.375, 0.50, 0.50), + (0.500, 0.15, 0.15), + (0.625, 0.00, 0.00), + (0.750, 0.10, 0.10), + (0.875, 0.50, 0.50), + (1.000, 1.00, 1.00))} + + +# An MIT licensed, colorblind-friendly heatmap from Wistia: +# https://github.com/wistia/heatmap-palette +# http://wistia.com/blog/heatmaps-for-colorblindness +# +# >>> import matplotlib.colors as c +# >>> colors = ["#e4ff7a", "#ffe81a", "#ffbd00", "#ffa000", "#fc7f00"] +# >>> cm = c.LinearSegmentedColormap.from_list('wistia', colors) +# >>> _wistia_data = cm._segmentdata +# >>> del _wistia_data['alpha'] +# +_wistia_data = { + 'red': [(0.0, 0.8941176470588236, 0.8941176470588236), + (0.25, 1.0, 1.0), + (0.5, 1.0, 1.0), + (0.75, 1.0, 1.0), + (1.0, 0.9882352941176471, 0.9882352941176471)], + 'green': [(0.0, 1.0, 1.0), + (0.25, 0.9098039215686274, 0.9098039215686274), + (0.5, 0.7411764705882353, 0.7411764705882353), + (0.75, 0.6274509803921569, 0.6274509803921569), + (1.0, 0.4980392156862745, 0.4980392156862745)], + 'blue': [(0.0, 0.47843137254901963, 0.47843137254901963), + (0.25, 0.10196078431372549, 0.10196078431372549), + (0.5, 0.0, 0.0), + (0.75, 0.0, 0.0), + (1.0, 0.0, 0.0)], +} + + +# Categorical palettes from Vega: +# https://github.com/vega/vega/wiki/Scales +# (divided by 255) +# + +_tab10_data = ( + (0.12156862745098039, 0.4666666666666667, 0.7058823529411765 ), # 1f77b4 + (1.0, 0.4980392156862745, 0.054901960784313725), # ff7f0e + (0.17254901960784313, 0.6274509803921569, 0.17254901960784313 ), # 2ca02c + (0.8392156862745098, 0.15294117647058825, 0.1568627450980392 ), # d62728 + (0.5803921568627451, 0.403921568627451, 0.7411764705882353 ), # 9467bd + (0.5490196078431373, 0.33725490196078434, 0.29411764705882354 ), # 8c564b + (0.8901960784313725, 0.4666666666666667, 0.7607843137254902 ), # e377c2 + (0.4980392156862745, 0.4980392156862745, 0.4980392156862745 ), # 7f7f7f + (0.7372549019607844, 0.7411764705882353, 0.13333333333333333 ), # bcbd22 + (0.09019607843137255, 0.7450980392156863, 0.8117647058823529), # 17becf +) + +_tab20_data = ( + (0.12156862745098039, 0.4666666666666667, 0.7058823529411765 ), # 1f77b4 + (0.6823529411764706, 0.7803921568627451, 0.9098039215686274 ), # aec7e8 + (1.0, 0.4980392156862745, 0.054901960784313725), # ff7f0e + (1.0, 0.7333333333333333, 0.47058823529411764 ), # ffbb78 + (0.17254901960784313, 0.6274509803921569, 0.17254901960784313 ), # 2ca02c + (0.596078431372549, 0.8745098039215686, 0.5411764705882353 ), # 98df8a + (0.8392156862745098, 0.15294117647058825, 0.1568627450980392 ), # d62728 + (1.0, 0.596078431372549, 0.5882352941176471 ), # ff9896 + (0.5803921568627451, 0.403921568627451, 0.7411764705882353 ), # 9467bd + (0.7725490196078432, 0.6901960784313725, 0.8352941176470589 ), # c5b0d5 + (0.5490196078431373, 0.33725490196078434, 0.29411764705882354 ), # 8c564b + (0.7686274509803922, 0.611764705882353, 0.5803921568627451 ), # c49c94 + (0.8901960784313725, 0.4666666666666667, 0.7607843137254902 ), # e377c2 + (0.9686274509803922, 0.7137254901960784, 0.8235294117647058 ), # f7b6d2 + (0.4980392156862745, 0.4980392156862745, 0.4980392156862745 ), # 7f7f7f + (0.7803921568627451, 0.7803921568627451, 0.7803921568627451 ), # c7c7c7 + (0.7372549019607844, 0.7411764705882353, 0.13333333333333333 ), # bcbd22 + (0.8588235294117647, 0.8588235294117647, 0.5529411764705883 ), # dbdb8d + (0.09019607843137255, 0.7450980392156863, 0.8117647058823529 ), # 17becf + (0.6196078431372549, 0.8549019607843137, 0.8980392156862745), # 9edae5 +) + +_tab20b_data = ( + (0.2235294117647059, 0.23137254901960785, 0.4745098039215686 ), # 393b79 + (0.3215686274509804, 0.32941176470588235, 0.6392156862745098 ), # 5254a3 + (0.4196078431372549, 0.43137254901960786, 0.8117647058823529 ), # 6b6ecf + (0.611764705882353, 0.6196078431372549, 0.8705882352941177 ), # 9c9ede + (0.38823529411764707, 0.4745098039215686, 0.2235294117647059 ), # 637939 + (0.5490196078431373, 0.6352941176470588, 0.3215686274509804 ), # 8ca252 + (0.7098039215686275, 0.8117647058823529, 0.4196078431372549 ), # b5cf6b + (0.807843137254902, 0.8588235294117647, 0.611764705882353 ), # cedb9c + (0.5490196078431373, 0.42745098039215684, 0.19215686274509805), # 8c6d31 + (0.7411764705882353, 0.6196078431372549, 0.2235294117647059 ), # bd9e39 + (0.9058823529411765, 0.7294117647058823, 0.3215686274509804 ), # e7ba52 + (0.9058823529411765, 0.796078431372549, 0.5803921568627451 ), # e7cb94 + (0.5176470588235295, 0.23529411764705882, 0.2235294117647059 ), # 843c39 + (0.6784313725490196, 0.28627450980392155, 0.2901960784313726 ), # ad494a + (0.8392156862745098, 0.3803921568627451, 0.4196078431372549 ), # d6616b + (0.9058823529411765, 0.5882352941176471, 0.611764705882353 ), # e7969c + (0.4823529411764706, 0.2549019607843137, 0.45098039215686275), # 7b4173 + (0.6470588235294118, 0.3176470588235294, 0.5803921568627451 ), # a55194 + (0.807843137254902, 0.42745098039215684, 0.7411764705882353 ), # ce6dbd + (0.8705882352941177, 0.6196078431372549, 0.8392156862745098 ), # de9ed6 +) + +_tab20c_data = ( + (0.19215686274509805, 0.5098039215686274, 0.7411764705882353 ), # 3182bd + (0.4196078431372549, 0.6823529411764706, 0.8392156862745098 ), # 6baed6 + (0.6196078431372549, 0.792156862745098, 0.8823529411764706 ), # 9ecae1 + (0.7764705882352941, 0.8588235294117647, 0.9372549019607843 ), # c6dbef + (0.9019607843137255, 0.3333333333333333, 0.050980392156862744), # e6550d + (0.9921568627450981, 0.5529411764705883, 0.23529411764705882 ), # fd8d3c + (0.9921568627450981, 0.6823529411764706, 0.4196078431372549 ), # fdae6b + (0.9921568627450981, 0.8156862745098039, 0.6352941176470588 ), # fdd0a2 + (0.19215686274509805, 0.6392156862745098, 0.32941176470588235 ), # 31a354 + (0.4549019607843137, 0.7686274509803922, 0.4627450980392157 ), # 74c476 + (0.6313725490196078, 0.8509803921568627, 0.6078431372549019 ), # a1d99b + (0.7803921568627451, 0.9137254901960784, 0.7529411764705882 ), # c7e9c0 + (0.4588235294117647, 0.4196078431372549, 0.6941176470588235 ), # 756bb1 + (0.6196078431372549, 0.6039215686274509, 0.7843137254901961 ), # 9e9ac8 + (0.7372549019607844, 0.7411764705882353, 0.8627450980392157 ), # bcbddc + (0.8549019607843137, 0.8549019607843137, 0.9215686274509803 ), # dadaeb + (0.38823529411764707, 0.38823529411764707, 0.38823529411764707 ), # 636363 + (0.5882352941176471, 0.5882352941176471, 0.5882352941176471 ), # 969696 + (0.7411764705882353, 0.7411764705882353, 0.7411764705882353 ), # bdbdbd + (0.8509803921568627, 0.8509803921568627, 0.8509803921568627 ), # d9d9d9 +) + + +datad = { + 'Blues': _Blues_data, + 'BrBG': _BrBG_data, + 'BuGn': _BuGn_data, + 'BuPu': _BuPu_data, + 'CMRmap': _CMRmap_data, + 'GnBu': _GnBu_data, + 'Greens': _Greens_data, + 'Greys': _Greys_data, + 'OrRd': _OrRd_data, + 'Oranges': _Oranges_data, + 'PRGn': _PRGn_data, + 'PiYG': _PiYG_data, + 'PuBu': _PuBu_data, + 'PuBuGn': _PuBuGn_data, + 'PuOr': _PuOr_data, + 'PuRd': _PuRd_data, + 'Purples': _Purples_data, + 'RdBu': _RdBu_data, + 'RdGy': _RdGy_data, + 'RdPu': _RdPu_data, + 'RdYlBu': _RdYlBu_data, + 'RdYlGn': _RdYlGn_data, + 'Reds': _Reds_data, + 'Spectral': _Spectral_data, + 'Wistia': _wistia_data, + 'YlGn': _YlGn_data, + 'YlGnBu': _YlGnBu_data, + 'YlOrBr': _YlOrBr_data, + 'YlOrRd': _YlOrRd_data, + 'afmhot': _afmhot_data, + 'autumn': _autumn_data, + 'binary': _binary_data, + 'bone': _bone_data, + 'brg': _brg_data, + 'bwr': _bwr_data, + 'cool': _cool_data, + 'coolwarm': _coolwarm_data, + 'copper': _copper_data, + 'cubehelix': _cubehelix_data, + 'flag': _flag_data, + 'gist_earth': _gist_earth_data, + 'gist_gray': _gist_gray_data, + 'gist_heat': _gist_heat_data, + 'gist_ncar': _gist_ncar_data, + 'gist_rainbow': _gist_rainbow_data, + 'gist_stern': _gist_stern_data, + 'gist_yarg': _gist_yarg_data, + 'gnuplot': _gnuplot_data, + 'gnuplot2': _gnuplot2_data, + 'gray': _gray_data, + 'hot': _hot_data, + 'hsv': _hsv_data, + 'jet': _jet_data, + 'nipy_spectral': _nipy_spectral_data, + 'ocean': _ocean_data, + 'pink': _pink_data, + 'prism': _prism_data, + 'rainbow': _rainbow_data, + 'seismic': _seismic_data, + 'spring': _spring_data, + 'summer': _summer_data, + 'terrain': _terrain_data, + 'winter': _winter_data, + # Qualitative + 'Accent': {'listed': _Accent_data}, + 'Dark2': {'listed': _Dark2_data}, + 'Paired': {'listed': _Paired_data}, + 'Pastel1': {'listed': _Pastel1_data}, + 'Pastel2': {'listed': _Pastel2_data}, + 'Set1': {'listed': _Set1_data}, + 'Set2': {'listed': _Set2_data}, + 'Set3': {'listed': _Set3_data}, + 'tab10': {'listed': _tab10_data}, + 'tab20': {'listed': _tab20_data}, + 'tab20b': {'listed': _tab20b_data}, + 'tab20c': {'listed': _tab20c_data}, +} diff --git a/venv/lib/python3.6/site-packages/matplotlib/_cm_listed.py b/venv/lib/python3.6/site-packages/matplotlib/_cm_listed.py new file mode 100644 index 0000000..cd70b28 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_cm_listed.py @@ -0,0 +1,1816 @@ +from .colors import ListedColormap + +_magma_data = [[0.001462, 0.000466, 0.013866], + [0.002258, 0.001295, 0.018331], + [0.003279, 0.002305, 0.023708], + [0.004512, 0.003490, 0.029965], + [0.005950, 0.004843, 0.037130], + [0.007588, 0.006356, 0.044973], + [0.009426, 0.008022, 0.052844], + [0.011465, 0.009828, 0.060750], + [0.013708, 0.011771, 0.068667], + [0.016156, 0.013840, 0.076603], + [0.018815, 0.016026, 0.084584], + [0.021692, 0.018320, 0.092610], + [0.024792, 0.020715, 0.100676], + [0.028123, 0.023201, 0.108787], + [0.031696, 0.025765, 0.116965], + [0.035520, 0.028397, 0.125209], + [0.039608, 0.031090, 0.133515], + [0.043830, 0.033830, 0.141886], + [0.048062, 0.036607, 0.150327], + [0.052320, 0.039407, 0.158841], + [0.056615, 0.042160, 0.167446], + [0.060949, 0.044794, 0.176129], + [0.065330, 0.047318, 0.184892], + [0.069764, 0.049726, 0.193735], + [0.074257, 0.052017, 0.202660], + [0.078815, 0.054184, 0.211667], + [0.083446, 0.056225, 0.220755], + [0.088155, 0.058133, 0.229922], + [0.092949, 0.059904, 0.239164], + [0.097833, 0.061531, 0.248477], + [0.102815, 0.063010, 0.257854], + [0.107899, 0.064335, 0.267289], + [0.113094, 0.065492, 0.276784], + [0.118405, 0.066479, 0.286321], + [0.123833, 0.067295, 0.295879], + [0.129380, 0.067935, 0.305443], + [0.135053, 0.068391, 0.315000], + [0.140858, 0.068654, 0.324538], + [0.146785, 0.068738, 0.334011], + [0.152839, 0.068637, 0.343404], + [0.159018, 0.068354, 0.352688], + [0.165308, 0.067911, 0.361816], + [0.171713, 0.067305, 0.370771], + [0.178212, 0.066576, 0.379497], + [0.184801, 0.065732, 0.387973], + [0.191460, 0.064818, 0.396152], + [0.198177, 0.063862, 0.404009], + [0.204935, 0.062907, 0.411514], + [0.211718, 0.061992, 0.418647], + [0.218512, 0.061158, 0.425392], + [0.225302, 0.060445, 0.431742], + [0.232077, 0.059889, 0.437695], + [0.238826, 0.059517, 0.443256], + [0.245543, 0.059352, 0.448436], + [0.252220, 0.059415, 0.453248], + [0.258857, 0.059706, 0.457710], + [0.265447, 0.060237, 0.461840], + [0.271994, 0.060994, 0.465660], + [0.278493, 0.061978, 0.469190], + [0.284951, 0.063168, 0.472451], + [0.291366, 0.064553, 0.475462], + [0.297740, 0.066117, 0.478243], + [0.304081, 0.067835, 0.480812], + [0.310382, 0.069702, 0.483186], + [0.316654, 0.071690, 0.485380], + [0.322899, 0.073782, 0.487408], + [0.329114, 0.075972, 0.489287], + [0.335308, 0.078236, 0.491024], + [0.341482, 0.080564, 0.492631], + [0.347636, 0.082946, 0.494121], + [0.353773, 0.085373, 0.495501], + [0.359898, 0.087831, 0.496778], + [0.366012, 0.090314, 0.497960], + [0.372116, 0.092816, 0.499053], + [0.378211, 0.095332, 0.500067], + [0.384299, 0.097855, 0.501002], + [0.390384, 0.100379, 0.501864], + [0.396467, 0.102902, 0.502658], + [0.402548, 0.105420, 0.503386], + [0.408629, 0.107930, 0.504052], + [0.414709, 0.110431, 0.504662], + [0.420791, 0.112920, 0.505215], + [0.426877, 0.115395, 0.505714], + [0.432967, 0.117855, 0.506160], + [0.439062, 0.120298, 0.506555], + [0.445163, 0.122724, 0.506901], + [0.451271, 0.125132, 0.507198], + [0.457386, 0.127522, 0.507448], + [0.463508, 0.129893, 0.507652], + [0.469640, 0.132245, 0.507809], + [0.475780, 0.134577, 0.507921], + [0.481929, 0.136891, 0.507989], + [0.488088, 0.139186, 0.508011], + [0.494258, 0.141462, 0.507988], + [0.500438, 0.143719, 0.507920], + [0.506629, 0.145958, 0.507806], + [0.512831, 0.148179, 0.507648], + [0.519045, 0.150383, 0.507443], + [0.525270, 0.152569, 0.507192], + [0.531507, 0.154739, 0.506895], + [0.537755, 0.156894, 0.506551], + [0.544015, 0.159033, 0.506159], + [0.550287, 0.161158, 0.505719], + [0.556571, 0.163269, 0.505230], + [0.562866, 0.165368, 0.504692], + [0.569172, 0.167454, 0.504105], + [0.575490, 0.169530, 0.503466], + [0.581819, 0.171596, 0.502777], + [0.588158, 0.173652, 0.502035], + [0.594508, 0.175701, 0.501241], + [0.600868, 0.177743, 0.500394], + [0.607238, 0.179779, 0.499492], + [0.613617, 0.181811, 0.498536], + [0.620005, 0.183840, 0.497524], + [0.626401, 0.185867, 0.496456], + [0.632805, 0.187893, 0.495332], + [0.639216, 0.189921, 0.494150], + [0.645633, 0.191952, 0.492910], + [0.652056, 0.193986, 0.491611], + [0.658483, 0.196027, 0.490253], + [0.664915, 0.198075, 0.488836], + [0.671349, 0.200133, 0.487358], + [0.677786, 0.202203, 0.485819], + [0.684224, 0.204286, 0.484219], + [0.690661, 0.206384, 0.482558], + [0.697098, 0.208501, 0.480835], + [0.703532, 0.210638, 0.479049], + [0.709962, 0.212797, 0.477201], + [0.716387, 0.214982, 0.475290], + [0.722805, 0.217194, 0.473316], + [0.729216, 0.219437, 0.471279], + [0.735616, 0.221713, 0.469180], + [0.742004, 0.224025, 0.467018], + [0.748378, 0.226377, 0.464794], + [0.754737, 0.228772, 0.462509], + [0.761077, 0.231214, 0.460162], + [0.767398, 0.233705, 0.457755], + [0.773695, 0.236249, 0.455289], + [0.779968, 0.238851, 0.452765], + [0.786212, 0.241514, 0.450184], + [0.792427, 0.244242, 0.447543], + [0.798608, 0.247040, 0.444848], + [0.804752, 0.249911, 0.442102], + [0.810855, 0.252861, 0.439305], + [0.816914, 0.255895, 0.436461], + [0.822926, 0.259016, 0.433573], + [0.828886, 0.262229, 0.430644], + [0.834791, 0.265540, 0.427671], + [0.840636, 0.268953, 0.424666], + [0.846416, 0.272473, 0.421631], + [0.852126, 0.276106, 0.418573], + [0.857763, 0.279857, 0.415496], + [0.863320, 0.283729, 0.412403], + [0.868793, 0.287728, 0.409303], + [0.874176, 0.291859, 0.406205], + [0.879464, 0.296125, 0.403118], + [0.884651, 0.300530, 0.400047], + [0.889731, 0.305079, 0.397002], + [0.894700, 0.309773, 0.393995], + [0.899552, 0.314616, 0.391037], + [0.904281, 0.319610, 0.388137], + [0.908884, 0.324755, 0.385308], + [0.913354, 0.330052, 0.382563], + [0.917689, 0.335500, 0.379915], + [0.921884, 0.341098, 0.377376], + [0.925937, 0.346844, 0.374959], + [0.929845, 0.352734, 0.372677], + [0.933606, 0.358764, 0.370541], + [0.937221, 0.364929, 0.368567], + [0.940687, 0.371224, 0.366762], + [0.944006, 0.377643, 0.365136], + [0.947180, 0.384178, 0.363701], + [0.950210, 0.390820, 0.362468], + [0.953099, 0.397563, 0.361438], + [0.955849, 0.404400, 0.360619], + [0.958464, 0.411324, 0.360014], + [0.960949, 0.418323, 0.359630], + [0.963310, 0.425390, 0.359469], + [0.965549, 0.432519, 0.359529], + [0.967671, 0.439703, 0.359810], + [0.969680, 0.446936, 0.360311], + [0.971582, 0.454210, 0.361030], + [0.973381, 0.461520, 0.361965], + [0.975082, 0.468861, 0.363111], + [0.976690, 0.476226, 0.364466], + [0.978210, 0.483612, 0.366025], + [0.979645, 0.491014, 0.367783], + [0.981000, 0.498428, 0.369734], + [0.982279, 0.505851, 0.371874], + [0.983485, 0.513280, 0.374198], + [0.984622, 0.520713, 0.376698], + [0.985693, 0.528148, 0.379371], + [0.986700, 0.535582, 0.382210], + [0.987646, 0.543015, 0.385210], + [0.988533, 0.550446, 0.388365], + [0.989363, 0.557873, 0.391671], + [0.990138, 0.565296, 0.395122], + [0.990871, 0.572706, 0.398714], + [0.991558, 0.580107, 0.402441], + [0.992196, 0.587502, 0.406299], + [0.992785, 0.594891, 0.410283], + [0.993326, 0.602275, 0.414390], + [0.993834, 0.609644, 0.418613], + [0.994309, 0.616999, 0.422950], + [0.994738, 0.624350, 0.427397], + [0.995122, 0.631696, 0.431951], + [0.995480, 0.639027, 0.436607], + [0.995810, 0.646344, 0.441361], + [0.996096, 0.653659, 0.446213], + [0.996341, 0.660969, 0.451160], + [0.996580, 0.668256, 0.456192], + [0.996775, 0.675541, 0.461314], + [0.996925, 0.682828, 0.466526], + [0.997077, 0.690088, 0.471811], + [0.997186, 0.697349, 0.477182], + [0.997254, 0.704611, 0.482635], + [0.997325, 0.711848, 0.488154], + [0.997351, 0.719089, 0.493755], + [0.997351, 0.726324, 0.499428], + [0.997341, 0.733545, 0.505167], + [0.997285, 0.740772, 0.510983], + [0.997228, 0.747981, 0.516859], + [0.997138, 0.755190, 0.522806], + [0.997019, 0.762398, 0.528821], + [0.996898, 0.769591, 0.534892], + [0.996727, 0.776795, 0.541039], + [0.996571, 0.783977, 0.547233], + [0.996369, 0.791167, 0.553499], + [0.996162, 0.798348, 0.559820], + [0.995932, 0.805527, 0.566202], + [0.995680, 0.812706, 0.572645], + [0.995424, 0.819875, 0.579140], + [0.995131, 0.827052, 0.585701], + [0.994851, 0.834213, 0.592307], + [0.994524, 0.841387, 0.598983], + [0.994222, 0.848540, 0.605696], + [0.993866, 0.855711, 0.612482], + [0.993545, 0.862859, 0.619299], + [0.993170, 0.870024, 0.626189], + [0.992831, 0.877168, 0.633109], + [0.992440, 0.884330, 0.640099], + [0.992089, 0.891470, 0.647116], + [0.991688, 0.898627, 0.654202], + [0.991332, 0.905763, 0.661309], + [0.990930, 0.912915, 0.668481], + [0.990570, 0.920049, 0.675675], + [0.990175, 0.927196, 0.682926], + [0.989815, 0.934329, 0.690198], + [0.989434, 0.941470, 0.697519], + [0.989077, 0.948604, 0.704863], + [0.988717, 0.955742, 0.712242], + [0.988367, 0.962878, 0.719649], + [0.988033, 0.970012, 0.727077], + [0.987691, 0.977154, 0.734536], + [0.987387, 0.984288, 0.742002], + [0.987053, 0.991438, 0.749504]] + +_inferno_data = [[0.001462, 0.000466, 0.013866], + [0.002267, 0.001270, 0.018570], + [0.003299, 0.002249, 0.024239], + [0.004547, 0.003392, 0.030909], + [0.006006, 0.004692, 0.038558], + [0.007676, 0.006136, 0.046836], + [0.009561, 0.007713, 0.055143], + [0.011663, 0.009417, 0.063460], + [0.013995, 0.011225, 0.071862], + [0.016561, 0.013136, 0.080282], + [0.019373, 0.015133, 0.088767], + [0.022447, 0.017199, 0.097327], + [0.025793, 0.019331, 0.105930], + [0.029432, 0.021503, 0.114621], + [0.033385, 0.023702, 0.123397], + [0.037668, 0.025921, 0.132232], + [0.042253, 0.028139, 0.141141], + [0.046915, 0.030324, 0.150164], + [0.051644, 0.032474, 0.159254], + [0.056449, 0.034569, 0.168414], + [0.061340, 0.036590, 0.177642], + [0.066331, 0.038504, 0.186962], + [0.071429, 0.040294, 0.196354], + [0.076637, 0.041905, 0.205799], + [0.081962, 0.043328, 0.215289], + [0.087411, 0.044556, 0.224813], + [0.092990, 0.045583, 0.234358], + [0.098702, 0.046402, 0.243904], + [0.104551, 0.047008, 0.253430], + [0.110536, 0.047399, 0.262912], + [0.116656, 0.047574, 0.272321], + [0.122908, 0.047536, 0.281624], + [0.129285, 0.047293, 0.290788], + [0.135778, 0.046856, 0.299776], + [0.142378, 0.046242, 0.308553], + [0.149073, 0.045468, 0.317085], + [0.155850, 0.044559, 0.325338], + [0.162689, 0.043554, 0.333277], + [0.169575, 0.042489, 0.340874], + [0.176493, 0.041402, 0.348111], + [0.183429, 0.040329, 0.354971], + [0.190367, 0.039309, 0.361447], + [0.197297, 0.038400, 0.367535], + [0.204209, 0.037632, 0.373238], + [0.211095, 0.037030, 0.378563], + [0.217949, 0.036615, 0.383522], + [0.224763, 0.036405, 0.388129], + [0.231538, 0.036405, 0.392400], + [0.238273, 0.036621, 0.396353], + [0.244967, 0.037055, 0.400007], + [0.251620, 0.037705, 0.403378], + [0.258234, 0.038571, 0.406485], + [0.264810, 0.039647, 0.409345], + [0.271347, 0.040922, 0.411976], + [0.277850, 0.042353, 0.414392], + [0.284321, 0.043933, 0.416608], + [0.290763, 0.045644, 0.418637], + [0.297178, 0.047470, 0.420491], + [0.303568, 0.049396, 0.422182], + [0.309935, 0.051407, 0.423721], + [0.316282, 0.053490, 0.425116], + [0.322610, 0.055634, 0.426377], + [0.328921, 0.057827, 0.427511], + [0.335217, 0.060060, 0.428524], + [0.341500, 0.062325, 0.429425], + [0.347771, 0.064616, 0.430217], + [0.354032, 0.066925, 0.430906], + [0.360284, 0.069247, 0.431497], + [0.366529, 0.071579, 0.431994], + [0.372768, 0.073915, 0.432400], + [0.379001, 0.076253, 0.432719], + [0.385228, 0.078591, 0.432955], + [0.391453, 0.080927, 0.433109], + [0.397674, 0.083257, 0.433183], + [0.403894, 0.085580, 0.433179], + [0.410113, 0.087896, 0.433098], + [0.416331, 0.090203, 0.432943], + [0.422549, 0.092501, 0.432714], + [0.428768, 0.094790, 0.432412], + [0.434987, 0.097069, 0.432039], + [0.441207, 0.099338, 0.431594], + [0.447428, 0.101597, 0.431080], + [0.453651, 0.103848, 0.430498], + [0.459875, 0.106089, 0.429846], + [0.466100, 0.108322, 0.429125], + [0.472328, 0.110547, 0.428334], + [0.478558, 0.112764, 0.427475], + [0.484789, 0.114974, 0.426548], + [0.491022, 0.117179, 0.425552], + [0.497257, 0.119379, 0.424488], + [0.503493, 0.121575, 0.423356], + [0.509730, 0.123769, 0.422156], + [0.515967, 0.125960, 0.420887], + [0.522206, 0.128150, 0.419549], + [0.528444, 0.130341, 0.418142], + [0.534683, 0.132534, 0.416667], + [0.540920, 0.134729, 0.415123], + [0.547157, 0.136929, 0.413511], + [0.553392, 0.139134, 0.411829], + [0.559624, 0.141346, 0.410078], + [0.565854, 0.143567, 0.408258], + [0.572081, 0.145797, 0.406369], + [0.578304, 0.148039, 0.404411], + [0.584521, 0.150294, 0.402385], + [0.590734, 0.152563, 0.400290], + [0.596940, 0.154848, 0.398125], + [0.603139, 0.157151, 0.395891], + [0.609330, 0.159474, 0.393589], + [0.615513, 0.161817, 0.391219], + [0.621685, 0.164184, 0.388781], + [0.627847, 0.166575, 0.386276], + [0.633998, 0.168992, 0.383704], + [0.640135, 0.171438, 0.381065], + [0.646260, 0.173914, 0.378359], + [0.652369, 0.176421, 0.375586], + [0.658463, 0.178962, 0.372748], + [0.664540, 0.181539, 0.369846], + [0.670599, 0.184153, 0.366879], + [0.676638, 0.186807, 0.363849], + [0.682656, 0.189501, 0.360757], + [0.688653, 0.192239, 0.357603], + [0.694627, 0.195021, 0.354388], + [0.700576, 0.197851, 0.351113], + [0.706500, 0.200728, 0.347777], + [0.712396, 0.203656, 0.344383], + [0.718264, 0.206636, 0.340931], + [0.724103, 0.209670, 0.337424], + [0.729909, 0.212759, 0.333861], + [0.735683, 0.215906, 0.330245], + [0.741423, 0.219112, 0.326576], + [0.747127, 0.222378, 0.322856], + [0.752794, 0.225706, 0.319085], + [0.758422, 0.229097, 0.315266], + [0.764010, 0.232554, 0.311399], + [0.769556, 0.236077, 0.307485], + [0.775059, 0.239667, 0.303526], + [0.780517, 0.243327, 0.299523], + [0.785929, 0.247056, 0.295477], + [0.791293, 0.250856, 0.291390], + [0.796607, 0.254728, 0.287264], + [0.801871, 0.258674, 0.283099], + [0.807082, 0.262692, 0.278898], + [0.812239, 0.266786, 0.274661], + [0.817341, 0.270954, 0.270390], + [0.822386, 0.275197, 0.266085], + [0.827372, 0.279517, 0.261750], + [0.832299, 0.283913, 0.257383], + [0.837165, 0.288385, 0.252988], + [0.841969, 0.292933, 0.248564], + [0.846709, 0.297559, 0.244113], + [0.851384, 0.302260, 0.239636], + [0.855992, 0.307038, 0.235133], + [0.860533, 0.311892, 0.230606], + [0.865006, 0.316822, 0.226055], + [0.869409, 0.321827, 0.221482], + [0.873741, 0.326906, 0.216886], + [0.878001, 0.332060, 0.212268], + [0.882188, 0.337287, 0.207628], + [0.886302, 0.342586, 0.202968], + [0.890341, 0.347957, 0.198286], + [0.894305, 0.353399, 0.193584], + [0.898192, 0.358911, 0.188860], + [0.902003, 0.364492, 0.184116], + [0.905735, 0.370140, 0.179350], + [0.909390, 0.375856, 0.174563], + [0.912966, 0.381636, 0.169755], + [0.916462, 0.387481, 0.164924], + [0.919879, 0.393389, 0.160070], + [0.923215, 0.399359, 0.155193], + [0.926470, 0.405389, 0.150292], + [0.929644, 0.411479, 0.145367], + [0.932737, 0.417627, 0.140417], + [0.935747, 0.423831, 0.135440], + [0.938675, 0.430091, 0.130438], + [0.941521, 0.436405, 0.125409], + [0.944285, 0.442772, 0.120354], + [0.946965, 0.449191, 0.115272], + [0.949562, 0.455660, 0.110164], + [0.952075, 0.462178, 0.105031], + [0.954506, 0.468744, 0.099874], + [0.956852, 0.475356, 0.094695], + [0.959114, 0.482014, 0.089499], + [0.961293, 0.488716, 0.084289], + [0.963387, 0.495462, 0.079073], + [0.965397, 0.502249, 0.073859], + [0.967322, 0.509078, 0.068659], + [0.969163, 0.515946, 0.063488], + [0.970919, 0.522853, 0.058367], + [0.972590, 0.529798, 0.053324], + [0.974176, 0.536780, 0.048392], + [0.975677, 0.543798, 0.043618], + [0.977092, 0.550850, 0.039050], + [0.978422, 0.557937, 0.034931], + [0.979666, 0.565057, 0.031409], + [0.980824, 0.572209, 0.028508], + [0.981895, 0.579392, 0.026250], + [0.982881, 0.586606, 0.024661], + [0.983779, 0.593849, 0.023770], + [0.984591, 0.601122, 0.023606], + [0.985315, 0.608422, 0.024202], + [0.985952, 0.615750, 0.025592], + [0.986502, 0.623105, 0.027814], + [0.986964, 0.630485, 0.030908], + [0.987337, 0.637890, 0.034916], + [0.987622, 0.645320, 0.039886], + [0.987819, 0.652773, 0.045581], + [0.987926, 0.660250, 0.051750], + [0.987945, 0.667748, 0.058329], + [0.987874, 0.675267, 0.065257], + [0.987714, 0.682807, 0.072489], + [0.987464, 0.690366, 0.079990], + [0.987124, 0.697944, 0.087731], + [0.986694, 0.705540, 0.095694], + [0.986175, 0.713153, 0.103863], + [0.985566, 0.720782, 0.112229], + [0.984865, 0.728427, 0.120785], + [0.984075, 0.736087, 0.129527], + [0.983196, 0.743758, 0.138453], + [0.982228, 0.751442, 0.147565], + [0.981173, 0.759135, 0.156863], + [0.980032, 0.766837, 0.166353], + [0.978806, 0.774545, 0.176037], + [0.977497, 0.782258, 0.185923], + [0.976108, 0.789974, 0.196018], + [0.974638, 0.797692, 0.206332], + [0.973088, 0.805409, 0.216877], + [0.971468, 0.813122, 0.227658], + [0.969783, 0.820825, 0.238686], + [0.968041, 0.828515, 0.249972], + [0.966243, 0.836191, 0.261534], + [0.964394, 0.843848, 0.273391], + [0.962517, 0.851476, 0.285546], + [0.960626, 0.859069, 0.298010], + [0.958720, 0.866624, 0.310820], + [0.956834, 0.874129, 0.323974], + [0.954997, 0.881569, 0.337475], + [0.953215, 0.888942, 0.351369], + [0.951546, 0.896226, 0.365627], + [0.950018, 0.903409, 0.380271], + [0.948683, 0.910473, 0.395289], + [0.947594, 0.917399, 0.410665], + [0.946809, 0.924168, 0.426373], + [0.946392, 0.930761, 0.442367], + [0.946403, 0.937159, 0.458592], + [0.946903, 0.943348, 0.474970], + [0.947937, 0.949318, 0.491426], + [0.949545, 0.955063, 0.507860], + [0.951740, 0.960587, 0.524203], + [0.954529, 0.965896, 0.540361], + [0.957896, 0.971003, 0.556275], + [0.961812, 0.975924, 0.571925], + [0.966249, 0.980678, 0.587206], + [0.971162, 0.985282, 0.602154], + [0.976511, 0.989753, 0.616760], + [0.982257, 0.994109, 0.631017], + [0.988362, 0.998364, 0.644924]] + +_plasma_data = [[0.050383, 0.029803, 0.527975], + [0.063536, 0.028426, 0.533124], + [0.075353, 0.027206, 0.538007], + [0.086222, 0.026125, 0.542658], + [0.096379, 0.025165, 0.547103], + [0.105980, 0.024309, 0.551368], + [0.115124, 0.023556, 0.555468], + [0.123903, 0.022878, 0.559423], + [0.132381, 0.022258, 0.563250], + [0.140603, 0.021687, 0.566959], + [0.148607, 0.021154, 0.570562], + [0.156421, 0.020651, 0.574065], + [0.164070, 0.020171, 0.577478], + [0.171574, 0.019706, 0.580806], + [0.178950, 0.019252, 0.584054], + [0.186213, 0.018803, 0.587228], + [0.193374, 0.018354, 0.590330], + [0.200445, 0.017902, 0.593364], + [0.207435, 0.017442, 0.596333], + [0.214350, 0.016973, 0.599239], + [0.221197, 0.016497, 0.602083], + [0.227983, 0.016007, 0.604867], + [0.234715, 0.015502, 0.607592], + [0.241396, 0.014979, 0.610259], + [0.248032, 0.014439, 0.612868], + [0.254627, 0.013882, 0.615419], + [0.261183, 0.013308, 0.617911], + [0.267703, 0.012716, 0.620346], + [0.274191, 0.012109, 0.622722], + [0.280648, 0.011488, 0.625038], + [0.287076, 0.010855, 0.627295], + [0.293478, 0.010213, 0.629490], + [0.299855, 0.009561, 0.631624], + [0.306210, 0.008902, 0.633694], + [0.312543, 0.008239, 0.635700], + [0.318856, 0.007576, 0.637640], + [0.325150, 0.006915, 0.639512], + [0.331426, 0.006261, 0.641316], + [0.337683, 0.005618, 0.643049], + [0.343925, 0.004991, 0.644710], + [0.350150, 0.004382, 0.646298], + [0.356359, 0.003798, 0.647810], + [0.362553, 0.003243, 0.649245], + [0.368733, 0.002724, 0.650601], + [0.374897, 0.002245, 0.651876], + [0.381047, 0.001814, 0.653068], + [0.387183, 0.001434, 0.654177], + [0.393304, 0.001114, 0.655199], + [0.399411, 0.000859, 0.656133], + [0.405503, 0.000678, 0.656977], + [0.411580, 0.000577, 0.657730], + [0.417642, 0.000564, 0.658390], + [0.423689, 0.000646, 0.658956], + [0.429719, 0.000831, 0.659425], + [0.435734, 0.001127, 0.659797], + [0.441732, 0.001540, 0.660069], + [0.447714, 0.002080, 0.660240], + [0.453677, 0.002755, 0.660310], + [0.459623, 0.003574, 0.660277], + [0.465550, 0.004545, 0.660139], + [0.471457, 0.005678, 0.659897], + [0.477344, 0.006980, 0.659549], + [0.483210, 0.008460, 0.659095], + [0.489055, 0.010127, 0.658534], + [0.494877, 0.011990, 0.657865], + [0.500678, 0.014055, 0.657088], + [0.506454, 0.016333, 0.656202], + [0.512206, 0.018833, 0.655209], + [0.517933, 0.021563, 0.654109], + [0.523633, 0.024532, 0.652901], + [0.529306, 0.027747, 0.651586], + [0.534952, 0.031217, 0.650165], + [0.540570, 0.034950, 0.648640], + [0.546157, 0.038954, 0.647010], + [0.551715, 0.043136, 0.645277], + [0.557243, 0.047331, 0.643443], + [0.562738, 0.051545, 0.641509], + [0.568201, 0.055778, 0.639477], + [0.573632, 0.060028, 0.637349], + [0.579029, 0.064296, 0.635126], + [0.584391, 0.068579, 0.632812], + [0.589719, 0.072878, 0.630408], + [0.595011, 0.077190, 0.627917], + [0.600266, 0.081516, 0.625342], + [0.605485, 0.085854, 0.622686], + [0.610667, 0.090204, 0.619951], + [0.615812, 0.094564, 0.617140], + [0.620919, 0.098934, 0.614257], + [0.625987, 0.103312, 0.611305], + [0.631017, 0.107699, 0.608287], + [0.636008, 0.112092, 0.605205], + [0.640959, 0.116492, 0.602065], + [0.645872, 0.120898, 0.598867], + [0.650746, 0.125309, 0.595617], + [0.655580, 0.129725, 0.592317], + [0.660374, 0.134144, 0.588971], + [0.665129, 0.138566, 0.585582], + [0.669845, 0.142992, 0.582154], + [0.674522, 0.147419, 0.578688], + [0.679160, 0.151848, 0.575189], + [0.683758, 0.156278, 0.571660], + [0.688318, 0.160709, 0.568103], + [0.692840, 0.165141, 0.564522], + [0.697324, 0.169573, 0.560919], + [0.701769, 0.174005, 0.557296], + [0.706178, 0.178437, 0.553657], + [0.710549, 0.182868, 0.550004], + [0.714883, 0.187299, 0.546338], + [0.719181, 0.191729, 0.542663], + [0.723444, 0.196158, 0.538981], + [0.727670, 0.200586, 0.535293], + [0.731862, 0.205013, 0.531601], + [0.736019, 0.209439, 0.527908], + [0.740143, 0.213864, 0.524216], + [0.744232, 0.218288, 0.520524], + [0.748289, 0.222711, 0.516834], + [0.752312, 0.227133, 0.513149], + [0.756304, 0.231555, 0.509468], + [0.760264, 0.235976, 0.505794], + [0.764193, 0.240396, 0.502126], + [0.768090, 0.244817, 0.498465], + [0.771958, 0.249237, 0.494813], + [0.775796, 0.253658, 0.491171], + [0.779604, 0.258078, 0.487539], + [0.783383, 0.262500, 0.483918], + [0.787133, 0.266922, 0.480307], + [0.790855, 0.271345, 0.476706], + [0.794549, 0.275770, 0.473117], + [0.798216, 0.280197, 0.469538], + [0.801855, 0.284626, 0.465971], + [0.805467, 0.289057, 0.462415], + [0.809052, 0.293491, 0.458870], + [0.812612, 0.297928, 0.455338], + [0.816144, 0.302368, 0.451816], + [0.819651, 0.306812, 0.448306], + [0.823132, 0.311261, 0.444806], + [0.826588, 0.315714, 0.441316], + [0.830018, 0.320172, 0.437836], + [0.833422, 0.324635, 0.434366], + [0.836801, 0.329105, 0.430905], + [0.840155, 0.333580, 0.427455], + [0.843484, 0.338062, 0.424013], + [0.846788, 0.342551, 0.420579], + [0.850066, 0.347048, 0.417153], + [0.853319, 0.351553, 0.413734], + [0.856547, 0.356066, 0.410322], + [0.859750, 0.360588, 0.406917], + [0.862927, 0.365119, 0.403519], + [0.866078, 0.369660, 0.400126], + [0.869203, 0.374212, 0.396738], + [0.872303, 0.378774, 0.393355], + [0.875376, 0.383347, 0.389976], + [0.878423, 0.387932, 0.386600], + [0.881443, 0.392529, 0.383229], + [0.884436, 0.397139, 0.379860], + [0.887402, 0.401762, 0.376494], + [0.890340, 0.406398, 0.373130], + [0.893250, 0.411048, 0.369768], + [0.896131, 0.415712, 0.366407], + [0.898984, 0.420392, 0.363047], + [0.901807, 0.425087, 0.359688], + [0.904601, 0.429797, 0.356329], + [0.907365, 0.434524, 0.352970], + [0.910098, 0.439268, 0.349610], + [0.912800, 0.444029, 0.346251], + [0.915471, 0.448807, 0.342890], + [0.918109, 0.453603, 0.339529], + [0.920714, 0.458417, 0.336166], + [0.923287, 0.463251, 0.332801], + [0.925825, 0.468103, 0.329435], + [0.928329, 0.472975, 0.326067], + [0.930798, 0.477867, 0.322697], + [0.933232, 0.482780, 0.319325], + [0.935630, 0.487712, 0.315952], + [0.937990, 0.492667, 0.312575], + [0.940313, 0.497642, 0.309197], + [0.942598, 0.502639, 0.305816], + [0.944844, 0.507658, 0.302433], + [0.947051, 0.512699, 0.299049], + [0.949217, 0.517763, 0.295662], + [0.951344, 0.522850, 0.292275], + [0.953428, 0.527960, 0.288883], + [0.955470, 0.533093, 0.285490], + [0.957469, 0.538250, 0.282096], + [0.959424, 0.543431, 0.278701], + [0.961336, 0.548636, 0.275305], + [0.963203, 0.553865, 0.271909], + [0.965024, 0.559118, 0.268513], + [0.966798, 0.564396, 0.265118], + [0.968526, 0.569700, 0.261721], + [0.970205, 0.575028, 0.258325], + [0.971835, 0.580382, 0.254931], + [0.973416, 0.585761, 0.251540], + [0.974947, 0.591165, 0.248151], + [0.976428, 0.596595, 0.244767], + [0.977856, 0.602051, 0.241387], + [0.979233, 0.607532, 0.238013], + [0.980556, 0.613039, 0.234646], + [0.981826, 0.618572, 0.231287], + [0.983041, 0.624131, 0.227937], + [0.984199, 0.629718, 0.224595], + [0.985301, 0.635330, 0.221265], + [0.986345, 0.640969, 0.217948], + [0.987332, 0.646633, 0.214648], + [0.988260, 0.652325, 0.211364], + [0.989128, 0.658043, 0.208100], + [0.989935, 0.663787, 0.204859], + [0.990681, 0.669558, 0.201642], + [0.991365, 0.675355, 0.198453], + [0.991985, 0.681179, 0.195295], + [0.992541, 0.687030, 0.192170], + [0.993032, 0.692907, 0.189084], + [0.993456, 0.698810, 0.186041], + [0.993814, 0.704741, 0.183043], + [0.994103, 0.710698, 0.180097], + [0.994324, 0.716681, 0.177208], + [0.994474, 0.722691, 0.174381], + [0.994553, 0.728728, 0.171622], + [0.994561, 0.734791, 0.168938], + [0.994495, 0.740880, 0.166335], + [0.994355, 0.746995, 0.163821], + [0.994141, 0.753137, 0.161404], + [0.993851, 0.759304, 0.159092], + [0.993482, 0.765499, 0.156891], + [0.993033, 0.771720, 0.154808], + [0.992505, 0.777967, 0.152855], + [0.991897, 0.784239, 0.151042], + [0.991209, 0.790537, 0.149377], + [0.990439, 0.796859, 0.147870], + [0.989587, 0.803205, 0.146529], + [0.988648, 0.809579, 0.145357], + [0.987621, 0.815978, 0.144363], + [0.986509, 0.822401, 0.143557], + [0.985314, 0.828846, 0.142945], + [0.984031, 0.835315, 0.142528], + [0.982653, 0.841812, 0.142303], + [0.981190, 0.848329, 0.142279], + [0.979644, 0.854866, 0.142453], + [0.977995, 0.861432, 0.142808], + [0.976265, 0.868016, 0.143351], + [0.974443, 0.874622, 0.144061], + [0.972530, 0.881250, 0.144923], + [0.970533, 0.887896, 0.145919], + [0.968443, 0.894564, 0.147014], + [0.966271, 0.901249, 0.148180], + [0.964021, 0.907950, 0.149370], + [0.961681, 0.914672, 0.150520], + [0.959276, 0.921407, 0.151566], + [0.956808, 0.928152, 0.152409], + [0.954287, 0.934908, 0.152921], + [0.951726, 0.941671, 0.152925], + [0.949151, 0.948435, 0.152178], + [0.946602, 0.955190, 0.150328], + [0.944152, 0.961916, 0.146861], + [0.941896, 0.968590, 0.140956], + [0.940015, 0.975158, 0.131326]] + +_viridis_data = [[0.267004, 0.004874, 0.329415], + [0.268510, 0.009605, 0.335427], + [0.269944, 0.014625, 0.341379], + [0.271305, 0.019942, 0.347269], + [0.272594, 0.025563, 0.353093], + [0.273809, 0.031497, 0.358853], + [0.274952, 0.037752, 0.364543], + [0.276022, 0.044167, 0.370164], + [0.277018, 0.050344, 0.375715], + [0.277941, 0.056324, 0.381191], + [0.278791, 0.062145, 0.386592], + [0.279566, 0.067836, 0.391917], + [0.280267, 0.073417, 0.397163], + [0.280894, 0.078907, 0.402329], + [0.281446, 0.084320, 0.407414], + [0.281924, 0.089666, 0.412415], + [0.282327, 0.094955, 0.417331], + [0.282656, 0.100196, 0.422160], + [0.282910, 0.105393, 0.426902], + [0.283091, 0.110553, 0.431554], + [0.283197, 0.115680, 0.436115], + [0.283229, 0.120777, 0.440584], + [0.283187, 0.125848, 0.444960], + [0.283072, 0.130895, 0.449241], + [0.282884, 0.135920, 0.453427], + [0.282623, 0.140926, 0.457517], + [0.282290, 0.145912, 0.461510], + [0.281887, 0.150881, 0.465405], + [0.281412, 0.155834, 0.469201], + [0.280868, 0.160771, 0.472899], + [0.280255, 0.165693, 0.476498], + [0.279574, 0.170599, 0.479997], + [0.278826, 0.175490, 0.483397], + [0.278012, 0.180367, 0.486697], + [0.277134, 0.185228, 0.489898], + [0.276194, 0.190074, 0.493001], + [0.275191, 0.194905, 0.496005], + [0.274128, 0.199721, 0.498911], + [0.273006, 0.204520, 0.501721], + [0.271828, 0.209303, 0.504434], + [0.270595, 0.214069, 0.507052], + [0.269308, 0.218818, 0.509577], + [0.267968, 0.223549, 0.512008], + [0.266580, 0.228262, 0.514349], + [0.265145, 0.232956, 0.516599], + [0.263663, 0.237631, 0.518762], + [0.262138, 0.242286, 0.520837], + [0.260571, 0.246922, 0.522828], + [0.258965, 0.251537, 0.524736], + [0.257322, 0.256130, 0.526563], + [0.255645, 0.260703, 0.528312], + [0.253935, 0.265254, 0.529983], + [0.252194, 0.269783, 0.531579], + [0.250425, 0.274290, 0.533103], + [0.248629, 0.278775, 0.534556], + [0.246811, 0.283237, 0.535941], + [0.244972, 0.287675, 0.537260], + [0.243113, 0.292092, 0.538516], + [0.241237, 0.296485, 0.539709], + [0.239346, 0.300855, 0.540844], + [0.237441, 0.305202, 0.541921], + [0.235526, 0.309527, 0.542944], + [0.233603, 0.313828, 0.543914], + [0.231674, 0.318106, 0.544834], + [0.229739, 0.322361, 0.545706], + [0.227802, 0.326594, 0.546532], + [0.225863, 0.330805, 0.547314], + [0.223925, 0.334994, 0.548053], + [0.221989, 0.339161, 0.548752], + [0.220057, 0.343307, 0.549413], + [0.218130, 0.347432, 0.550038], + [0.216210, 0.351535, 0.550627], + [0.214298, 0.355619, 0.551184], + [0.212395, 0.359683, 0.551710], + [0.210503, 0.363727, 0.552206], + [0.208623, 0.367752, 0.552675], + [0.206756, 0.371758, 0.553117], + [0.204903, 0.375746, 0.553533], + [0.203063, 0.379716, 0.553925], + [0.201239, 0.383670, 0.554294], + [0.199430, 0.387607, 0.554642], + [0.197636, 0.391528, 0.554969], + [0.195860, 0.395433, 0.555276], + [0.194100, 0.399323, 0.555565], + [0.192357, 0.403199, 0.555836], + [0.190631, 0.407061, 0.556089], + [0.188923, 0.410910, 0.556326], + [0.187231, 0.414746, 0.556547], + [0.185556, 0.418570, 0.556753], + [0.183898, 0.422383, 0.556944], + [0.182256, 0.426184, 0.557120], + [0.180629, 0.429975, 0.557282], + [0.179019, 0.433756, 0.557430], + [0.177423, 0.437527, 0.557565], + [0.175841, 0.441290, 0.557685], + [0.174274, 0.445044, 0.557792], + [0.172719, 0.448791, 0.557885], + [0.171176, 0.452530, 0.557965], + [0.169646, 0.456262, 0.558030], + [0.168126, 0.459988, 0.558082], + [0.166617, 0.463708, 0.558119], + [0.165117, 0.467423, 0.558141], + [0.163625, 0.471133, 0.558148], + [0.162142, 0.474838, 0.558140], + [0.160665, 0.478540, 0.558115], + [0.159194, 0.482237, 0.558073], + [0.157729, 0.485932, 0.558013], + [0.156270, 0.489624, 0.557936], + [0.154815, 0.493313, 0.557840], + [0.153364, 0.497000, 0.557724], + [0.151918, 0.500685, 0.557587], + [0.150476, 0.504369, 0.557430], + [0.149039, 0.508051, 0.557250], + [0.147607, 0.511733, 0.557049], + [0.146180, 0.515413, 0.556823], + [0.144759, 0.519093, 0.556572], + [0.143343, 0.522773, 0.556295], + [0.141935, 0.526453, 0.555991], + [0.140536, 0.530132, 0.555659], + [0.139147, 0.533812, 0.555298], + [0.137770, 0.537492, 0.554906], + [0.136408, 0.541173, 0.554483], + [0.135066, 0.544853, 0.554029], + [0.133743, 0.548535, 0.553541], + [0.132444, 0.552216, 0.553018], + [0.131172, 0.555899, 0.552459], + [0.129933, 0.559582, 0.551864], + [0.128729, 0.563265, 0.551229], + [0.127568, 0.566949, 0.550556], + [0.126453, 0.570633, 0.549841], + [0.125394, 0.574318, 0.549086], + [0.124395, 0.578002, 0.548287], + [0.123463, 0.581687, 0.547445], + [0.122606, 0.585371, 0.546557], + [0.121831, 0.589055, 0.545623], + [0.121148, 0.592739, 0.544641], + [0.120565, 0.596422, 0.543611], + [0.120092, 0.600104, 0.542530], + [0.119738, 0.603785, 0.541400], + [0.119512, 0.607464, 0.540218], + [0.119423, 0.611141, 0.538982], + [0.119483, 0.614817, 0.537692], + [0.119699, 0.618490, 0.536347], + [0.120081, 0.622161, 0.534946], + [0.120638, 0.625828, 0.533488], + [0.121380, 0.629492, 0.531973], + [0.122312, 0.633153, 0.530398], + [0.123444, 0.636809, 0.528763], + [0.124780, 0.640461, 0.527068], + [0.126326, 0.644107, 0.525311], + [0.128087, 0.647749, 0.523491], + [0.130067, 0.651384, 0.521608], + [0.132268, 0.655014, 0.519661], + [0.134692, 0.658636, 0.517649], + [0.137339, 0.662252, 0.515571], + [0.140210, 0.665859, 0.513427], + [0.143303, 0.669459, 0.511215], + [0.146616, 0.673050, 0.508936], + [0.150148, 0.676631, 0.506589], + [0.153894, 0.680203, 0.504172], + [0.157851, 0.683765, 0.501686], + [0.162016, 0.687316, 0.499129], + [0.166383, 0.690856, 0.496502], + [0.170948, 0.694384, 0.493803], + [0.175707, 0.697900, 0.491033], + [0.180653, 0.701402, 0.488189], + [0.185783, 0.704891, 0.485273], + [0.191090, 0.708366, 0.482284], + [0.196571, 0.711827, 0.479221], + [0.202219, 0.715272, 0.476084], + [0.208030, 0.718701, 0.472873], + [0.214000, 0.722114, 0.469588], + [0.220124, 0.725509, 0.466226], + [0.226397, 0.728888, 0.462789], + [0.232815, 0.732247, 0.459277], + [0.239374, 0.735588, 0.455688], + [0.246070, 0.738910, 0.452024], + [0.252899, 0.742211, 0.448284], + [0.259857, 0.745492, 0.444467], + [0.266941, 0.748751, 0.440573], + [0.274149, 0.751988, 0.436601], + [0.281477, 0.755203, 0.432552], + [0.288921, 0.758394, 0.428426], + [0.296479, 0.761561, 0.424223], + [0.304148, 0.764704, 0.419943], + [0.311925, 0.767822, 0.415586], + [0.319809, 0.770914, 0.411152], + [0.327796, 0.773980, 0.406640], + [0.335885, 0.777018, 0.402049], + [0.344074, 0.780029, 0.397381], + [0.352360, 0.783011, 0.392636], + [0.360741, 0.785964, 0.387814], + [0.369214, 0.788888, 0.382914], + [0.377779, 0.791781, 0.377939], + [0.386433, 0.794644, 0.372886], + [0.395174, 0.797475, 0.367757], + [0.404001, 0.800275, 0.362552], + [0.412913, 0.803041, 0.357269], + [0.421908, 0.805774, 0.351910], + [0.430983, 0.808473, 0.346476], + [0.440137, 0.811138, 0.340967], + [0.449368, 0.813768, 0.335384], + [0.458674, 0.816363, 0.329727], + [0.468053, 0.818921, 0.323998], + [0.477504, 0.821444, 0.318195], + [0.487026, 0.823929, 0.312321], + [0.496615, 0.826376, 0.306377], + [0.506271, 0.828786, 0.300362], + [0.515992, 0.831158, 0.294279], + [0.525776, 0.833491, 0.288127], + [0.535621, 0.835785, 0.281908], + [0.545524, 0.838039, 0.275626], + [0.555484, 0.840254, 0.269281], + [0.565498, 0.842430, 0.262877], + [0.575563, 0.844566, 0.256415], + [0.585678, 0.846661, 0.249897], + [0.595839, 0.848717, 0.243329], + [0.606045, 0.850733, 0.236712], + [0.616293, 0.852709, 0.230052], + [0.626579, 0.854645, 0.223353], + [0.636902, 0.856542, 0.216620], + [0.647257, 0.858400, 0.209861], + [0.657642, 0.860219, 0.203082], + [0.668054, 0.861999, 0.196293], + [0.678489, 0.863742, 0.189503], + [0.688944, 0.865448, 0.182725], + [0.699415, 0.867117, 0.175971], + [0.709898, 0.868751, 0.169257], + [0.720391, 0.870350, 0.162603], + [0.730889, 0.871916, 0.156029], + [0.741388, 0.873449, 0.149561], + [0.751884, 0.874951, 0.143228], + [0.762373, 0.876424, 0.137064], + [0.772852, 0.877868, 0.131109], + [0.783315, 0.879285, 0.125405], + [0.793760, 0.880678, 0.120005], + [0.804182, 0.882046, 0.114965], + [0.814576, 0.883393, 0.110347], + [0.824940, 0.884720, 0.106217], + [0.835270, 0.886029, 0.102646], + [0.845561, 0.887322, 0.099702], + [0.855810, 0.888601, 0.097452], + [0.866013, 0.889868, 0.095953], + [0.876168, 0.891125, 0.095250], + [0.886271, 0.892374, 0.095374], + [0.896320, 0.893616, 0.096335], + [0.906311, 0.894855, 0.098125], + [0.916242, 0.896091, 0.100717], + [0.926106, 0.897330, 0.104071], + [0.935904, 0.898570, 0.108131], + [0.945636, 0.899815, 0.112838], + [0.955300, 0.901065, 0.118128], + [0.964894, 0.902323, 0.123941], + [0.974417, 0.903590, 0.130215], + [0.983868, 0.904867, 0.136897], + [0.993248, 0.906157, 0.143936]] + +_cividis_data = [[0.000000, 0.135112, 0.304751], + [0.000000, 0.138068, 0.311105], + [0.000000, 0.141013, 0.317579], + [0.000000, 0.143951, 0.323982], + [0.000000, 0.146877, 0.330479], + [0.000000, 0.149791, 0.337065], + [0.000000, 0.152673, 0.343704], + [0.000000, 0.155377, 0.350500], + [0.000000, 0.157932, 0.357521], + [0.000000, 0.160495, 0.364534], + [0.000000, 0.163058, 0.371608], + [0.000000, 0.165621, 0.378769], + [0.000000, 0.168204, 0.385902], + [0.000000, 0.170800, 0.393100], + [0.000000, 0.173420, 0.400353], + [0.000000, 0.176082, 0.407577], + [0.000000, 0.178802, 0.414764], + [0.000000, 0.181610, 0.421859], + [0.000000, 0.184550, 0.428802], + [0.000000, 0.186915, 0.435532], + [0.000000, 0.188769, 0.439563], + [0.000000, 0.190950, 0.441085], + [0.000000, 0.193366, 0.441561], + [0.003602, 0.195911, 0.441564], + [0.017852, 0.198528, 0.441248], + [0.032110, 0.201199, 0.440785], + [0.046205, 0.203903, 0.440196], + [0.058378, 0.206629, 0.439531], + [0.068968, 0.209372, 0.438863], + [0.078624, 0.212122, 0.438105], + [0.087465, 0.214879, 0.437342], + [0.095645, 0.217643, 0.436593], + [0.103401, 0.220406, 0.435790], + [0.110658, 0.223170, 0.435067], + [0.117612, 0.225935, 0.434308], + [0.124291, 0.228697, 0.433547], + [0.130669, 0.231458, 0.432840], + [0.136830, 0.234216, 0.432148], + [0.142852, 0.236972, 0.431404], + [0.148638, 0.239724, 0.430752], + [0.154261, 0.242475, 0.430120], + [0.159733, 0.245221, 0.429528], + [0.165113, 0.247965, 0.428908], + [0.170362, 0.250707, 0.428325], + [0.175490, 0.253444, 0.427790], + [0.180503, 0.256180, 0.427299], + [0.185453, 0.258914, 0.426788], + [0.190303, 0.261644, 0.426329], + [0.195057, 0.264372, 0.425924], + [0.199764, 0.267099, 0.425497], + [0.204385, 0.269823, 0.425126], + [0.208926, 0.272546, 0.424809], + [0.213431, 0.275266, 0.424480], + [0.217863, 0.277985, 0.424206], + [0.222264, 0.280702, 0.423914], + [0.226598, 0.283419, 0.423678], + [0.230871, 0.286134, 0.423498], + [0.235120, 0.288848, 0.423304], + [0.239312, 0.291562, 0.423167], + [0.243485, 0.294274, 0.423014], + [0.247605, 0.296986, 0.422917], + [0.251675, 0.299698, 0.422873], + [0.255731, 0.302409, 0.422814], + [0.259740, 0.305120, 0.422810], + [0.263738, 0.307831, 0.422789], + [0.267693, 0.310542, 0.422821], + [0.271639, 0.313253, 0.422837], + [0.275513, 0.315965, 0.422979], + [0.279411, 0.318677, 0.423031], + [0.283240, 0.321390, 0.423211], + [0.287065, 0.324103, 0.423373], + [0.290884, 0.326816, 0.423517], + [0.294669, 0.329531, 0.423716], + [0.298421, 0.332247, 0.423973], + [0.302169, 0.334963, 0.424213], + [0.305886, 0.337681, 0.424512], + [0.309601, 0.340399, 0.424790], + [0.313287, 0.343120, 0.425120], + [0.316941, 0.345842, 0.425512], + [0.320595, 0.348565, 0.425889], + [0.324250, 0.351289, 0.426250], + [0.327875, 0.354016, 0.426670], + [0.331474, 0.356744, 0.427144], + [0.335073, 0.359474, 0.427605], + [0.338673, 0.362206, 0.428053], + [0.342246, 0.364939, 0.428559], + [0.345793, 0.367676, 0.429127], + [0.349341, 0.370414, 0.429685], + [0.352892, 0.373153, 0.430226], + [0.356418, 0.375896, 0.430823], + [0.359916, 0.378641, 0.431501], + [0.363446, 0.381388, 0.432075], + [0.366923, 0.384139, 0.432796], + [0.370430, 0.386890, 0.433428], + [0.373884, 0.389646, 0.434209], + [0.377371, 0.392404, 0.434890], + [0.380830, 0.395164, 0.435653], + [0.384268, 0.397928, 0.436475], + [0.387705, 0.400694, 0.437305], + [0.391151, 0.403464, 0.438096], + [0.394568, 0.406236, 0.438986], + [0.397991, 0.409011, 0.439848], + [0.401418, 0.411790, 0.440708], + [0.404820, 0.414572, 0.441642], + [0.408226, 0.417357, 0.442570], + [0.411607, 0.420145, 0.443577], + [0.414992, 0.422937, 0.444578], + [0.418383, 0.425733, 0.445560], + [0.421748, 0.428531, 0.446640], + [0.425120, 0.431334, 0.447692], + [0.428462, 0.434140, 0.448864], + [0.431817, 0.436950, 0.449982], + [0.435168, 0.439763, 0.451134], + [0.438504, 0.442580, 0.452341], + [0.441810, 0.445402, 0.453659], + [0.445148, 0.448226, 0.454885], + [0.448447, 0.451053, 0.456264], + [0.451759, 0.453887, 0.457582], + [0.455072, 0.456718, 0.458976], + [0.458366, 0.459552, 0.460457], + [0.461616, 0.462405, 0.461969], + [0.464947, 0.465241, 0.463395], + [0.468254, 0.468083, 0.464908], + [0.471501, 0.470960, 0.466357], + [0.474812, 0.473832, 0.467681], + [0.478186, 0.476699, 0.468845], + [0.481622, 0.479573, 0.469767], + [0.485141, 0.482451, 0.470384], + [0.488697, 0.485318, 0.471008], + [0.492278, 0.488198, 0.471453], + [0.495913, 0.491076, 0.471751], + [0.499552, 0.493960, 0.472032], + [0.503185, 0.496851, 0.472305], + [0.506866, 0.499743, 0.472432], + [0.510540, 0.502643, 0.472550], + [0.514226, 0.505546, 0.472640], + [0.517920, 0.508454, 0.472707], + [0.521643, 0.511367, 0.472639], + [0.525348, 0.514285, 0.472660], + [0.529086, 0.517207, 0.472543], + [0.532829, 0.520135, 0.472401], + [0.536553, 0.523067, 0.472352], + [0.540307, 0.526005, 0.472163], + [0.544069, 0.528948, 0.471947], + [0.547840, 0.531895, 0.471704], + [0.551612, 0.534849, 0.471439], + [0.555393, 0.537807, 0.471147], + [0.559181, 0.540771, 0.470829], + [0.562972, 0.543741, 0.470488], + [0.566802, 0.546715, 0.469988], + [0.570607, 0.549695, 0.469593], + [0.574417, 0.552682, 0.469172], + [0.578236, 0.555673, 0.468724], + [0.582087, 0.558670, 0.468118], + [0.585916, 0.561674, 0.467618], + [0.589753, 0.564682, 0.467090], + [0.593622, 0.567697, 0.466401], + [0.597469, 0.570718, 0.465821], + [0.601354, 0.573743, 0.465074], + [0.605211, 0.576777, 0.464441], + [0.609105, 0.579816, 0.463638], + [0.612977, 0.582861, 0.462950], + [0.616852, 0.585913, 0.462237], + [0.620765, 0.588970, 0.461351], + [0.624654, 0.592034, 0.460583], + [0.628576, 0.595104, 0.459641], + [0.632506, 0.598180, 0.458668], + [0.636412, 0.601264, 0.457818], + [0.640352, 0.604354, 0.456791], + [0.644270, 0.607450, 0.455886], + [0.648222, 0.610553, 0.454801], + [0.652178, 0.613664, 0.453689], + [0.656114, 0.616780, 0.452702], + [0.660082, 0.619904, 0.451534], + [0.664055, 0.623034, 0.450338], + [0.668008, 0.626171, 0.449270], + [0.671991, 0.629316, 0.448018], + [0.675981, 0.632468, 0.446736], + [0.679979, 0.635626, 0.445424], + [0.683950, 0.638793, 0.444251], + [0.687957, 0.641966, 0.442886], + [0.691971, 0.645145, 0.441491], + [0.695985, 0.648334, 0.440072], + [0.700008, 0.651529, 0.438624], + [0.704037, 0.654731, 0.437147], + [0.708067, 0.657942, 0.435647], + [0.712105, 0.661160, 0.434117], + [0.716177, 0.664384, 0.432386], + [0.720222, 0.667618, 0.430805], + [0.724274, 0.670859, 0.429194], + [0.728334, 0.674107, 0.427554], + [0.732422, 0.677364, 0.425717], + [0.736488, 0.680629, 0.424028], + [0.740589, 0.683900, 0.422131], + [0.744664, 0.687181, 0.420393], + [0.748772, 0.690470, 0.418448], + [0.752886, 0.693766, 0.416472], + [0.756975, 0.697071, 0.414659], + [0.761096, 0.700384, 0.412638], + [0.765223, 0.703705, 0.410587], + [0.769353, 0.707035, 0.408516], + [0.773486, 0.710373, 0.406422], + [0.777651, 0.713719, 0.404112], + [0.781795, 0.717074, 0.401966], + [0.785965, 0.720438, 0.399613], + [0.790116, 0.723810, 0.397423], + [0.794298, 0.727190, 0.395016], + [0.798480, 0.730580, 0.392597], + [0.802667, 0.733978, 0.390153], + [0.806859, 0.737385, 0.387684], + [0.811054, 0.740801, 0.385198], + [0.815274, 0.744226, 0.382504], + [0.819499, 0.747659, 0.379785], + [0.823729, 0.751101, 0.377043], + [0.827959, 0.754553, 0.374292], + [0.832192, 0.758014, 0.371529], + [0.836429, 0.761483, 0.368747], + [0.840693, 0.764962, 0.365746], + [0.844957, 0.768450, 0.362741], + [0.849223, 0.771947, 0.359729], + [0.853515, 0.775454, 0.356500], + [0.857809, 0.778969, 0.353259], + [0.862105, 0.782494, 0.350011], + [0.866421, 0.786028, 0.346571], + [0.870717, 0.789572, 0.343333], + [0.875057, 0.793125, 0.339685], + [0.879378, 0.796687, 0.336241], + [0.883720, 0.800258, 0.332599], + [0.888081, 0.803839, 0.328770], + [0.892440, 0.807430, 0.324968], + [0.896818, 0.811030, 0.320982], + [0.901195, 0.814639, 0.317021], + [0.905589, 0.818257, 0.312889], + [0.910000, 0.821885, 0.308594], + [0.914407, 0.825522, 0.304348], + [0.918828, 0.829168, 0.299960], + [0.923279, 0.832822, 0.295244], + [0.927724, 0.836486, 0.290611], + [0.932180, 0.840159, 0.285880], + [0.936660, 0.843841, 0.280876], + [0.941147, 0.847530, 0.275815], + [0.945654, 0.851228, 0.270532], + [0.950178, 0.854933, 0.265085], + [0.954725, 0.858646, 0.259365], + [0.959284, 0.862365, 0.253563], + [0.963872, 0.866089, 0.247445], + [0.968469, 0.869819, 0.241310], + [0.973114, 0.873550, 0.234677], + [0.977780, 0.877281, 0.227954], + [0.982497, 0.881008, 0.220878], + [0.987293, 0.884718, 0.213336], + [0.992218, 0.888385, 0.205468], + [0.994847, 0.892954, 0.203445], + [0.995249, 0.898384, 0.207561], + [0.995503, 0.903866, 0.212370], + [0.995737, 0.909344, 0.217772]] + +_twilight_data = [ + [0.88575015840754434, 0.85000924943067835, 0.8879736506427196], + [0.88378520195539056, 0.85072940540310626, 0.88723222096949894], + [0.88172231059285788, 0.85127594077653468, 0.88638056925514819], + [0.8795410528270573, 0.85165675407495722, 0.8854143767924102], + [0.87724880858965482, 0.85187028338870274, 0.88434120381311432], + [0.87485347508575972, 0.85191526123023187, 0.88316926967613829], + [0.87233134085124076, 0.85180165478080894, 0.88189704355001619], + [0.86970474853509816, 0.85152403004797894, 0.88053883390003362], + [0.86696015505333579, 0.8510896085314068, 0.87909766977173343], + [0.86408985081463996, 0.85050391167507788, 0.87757925784892632], + [0.86110245436899846, 0.84976754857001258, 0.87599242923439569], + [0.85798259245670372, 0.84888934810281835, 0.87434038553446281], + [0.85472593189256985, 0.84787488124672816, 0.8726282980930582], + [0.85133714570857189, 0.84672735796116472, 0.87086081657350445], + [0.84780710702577922, 0.8454546229209523, 0.86904036783694438], + [0.8441261828674842, 0.84406482711037389, 0.86716973322690072], + [0.84030420805957784, 0.8425605950855084, 0.865250882410458], + [0.83634031809191178, 0.84094796518951942, 0.86328528001070159], + [0.83222705712934408, 0.83923490627754482, 0.86127563500427884], + [0.82796894316013536, 0.83742600751395202, 0.85922399451306786], + [0.82357429680252847, 0.83552487764795436, 0.85713191328514948], + [0.81904654677937527, 0.8335364929949034, 0.85500206287010105], + [0.81438982121143089, 0.83146558694197847, 0.85283759062147024], + [0.8095999819094809, 0.82931896673505456, 0.85064441601050367], + [0.80469164429814577, 0.82709838780560663, 0.84842449296974021], + [0.79967075421267997, 0.82480781812080928, 0.84618210029578533], + [0.79454305089231114, 0.82245116226304615, 0.84392184786827984], + [0.78931445564608915, 0.82003213188702007, 0.8416486380471222], + [0.78399101042764918, 0.81755426400533426, 0.83936747464036732], + [0.77857892008227592, 0.81502089378742548, 0.8370834463093898], + [0.77308416590170936, 0.81243524735466011, 0.83480172950579679], + [0.76751108504417864, 0.8098007598713145, 0.83252816638059668], + [0.76186907937980286, 0.80711949387647486, 0.830266486168872], + [0.75616443584381976, 0.80439408733477935, 0.82802138994719998], + [0.75040346765406696, 0.80162699008965321, 0.82579737851082424], + [0.74459247771890169, 0.79882047719583249, 0.82359867586156521], + [0.73873771700494939, 0.79597665735031009, 0.82142922780433014], + [0.73284543645523459, 0.79309746468844067, 0.81929263384230377], + [0.72692177512829703, 0.7901846863592763, 0.81719217466726379], + [0.72097280665536778, 0.78723995923452639, 0.81513073920879264], + [0.71500403076252128, 0.78426487091581187, 0.81311116559949914], + [0.70902078134539304, 0.78126088716070907, 0.81113591855117928], + [0.7030297722540817, 0.77822904973358131, 0.80920618848056969], + [0.6970365443886174, 0.77517050008066057, 0.80732335380063447], + [0.69104641009309098, 0.77208629460678091, 0.80548841690679074], + [0.68506446154395928, 0.7689774029354699, 0.80370206267176914], + [0.67909554499882152, 0.76584472131395898, 0.8019646617300199], + [0.67314422559426212, 0.76268908733890484, 0.80027628545809526], + [0.66721479803752815, 0.7595112803730375, 0.79863674654537764], + [0.6613112930078745, 0.75631202708719025, 0.7970456043491897], + [0.65543692326454717, 0.75309208756768431, 0.79550271129031047], + [0.64959573004253479, 0.74985201221941766, 0.79400674021499107], + [0.6437910831099849, 0.7465923800833657, 0.79255653201306053], + [0.63802586828545982, 0.74331376714033193, 0.79115100459573173], + [0.6323027138710603, 0.74001672160131404, 0.78978892762640429], + [0.62662402022604591, 0.73670175403699445, 0.78846901316334561], + [0.62099193064817548, 0.73336934798923203, 0.78718994624696581], + [0.61540846411770478, 0.73001995232739691, 0.78595022706750484], + [0.60987543176093062, 0.72665398759758293, 0.78474835732694714], + [0.60439434200274855, 0.7232718614323369, 0.78358295593535587], + [0.5989665814482068, 0.71987394892246725, 0.78245259899346642], + [0.59359335696837223, 0.7164606049658685, 0.78135588237640097], + [0.58827579780555495, 0.71303214646458135, 0.78029141405636515], + [0.58301487036932409, 0.70958887676997473, 0.77925781820476592], + [0.5778116438998202, 0.70613106157153982, 0.77825345121025524], + [0.5726668948158774, 0.7026589535425779, 0.77727702680911992], + [0.56758117853861967, 0.69917279302646274, 0.77632748534275298], + [0.56255515357219343, 0.69567278381629649, 0.77540359142309845], + [0.55758940419605174, 0.69215911458254054, 0.7745041337932782], + [0.55268450589347129, 0.68863194515166382, 0.7736279426902245], + [0.54784098153018634, 0.68509142218509878, 0.77277386473440868], + [0.54305932424018233, 0.68153767253065878, 0.77194079697835083], + [0.53834015575176275, 0.67797081129095405, 0.77112734439057717], + [0.53368389147728401, 0.67439093705212727, 0.7703325054879735], + [0.529090861832473, 0.67079812302806219, 0.76955552292313134], + [0.52456151470593582, 0.66719242996142225, 0.76879541714230948], + [0.52009627392235558, 0.66357391434030388, 0.76805119403344102], + [0.5156955988596057, 0.65994260812897998, 0.76732191489596169], + [0.51135992541601927, 0.65629853981831865, 0.76660663780645333], + [0.50708969576451657, 0.65264172403146448, 0.76590445660835849], + [0.5028853540415561, 0.64897216734095264, 0.76521446718174913], + [0.49874733661356069, 0.6452898684900934, 0.76453578734180083], + [0.4946761847863938, 0.64159484119504429, 0.76386719002130909], + [0.49067224938561221, 0.63788704858847078, 0.76320812763163837], + [0.4867359599430568, 0.63416646251100506, 0.76255780085924041], + [0.4828677867260272, 0.6304330455306234, 0.76191537149895305], + [0.47906816236197386, 0.62668676251860134, 0.76128000375662419], + [0.47533752394906287, 0.62292757283835809, 0.76065085571817748], + [0.47167629518877091, 0.61915543242884641, 0.76002709227883047], + [0.46808490970531597, 0.61537028695790286, 0.75940789891092741], + [0.46456376716303932, 0.61157208822864151, 0.75879242623025811], + [0.46111326647023881, 0.607760777169989, 0.75817986436807139], + [0.45773377230160567, 0.60393630046586455, 0.75756936901859162], + [0.45442563977552913, 0.60009859503858665, 0.75696013660606487], + [0.45118918687617743, 0.59624762051353541, 0.75635120643246645], + [0.44802470933589172, 0.59238331452146575, 0.75574176474107924], + [0.44493246854215379, 0.5885055998308617, 0.7551311041857901], + [0.44191271766696399, 0.58461441100175571, 0.75451838884410671], + [0.43896563958048396, 0.58070969241098491, 0.75390276208285945], + [0.43609138958356369, 0.57679137998186081, 0.7532834105961016], + [0.43329008867358393, 0.57285941625606673, 0.75265946532566674], + [0.43056179073057571, 0.56891374572457176, 0.75203008099312696], + [0.42790652284925834, 0.5649543060909209, 0.75139443521914839], + [0.42532423665011354, 0.56098104959950301, 0.75075164989005116], + [0.42281485675772662, 0.55699392126996583, 0.75010086988227642], + [0.42037822361396326, 0.55299287158108168, 0.7494412559451894], + [0.41801414079233629, 0.54897785421888889, 0.74877193167001121], + [0.4157223260454232, 0.54494882715350401, 0.74809204459000522], + [0.41350245743314729, 0.54090574771098476, 0.74740073297543086], + [0.41135414697304568, 0.53684857765005933, 0.74669712855065784], + [0.4092768899914751, 0.53277730177130322, 0.74598030635707824], + [0.40727018694219069, 0.52869188011057411, 0.74524942637581271], + [0.40533343789303178, 0.52459228174983119, 0.74450365836708132], + [0.40346600333905397, 0.52047847653840029, 0.74374215223567086], + [0.40166714010896104, 0.51635044969688759, 0.7429640345324835], + [0.39993606933454834, 0.51220818143218516, 0.74216844571317986], + [0.3982719152586337, 0.50805166539276136, 0.74135450918099721], + [0.39667374905665609, 0.50388089053847973, 0.74052138580516735], + [0.39514058808207631, 0.49969585326377758, 0.73966820211715711], + [0.39367135736822567, 0.49549655777451179, 0.738794102296364], + [0.39226494876209317, 0.49128300332899261, 0.73789824784475078], + [0.39092017571994903, 0.48705520251223039, 0.73697977133881254], + [0.38963580160340855, 0.48281316715123496, 0.73603782546932739], + [0.38841053300842432, 0.47855691131792805, 0.73507157641157261], + [0.38724301459330251, 0.47428645933635388, 0.73408016787854391], + [0.38613184178892102, 0.4700018340988123, 0.7330627749243106], + [0.38507556793651387, 0.46570306719930193, 0.73201854033690505], + [0.38407269378943537, 0.46139018782416635, 0.73094665432902683], + [0.38312168084402748, 0.45706323581407199, 0.72984626791353258], + [0.38222094988570376, 0.45272225034283325, 0.72871656144003782], + [0.38136887930454161, 0.44836727669277859, 0.72755671317141346], + [0.38056380696565623, 0.44399837208633719, 0.72636587045135315], + [0.37980403744848751, 0.43961558821222629, 0.72514323778761092], + [0.37908789283110761, 0.43521897612544935, 0.72388798691323131], + [0.378413635091359, 0.43080859411413064, 0.72259931993061044], + [0.37777949753513729, 0.4263845142616835, 0.72127639993530235], + [0.37718371844251231, 0.42194680223454828, 0.71991841524475775], + [0.37662448930806297, 0.41749553747893614, 0.71852454736176108], + [0.37610001286385814, 0.41303079952477062, 0.71709396919920232], + [0.37560846919442398, 0.40855267638072096, 0.71562585091587549], + [0.37514802505380473, 0.4040612609993941, 0.7141193695725726], + [0.37471686019302231, 0.3995566498711684, 0.71257368516500463], + [0.37431313199312338, 0.39503894828283309, 0.71098796522377461], + [0.37393499330475782, 0.39050827529375831, 0.70936134293478448], + [0.3735806215098284, 0.38596474386057539, 0.70769297607310577], + [0.37324816143326384, 0.38140848555753937, 0.70598200974806036], + [0.37293578646665032, 0.37683963835219841, 0.70422755780589941], + [0.37264166757849604, 0.37225835004836849, 0.7024287314570723], + [0.37236397858465387, 0.36766477862108266, 0.70058463496520773], + [0.37210089702443822, 0.36305909736982378, 0.69869434615073722], + [0.3718506155898596, 0.35844148285875221, 0.69675695810256544], + [0.37161133234400479, 0.3538121372967869, 0.69477149919380887], + [0.37138124223736607, 0.34917126878479027, 0.69273703471928827], + [0.37115856636209105, 0.34451911410230168, 0.69065253586464992], + [0.37094151551337329, 0.33985591488818123, 0.68851703379505125], + [0.37072833279422668, 0.33518193808489577, 0.68632948169606767], + [0.37051738634484427, 0.33049741244307851, 0.68408888788857214], + [0.37030682071842685, 0.32580269697872455, 0.68179411684486679], + [0.37009487130772695, 0.3210981375964933, 0.67944405399056851], + [0.36987980329025361, 0.31638410101153364, 0.67703755438090574], + [0.36965987626565955, 0.31166098762951971, 0.67457344743419545], + [0.36943334591276228, 0.30692923551862339, 0.67205052849120617], + [0.36919847837592484, 0.30218932176507068, 0.66946754331614522], + [0.36895355306596778, 0.29744175492366276, 0.66682322089824264], + [0.36869682231895268, 0.29268709856150099, 0.66411625298236909], + [0.36842655638020444, 0.28792596437778462, 0.66134526910944602], + [0.36814101479899719, 0.28315901221182987, 0.65850888806972308], + [0.36783843696531082, 0.27838697181297761, 0.65560566838453704], + [0.36751707094367697, 0.27361063317090978, 0.65263411711618635], + [0.36717513650699446, 0.26883085667326956, 0.64959272297892245], + [0.36681085540107988, 0.26404857724525643, 0.64647991652908243], + [0.36642243251550632, 0.25926481158628106, 0.64329409140765537], + [0.36600853966739794, 0.25448043878086224, 0.64003361803368586], + [0.36556698373538982, 0.24969683475296395, 0.63669675187488584], + [0.36509579845886808, 0.24491536803550484, 0.63328173520055586], + [0.36459308890125008, 0.24013747024823828, 0.62978680155026101], + [0.36405693022088509, 0.23536470386204195, 0.62621013451953023], + [0.36348537610385145, 0.23059876218396419, 0.62254988622392882], + [0.36287643560041027, 0.22584149293287031, 0.61880417410823019], + [0.36222809558295926, 0.22109488427338303, 0.61497112346096128], + [0.36153829010998356, 0.21636111429594002, 0.61104880679640927], + [0.36080493826624654, 0.21164251793458128, 0.60703532172064711], + [0.36002681809096376, 0.20694122817889948, 0.60292845431916875], + [0.35920088560930186, 0.20226037920758122, 0.5987265295935138], + [0.35832489966617809, 0.197602942459778, 0.59442768517501066], + [0.35739663292915563, 0.19297208197842461, 0.59003011251063131], + [0.35641381143126327, 0.18837119869242164, 0.5855320765920552], + [0.35537415306906722, 0.18380392577704466, 0.58093191431832802], + [0.35427534960663759, 0.17927413271618647, 0.57622809660668717], + [0.35311574421123737, 0.17478570377561287, 0.57141871523555288], + [0.35189248608873791, 0.17034320478524959, 0.56650284911216653], + [0.35060304441931012, 0.16595129984720861, 0.56147964703993225], + [0.34924513554955644, 0.16161477763045118, 0.55634837474163779], + [0.34781653238777782, 0.15733863511152979, 0.55110853452703257], + [0.34631507175793091, 0.15312802296627787, 0.5457599924248665], + [0.34473901574536375, 0.14898820589826409, 0.54030245920406539], + [0.34308600291572294, 0.14492465359918028, 0.53473704282067103], + [0.34135411074506483, 0.1409427920655632, 0.52906500940336754], + [0.33954168752669694, 0.13704801896718169, 0.52328797535085236], + [0.33764732090671112, 0.13324562282438077, 0.51740807573979475], + [0.33566978565015315, 0.12954074251271822, 0.51142807215168951], + [0.33360804901486002, 0.12593818301005921, 0.50535164796654897], + [0.33146154891145124, 0.12244245263391232, 0.49918274588431072], + [0.32923005203231409, 0.11905764321981127, 0.49292595612342666], + [0.3269137124539796, 0.1157873496841953, 0.48658646495697461], + [0.32451307931207785, 0.11263459791730848, 0.48017007211645196], + [0.32202882276069322, 0.10960114111258401, 0.47368494725726878], + [0.31946262395497965, 0.10668879882392659, 0.46713728801395243], + [0.31681648089023501, 0.10389861387653518, 0.46053414662739794], + [0.31409278414755532, 0.10123077676403242, 0.45388335612058467], + [0.31129434479712365, 0.098684771934052201, 0.44719313715161618], + [0.30842444457210105, 0.096259385340577736, 0.44047194882050544], + [0.30548675819945936, 0.093952764840823738, 0.43372849999361113], + [0.30248536364574252, 0.091761187397303601, 0.42697404043749887], + [0.29942483960214772, 0.089682253716750038, 0.42021619665853854], + [0.29631000388905288, 0.087713250960463951, 0.41346259134143476], + [0.29314593096985248, 0.085850656889620708, 0.40672178082365834], + [0.28993792445176608, 0.08409078829085731, 0.40000214725256295], + [0.28669151388283165, 0.082429873848480689, 0.39331182532243375], + [0.28341239797185225, 0.080864153365499375, 0.38665868550105914], + [0.28010638576975472, 0.079389994802261526, 0.38005028528138707], + [0.27677939615815589, 0.078003941033788216, 0.37349382846504675], + [0.27343739342450812, 0.076702800237496066, 0.36699616136347685], + [0.27008637749114051, 0.075483675584275545, 0.36056376228111864], + [0.26673233211995284, 0.074344018028546205, 0.35420276066240958], + [0.26338121807151404, 0.073281657939897077, 0.34791888996380105], + [0.26003895187439957, 0.072294781043362205, 0.3417175669546984], + [0.25671191651083902, 0.071380106242082242, 0.33560648984600089], + [0.25340685873736807, 0.070533582926851829, 0.3295945757321303], + [0.25012845306199383, 0.069758206429106989, 0.32368100685760637], + [0.24688226237958999, 0.069053639449204451, 0.31786993834254956], + [0.24367372557466271, 0.068419855150922693, 0.31216524050888372], + [0.24050813332295939, 0.067857103814855602, 0.30657054493678321], + [0.23739062429054825, 0.067365888050555517, 0.30108922184065873], + [0.23433055727563878, 0.066935599661639394, 0.29574009929867601], + [0.23132955273021344, 0.066576186939090592, 0.29051361067988485], + [0.2283917709422868, 0.06628997924139618, 0.28541074411068496], + [0.22552164337737857, 0.066078173119395595, 0.28043398847505197], + [0.22272706739121817, 0.065933790675651943, 0.27559714652053702], + [0.22001251100779617, 0.065857918918907604, 0.27090279994325861], + [0.21737845072382705, 0.065859661233562045, 0.26634209349669508], + [0.21482843531473683, 0.065940385613778491, 0.26191675992376573], + [0.21237411048541005, 0.066085024661758446, 0.25765165093569542], + [0.21001214221188125, 0.066308573918947178, 0.2535289048041211], + [0.2077442377448806, 0.06661453200418091, 0.24954644291943817], + [0.20558051999470117, 0.066990462397868739, 0.24572497420147632], + [0.20352007949514977, 0.067444179612424215, 0.24205576625191821], + [0.20156133764129841, 0.067983271026200248, 0.23852974228695395], + [0.19971571438603364, 0.068592710553704722, 0.23517094067076993], + [0.19794834061899208, 0.069314066071660657, 0.23194647381302336], + [0.1960826032659409, 0.070321227242423623, 0.22874673279569585], + [0.19410351363791453, 0.071608304856891569, 0.22558727307410353], + [0.19199449184606268, 0.073182830649273306, 0.22243385243433622], + [0.18975853639094634, 0.075019861862143766, 0.2193005075652994], + [0.18739228342697645, 0.077102096899588329, 0.21618875376309582], + [0.18488035509396164, 0.079425730279723883, 0.21307651648984993], + [0.18774482037046955, 0.077251588468039312, 0.21387448578597812], + [0.19049578401722037, 0.075311278416787641, 0.2146562337112265], + [0.1931548636579131, 0.073606819040117955, 0.21542362939081539], + [0.19571853588267552, 0.072157781039602742, 0.21617499187076789], + [0.19819343656336558, 0.070974625252738788, 0.21690975060032436], + [0.20058760685133747, 0.070064576149984209, 0.21762721310371608], + [0.20290365333558247, 0.069435248580458964, 0.21833167885096033], + [0.20531725273301316, 0.068919592266397572, 0.21911516689288835], + [0.20785704662965598, 0.068484398797025281, 0.22000133917653536], + [0.21052882914958676, 0.06812195249816172, 0.22098759107715404], + [0.2133313859647627, 0.067830148426026665, 0.22207043213024291], + [0.21625279838647882, 0.067616330270516389, 0.22324568672294431], + [0.21930503925136402, 0.067465786362940039, 0.22451023616807558], + [0.22247308588973624, 0.067388214053092838, 0.22585960379408354], + [0.2257539681670791, 0.067382132300147474, 0.22728984778098055], + [0.22915620278592841, 0.067434730871152565, 0.22879681433956656], + [0.23266299920501882, 0.067557104388479783, 0.23037617493752832], + [0.23627495835774248, 0.06774359820987802, 0.23202360805926608], + [0.23999586188690308, 0.067985029964779953, 0.23373434258507808], + [0.24381149720247919, 0.068289851529011875, 0.23550427698321885], + [0.24772092990501099, 0.068653337909486523, 0.2373288009471749], + [0.25172899728289466, 0.069064630826035506, 0.23920260612763083], + [0.25582135547481771, 0.06953231029187984, 0.24112190491594204], + [0.25999463887892144, 0.070053855603861875, 0.24308218808684579], + [0.26425512207060942, 0.070616595622995437, 0.24507758869355967], + [0.26859095948172862, 0.071226716277922458, 0.24710443563450618], + [0.27299701518897301, 0.071883555446163511, 0.24915847093232929], + [0.27747150809142801, 0.072582969899254779, 0.25123493995942769], + [0.28201746297366942, 0.073315693214040967, 0.25332800295084507], + [0.28662309235899847, 0.074088460826808866, 0.25543478673717029], + [0.29128515387578635, 0.074899049847466703, 0.25755101595750435], + [0.2960004726065818, 0.075745336000958424, 0.25967245030364566], + [0.30077276812918691, 0.076617824336164764, 0.26179294097819672], + [0.30559226007249934, 0.077521963107537312, 0.26391006692119662], + [0.31045520848595526, 0.078456871676182177, 0.2660200572779356], + [0.31535870009205808, 0.079420997315243186, 0.26811904076941961], + [0.32029986557994061, 0.080412994737554838, 0.27020322893039511], + [0.32527888860401261, 0.081428390076546092, 0.27226772884656186], + [0.33029174471181438, 0.08246763389003825, 0.27430929404579435], + [0.33533353224455448, 0.083532434119003962, 0.27632534356790039], + [0.34040164359597463, 0.084622236191702671, 0.27831254595259397], + [0.34549355713871799, 0.085736654965126335, 0.28026769921081435], + [0.35060678246032478, 0.08687555176033529, 0.28218770540182386], + [0.35573889947341125, 0.088038974350243354, 0.2840695897279818], + [0.36088752387578377, 0.089227194362745205, 0.28591050458531014], + [0.36605031412464006, 0.090440685427697898, 0.2877077458811747], + [0.37122508431309342, 0.091679997480262732, 0.28945865397633169], + [0.3764103053221462, 0.092945198093777909, 0.29116024157313919], + [0.38160247377467543, 0.094238731263712183, 0.29281107506269488], + [0.38679939079544168, 0.09556181960083443, 0.29440901248173756], + [0.39199887556812907, 0.09691583650296684, 0.29595212005509081], + [0.39719876876325577, 0.098302320968278623, 0.29743856476285779], + [0.40239692379737496, 0.099722930314950553, 0.29886674369733968], + [0.40759120392688708, 0.10117945586419633, 0.30023519507728602], + [0.41277985630360303, 0.1026734006932461, 0.30154226437468967], + [0.41796105205173684, 0.10420644885760968, 0.30278652039631843], + [0.42313214269556043, 0.10578120994917611, 0.3039675809469457], + [0.42829101315789753, 0.1073997763055258, 0.30508479060294547], + [0.4334355841041439, 0.1090642347484701, 0.30613767928289148], + [0.43856378187931538, 0.11077667828375456, 0.30712600062348083], + [0.44367358645071275, 0.11253912421257944, 0.30804973095465449], + [0.44876299173174822, 0.11435355574622549, 0.30890905921943196], + [0.45383005086999889, 0.11622183788331528, 0.30970441249844921], + [0.45887288947308297, 0.11814571137706886, 0.31043636979038808], + [0.46389102840284874, 0.12012561256850712, 0.31110343446582983], + [0.46888111384598413, 0.12216445576414045, 0.31170911458932665], + [0.473841437035254, 0.12426354237989065, 0.31225470169927194], + [0.47877034239726296, 0.12642401401409453, 0.31274172735821959], + [0.48366628618847957, 0.12864679022013889, 0.31317188565991266], + [0.48852847371852987, 0.13093210934893723, 0.31354553695453014], + [0.49335504375145617, 0.13328091630401023, 0.31386561956734976], + [0.49814435462074153, 0.13569380302451714, 0.314135190862664], + [0.50289524974970612, 0.13817086581280427, 0.31435662153833671], + [0.50760681181053691, 0.14071192654913128, 0.31453200120082569], + [0.51227835105321762, 0.14331656120063752, 0.3146630922831542], + [0.51690848800544464, 0.14598463068714407, 0.31475407592280041], + [0.52149652863229956, 0.14871544765633712, 0.31480767954534428], + [0.52604189625477482, 0.15150818660835483, 0.31482653406646727], + [0.53054420489856446, 0.15436183633886777, 0.31481299789187128], + [0.5350027976174474, 0.15727540775107324, 0.31477085207396532], + [0.53941736649199057, 0.16024769309971934, 0.31470295028655965], + [0.54378771313608565, 0.16327738551419116, 0.31461204226295625], + [0.54811370033467621, 0.1663630904279047, 0.31450102990914708], + [0.55239521572711914, 0.16950338809328983, 0.31437291554615371], + [0.55663229034969341, 0.17269677158182117, 0.31423043195101424], + [0.56082499039117173, 0.17594170887918095, 0.31407639883970623], + [0.56497343529017696, 0.17923664950367169, 0.3139136046337036], + [0.56907784784011428, 0.18258004462335425, 0.31374440956796529], + [0.57313845754107873, 0.18597036007065024, 0.31357126868520002], + [0.57715550812992045, 0.18940601489760422, 0.31339704333572083], + [0.58112932761586555, 0.19288548904692518, 0.31322399394183942], + [0.58506024396466882, 0.19640737049066315, 0.31305401163732732], + [0.58894861935544707, 0.19997020971775276, 0.31288922211590126], + [0.59279480536520257, 0.20357251410079796, 0.31273234839304942], + [0.59659918109122367, 0.207212956082026, 0.31258523031121233], + [0.60036213010411577, 0.21089030138947745, 0.31244934410414688], + [0.60408401696732739, 0.21460331490206347, 0.31232652641170694], + [0.60776523994818654, 0.21835070166659282, 0.31221903291870201], + [0.6114062072731884, 0.22213124697023234, 0.31212881396435238], + [0.61500723236391375, 0.22594402043981826, 0.31205680685765741], + [0.61856865258877192, 0.22978799249179921, 0.31200463838728931], + [0.62209079821082613, 0.2336621873300741, 0.31197383273627388], + [0.62557416500434959, 0.23756535071152696, 0.31196698314912269], + [0.62901892016985872, 0.24149689191922535, 0.31198447195645718], + [0.63242534854210275, 0.24545598775548677, 0.31202765974624452], + [0.6357937104834237, 0.24944185818822678, 0.31209793953300591], + [0.6391243387840212, 0.25345365461983138, 0.31219689612063978], + [0.642417577481186, 0.257490519876798, 0.31232631707560987], + [0.64567349382645434, 0.26155203161615281, 0.31248673753935263], + [0.64889230169458245, 0.26563755336209077, 0.31267941819570189], + [0.65207417290277303, 0.26974650525236699, 0.31290560605819168], + [0.65521932609327127, 0.27387826652410152, 0.3131666792687211], + [0.6583280801134499, 0.27803210957665631, 0.3134643447952643], + [0.66140037532601781, 0.28220778870555907, 0.31379912926498488], + [0.66443632469878844, 0.28640483614256179, 0.31417223403606975], + [0.66743603766369131, 0.29062280081258873, 0.31458483752056837], + [0.67039959547676198, 0.29486126309253047, 0.31503813956872212], + [0.67332725564817331, 0.29911962764489264, 0.31553372323982209], + [0.67621897924409746, 0.30339762792450425, 0.3160724937230589], + [0.67907474028157344, 0.30769497879760166, 0.31665545668946665], + [0.68189457150944521, 0.31201133280550686, 0.31728380489244951], + [0.68467850942494535, 0.31634634821222207, 0.31795870784057567], + [0.68742656435169625, 0.32069970535138104, 0.31868137622277692], + [0.6901389321505248, 0.32507091815606004, 0.31945332332898302], + [0.69281544846764931, 0.32945984647042675, 0.3202754315314667], + [0.69545608346891119, 0.33386622163232865, 0.32114884306985791], + [0.6980608153581771, 0.33828976326048621, 0.32207478855218091], + [0.70062962477242097, 0.34273019305341756, 0.32305449047765694], + [0.70316249458814151, 0.34718723719597999, 0.32408913679491225], + [0.70565951122610093, 0.35166052978120937, 0.32518014084085567], + [0.70812059568420482, 0.35614985523380299, 0.32632861885644465], + [0.7105456546582587, 0.36065500290840113, 0.32753574162788762], + [0.71293466839773467, 0.36517570519856757, 0.3288027427038317], + [0.71528760614847287, 0.36971170225223449, 0.3301308728723546], + [0.71760444908133847, 0.37426272710686193, 0.33152138620958932], + [0.71988521490549851, 0.37882848839337313, 0.33297555200245399], + [0.7221299918421461, 0.38340864508963057, 0.33449469983585844], + [0.72433865647781592, 0.38800301593162145, 0.33607995965691828], + [0.72651122900227549, 0.3926113126792577, 0.3377325942005665], + [0.72864773856716547, 0.39723324476747235, 0.33945384341064017], + [0.73074820754845171, 0.401868526884681, 0.3412449533046818], + [0.73281270506268747, 0.4065168468778026, 0.34310715173410822], + [0.73484133598564938, 0.41117787004519513, 0.34504169470809071], + [0.73683422173585866, 0.41585125850290111, 0.34704978520758401], + [0.73879140024599266, 0.42053672992315327, 0.34913260148542435], + [0.74071301619506091, 0.4252339389526239, 0.35129130890802607], + [0.7425992159973317, 0.42994254036133867, 0.35352709245374592], + [0.74445018676570673, 0.43466217184617112, 0.35584108091122535], + [0.74626615789163442, 0.43939245044973502, 0.35823439142300639], + [0.74804739275559562, 0.44413297780351974, 0.36070813602540136], + [0.74979420547170472, 0.44888333481548809, 0.36326337558360278], + [0.75150685045891663, 0.45364314496866825, 0.36590112443835765], + [0.75318566369046569, 0.45841199172949604, 0.36862236642234769], + [0.75483105066959544, 0.46318942799460555, 0.3714280448394211], + [0.75644341577140706, 0.46797501437948458, 0.37431909037543515], + [0.75802325538455839, 0.4727682731566229, 0.37729635531096678], + [0.75957111105340058, 0.47756871222057079, 0.380360657784311], + [0.7610876378057071, 0.48237579130289127, 0.38351275723852291], + [0.76257333554052609, 0.48718906673415824, 0.38675335037837993], + [0.76402885609288662, 0.49200802533379656, 0.39008308392311997], + [0.76545492593330511, 0.49683212909727231, 0.39350254000115381], + [0.76685228950643891, 0.5016608471009063, 0.39701221751773474], + [0.76822176599735303, 0.50649362371287909, 0.40061257089416885], + [0.7695642334401418, 0.5113298901696085, 0.40430398069682483], + [0.77088091962302474, 0.51616892643469103, 0.40808667584648967], + [0.77217257229605551, 0.5210102658711383, 0.41196089987122869], + [0.77344021829889886, 0.52585332093451564, 0.41592679539764366], + [0.77468494746063199, 0.53069749384776732, 0.41998440356963762], + [0.77590790730685699, 0.53554217882461186, 0.42413367909988375], + [0.7771103295521099, 0.54038674910561235, 0.42837450371258479], + [0.77829345807633121, 0.54523059488426595, 0.432706647838971], + [0.77945862731506643, 0.55007308413977274, 0.43712979856444761], + [0.78060774749483774, 0.55491335744890613, 0.44164332426364639], + [0.78174180478981836, 0.55975098052594863, 0.44624687186865436], + [0.78286225264440912, 0.56458533111166875, 0.45093985823706345], + [0.78397060836414478, 0.56941578326710418, 0.45572154742892063], + [0.78506845019606841, 0.5742417003617839, 0.46059116206904965], + [0.78615737132332963, 0.5790624629815756, 0.46554778281918402], + [0.78723904108188347, 0.58387743744557208, 0.47059039582133383], + [0.78831514045623963, 0.58868600173562435, 0.47571791879076081], + [0.78938737766251943, 0.5934875421745599, 0.48092913815357724], + [0.79045776847727878, 0.59828134277062461, 0.48622257801969754], + [0.79152832843475607, 0.60306670593147205, 0.49159667021646397], + [0.79260034304237448, 0.60784322087037024, 0.49705020621532009], + [0.79367559698664958, 0.61261029334072192, 0.50258161291269432], + [0.79475585972654039, 0.61736734400220705, 0.50818921213102985], + [0.79584292379583765, 0.62211378808451145, 0.51387124091909786], + [0.79693854719951607, 0.62684905679296699, 0.5196258425240281], + [0.79804447815136637, 0.63157258225089552, 0.52545108144834785], + [0.7991624518501963, 0.63628379372029187, 0.53134495942561433], + [0.80029415389753977, 0.64098213306749863, 0.53730535185141037], + [0.80144124292560048, 0.64566703459218766, 0.5433300863249918], + [0.80260531146112946, 0.65033793748103852, 0.54941691584603647], + [0.80378792531077625, 0.65499426549472628, 0.55556350867083815], + [0.80499054790810298, 0.65963545027564163, 0.56176745110546977], + [0.80621460526927058, 0.66426089585282289, 0.56802629178649788], + [0.8074614045096935, 0.6688700095398864, 0.57433746373459582], + [0.80873219170089694, 0.67346216702194517, 0.58069834805576737], + [0.81002809466520687, 0.67803672673971815, 0.58710626908082753], + [0.81135014011763329, 0.68259301546243389, 0.59355848909050757], + [0.81269922039881493, 0.68713033714618876, 0.60005214820435104], + [0.81407611046993344, 0.69164794791482131, 0.6065843782630862], + [0.81548146627279483, 0.69614505508308089, 0.61315221209322646], + [0.81691575775055891, 0.70062083014783982, 0.61975260637257923], + [0.81837931164498223, 0.70507438189635097, 0.62638245478933297], + [0.81987230650455289, 0.70950474978787481, 0.63303857040067113], + [0.8213947205565636, 0.7139109141951604, 0.63971766697672761], + [0.82294635110428427, 0.71829177331290062, 0.6464164243818421], + [0.8245268129450285, 0.72264614312088882, 0.65313137915422603], + [0.82613549710580259, 0.72697275518238258, 0.65985900156216504], + [0.8277716072353446, 0.73127023324078089, 0.66659570204682972], + [0.82943407816481474, 0.7355371221572935, 0.67333772009301907], + [0.83112163529096306, 0.73977184647638616, 0.68008125203631464], + [0.83283277185777982, 0.74397271817459876, 0.68682235874648545], + [0.8345656905566583, 0.7481379479992134, 0.69355697649863846], + [0.83631898844737929, 0.75226548952875261, 0.70027999028864962], + [0.83809123476131964, 0.75635314860808633, 0.70698561390212977], + [0.83987839884120874, 0.76039907199779677, 0.71367147811129228], + [0.84167750766845151, 0.76440101200982946, 0.72033299387284622], + [0.84348529222933699, 0.76835660399870176, 0.72696536998972039], + [0.84529810731955113, 0.77226338601044719, 0.73356368240541492], + [0.84711195507965098, 0.77611880236047159, 0.74012275762807056], + [0.84892245563117641, 0.77992021407650147, 0.74663719293664366], + [0.85072697023178789, 0.78366457342383888, 0.7530974636118285], + [0.85251907207708444, 0.78734936133548439, 0.7594994148789691], + [0.85429219611470464, 0.79097196777091994, 0.76583801477914104], + [0.85604022314725403, 0.79452963601550608, 0.77210610037674143], + [0.85775662943504905, 0.79801963142713928, 0.77829571667247499], + [0.8594346370300241, 0.8014392309950078, 0.78439788751383921], + [0.86107117027565516, 0.80478517909812231, 0.79039529663736285], + [0.86265601051127572, 0.80805523804261525, 0.796282666437655], + [0.86418343723941027, 0.81124644224653542, 0.80204612696863953], + [0.86564934325605325, 0.81435544067514909, 0.80766972324164554], + [0.86705314907048503, 0.81737804041911244, 0.81313419626911398], + [0.86839954695818633, 0.82030875512181523, 0.81841638963128993], + [0.86969131502613806, 0.82314158859569164, 0.82350476683173168], + [0.87093846717297507, 0.82586857889438514, 0.82838497261149613], + [0.87215331978454325, 0.82848052823709672, 0.8330486712880828], + [0.87335171360916275, 0.83096715251272624, 0.83748851001197089], + [0.87453793320260187, 0.83331972948645461, 0.84171925358069011], + [0.87571458709961403, 0.8355302318472394, 0.84575537519027078], + [0.87687848451614692, 0.83759238071186537, 0.84961373549150254], + [0.87802298436649007, 0.83950165618540074, 0.85330645352458923], + [0.87913244240792765, 0.84125554884475906, 0.85685572291039636], + [0.88019293315695812, 0.84285224824778615, 0.86027399927156634], + [0.88119169871341951, 0.84429066717717349, 0.86356595168669881], + [0.88211542489401606, 0.84557007254559347, 0.86673765046233331], + [0.88295168595448525, 0.84668970275699273, 0.86979617048190971], + [0.88369127145898041, 0.84764891761519268, 0.87274147101441557], + [0.88432713054113543, 0.84844741572055415, 0.87556785228242973], + [0.88485138159908572, 0.84908426422893801, 0.87828235285372469], + [0.88525897972630474, 0.84955892810989209, 0.88088414794024839], + [0.88554714811952384, 0.84987174283631584, 0.88336206121170946], + [0.88571155122845646, 0.85002186115856315, 0.88572538990087124]] + +_twilight_shifted_data = (_twilight_data[len(_twilight_data)//2:] + + _twilight_data[:len(_twilight_data)//2]) +_twilight_shifted_data.reverse() + +cmaps = {} +for (name, data) in (('magma', _magma_data), + ('inferno', _inferno_data), + ('plasma', _plasma_data), + ('viridis', _viridis_data), + ('cividis', _cividis_data), + ('twilight', _twilight_data), + ('twilight_shifted', _twilight_shifted_data)): + + cmaps[name] = ListedColormap(data, name=name) + # generate reversed colormap + name = name + '_r' + cmaps[name] = ListedColormap(list(reversed(data)), name=name) diff --git a/venv/lib/python3.6/site-packages/matplotlib/_color_data.py b/venv/lib/python3.6/site-packages/matplotlib/_color_data.py new file mode 100644 index 0000000..32420fe --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_color_data.py @@ -0,0 +1,1144 @@ +from collections import OrderedDict + + +BASE_COLORS = { + 'b': (0, 0, 1), + 'g': (0, 0.5, 0), + 'r': (1, 0, 0), + 'c': (0, 0.75, 0.75), + 'm': (0.75, 0, 0.75), + 'y': (0.75, 0.75, 0), + 'k': (0, 0, 0), + 'w': (1, 1, 1)} + + +# These colors are from Tableau +TABLEAU_COLORS = ( + ('blue', '#1f77b4'), + ('orange', '#ff7f0e'), + ('green', '#2ca02c'), + ('red', '#d62728'), + ('purple', '#9467bd'), + ('brown', '#8c564b'), + ('pink', '#e377c2'), + ('gray', '#7f7f7f'), + ('olive', '#bcbd22'), + ('cyan', '#17becf'), +) + +# Normalize name to "tab:" to avoid name collisions. +TABLEAU_COLORS = OrderedDict( + ('tab:' + name, value) for name, value in TABLEAU_COLORS) + +# This mapping of color names -> hex values is taken from +# a survey run by Randall Munroe see: +# http://blog.xkcd.com/2010/05/03/color-survey-results/ +# for more details. The results are hosted at +# https://xkcd.com/color/rgb.txt +# +# License: http://creativecommons.org/publicdomain/zero/1.0/ +XKCD_COLORS = { + 'cloudy blue': '#acc2d9', + 'dark pastel green': '#56ae57', + 'dust': '#b2996e', + 'electric lime': '#a8ff04', + 'fresh green': '#69d84f', + 'light eggplant': '#894585', + 'nasty green': '#70b23f', + 'really light blue': '#d4ffff', + 'tea': '#65ab7c', + 'warm purple': '#952e8f', + 'yellowish tan': '#fcfc81', + 'cement': '#a5a391', + 'dark grass green': '#388004', + 'dusty teal': '#4c9085', + 'grey teal': '#5e9b8a', + 'macaroni and cheese': '#efb435', + 'pinkish tan': '#d99b82', + 'spruce': '#0a5f38', + 'strong blue': '#0c06f7', + 'toxic green': '#61de2a', + 'windows blue': '#3778bf', + 'blue blue': '#2242c7', + 'blue with a hint of purple': '#533cc6', + 'booger': '#9bb53c', + 'bright sea green': '#05ffa6', + 'dark green blue': '#1f6357', + 'deep turquoise': '#017374', + 'green teal': '#0cb577', + 'strong pink': '#ff0789', + 'bland': '#afa88b', + 'deep aqua': '#08787f', + 'lavender pink': '#dd85d7', + 'light moss green': '#a6c875', + 'light seafoam green': '#a7ffb5', + 'olive yellow': '#c2b709', + 'pig pink': '#e78ea5', + 'deep lilac': '#966ebd', + 'desert': '#ccad60', + 'dusty lavender': '#ac86a8', + 'purpley grey': '#947e94', + 'purply': '#983fb2', + 'candy pink': '#ff63e9', + 'light pastel green': '#b2fba5', + 'boring green': '#63b365', + 'kiwi green': '#8ee53f', + 'light grey green': '#b7e1a1', + 'orange pink': '#ff6f52', + 'tea green': '#bdf8a3', + 'very light brown': '#d3b683', + 'egg shell': '#fffcc4', + 'eggplant purple': '#430541', + 'powder pink': '#ffb2d0', + 'reddish grey': '#997570', + 'baby shit brown': '#ad900d', + 'liliac': '#c48efd', + 'stormy blue': '#507b9c', + 'ugly brown': '#7d7103', + 'custard': '#fffd78', + 'darkish pink': '#da467d', + 'deep brown': '#410200', + 'greenish beige': '#c9d179', + 'manilla': '#fffa86', + 'off blue': '#5684ae', + 'battleship grey': '#6b7c85', + 'browny green': '#6f6c0a', + 'bruise': '#7e4071', + 'kelley green': '#009337', + 'sickly yellow': '#d0e429', + 'sunny yellow': '#fff917', + 'azul': '#1d5dec', + 'darkgreen': '#054907', + 'green/yellow': '#b5ce08', + 'lichen': '#8fb67b', + 'light light green': '#c8ffb0', + 'pale gold': '#fdde6c', + 'sun yellow': '#ffdf22', + 'tan green': '#a9be70', + 'burple': '#6832e3', + 'butterscotch': '#fdb147', + 'toupe': '#c7ac7d', + 'dark cream': '#fff39a', + 'indian red': '#850e04', + 'light lavendar': '#efc0fe', + 'poison green': '#40fd14', + 'baby puke green': '#b6c406', + 'bright yellow green': '#9dff00', + 'charcoal grey': '#3c4142', + 'squash': '#f2ab15', + 'cinnamon': '#ac4f06', + 'light pea green': '#c4fe82', + 'radioactive green': '#2cfa1f', + 'raw sienna': '#9a6200', + 'baby purple': '#ca9bf7', + 'cocoa': '#875f42', + 'light royal blue': '#3a2efe', + 'orangeish': '#fd8d49', + 'rust brown': '#8b3103', + 'sand brown': '#cba560', + 'swamp': '#698339', + 'tealish green': '#0cdc73', + 'burnt siena': '#b75203', + 'camo': '#7f8f4e', + 'dusk blue': '#26538d', + 'fern': '#63a950', + 'old rose': '#c87f89', + 'pale light green': '#b1fc99', + 'peachy pink': '#ff9a8a', + 'rosy pink': '#f6688e', + 'light bluish green': '#76fda8', + 'light bright green': '#53fe5c', + 'light neon green': '#4efd54', + 'light seafoam': '#a0febf', + 'tiffany blue': '#7bf2da', + 'washed out green': '#bcf5a6', + 'browny orange': '#ca6b02', + 'nice blue': '#107ab0', + 'sapphire': '#2138ab', + 'greyish teal': '#719f91', + 'orangey yellow': '#fdb915', + 'parchment': '#fefcaf', + 'straw': '#fcf679', + 'very dark brown': '#1d0200', + 'terracota': '#cb6843', + 'ugly blue': '#31668a', + 'clear blue': '#247afd', + 'creme': '#ffffb6', + 'foam green': '#90fda9', + 'grey/green': '#86a17d', + 'light gold': '#fddc5c', + 'seafoam blue': '#78d1b6', + 'topaz': '#13bbaf', + 'violet pink': '#fb5ffc', + 'wintergreen': '#20f986', + 'yellow tan': '#ffe36e', + 'dark fuchsia': '#9d0759', + 'indigo blue': '#3a18b1', + 'light yellowish green': '#c2ff89', + 'pale magenta': '#d767ad', + 'rich purple': '#720058', + 'sunflower yellow': '#ffda03', + 'green/blue': '#01c08d', + 'leather': '#ac7434', + 'racing green': '#014600', + 'vivid purple': '#9900fa', + 'dark royal blue': '#02066f', + 'hazel': '#8e7618', + 'muted pink': '#d1768f', + 'booger green': '#96b403', + 'canary': '#fdff63', + 'cool grey': '#95a3a6', + 'dark taupe': '#7f684e', + 'darkish purple': '#751973', + 'true green': '#089404', + 'coral pink': '#ff6163', + 'dark sage': '#598556', + 'dark slate blue': '#214761', + 'flat blue': '#3c73a8', + 'mushroom': '#ba9e88', + 'rich blue': '#021bf9', + 'dirty purple': '#734a65', + 'greenblue': '#23c48b', + 'icky green': '#8fae22', + 'light khaki': '#e6f2a2', + 'warm blue': '#4b57db', + 'dark hot pink': '#d90166', + 'deep sea blue': '#015482', + 'carmine': '#9d0216', + 'dark yellow green': '#728f02', + 'pale peach': '#ffe5ad', + 'plum purple': '#4e0550', + 'golden rod': '#f9bc08', + 'neon red': '#ff073a', + 'old pink': '#c77986', + 'very pale blue': '#d6fffe', + 'blood orange': '#fe4b03', + 'grapefruit': '#fd5956', + 'sand yellow': '#fce166', + 'clay brown': '#b2713d', + 'dark blue grey': '#1f3b4d', + 'flat green': '#699d4c', + 'light green blue': '#56fca2', + 'warm pink': '#fb5581', + 'dodger blue': '#3e82fc', + 'gross green': '#a0bf16', + 'ice': '#d6fffa', + 'metallic blue': '#4f738e', + 'pale salmon': '#ffb19a', + 'sap green': '#5c8b15', + 'algae': '#54ac68', + 'bluey grey': '#89a0b0', + 'greeny grey': '#7ea07a', + 'highlighter green': '#1bfc06', + 'light light blue': '#cafffb', + 'light mint': '#b6ffbb', + 'raw umber': '#a75e09', + 'vivid blue': '#152eff', + 'deep lavender': '#8d5eb7', + 'dull teal': '#5f9e8f', + 'light greenish blue': '#63f7b4', + 'mud green': '#606602', + 'pinky': '#fc86aa', + 'red wine': '#8c0034', + 'shit green': '#758000', + 'tan brown': '#ab7e4c', + 'darkblue': '#030764', + 'rosa': '#fe86a4', + 'lipstick': '#d5174e', + 'pale mauve': '#fed0fc', + 'claret': '#680018', + 'dandelion': '#fedf08', + 'orangered': '#fe420f', + 'poop green': '#6f7c00', + 'ruby': '#ca0147', + 'dark': '#1b2431', + 'greenish turquoise': '#00fbb0', + 'pastel red': '#db5856', + 'piss yellow': '#ddd618', + 'bright cyan': '#41fdfe', + 'dark coral': '#cf524e', + 'algae green': '#21c36f', + 'darkish red': '#a90308', + 'reddy brown': '#6e1005', + 'blush pink': '#fe828c', + 'camouflage green': '#4b6113', + 'lawn green': '#4da409', + 'putty': '#beae8a', + 'vibrant blue': '#0339f8', + 'dark sand': '#a88f59', + 'purple/blue': '#5d21d0', + 'saffron': '#feb209', + 'twilight': '#4e518b', + 'warm brown': '#964e02', + 'bluegrey': '#85a3b2', + 'bubble gum pink': '#ff69af', + 'duck egg blue': '#c3fbf4', + 'greenish cyan': '#2afeb7', + 'petrol': '#005f6a', + 'royal': '#0c1793', + 'butter': '#ffff81', + 'dusty orange': '#f0833a', + 'off yellow': '#f1f33f', + 'pale olive green': '#b1d27b', + 'orangish': '#fc824a', + 'leaf': '#71aa34', + 'light blue grey': '#b7c9e2', + 'dried blood': '#4b0101', + 'lightish purple': '#a552e6', + 'rusty red': '#af2f0d', + 'lavender blue': '#8b88f8', + 'light grass green': '#9af764', + 'light mint green': '#a6fbb2', + 'sunflower': '#ffc512', + 'velvet': '#750851', + 'brick orange': '#c14a09', + 'lightish red': '#fe2f4a', + 'pure blue': '#0203e2', + 'twilight blue': '#0a437a', + 'violet red': '#a50055', + 'yellowy brown': '#ae8b0c', + 'carnation': '#fd798f', + 'muddy yellow': '#bfac05', + 'dark seafoam green': '#3eaf76', + 'deep rose': '#c74767', + 'dusty red': '#b9484e', + 'grey/blue': '#647d8e', + 'lemon lime': '#bffe28', + 'purple/pink': '#d725de', + 'brown yellow': '#b29705', + 'purple brown': '#673a3f', + 'wisteria': '#a87dc2', + 'banana yellow': '#fafe4b', + 'lipstick red': '#c0022f', + 'water blue': '#0e87cc', + 'brown grey': '#8d8468', + 'vibrant purple': '#ad03de', + 'baby green': '#8cff9e', + 'barf green': '#94ac02', + 'eggshell blue': '#c4fff7', + 'sandy yellow': '#fdee73', + 'cool green': '#33b864', + 'pale': '#fff9d0', + 'blue/grey': '#758da3', + 'hot magenta': '#f504c9', + 'greyblue': '#77a1b5', + 'purpley': '#8756e4', + 'baby shit green': '#889717', + 'brownish pink': '#c27e79', + 'dark aquamarine': '#017371', + 'diarrhea': '#9f8303', + 'light mustard': '#f7d560', + 'pale sky blue': '#bdf6fe', + 'turtle green': '#75b84f', + 'bright olive': '#9cbb04', + 'dark grey blue': '#29465b', + 'greeny brown': '#696006', + 'lemon green': '#adf802', + 'light periwinkle': '#c1c6fc', + 'seaweed green': '#35ad6b', + 'sunshine yellow': '#fffd37', + 'ugly purple': '#a442a0', + 'medium pink': '#f36196', + 'puke brown': '#947706', + 'very light pink': '#fff4f2', + 'viridian': '#1e9167', + 'bile': '#b5c306', + 'faded yellow': '#feff7f', + 'very pale green': '#cffdbc', + 'vibrant green': '#0add08', + 'bright lime': '#87fd05', + 'spearmint': '#1ef876', + 'light aquamarine': '#7bfdc7', + 'light sage': '#bcecac', + 'yellowgreen': '#bbf90f', + 'baby poo': '#ab9004', + 'dark seafoam': '#1fb57a', + 'deep teal': '#00555a', + 'heather': '#a484ac', + 'rust orange': '#c45508', + 'dirty blue': '#3f829d', + 'fern green': '#548d44', + 'bright lilac': '#c95efb', + 'weird green': '#3ae57f', + 'peacock blue': '#016795', + 'avocado green': '#87a922', + 'faded orange': '#f0944d', + 'grape purple': '#5d1451', + 'hot green': '#25ff29', + 'lime yellow': '#d0fe1d', + 'mango': '#ffa62b', + 'shamrock': '#01b44c', + 'bubblegum': '#ff6cb5', + 'purplish brown': '#6b4247', + 'vomit yellow': '#c7c10c', + 'pale cyan': '#b7fffa', + 'key lime': '#aeff6e', + 'tomato red': '#ec2d01', + 'lightgreen': '#76ff7b', + 'merlot': '#730039', + 'night blue': '#040348', + 'purpleish pink': '#df4ec8', + 'apple': '#6ecb3c', + 'baby poop green': '#8f9805', + 'green apple': '#5edc1f', + 'heliotrope': '#d94ff5', + 'yellow/green': '#c8fd3d', + 'almost black': '#070d0d', + 'cool blue': '#4984b8', + 'leafy green': '#51b73b', + 'mustard brown': '#ac7e04', + 'dusk': '#4e5481', + 'dull brown': '#876e4b', + 'frog green': '#58bc08', + 'vivid green': '#2fef10', + 'bright light green': '#2dfe54', + 'fluro green': '#0aff02', + 'kiwi': '#9cef43', + 'seaweed': '#18d17b', + 'navy green': '#35530a', + 'ultramarine blue': '#1805db', + 'iris': '#6258c4', + 'pastel orange': '#ff964f', + 'yellowish orange': '#ffab0f', + 'perrywinkle': '#8f8ce7', + 'tealish': '#24bca8', + 'dark plum': '#3f012c', + 'pear': '#cbf85f', + 'pinkish orange': '#ff724c', + 'midnight purple': '#280137', + 'light urple': '#b36ff6', + 'dark mint': '#48c072', + 'greenish tan': '#bccb7a', + 'light burgundy': '#a8415b', + 'turquoise blue': '#06b1c4', + 'ugly pink': '#cd7584', + 'sandy': '#f1da7a', + 'electric pink': '#ff0490', + 'muted purple': '#805b87', + 'mid green': '#50a747', + 'greyish': '#a8a495', + 'neon yellow': '#cfff04', + 'banana': '#ffff7e', + 'carnation pink': '#ff7fa7', + 'tomato': '#ef4026', + 'sea': '#3c9992', + 'muddy brown': '#886806', + 'turquoise green': '#04f489', + 'buff': '#fef69e', + 'fawn': '#cfaf7b', + 'muted blue': '#3b719f', + 'pale rose': '#fdc1c5', + 'dark mint green': '#20c073', + 'amethyst': '#9b5fc0', + 'blue/green': '#0f9b8e', + 'chestnut': '#742802', + 'sick green': '#9db92c', + 'pea': '#a4bf20', + 'rusty orange': '#cd5909', + 'stone': '#ada587', + 'rose red': '#be013c', + 'pale aqua': '#b8ffeb', + 'deep orange': '#dc4d01', + 'earth': '#a2653e', + 'mossy green': '#638b27', + 'grassy green': '#419c03', + 'pale lime green': '#b1ff65', + 'light grey blue': '#9dbcd4', + 'pale grey': '#fdfdfe', + 'asparagus': '#77ab56', + 'blueberry': '#464196', + 'purple red': '#990147', + 'pale lime': '#befd73', + 'greenish teal': '#32bf84', + 'caramel': '#af6f09', + 'deep magenta': '#a0025c', + 'light peach': '#ffd8b1', + 'milk chocolate': '#7f4e1e', + 'ocher': '#bf9b0c', + 'off green': '#6ba353', + 'purply pink': '#f075e6', + 'lightblue': '#7bc8f6', + 'dusky blue': '#475f94', + 'golden': '#f5bf03', + 'light beige': '#fffeb6', + 'butter yellow': '#fffd74', + 'dusky purple': '#895b7b', + 'french blue': '#436bad', + 'ugly yellow': '#d0c101', + 'greeny yellow': '#c6f808', + 'orangish red': '#f43605', + 'shamrock green': '#02c14d', + 'orangish brown': '#b25f03', + 'tree green': '#2a7e19', + 'deep violet': '#490648', + 'gunmetal': '#536267', + 'blue/purple': '#5a06ef', + 'cherry': '#cf0234', + 'sandy brown': '#c4a661', + 'warm grey': '#978a84', + 'dark indigo': '#1f0954', + 'midnight': '#03012d', + 'bluey green': '#2bb179', + 'grey pink': '#c3909b', + 'soft purple': '#a66fb5', + 'blood': '#770001', + 'brown red': '#922b05', + 'medium grey': '#7d7f7c', + 'berry': '#990f4b', + 'poo': '#8f7303', + 'purpley pink': '#c83cb9', + 'light salmon': '#fea993', + 'snot': '#acbb0d', + 'easter purple': '#c071fe', + 'light yellow green': '#ccfd7f', + 'dark navy blue': '#00022e', + 'drab': '#828344', + 'light rose': '#ffc5cb', + 'rouge': '#ab1239', + 'purplish red': '#b0054b', + 'slime green': '#99cc04', + 'baby poop': '#937c00', + 'irish green': '#019529', + 'pink/purple': '#ef1de7', + 'dark navy': '#000435', + 'greeny blue': '#42b395', + 'light plum': '#9d5783', + 'pinkish grey': '#c8aca9', + 'dirty orange': '#c87606', + 'rust red': '#aa2704', + 'pale lilac': '#e4cbff', + 'orangey red': '#fa4224', + 'primary blue': '#0804f9', + 'kermit green': '#5cb200', + 'brownish purple': '#76424e', + 'murky green': '#6c7a0e', + 'wheat': '#fbdd7e', + 'very dark purple': '#2a0134', + 'bottle green': '#044a05', + 'watermelon': '#fd4659', + 'deep sky blue': '#0d75f8', + 'fire engine red': '#fe0002', + 'yellow ochre': '#cb9d06', + 'pumpkin orange': '#fb7d07', + 'pale olive': '#b9cc81', + 'light lilac': '#edc8ff', + 'lightish green': '#61e160', + 'carolina blue': '#8ab8fe', + 'mulberry': '#920a4e', + 'shocking pink': '#fe02a2', + 'auburn': '#9a3001', + 'bright lime green': '#65fe08', + 'celadon': '#befdb7', + 'pinkish brown': '#b17261', + 'poo brown': '#885f01', + 'bright sky blue': '#02ccfe', + 'celery': '#c1fd95', + 'dirt brown': '#836539', + 'strawberry': '#fb2943', + 'dark lime': '#84b701', + 'copper': '#b66325', + 'medium brown': '#7f5112', + 'muted green': '#5fa052', + "robin's egg": '#6dedfd', + 'bright aqua': '#0bf9ea', + 'bright lavender': '#c760ff', + 'ivory': '#ffffcb', + 'very light purple': '#f6cefc', + 'light navy': '#155084', + 'pink red': '#f5054f', + 'olive brown': '#645403', + 'poop brown': '#7a5901', + 'mustard green': '#a8b504', + 'ocean green': '#3d9973', + 'very dark blue': '#000133', + 'dusty green': '#76a973', + 'light navy blue': '#2e5a88', + 'minty green': '#0bf77d', + 'adobe': '#bd6c48', + 'barney': '#ac1db8', + 'jade green': '#2baf6a', + 'bright light blue': '#26f7fd', + 'light lime': '#aefd6c', + 'dark khaki': '#9b8f55', + 'orange yellow': '#ffad01', + 'ocre': '#c69c04', + 'maize': '#f4d054', + 'faded pink': '#de9dac', + 'british racing green': '#05480d', + 'sandstone': '#c9ae74', + 'mud brown': '#60460f', + 'light sea green': '#98f6b0', + 'robin egg blue': '#8af1fe', + 'aqua marine': '#2ee8bb', + 'dark sea green': '#11875d', + 'soft pink': '#fdb0c0', + 'orangey brown': '#b16002', + 'cherry red': '#f7022a', + 'burnt yellow': '#d5ab09', + 'brownish grey': '#86775f', + 'camel': '#c69f59', + 'purplish grey': '#7a687f', + 'marine': '#042e60', + 'greyish pink': '#c88d94', + 'pale turquoise': '#a5fbd5', + 'pastel yellow': '#fffe71', + 'bluey purple': '#6241c7', + 'canary yellow': '#fffe40', + 'faded red': '#d3494e', + 'sepia': '#985e2b', + 'coffee': '#a6814c', + 'bright magenta': '#ff08e8', + 'mocha': '#9d7651', + 'ecru': '#feffca', + 'purpleish': '#98568d', + 'cranberry': '#9e003a', + 'darkish green': '#287c37', + 'brown orange': '#b96902', + 'dusky rose': '#ba6873', + 'melon': '#ff7855', + 'sickly green': '#94b21c', + 'silver': '#c5c9c7', + 'purply blue': '#661aee', + 'purpleish blue': '#6140ef', + 'hospital green': '#9be5aa', + 'shit brown': '#7b5804', + 'mid blue': '#276ab3', + 'amber': '#feb308', + 'easter green': '#8cfd7e', + 'soft blue': '#6488ea', + 'cerulean blue': '#056eee', + 'golden brown': '#b27a01', + 'bright turquoise': '#0ffef9', + 'red pink': '#fa2a55', + 'red purple': '#820747', + 'greyish brown': '#7a6a4f', + 'vermillion': '#f4320c', + 'russet': '#a13905', + 'steel grey': '#6f828a', + 'lighter purple': '#a55af4', + 'bright violet': '#ad0afd', + 'prussian blue': '#004577', + 'slate green': '#658d6d', + 'dirty pink': '#ca7b80', + 'dark blue green': '#005249', + 'pine': '#2b5d34', + 'yellowy green': '#bff128', + 'dark gold': '#b59410', + 'bluish': '#2976bb', + 'darkish blue': '#014182', + 'dull red': '#bb3f3f', + 'pinky red': '#fc2647', + 'bronze': '#a87900', + 'pale teal': '#82cbb2', + 'military green': '#667c3e', + 'barbie pink': '#fe46a5', + 'bubblegum pink': '#fe83cc', + 'pea soup green': '#94a617', + 'dark mustard': '#a88905', + 'shit': '#7f5f00', + 'medium purple': '#9e43a2', + 'very dark green': '#062e03', + 'dirt': '#8a6e45', + 'dusky pink': '#cc7a8b', + 'red violet': '#9e0168', + 'lemon yellow': '#fdff38', + 'pistachio': '#c0fa8b', + 'dull yellow': '#eedc5b', + 'dark lime green': '#7ebd01', + 'denim blue': '#3b5b92', + 'teal blue': '#01889f', + 'lightish blue': '#3d7afd', + 'purpley blue': '#5f34e7', + 'light indigo': '#6d5acf', + 'swamp green': '#748500', + 'brown green': '#706c11', + 'dark maroon': '#3c0008', + 'hot purple': '#cb00f5', + 'dark forest green': '#002d04', + 'faded blue': '#658cbb', + 'drab green': '#749551', + 'light lime green': '#b9ff66', + 'snot green': '#9dc100', + 'yellowish': '#faee66', + 'light blue green': '#7efbb3', + 'bordeaux': '#7b002c', + 'light mauve': '#c292a1', + 'ocean': '#017b92', + 'marigold': '#fcc006', + 'muddy green': '#657432', + 'dull orange': '#d8863b', + 'steel': '#738595', + 'electric purple': '#aa23ff', + 'fluorescent green': '#08ff08', + 'yellowish brown': '#9b7a01', + 'blush': '#f29e8e', + 'soft green': '#6fc276', + 'bright orange': '#ff5b00', + 'lemon': '#fdff52', + 'purple grey': '#866f85', + 'acid green': '#8ffe09', + 'pale lavender': '#eecffe', + 'violet blue': '#510ac9', + 'light forest green': '#4f9153', + 'burnt red': '#9f2305', + 'khaki green': '#728639', + 'cerise': '#de0c62', + 'faded purple': '#916e99', + 'apricot': '#ffb16d', + 'dark olive green': '#3c4d03', + 'grey brown': '#7f7053', + 'green grey': '#77926f', + 'true blue': '#010fcc', + 'pale violet': '#ceaefa', + 'periwinkle blue': '#8f99fb', + 'light sky blue': '#c6fcff', + 'blurple': '#5539cc', + 'green brown': '#544e03', + 'bluegreen': '#017a79', + 'bright teal': '#01f9c6', + 'brownish yellow': '#c9b003', + 'pea soup': '#929901', + 'forest': '#0b5509', + 'barney purple': '#a00498', + 'ultramarine': '#2000b1', + 'purplish': '#94568c', + 'puke yellow': '#c2be0e', + 'bluish grey': '#748b97', + 'dark periwinkle': '#665fd1', + 'dark lilac': '#9c6da5', + 'reddish': '#c44240', + 'light maroon': '#a24857', + 'dusty purple': '#825f87', + 'terra cotta': '#c9643b', + 'avocado': '#90b134', + 'marine blue': '#01386a', + 'teal green': '#25a36f', + 'slate grey': '#59656d', + 'lighter green': '#75fd63', + 'electric green': '#21fc0d', + 'dusty blue': '#5a86ad', + 'golden yellow': '#fec615', + 'bright yellow': '#fffd01', + 'light lavender': '#dfc5fe', + 'umber': '#b26400', + 'poop': '#7f5e00', + 'dark peach': '#de7e5d', + 'jungle green': '#048243', + 'eggshell': '#ffffd4', + 'denim': '#3b638c', + 'yellow brown': '#b79400', + 'dull purple': '#84597e', + 'chocolate brown': '#411900', + 'wine red': '#7b0323', + 'neon blue': '#04d9ff', + 'dirty green': '#667e2c', + 'light tan': '#fbeeac', + 'ice blue': '#d7fffe', + 'cadet blue': '#4e7496', + 'dark mauve': '#874c62', + 'very light blue': '#d5ffff', + 'grey purple': '#826d8c', + 'pastel pink': '#ffbacd', + 'very light green': '#d1ffbd', + 'dark sky blue': '#448ee4', + 'evergreen': '#05472a', + 'dull pink': '#d5869d', + 'aubergine': '#3d0734', + 'mahogany': '#4a0100', + 'reddish orange': '#f8481c', + 'deep green': '#02590f', + 'vomit green': '#89a203', + 'purple pink': '#e03fd8', + 'dusty pink': '#d58a94', + 'faded green': '#7bb274', + 'camo green': '#526525', + 'pinky purple': '#c94cbe', + 'pink purple': '#db4bda', + 'brownish red': '#9e3623', + 'dark rose': '#b5485d', + 'mud': '#735c12', + 'brownish': '#9c6d57', + 'emerald green': '#028f1e', + 'pale brown': '#b1916e', + 'dull blue': '#49759c', + 'burnt umber': '#a0450e', + 'medium green': '#39ad48', + 'clay': '#b66a50', + 'light aqua': '#8cffdb', + 'light olive green': '#a4be5c', + 'brownish orange': '#cb7723', + 'dark aqua': '#05696b', + 'purplish pink': '#ce5dae', + 'dark salmon': '#c85a53', + 'greenish grey': '#96ae8d', + 'jade': '#1fa774', + 'ugly green': '#7a9703', + 'dark beige': '#ac9362', + 'emerald': '#01a049', + 'pale red': '#d9544d', + 'light magenta': '#fa5ff7', + 'sky': '#82cafc', + 'light cyan': '#acfffc', + 'yellow orange': '#fcb001', + 'reddish purple': '#910951', + 'reddish pink': '#fe2c54', + 'orchid': '#c875c4', + 'dirty yellow': '#cdc50a', + 'orange red': '#fd411e', + 'deep red': '#9a0200', + 'orange brown': '#be6400', + 'cobalt blue': '#030aa7', + 'neon pink': '#fe019a', + 'rose pink': '#f7879a', + 'greyish purple': '#887191', + 'raspberry': '#b00149', + 'aqua green': '#12e193', + 'salmon pink': '#fe7b7c', + 'tangerine': '#ff9408', + 'brownish green': '#6a6e09', + 'red brown': '#8b2e16', + 'greenish brown': '#696112', + 'pumpkin': '#e17701', + 'pine green': '#0a481e', + 'charcoal': '#343837', + 'baby pink': '#ffb7ce', + 'cornflower': '#6a79f7', + 'blue violet': '#5d06e9', + 'chocolate': '#3d1c02', + 'greyish green': '#82a67d', + 'scarlet': '#be0119', + 'green yellow': '#c9ff27', + 'dark olive': '#373e02', + 'sienna': '#a9561e', + 'pastel purple': '#caa0ff', + 'terracotta': '#ca6641', + 'aqua blue': '#02d8e9', + 'sage green': '#88b378', + 'blood red': '#980002', + 'deep pink': '#cb0162', + 'grass': '#5cac2d', + 'moss': '#769958', + 'pastel blue': '#a2bffe', + 'bluish green': '#10a674', + 'green blue': '#06b48b', + 'dark tan': '#af884a', + 'greenish blue': '#0b8b87', + 'pale orange': '#ffa756', + 'vomit': '#a2a415', + 'forrest green': '#154406', + 'dark lavender': '#856798', + 'dark violet': '#34013f', + 'purple blue': '#632de9', + 'dark cyan': '#0a888a', + 'olive drab': '#6f7632', + 'pinkish': '#d46a7e', + 'cobalt': '#1e488f', + 'neon purple': '#bc13fe', + 'light turquoise': '#7ef4cc', + 'apple green': '#76cd26', + 'dull green': '#74a662', + 'wine': '#80013f', + 'powder blue': '#b1d1fc', + 'off white': '#ffffe4', + 'electric blue': '#0652ff', + 'dark turquoise': '#045c5a', + 'blue purple': '#5729ce', + 'azure': '#069af3', + 'bright red': '#ff000d', + 'pinkish red': '#f10c45', + 'cornflower blue': '#5170d7', + 'light olive': '#acbf69', + 'grape': '#6c3461', + 'greyish blue': '#5e819d', + 'purplish blue': '#601ef9', + 'yellowish green': '#b0dd16', + 'greenish yellow': '#cdfd02', + 'medium blue': '#2c6fbb', + 'dusty rose': '#c0737a', + 'light violet': '#d6b4fc', + 'midnight blue': '#020035', + 'bluish purple': '#703be7', + 'red orange': '#fd3c06', + 'dark magenta': '#960056', + 'greenish': '#40a368', + 'ocean blue': '#03719c', + 'coral': '#fc5a50', + 'cream': '#ffffc2', + 'reddish brown': '#7f2b0a', + 'burnt sienna': '#b04e0f', + 'brick': '#a03623', + 'sage': '#87ae73', + 'grey green': '#789b73', + 'white': '#ffffff', + "robin's egg blue": '#98eff9', + 'moss green': '#658b38', + 'steel blue': '#5a7d9a', + 'eggplant': '#380835', + 'light yellow': '#fffe7a', + 'leaf green': '#5ca904', + 'light grey': '#d8dcd6', + 'puke': '#a5a502', + 'pinkish purple': '#d648d7', + 'sea blue': '#047495', + 'pale purple': '#b790d4', + 'slate blue': '#5b7c99', + 'blue grey': '#607c8e', + 'hunter green': '#0b4008', + 'fuchsia': '#ed0dd9', + 'crimson': '#8c000f', + 'pale yellow': '#ffff84', + 'ochre': '#bf9005', + 'mustard yellow': '#d2bd0a', + 'light red': '#ff474c', + 'cerulean': '#0485d1', + 'pale pink': '#ffcfdc', + 'deep blue': '#040273', + 'rust': '#a83c09', + 'light teal': '#90e4c1', + 'slate': '#516572', + 'goldenrod': '#fac205', + 'dark yellow': '#d5b60a', + 'dark grey': '#363737', + 'army green': '#4b5d16', + 'grey blue': '#6b8ba4', + 'seafoam': '#80f9ad', + 'puce': '#a57e52', + 'spring green': '#a9f971', + 'dark orange': '#c65102', + 'sand': '#e2ca76', + 'pastel green': '#b0ff9d', + 'mint': '#9ffeb0', + 'light orange': '#fdaa48', + 'bright pink': '#fe01b1', + 'chartreuse': '#c1f80a', + 'deep purple': '#36013f', + 'dark brown': '#341c02', + 'taupe': '#b9a281', + 'pea green': '#8eab12', + 'puke green': '#9aae07', + 'kelly green': '#02ab2e', + 'seafoam green': '#7af9ab', + 'blue green': '#137e6d', + 'khaki': '#aaa662', + 'burgundy': '#610023', + 'dark teal': '#014d4e', + 'brick red': '#8f1402', + 'royal purple': '#4b006e', + 'plum': '#580f41', + 'mint green': '#8fff9f', + 'gold': '#dbb40c', + 'baby blue': '#a2cffe', + 'yellow green': '#c0fb2d', + 'bright purple': '#be03fd', + 'dark red': '#840000', + 'pale blue': '#d0fefe', + 'grass green': '#3f9b0b', + 'navy': '#01153e', + 'aquamarine': '#04d8b2', + 'burnt orange': '#c04e01', + 'neon green': '#0cff0c', + 'bright blue': '#0165fc', + 'rose': '#cf6275', + 'light pink': '#ffd1df', + 'mustard': '#ceb301', + 'indigo': '#380282', + 'lime': '#aaff32', + 'sea green': '#53fca1', + 'periwinkle': '#8e82fe', + 'dark pink': '#cb416b', + 'olive green': '#677a04', + 'peach': '#ffb07c', + 'pale green': '#c7fdb5', + 'light brown': '#ad8150', + 'hot pink': '#ff028d', + 'black': '#000000', + 'lilac': '#cea2fd', + 'navy blue': '#001146', + 'royal blue': '#0504aa', + 'beige': '#e6daa6', + 'salmon': '#ff796c', + 'olive': '#6e750e', + 'maroon': '#650021', + 'bright green': '#01ff07', + 'dark purple': '#35063e', + 'mauve': '#ae7181', + 'forest green': '#06470c', + 'aqua': '#13eac9', + 'cyan': '#00ffff', + 'tan': '#d1b26f', + 'dark blue': '#00035b', + 'lavender': '#c79fef', + 'turquoise': '#06c2ac', + 'dark green': '#033500', + 'violet': '#9a0eea', + 'light purple': '#bf77f6', + 'lime green': '#89fe05', + 'grey': '#929591', + 'sky blue': '#75bbfd', + 'yellow': '#ffff14', + 'magenta': '#c20078', + 'light green': '#96f97b', + 'orange': '#f97306', + 'teal': '#029386', + 'light blue': '#95d0fc', + 'red': '#e50000', + 'brown': '#653700', + 'pink': '#ff81c0', + 'blue': '#0343df', + 'green': '#15b01a', + 'purple': '#7e1e9c'} + +# Normalize name to "xkcd:" to avoid name collisions. +XKCD_COLORS = {'xkcd:' + name: value for name, value in XKCD_COLORS.items()} + + +# https://drafts.csswg.org/css-color-4/#named-colors +CSS4_COLORS = { + 'aliceblue': '#F0F8FF', + 'antiquewhite': '#FAEBD7', + 'aqua': '#00FFFF', + 'aquamarine': '#7FFFD4', + 'azure': '#F0FFFF', + 'beige': '#F5F5DC', + 'bisque': '#FFE4C4', + 'black': '#000000', + 'blanchedalmond': '#FFEBCD', + 'blue': '#0000FF', + 'blueviolet': '#8A2BE2', + 'brown': '#A52A2A', + 'burlywood': '#DEB887', + 'cadetblue': '#5F9EA0', + 'chartreuse': '#7FFF00', + 'chocolate': '#D2691E', + 'coral': '#FF7F50', + 'cornflowerblue': '#6495ED', + 'cornsilk': '#FFF8DC', + 'crimson': '#DC143C', + 'cyan': '#00FFFF', + 'darkblue': '#00008B', + 'darkcyan': '#008B8B', + 'darkgoldenrod': '#B8860B', + 'darkgray': '#A9A9A9', + 'darkgreen': '#006400', + 'darkgrey': '#A9A9A9', + 'darkkhaki': '#BDB76B', + 'darkmagenta': '#8B008B', + 'darkolivegreen': '#556B2F', + 'darkorange': '#FF8C00', + 'darkorchid': '#9932CC', + 'darkred': '#8B0000', + 'darksalmon': '#E9967A', + 'darkseagreen': '#8FBC8F', + 'darkslateblue': '#483D8B', + 'darkslategray': '#2F4F4F', + 'darkslategrey': '#2F4F4F', + 'darkturquoise': '#00CED1', + 'darkviolet': '#9400D3', + 'deeppink': '#FF1493', + 'deepskyblue': '#00BFFF', + 'dimgray': '#696969', + 'dimgrey': '#696969', + 'dodgerblue': '#1E90FF', + 'firebrick': '#B22222', + 'floralwhite': '#FFFAF0', + 'forestgreen': '#228B22', + 'fuchsia': '#FF00FF', + 'gainsboro': '#DCDCDC', + 'ghostwhite': '#F8F8FF', + 'gold': '#FFD700', + 'goldenrod': '#DAA520', + 'gray': '#808080', + 'green': '#008000', + 'greenyellow': '#ADFF2F', + 'grey': '#808080', + 'honeydew': '#F0FFF0', + 'hotpink': '#FF69B4', + 'indianred': '#CD5C5C', + 'indigo': '#4B0082', + 'ivory': '#FFFFF0', + 'khaki': '#F0E68C', + 'lavender': '#E6E6FA', + 'lavenderblush': '#FFF0F5', + 'lawngreen': '#7CFC00', + 'lemonchiffon': '#FFFACD', + 'lightblue': '#ADD8E6', + 'lightcoral': '#F08080', + 'lightcyan': '#E0FFFF', + 'lightgoldenrodyellow': '#FAFAD2', + 'lightgray': '#D3D3D3', + 'lightgreen': '#90EE90', + 'lightgrey': '#D3D3D3', + 'lightpink': '#FFB6C1', + 'lightsalmon': '#FFA07A', + 'lightseagreen': '#20B2AA', + 'lightskyblue': '#87CEFA', + 'lightslategray': '#778899', + 'lightslategrey': '#778899', + 'lightsteelblue': '#B0C4DE', + 'lightyellow': '#FFFFE0', + 'lime': '#00FF00', + 'limegreen': '#32CD32', + 'linen': '#FAF0E6', + 'magenta': '#FF00FF', + 'maroon': '#800000', + 'mediumaquamarine': '#66CDAA', + 'mediumblue': '#0000CD', + 'mediumorchid': '#BA55D3', + 'mediumpurple': '#9370DB', + 'mediumseagreen': '#3CB371', + 'mediumslateblue': '#7B68EE', + 'mediumspringgreen': '#00FA9A', + 'mediumturquoise': '#48D1CC', + 'mediumvioletred': '#C71585', + 'midnightblue': '#191970', + 'mintcream': '#F5FFFA', + 'mistyrose': '#FFE4E1', + 'moccasin': '#FFE4B5', + 'navajowhite': '#FFDEAD', + 'navy': '#000080', + 'oldlace': '#FDF5E6', + 'olive': '#808000', + 'olivedrab': '#6B8E23', + 'orange': '#FFA500', + 'orangered': '#FF4500', + 'orchid': '#DA70D6', + 'palegoldenrod': '#EEE8AA', + 'palegreen': '#98FB98', + 'paleturquoise': '#AFEEEE', + 'palevioletred': '#DB7093', + 'papayawhip': '#FFEFD5', + 'peachpuff': '#FFDAB9', + 'peru': '#CD853F', + 'pink': '#FFC0CB', + 'plum': '#DDA0DD', + 'powderblue': '#B0E0E6', + 'purple': '#800080', + 'rebeccapurple': '#663399', + 'red': '#FF0000', + 'rosybrown': '#BC8F8F', + 'royalblue': '#4169E1', + 'saddlebrown': '#8B4513', + 'salmon': '#FA8072', + 'sandybrown': '#F4A460', + 'seagreen': '#2E8B57', + 'seashell': '#FFF5EE', + 'sienna': '#A0522D', + 'silver': '#C0C0C0', + 'skyblue': '#87CEEB', + 'slateblue': '#6A5ACD', + 'slategray': '#708090', + 'slategrey': '#708090', + 'snow': '#FFFAFA', + 'springgreen': '#00FF7F', + 'steelblue': '#4682B4', + 'tan': '#D2B48C', + 'teal': '#008080', + 'thistle': '#D8BFD8', + 'tomato': '#FF6347', + 'turquoise': '#40E0D0', + 'violet': '#EE82EE', + 'wheat': '#F5DEB3', + 'white': '#FFFFFF', + 'whitesmoke': '#F5F5F5', + 'yellow': '#FFFF00', + 'yellowgreen': '#9ACD32'} diff --git a/venv/lib/python3.6/site-packages/matplotlib/_constrained_layout.py b/venv/lib/python3.6/site-packages/matplotlib/_constrained_layout.py new file mode 100644 index 0000000..a2a70fd --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_constrained_layout.py @@ -0,0 +1,744 @@ +""" +This module provides the routine to adjust subplot layouts so that there are +no overlapping axes or axes decorations. All axes decorations are dealt with +(labels, ticks, titles, ticklabels) and some dependent artists are also dealt +with (colorbar, suptitle, legend). + +Layout is done via :meth:`~matplotlib.gridspec`, with one constraint per +gridspec, so it is possible to have overlapping axes if the gridspecs +overlap (i.e. using :meth:`~matplotlib.gridspec.GridSpecFromSubplotSpec`). +Axes placed using ``figure.subplots()`` or ``figure.add_subplots()`` will +participate in the layout. Axes manually placed via ``figure.add_axes()`` +will not. + +See Tutorial: :doc:`/tutorials/intermediate/constrainedlayout_guide` + +""" + +# Development Notes: + +# What gets a layoutbox: +# - figure +# - gridspec +# - subplotspec +# EITHER: +# - axes + pos for the axes (i.e. the total area taken by axis and +# the actual "position" argument that needs to be sent to +# ax.set_position.) +# - The axes layout box will also encompass the legend, and that is +# how legends get included (axes legends, not figure legends) +# - colorbars are siblings of the axes if they are single-axes +# colorbars +# OR: +# - a gridspec can be inside a subplotspec. +# - subplotspec +# EITHER: +# - axes... +# OR: +# - gridspec... with arbitrary nesting... +# - colorbars are siblings of the subplotspecs if they are multi-axes +# colorbars. +# - suptitle: +# - right now suptitles are just stacked atop everything else in figure. +# Could imagine suptitles being gridspec suptitles, but not implemented +# +# Todo: AnchoredOffsetbox connected to gridspecs or axes. This would +# be more general way to add extra-axes annotations. + +import logging + +import numpy as np + +import matplotlib.cbook as cbook +import matplotlib._layoutbox as layoutbox + +_log = logging.getLogger(__name__) + + +def _in_same_column(colnum0min, colnum0max, colnumCmin, colnumCmax): + return (colnumCmin <= colnum0min <= colnumCmax + or colnumCmin <= colnum0max <= colnumCmax) + + +def _in_same_row(rownum0min, rownum0max, rownumCmin, rownumCmax): + return (rownumCmin <= rownum0min <= rownumCmax + or rownumCmin <= rownum0max <= rownumCmax) + + +def _axes_all_finite_sized(fig): + """ + helper function to make sure all axes in the + figure have a finite width and height. If not, return False + """ + for ax in fig.axes: + if ax._layoutbox is not None: + newpos = ax._poslayoutbox.get_rect() + if newpos[2] <= 0 or newpos[3] <= 0: + return False + return True + + +###################################################### +def do_constrained_layout(fig, renderer, h_pad, w_pad, + hspace=None, wspace=None): + + """ + Do the constrained_layout. Called at draw time in + ``figure.constrained_layout()`` + + Parameters + ---------- + + + fig : Figure + is the ``figure`` instance to do the layout in. + + renderer : Renderer + the renderer to use. + + h_pad, w_pad : float + are in figure-normalized units, and are a padding around the axes + elements. + + hspace, wspace : float + are in fractions of the subplot sizes. + + """ + + ''' Steps: + + 1. get a list of unique gridspecs in this figure. Each gridspec will be + constrained separately. + 2. Check for gaps in the gridspecs. i.e. if not every axes slot in the + gridspec has been filled. If empty, add a ghost axis that is made so + that it cannot be seen (though visible=True). This is needed to make + a blank spot in the layout. + 3. Compare the tight_bbox of each axes to its `position`, and assume that + the difference is the space needed by the elements around the edge of + the axes (decorations) like the title, ticklabels, x-labels, etc. This + can include legends who overspill the axes boundaries. + 4. Constrain gridspec elements to line up: + a) if colnum0 != colnumC, the two subplotspecs are stacked next to + each other, with the appropriate order. + b) if colnum0 == colnumC, line up the left or right side of the + _poslayoutbox (depending if it is the min or max num that is equal). + c) do the same for rows... + 5. The above doesn't constrain relative sizes of the _poslayoutboxes at + all, and indeed zero-size is a solution that the solver often finds more + convenient than expanding the sizes. Right now the solution is to compare + subplotspec sizes (i.e. drowsC and drows0) and constrain the larger + _poslayoutbox to be larger than the ratio of the sizes. i.e. if drows0 > + drowsC, then ax._poslayoutbox > axc._poslayoutbox * drowsC / drows0. This + works fine *if* the decorations are similar between the axes. If the + larger subplotspec has much larger axes decorations, then the constraint + above is incorrect. + + We need the greater than in the above, in general, rather than an equals + sign. Consider the case of the left column having 2 rows, and the right + column having 1 row. We want the top and bottom of the _poslayoutboxes to + line up. So that means if there are decorations on the left column axes + they will be smaller than half as large as the right hand axis. + + This can break down if the decoration size for the right hand axis (the + margins) is very large. There must be a math way to check for this case. + + ''' + + invTransFig = fig.transFigure.inverted().transform_bbox + + # list of unique gridspecs that contain child axes: + gss = set() + for ax in fig.axes: + if hasattr(ax, 'get_subplotspec'): + gs = ax.get_subplotspec().get_gridspec() + if gs._layoutbox is not None: + gss.add(gs) + if len(gss) == 0: + cbook._warn_external('There are no gridspecs with layoutboxes. ' + 'Possibly did not call parent GridSpec with the' + ' figure= keyword') + + if fig._layoutbox.constrained_layout_called < 1: + for gs in gss: + # fill in any empty gridspec slots w/ ghost axes... + _make_ghost_gridspec_slots(fig, gs) + + for nnn in range(2): + # do the algorithm twice. This has to be done because decorators + # change size after the first re-position (i.e. x/yticklabels get + # larger/smaller). This second reposition tends to be much milder, + # so doing twice makes things work OK. + for ax in fig.axes: + _log.debug(ax._layoutbox) + if ax._layoutbox is not None: + # make margins for each layout box based on the size of + # the decorators. + _make_layout_margins(ax, renderer, h_pad, w_pad) + + # do layout for suptitle. + suptitle = fig._suptitle + do_suptitle = (suptitle is not None and + suptitle._layoutbox is not None and + suptitle.get_in_layout()) + if do_suptitle: + bbox = invTransFig( + suptitle.get_window_extent(renderer=renderer)) + height = bbox.y1 - bbox.y0 + if np.isfinite(height): + # reserve at top of figure include an h_pad above and below + suptitle._layoutbox.edit_height(height + h_pad * 2) + + # OK, the above lines up ax._poslayoutbox with ax._layoutbox + # now we need to + # 1) arrange the subplotspecs. We do it at this level because + # the subplotspecs are meant to contain other dependent axes + # like colorbars or legends. + # 2) line up the right and left side of the ax._poslayoutbox + # that have the same subplotspec maxes. + + if fig._layoutbox.constrained_layout_called < 1: + # arrange the subplotspecs... This is all done relative to each + # other. Some subplotspecs contain axes, and others contain + # gridspecs the ones that contain gridspecs are a set proportion + # of their parent gridspec. The ones that contain axes are + # not so constrained. + figlb = fig._layoutbox + for child in figlb.children: + if child._is_gridspec_layoutbox(): + # This routine makes all the subplot spec containers + # have the correct arrangement. It just stacks the + # subplot layoutboxes in the correct order... + _arrange_subplotspecs(child, hspace=hspace, wspace=wspace) + + for gs in gss: + _align_spines(fig, gs) + + fig._layoutbox.constrained_layout_called += 1 + fig._layoutbox.update_variables() + + # check if any axes collapsed to zero. If not, don't change positions: + if _axes_all_finite_sized(fig): + # Now set the position of the axes... + for ax in fig.axes: + if ax._layoutbox is not None: + newpos = ax._poslayoutbox.get_rect() + # Now set the new position. + # ax.set_position will zero out the layout for + # this axis, allowing users to hard-code the position, + # so this does the same w/o zeroing layout. + ax._set_position(newpos, which='original') + if do_suptitle: + newpos = suptitle._layoutbox.get_rect() + suptitle.set_y(1.0 - h_pad) + else: + if suptitle is not None and suptitle._layoutbox is not None: + suptitle._layoutbox.edit_height(0) + else: + cbook._warn_external('constrained_layout not applied. At least ' + 'one axes collapsed to zero width or height.') + + +def _make_ghost_gridspec_slots(fig, gs): + """ + Check for unoccupied gridspec slots and make ghost axes for these + slots... Do for each gs separately. This is a pretty big kludge + but shouldn't have too much ill effect. The worst is that + someone querying the figure will wonder why there are more + axes than they thought. + """ + nrows, ncols = gs.get_geometry() + hassubplotspec = np.zeros(nrows * ncols, dtype=bool) + axs = [] + for ax in fig.axes: + if (hasattr(ax, 'get_subplotspec') + and ax._layoutbox is not None + and ax.get_subplotspec().get_gridspec() == gs): + axs += [ax] + for ax in axs: + ss0 = ax.get_subplotspec() + if ss0.num2 is None: + ss0.num2 = ss0.num1 + hassubplotspec[ss0.num1:(ss0.num2 + 1)] = True + for nn, hss in enumerate(hassubplotspec): + if not hss: + # this gridspec slot doesn't have an axis so we + # make a "ghost". + ax = fig.add_subplot(gs[nn]) + ax.set_frame_on(False) + ax.set_xticks([]) + ax.set_yticks([]) + ax.set_facecolor((1, 0, 0, 0)) + + +def _make_layout_margins(ax, renderer, h_pad, w_pad): + """ + For each axes, make a margin between the *pos* layoutbox and the + *axes* layoutbox be a minimum size that can accommodate the + decorations on the axis. + """ + fig = ax.figure + invTransFig = fig.transFigure.inverted().transform_bbox + pos = ax.get_position(original=True) + tightbbox = ax.get_tightbbox(renderer=renderer) + bbox = invTransFig(tightbbox) + # this can go wrong: + if not (np.isfinite(bbox.width) and np.isfinite(bbox.height)): + # just abort, this is likely a bad set of co-ordinates that + # is transitory... + return + # use stored h_pad if it exists + h_padt = ax._poslayoutbox.h_pad + if h_padt is None: + h_padt = h_pad + w_padt = ax._poslayoutbox.w_pad + if w_padt is None: + w_padt = w_pad + ax._poslayoutbox.edit_left_margin_min(-bbox.x0 + + pos.x0 + w_padt) + ax._poslayoutbox.edit_right_margin_min(bbox.x1 - + pos.x1 + w_padt) + ax._poslayoutbox.edit_bottom_margin_min( + -bbox.y0 + pos.y0 + h_padt) + ax._poslayoutbox.edit_top_margin_min(bbox.y1-pos.y1+h_padt) + _log.debug('left %f', (-bbox.x0 + pos.x0 + w_pad)) + _log.debug('right %f', (bbox.x1 - pos.x1 + w_pad)) + _log.debug('bottom %f', (-bbox.y0 + pos.y0 + h_padt)) + _log.debug('bbox.y0 %f', bbox.y0) + _log.debug('pos.y0 %f', pos.y0) + # Sometimes its possible for the solver to collapse + # rather than expand axes, so they all have zero height + # or width. This stops that... It *should* have been + # taken into account w/ pref_width... + if fig._layoutbox.constrained_layout_called < 1: + ax._poslayoutbox.constrain_height_min(20, strength='weak') + ax._poslayoutbox.constrain_width_min(20, strength='weak') + ax._layoutbox.constrain_height_min(20, strength='weak') + ax._layoutbox.constrain_width_min(20, strength='weak') + ax._poslayoutbox.constrain_top_margin(0, strength='weak') + ax._poslayoutbox.constrain_bottom_margin(0, + strength='weak') + ax._poslayoutbox.constrain_right_margin(0, strength='weak') + ax._poslayoutbox.constrain_left_margin(0, strength='weak') + + +def _align_spines(fig, gs): + """ + - Align right/left and bottom/top spines of appropriate subplots. + - Compare size of subplotspec including height and width ratios + and make sure that the axes spines are at least as large + as they should be. + """ + # for each gridspec... + nrows, ncols = gs.get_geometry() + width_ratios = gs.get_width_ratios() + height_ratios = gs.get_height_ratios() + if width_ratios is None: + width_ratios = np.ones(ncols) + if height_ratios is None: + height_ratios = np.ones(nrows) + + # get axes in this gridspec.... + axs = [] + for ax in fig.axes: + if (hasattr(ax, 'get_subplotspec') + and ax._layoutbox is not None): + if ax.get_subplotspec().get_gridspec() == gs: + axs += [ax] + rownummin = np.zeros(len(axs), dtype=np.int8) + rownummax = np.zeros(len(axs), dtype=np.int8) + colnummin = np.zeros(len(axs), dtype=np.int8) + colnummax = np.zeros(len(axs), dtype=np.int8) + width = np.zeros(len(axs)) + height = np.zeros(len(axs)) + + for n, ax in enumerate(axs): + ss0 = ax.get_subplotspec() + if ss0.num2 is None: + ss0.num2 = ss0.num1 + rownummin[n], colnummin[n] = divmod(ss0.num1, ncols) + rownummax[n], colnummax[n] = divmod(ss0.num2, ncols) + width[n] = np.sum( + width_ratios[colnummin[n]:(colnummax[n] + 1)]) + height[n] = np.sum( + height_ratios[rownummin[n]:(rownummax[n] + 1)]) + + for nn, ax in enumerate(axs[:-1]): + # now compare ax to all the axs: + # + # If the subplotspecs have the same colnumXmax, then line + # up their right sides. If they have the same min, then + # line up their left sides (and vertical equivalents). + rownum0min, colnum0min = rownummin[nn], colnummin[nn] + rownum0max, colnum0max = rownummax[nn], colnummax[nn] + width0, height0 = width[nn], height[nn] + alignleft = False + alignright = False + alignbot = False + aligntop = False + alignheight = False + alignwidth = False + for mm in range(nn+1, len(axs)): + axc = axs[mm] + rownumCmin, colnumCmin = rownummin[mm], colnummin[mm] + rownumCmax, colnumCmax = rownummax[mm], colnummax[mm] + widthC, heightC = width[mm], height[mm] + # Horizontally align axes spines if they have the + # same min or max: + if not alignleft and colnum0min == colnumCmin: + # we want the _poslayoutboxes to line up on left + # side of the axes spines... + layoutbox.align([ax._poslayoutbox, + axc._poslayoutbox], + 'left') + alignleft = True + + if not alignright and colnum0max == colnumCmax: + # line up right sides of _poslayoutbox + layoutbox.align([ax._poslayoutbox, + axc._poslayoutbox], + 'right') + alignright = True + # Vertically align axes spines if they have the + # same min or max: + if not aligntop and rownum0min == rownumCmin: + # line up top of _poslayoutbox + _log.debug('rownum0min == rownumCmin') + layoutbox.align([ax._poslayoutbox, axc._poslayoutbox], + 'top') + aligntop = True + + if not alignbot and rownum0max == rownumCmax: + # line up bottom of _poslayoutbox + _log.debug('rownum0max == rownumCmax') + layoutbox.align([ax._poslayoutbox, axc._poslayoutbox], + 'bottom') + alignbot = True + ########### + # Now we make the widths and heights of position boxes + # similar. (i.e the spine locations) + # This allows vertically stacked subplots to have + # different sizes if they occupy different amounts + # of the gridspec: i.e. + # gs = gridspec.GridSpec(3,1) + # ax1 = gs[0,:] + # ax2 = gs[1:,:] + # then drows0 = 1, and drowsC = 2, and ax2 + # should be at least twice as large as ax1. + # But it can be more than twice as large because + # it needs less room for the labeling. + # + # For height, this only needs to be done if the + # subplots share a column. For width if they + # share a row. + + drowsC = (rownumCmax - rownumCmin + 1) + drows0 = (rownum0max - rownum0min + 1) + dcolsC = (colnumCmax - colnumCmin + 1) + dcols0 = (colnum0max - colnum0min + 1) + + if not alignheight and drows0 == drowsC: + ax._poslayoutbox.constrain_height( + axc._poslayoutbox.height * height0 / heightC) + alignheight = True + elif _in_same_column(colnum0min, colnum0max, + colnumCmin, colnumCmax): + if height0 > heightC: + ax._poslayoutbox.constrain_height_min( + axc._poslayoutbox.height * height0 / heightC) + # these constraints stop the smaller axes from + # being allowed to go to zero height... + axc._poslayoutbox.constrain_height_min( + ax._poslayoutbox.height * heightC / + (height0*1.8)) + elif height0 < heightC: + axc._poslayoutbox.constrain_height_min( + ax._poslayoutbox.height * heightC / height0) + ax._poslayoutbox.constrain_height_min( + ax._poslayoutbox.height * height0 / + (heightC*1.8)) + # widths... + if not alignwidth and dcols0 == dcolsC: + ax._poslayoutbox.constrain_width( + axc._poslayoutbox.width * width0 / widthC) + alignwidth = True + elif _in_same_row(rownum0min, rownum0max, + rownumCmin, rownumCmax): + if width0 > widthC: + ax._poslayoutbox.constrain_width_min( + axc._poslayoutbox.width * width0 / widthC) + axc._poslayoutbox.constrain_width_min( + ax._poslayoutbox.width * widthC / + (width0*1.8)) + elif width0 < widthC: + axc._poslayoutbox.constrain_width_min( + ax._poslayoutbox.width * widthC / width0) + ax._poslayoutbox.constrain_width_min( + axc._poslayoutbox.width * width0 / + (widthC*1.8)) + + +def _arrange_subplotspecs(gs, hspace=0, wspace=0): + """ + arrange the subplotspec children of this gridspec, and then recursively + do the same of any gridspec children of those gridspecs... + """ + sschildren = [] + for child in gs.children: + if child._is_subplotspec_layoutbox(): + for child2 in child.children: + # check for gridspec children... + if child2._is_gridspec_layoutbox(): + _arrange_subplotspecs(child2, hspace=hspace, wspace=wspace) + sschildren += [child] + # now arrange the subplots... + for child0 in sschildren: + ss0 = child0.artist + nrows, ncols = ss0.get_gridspec().get_geometry() + if ss0.num2 is None: + ss0.num2 = ss0.num1 + rowNum0min, colNum0min = divmod(ss0.num1, ncols) + rowNum0max, colNum0max = divmod(ss0.num2, ncols) + sschildren = sschildren[1:] + for childc in sschildren: + ssc = childc.artist + rowNumCmin, colNumCmin = divmod(ssc.num1, ncols) + if ssc.num2 is None: + ssc.num2 = ssc.num1 + rowNumCmax, colNumCmax = divmod(ssc.num2, ncols) + # OK, this tells us the relative layout of ax + # with axc + thepad = wspace / ncols + if colNum0max < colNumCmin: + layoutbox.hstack([ss0._layoutbox, ssc._layoutbox], + padding=thepad) + if colNumCmax < colNum0min: + layoutbox.hstack([ssc._layoutbox, ss0._layoutbox], + padding=thepad) + + #### + # vertical alignment + thepad = hspace / nrows + if rowNum0max < rowNumCmin: + layoutbox.vstack([ss0._layoutbox, + ssc._layoutbox], + padding=thepad) + if rowNumCmax < rowNum0min: + layoutbox.vstack([ssc._layoutbox, + ss0._layoutbox], + padding=thepad) + + +def layoutcolorbarsingle(ax, cax, shrink, aspect, location, pad=0.05): + """ + Do the layout for a colorbar, to not overly pollute colorbar.py + + `pad` is in fraction of the original axis size. + """ + axlb = ax._layoutbox + axpos = ax._poslayoutbox + axsslb = ax.get_subplotspec()._layoutbox + lb = layoutbox.LayoutBox( + parent=axsslb, + name=axsslb.name + '.cbar', + artist=cax) + + if location in ('left', 'right'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightwidth=False, + pos=True, + subplot=False, + artist=cax) + + if location == 'right': + # arrange to right of parent axis + layoutbox.hstack([axlb, lb], padding=pad * axlb.width, + strength='strong') + else: + layoutbox.hstack([lb, axlb], padding=pad * axlb.width) + # constrain the height and center... + layoutbox.match_heights([axpos, lbpos], [1, shrink]) + layoutbox.align([axpos, lbpos], 'v_center') + # set the width of the pos box + lbpos.constrain_width(shrink * axpos.height * (1/aspect), + strength='strong') + elif location in ('bottom', 'top'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightheight=True, + pos=True, + subplot=False, + artist=cax) + + if location == 'bottom': + layoutbox.vstack([axlb, lb], padding=pad * axlb.height) + else: + layoutbox.vstack([lb, axlb], padding=pad * axlb.height) + # constrain the height and center... + layoutbox.match_widths([axpos, lbpos], + [1, shrink], strength='strong') + layoutbox.align([axpos, lbpos], 'h_center') + # set the height of the pos box + lbpos.constrain_height(axpos.width * aspect * shrink, + strength='medium') + + return lb, lbpos + + +def _getmaxminrowcolumn(axs): + # helper to get the min/max rows and columns of a list of axes. + maxrow = -100000 + minrow = 1000000 + maxax = None + minax = None + maxcol = -100000 + mincol = 1000000 + maxax_col = None + minax_col = None + + for ax in axs: + subspec = ax.get_subplotspec() + nrows, ncols, row_start, row_stop, col_start, col_stop = \ + subspec.get_rows_columns() + if row_stop > maxrow: + maxrow = row_stop + maxax = ax + if row_start < minrow: + minrow = row_start + minax = ax + if col_stop > maxcol: + maxcol = col_stop + maxax_col = ax + if col_start < mincol: + mincol = col_start + minax_col = ax + return (minrow, maxrow, minax, maxax, mincol, maxcol, minax_col, maxax_col) + + +def layoutcolorbargridspec(parents, cax, shrink, aspect, location, pad=0.05): + """ + Do the layout for a colorbar, to not overly pollute colorbar.py + + `pad` is in fraction of the original axis size. + """ + + gs = parents[0].get_subplotspec().get_gridspec() + # parent layout box.... + gslb = gs._layoutbox + + lb = layoutbox.LayoutBox(parent=gslb.parent, + name=gslb.parent.name + '.cbar', + artist=cax) + # figure out the row and column extent of the parents. + (minrow, maxrow, minax_row, maxax_row, + mincol, maxcol, minax_col, maxax_col) = _getmaxminrowcolumn(parents) + + if location in ('left', 'right'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightwidth=False, + pos=True, + subplot=False, + artist=cax) + for ax in parents: + if location == 'right': + order = [ax._layoutbox, lb] + else: + order = [lb, ax._layoutbox] + layoutbox.hstack(order, padding=pad * gslb.width, + strength='strong') + # constrain the height and center... + # This isn't quite right. We'd like the colorbar + # pos to line up w/ the axes poss, not the size of the + # gs. + + # Horizontal Layout: need to check all the axes in this gridspec + for ch in gslb.children: + subspec = ch.artist + nrows, ncols, row_start, row_stop, col_start, col_stop = \ + subspec.get_rows_columns() + if location == 'right': + if col_stop <= maxcol: + order = [subspec._layoutbox, lb] + # arrange to right of the parents + if col_start > maxcol: + order = [lb, subspec._layoutbox] + elif location == 'left': + if col_start >= mincol: + order = [lb, subspec._layoutbox] + if col_stop < mincol: + order = [subspec._layoutbox, lb] + layoutbox.hstack(order, padding=pad * gslb.width, + strength='strong') + + # Vertical layout: + maxposlb = minax_row._poslayoutbox + minposlb = maxax_row._poslayoutbox + # now we want the height of the colorbar pos to be + # set by the top and bottom of the min/max axes... + # bottom top + # b t + # h = (top-bottom)*shrink + # b = bottom + (top-bottom - h) / 2. + lbpos.constrain_height( + (maxposlb.top - minposlb.bottom) * + shrink, strength='strong') + lbpos.constrain_bottom( + (maxposlb.top - minposlb.bottom) * + (1 - shrink)/2 + minposlb.bottom, + strength='strong') + + # set the width of the pos box + lbpos.constrain_width(lbpos.height * (shrink / aspect), + strength='strong') + elif location in ('bottom', 'top'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightheight=True, + pos=True, + subplot=False, + artist=cax) + + for ax in parents: + if location == 'bottom': + order = [ax._layoutbox, lb] + else: + order = [lb, ax._layoutbox] + layoutbox.vstack(order, padding=pad * gslb.width, + strength='strong') + + # Vertical Layout: need to check all the axes in this gridspec + for ch in gslb.children: + subspec = ch.artist + nrows, ncols, row_start, row_stop, col_start, col_stop = \ + subspec.get_rows_columns() + if location == 'bottom': + if row_stop <= minrow: + order = [subspec._layoutbox, lb] + if row_start > maxrow: + order = [lb, subspec._layoutbox] + elif location == 'top': + if row_stop < minrow: + order = [subspec._layoutbox, lb] + if row_start >= maxrow: + order = [lb, subspec._layoutbox] + layoutbox.vstack(order, padding=pad * gslb.width, + strength='strong') + + # Do horizontal layout... + maxposlb = maxax_col._poslayoutbox + minposlb = minax_col._poslayoutbox + lbpos.constrain_width((maxposlb.right - minposlb.left) * + shrink) + lbpos.constrain_left( + (maxposlb.right - minposlb.left) * + (1-shrink)/2 + minposlb.left) + # set the height of the pos box + lbpos.constrain_height(lbpos.width * shrink * aspect, + strength='medium') + + return lb, lbpos diff --git a/venv/lib/python3.6/site-packages/matplotlib/_contour.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/matplotlib/_contour.cpython-36m-x86_64-linux-gnu.so new file mode 100644 index 0000000..9c106da Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/_contour.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_image.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/matplotlib/_image.cpython-36m-x86_64-linux-gnu.so new file mode 100644 index 0000000..009cd13 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/_image.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_layoutbox.py b/venv/lib/python3.6/site-packages/matplotlib/_layoutbox.py new file mode 100644 index 0000000..4fff13e --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_layoutbox.py @@ -0,0 +1,732 @@ +""" + +Conventions: + +"constrain_x" means to constrain the variable with either +another kiwisolver variable, or a float. i.e. `constrain_width(0.2)` +will set a constraint that the width has to be 0.2 and this constraint is +permanent - i.e. it will not be removed if it becomes obsolete. + +"edit_x" means to set x to a value (just a float), and that this value can +change. So `edit_width(0.2)` will set width to be 0.2, but `edit_width(0.3)` +will allow it to change to 0.3 later. Note that these values are still just +"suggestions" in `kiwisolver` parlance, and could be over-ridden by +other constrains. + +""" + +import itertools +import kiwisolver as kiwi +import logging +import numpy as np + + +_log = logging.getLogger(__name__) + + +# renderers can be complicated +def get_renderer(fig): + if fig._cachedRenderer: + renderer = fig._cachedRenderer + else: + canvas = fig.canvas + if canvas and hasattr(canvas, "get_renderer"): + renderer = canvas.get_renderer() + else: + # not sure if this can happen + # seems to with PDF... + _log.info("constrained_layout : falling back to Agg renderer") + from matplotlib.backends.backend_agg import FigureCanvasAgg + canvas = FigureCanvasAgg(fig) + renderer = canvas.get_renderer() + + return renderer + + +class LayoutBox(object): + """ + Basic rectangle representation using kiwi solver variables + """ + + def __init__(self, parent=None, name='', tightwidth=False, + tightheight=False, artist=None, + lower_left=(0, 0), upper_right=(1, 1), pos=False, + subplot=False, h_pad=None, w_pad=None): + Variable = kiwi.Variable + self.parent = parent + self.name = name + sn = self.name + '_' + if parent is None: + self.solver = kiwi.Solver() + self.constrained_layout_called = 0 + else: + self.solver = parent.solver + self.constrained_layout_called = None + # parent wants to know about this child! + parent.add_child(self) + # keep track of artist associated w/ this layout. Can be none + self.artist = artist + # keep track if this box is supposed to be a pos that is constrained + # by the parent. + self.pos = pos + # keep track of whether we need to match this subplot up with others. + self.subplot = subplot + + # we need the str below for Py 2 which complains the string is unicode + self.top = Variable(str(sn + 'top')) + self.bottom = Variable(str(sn + 'bottom')) + self.left = Variable(str(sn + 'left')) + self.right = Variable(str(sn + 'right')) + + self.width = Variable(str(sn + 'width')) + self.height = Variable(str(sn + 'height')) + self.h_center = Variable(str(sn + 'h_center')) + self.v_center = Variable(str(sn + 'v_center')) + + self.min_width = Variable(str(sn + 'min_width')) + self.min_height = Variable(str(sn + 'min_height')) + self.pref_width = Variable(str(sn + 'pref_width')) + self.pref_height = Variable(str(sn + 'pref_height')) + # margins are only used for axes-position layout boxes. maybe should + # be a separate subclass: + self.left_margin = Variable(str(sn + 'left_margin')) + self.right_margin = Variable(str(sn + 'right_margin')) + self.bottom_margin = Variable(str(sn + 'bottom_margin')) + self.top_margin = Variable(str(sn + 'top_margin')) + # mins + self.left_margin_min = Variable(str(sn + 'left_margin_min')) + self.right_margin_min = Variable(str(sn + 'right_margin_min')) + self.bottom_margin_min = Variable(str(sn + 'bottom_margin_min')) + self.top_margin_min = Variable(str(sn + 'top_margin_min')) + + right, top = upper_right + left, bottom = lower_left + self.tightheight = tightheight + self.tightwidth = tightwidth + self.add_constraints() + self.children = [] + self.subplotspec = None + if self.pos: + self.constrain_margins() + self.h_pad = h_pad + self.w_pad = w_pad + + def constrain_margins(self): + """ + Only do this for pos. This sets a variable distance + margin between the position of the axes and the outer edge of + the axes. + + Margins are variable because they change with the figure size. + + Margin minimums are set to make room for axes decorations. However, + the margins can be larger if we are mathicng the position size to + other axes. + """ + sol = self.solver + + # left + if not sol.hasEditVariable(self.left_margin_min): + sol.addEditVariable(self.left_margin_min, 'strong') + sol.suggestValue(self.left_margin_min, 0.0001) + c = (self.left_margin == self.left - self.parent.left) + self.solver.addConstraint(c | 'required') + c = (self.left_margin >= self.left_margin_min) + self.solver.addConstraint(c | 'strong') + + # right + if not sol.hasEditVariable(self.right_margin_min): + sol.addEditVariable(self.right_margin_min, 'strong') + sol.suggestValue(self.right_margin_min, 0.0001) + c = (self.right_margin == self.parent.right - self.right) + self.solver.addConstraint(c | 'required') + c = (self.right_margin >= self.right_margin_min) + self.solver.addConstraint(c | 'required') + # bottom + if not sol.hasEditVariable(self.bottom_margin_min): + sol.addEditVariable(self.bottom_margin_min, 'strong') + sol.suggestValue(self.bottom_margin_min, 0.0001) + c = (self.bottom_margin == self.bottom - self.parent.bottom) + self.solver.addConstraint(c | 'required') + c = (self.bottom_margin >= self.bottom_margin_min) + self.solver.addConstraint(c | 'required') + # top + if not sol.hasEditVariable(self.top_margin_min): + sol.addEditVariable(self.top_margin_min, 'strong') + sol.suggestValue(self.top_margin_min, 0.0001) + c = (self.top_margin == self.parent.top - self.top) + self.solver.addConstraint(c | 'required') + c = (self.top_margin >= self.top_margin_min) + self.solver.addConstraint(c | 'required') + + def add_child(self, child): + self.children += [child] + + def remove_child(self, child): + try: + self.children.remove(child) + except ValueError: + _log.info("Tried to remove child that doesn't belong to parent") + + def add_constraints(self): + sol = self.solver + # never let width and height go negative. + for i in [self.min_width, self.min_height]: + sol.addEditVariable(i, 1e9) + sol.suggestValue(i, 0.0) + # define relation ships between things thing width and right and left + self.hard_constraints() + # self.soft_constraints() + if self.parent: + self.parent_constrain() + # sol.updateVariables() + + def parent_constrain(self): + parent = self.parent + hc = [self.left >= parent.left, + self.bottom >= parent.bottom, + self.top <= parent.top, + self.right <= parent.right] + for c in hc: + self.solver.addConstraint(c | 'required') + + def hard_constraints(self): + hc = [self.width == self.right - self.left, + self.height == self.top - self.bottom, + self.h_center == (self.left + self.right) * 0.5, + self.v_center == (self.top + self.bottom) * 0.5, + self.width >= self.min_width, + self.height >= self.min_height] + for c in hc: + self.solver.addConstraint(c | 'required') + + def soft_constraints(self): + sol = self.solver + if self.tightwidth: + suggest = 0. + else: + suggest = 20. + c = (self.pref_width == suggest) + for i in c: + sol.addConstraint(i | 'required') + if self.tightheight: + suggest = 0. + else: + suggest = 20. + c = (self.pref_height == suggest) + for i in c: + sol.addConstraint(i | 'required') + + c = [(self.width >= suggest), + (self.height >= suggest)] + for i in c: + sol.addConstraint(i | 150000) + + def set_parent(self, parent): + ''' replace the parent of this with the new parent + ''' + self.parent = parent + self.parent_constrain() + + def constrain_geometry(self, left, bottom, right, top, strength='strong'): + hc = [self.left == left, + self.right == right, + self.bottom == bottom, + self.top == top] + for c in hc: + self.solver.addConstraint(c | strength) + # self.solver.updateVariables() + + def constrain_same(self, other, strength='strong'): + """ + Make the layoutbox have same position as other layoutbox + """ + hc = [self.left == other.left, + self.right == other.right, + self.bottom == other.bottom, + self.top == other.top] + for c in hc: + self.solver.addConstraint(c | strength) + + def constrain_left_margin(self, margin, strength='strong'): + c = (self.left == self.parent.left + margin) + self.solver.addConstraint(c | strength) + + def edit_left_margin_min(self, margin): + self.solver.suggestValue(self.left_margin_min, margin) + + def constrain_right_margin(self, margin, strength='strong'): + c = (self.right == self.parent.right - margin) + self.solver.addConstraint(c | strength) + + def edit_right_margin_min(self, margin): + self.solver.suggestValue(self.right_margin_min, margin) + + def constrain_bottom_margin(self, margin, strength='strong'): + c = (self.bottom == self.parent.bottom + margin) + self.solver.addConstraint(c | strength) + + def edit_bottom_margin_min(self, margin): + self.solver.suggestValue(self.bottom_margin_min, margin) + + def constrain_top_margin(self, margin, strength='strong'): + c = (self.top == self.parent.top - margin) + self.solver.addConstraint(c | strength) + + def edit_top_margin_min(self, margin): + self.solver.suggestValue(self.top_margin_min, margin) + + def get_rect(self): + return (self.left.value(), self.bottom.value(), + self.width.value(), self.height.value()) + + def update_variables(self): + ''' + Update *all* the variables that are part of the solver this LayoutBox + is created with + ''' + self.solver.updateVariables() + + def edit_height(self, height, strength='strong'): + ''' + Set the height of the layout box. + + This is done as an editable variable so that the value can change + due to resizing. + ''' + sol = self.solver + for i in [self.height]: + if not sol.hasEditVariable(i): + sol.addEditVariable(i, strength) + sol.suggestValue(self.height, height) + + def constrain_height(self, height, strength='strong'): + ''' + Constrain the height of the layout box. height is + either a float or a layoutbox.height. + ''' + c = (self.height == height) + self.solver.addConstraint(c | strength) + + def constrain_height_min(self, height, strength='strong'): + c = (self.height >= height) + self.solver.addConstraint(c | strength) + + def edit_width(self, width, strength='strong'): + sol = self.solver + for i in [self.width]: + if not sol.hasEditVariable(i): + sol.addEditVariable(i, strength) + sol.suggestValue(self.width, width) + + def constrain_width(self, width, strength='strong'): + ''' + Constrain the width of the layout box. `width` is + either a float or a layoutbox.width. + ''' + c = (self.width == width) + self.solver.addConstraint(c | strength) + + def constrain_width_min(self, width, strength='strong'): + c = (self.width >= width) + self.solver.addConstraint(c | strength) + + def constrain_left(self, left, strength='strong'): + c = (self.left == left) + self.solver.addConstraint(c | strength) + + def constrain_bottom(self, bottom, strength='strong'): + c = (self.bottom == bottom) + self.solver.addConstraint(c | strength) + + def constrain_right(self, right, strength='strong'): + c = (self.right == right) + self.solver.addConstraint(c | strength) + + def constrain_top(self, top, strength='strong'): + c = (self.top == top) + self.solver.addConstraint(c | strength) + + def _is_subplotspec_layoutbox(self): + ''' + Helper to check if this layoutbox is the layoutbox of a + subplotspec + ''' + name = (self.name).split('.')[-1] + return name[:2] == 'ss' + + def _is_gridspec_layoutbox(self): + ''' + Helper to check if this layoutbox is the layoutbox of a + gridspec + ''' + name = (self.name).split('.')[-1] + return name[:8] == 'gridspec' + + def find_child_subplots(self): + ''' + Find children of this layout box that are subplots. We want to line + poss up, and this is an easy way to find them all. + ''' + if self.subplot: + subplots = [self] + else: + subplots = [] + for child in self.children: + subplots += child.find_child_subplots() + return subplots + + def layout_from_subplotspec(self, subspec, + name='', artist=None, pos=False): + ''' Make a layout box from a subplotspec. The layout box is + constrained to be a fraction of the width/height of the parent, + and be a fraction of the parent width/height from the left/bottom + of the parent. Therefore the parent can move around and the + layout for the subplot spec should move with it. + + The parent is *usually* the gridspec that made the subplotspec.?? + ''' + lb = LayoutBox(parent=self, name=name, artist=artist, pos=pos) + gs = subspec.get_gridspec() + nrows, ncols = gs.get_geometry() + parent = self.parent + + # OK, now, we want to set the position of this subplotspec + # based on its subplotspec parameters. The new gridspec will inherit. + + # from gridspec. prob should be new method in gridspec + left = 0.0 + right = 1.0 + bottom = 0.0 + top = 1.0 + totWidth = right-left + totHeight = top-bottom + hspace = 0. + wspace = 0. + + # calculate accumulated heights of columns + cellH = totHeight / (nrows + hspace * (nrows - 1)) + sepH = hspace*cellH + + if gs._row_height_ratios is not None: + netHeight = cellH * nrows + tr = float(sum(gs._row_height_ratios)) + cellHeights = [netHeight*r/tr for r in gs._row_height_ratios] + else: + cellHeights = [cellH] * nrows + + sepHeights = [0] + ([sepH] * (nrows - 1)) + cellHs = np.add.accumulate(np.ravel( + list(zip(sepHeights, cellHeights)))) + + # calculate accumulated widths of rows + cellW = totWidth/(ncols + wspace * (ncols - 1)) + sepW = wspace*cellW + + if gs._col_width_ratios is not None: + netWidth = cellW * ncols + tr = float(sum(gs._col_width_ratios)) + cellWidths = [netWidth * r / tr for r in gs._col_width_ratios] + else: + cellWidths = [cellW] * ncols + + sepWidths = [0] + ([sepW] * (ncols - 1)) + cellWs = np.add.accumulate(np.ravel(list(zip(sepWidths, cellWidths)))) + + figTops = [top - cellHs[2 * rowNum] for rowNum in range(nrows)] + figBottoms = [top - cellHs[2 * rowNum + 1] for rowNum in range(nrows)] + figLefts = [left + cellWs[2 * colNum] for colNum in range(ncols)] + figRights = [left + cellWs[2 * colNum + 1] for colNum in range(ncols)] + + rowNum, colNum = divmod(subspec.num1, ncols) + figBottom = figBottoms[rowNum] + figTop = figTops[rowNum] + figLeft = figLefts[colNum] + figRight = figRights[colNum] + + if subspec.num2 is not None: + + rowNum2, colNum2 = divmod(subspec.num2, ncols) + figBottom2 = figBottoms[rowNum2] + figTop2 = figTops[rowNum2] + figLeft2 = figLefts[colNum2] + figRight2 = figRights[colNum2] + + figBottom = min(figBottom, figBottom2) + figLeft = min(figLeft, figLeft2) + figTop = max(figTop, figTop2) + figRight = max(figRight, figRight2) + # These are numbers relative to 0,0,1,1. Need to constrain + # relative to parent. + + width = figRight - figLeft + height = figTop - figBottom + parent = self.parent + cs = [self.left == parent.left + parent.width * figLeft, + self.bottom == parent.bottom + parent.height * figBottom, + self.width == parent.width * width, + self.height == parent.height * height] + for c in cs: + self.solver.addConstraint(c | 'required') + + return lb + + def __repr__(self): + args = (self.name, self.left.value(), self.bottom.value(), + self.right.value(), self.top.value()) + return ('LayoutBox: %25s, (left: %1.3f) (bot: %1.3f) ' + '(right: %1.3f) (top: %1.3f) ') % args + + +# Utility functions that act on layoutboxes... +def hstack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from left to right. + `padding` is in figure-relative units. + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].right + padding <= boxes[i].left) + boxes[i].solver.addConstraint(c | strength) + + +def hpack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from left to right. + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].right + padding == boxes[i].left) + boxes[i].solver.addConstraint(c | strength) + + +def vstack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].bottom - padding >= boxes[i].top) + boxes[i].solver.addConstraint(c | strength) + + +def vpack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].bottom - padding >= boxes[i].top) + boxes[i].solver.addConstraint(c | strength) + + +def match_heights(boxes, height_ratios=None, strength='medium'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + if height_ratios is None: + height_ratios = np.ones(len(boxes)) + for i in range(1, len(boxes)): + c = (boxes[i-1].height == + boxes[i].height*height_ratios[i-1]/height_ratios[i]) + boxes[i].solver.addConstraint(c | strength) + + +def match_widths(boxes, width_ratios=None, strength='medium'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + if width_ratios is None: + width_ratios = np.ones(len(boxes)) + for i in range(1, len(boxes)): + c = (boxes[i-1].width == + boxes[i].width*width_ratios[i-1]/width_ratios[i]) + boxes[i].solver.addConstraint(c | strength) + + +def vstackeq(boxes, padding=0, height_ratios=None): + vstack(boxes, padding=padding) + match_heights(boxes, height_ratios=height_ratios) + + +def hstackeq(boxes, padding=0, width_ratios=None): + hstack(boxes, padding=padding) + match_widths(boxes, width_ratios=width_ratios) + + +def align(boxes, attr, strength='strong'): + cons = [] + for box in boxes[1:]: + cons = (getattr(boxes[0], attr) == getattr(box, attr)) + boxes[0].solver.addConstraint(cons | strength) + + +def match_top_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.top-top0.top == box.top-topb.top) + box0.solver.addConstraint(c | 'strong') + + +def match_bottom_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.bottom-top0.bottom == box.bottom-topb.bottom) + box0.solver.addConstraint(c | 'strong') + + +def match_left_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.left-top0.left == box.left-topb.left) + box0.solver.addConstraint(c | 'strong') + + +def match_right_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.right-top0.right == box.right-topb.right) + box0.solver.addConstraint(c | 'strong') + + +def match_width_margins(boxes, levels=1): + match_left_margins(boxes, levels=levels) + match_right_margins(boxes, levels=levels) + + +def match_height_margins(boxes, levels=1): + match_top_margins(boxes, levels=levels) + match_bottom_margins(boxes, levels=levels) + + +def match_margins(boxes, levels=1): + match_width_margins(boxes, levels=levels) + match_height_margins(boxes, levels=levels) + + +_layoutboxobjnum = itertools.count() + + +def seq_id(): + ''' + Generate a short sequential id for layoutbox objects... + ''' + + global _layoutboxobjnum + + return ('%06d' % (next(_layoutboxobjnum))) + + +def print_children(lb): + ''' + Print the children of the layoutbox + ''' + print(lb) + for child in lb.children: + print_children(child) + + +def nonetree(lb): + ''' + Make all elements in this tree none... This signals not to do any more + layout. + ''' + if lb is not None: + if lb.parent is None: + # Clear the solver. Hopefully this garbage collects. + lb.solver.reset() + nonechildren(lb) + else: + nonetree(lb.parent) + + +def nonechildren(lb): + for child in lb.children: + nonechildren(child) + lb.artist._layoutbox = None + lb = None + + +def print_tree(lb): + ''' + Print the tree of layoutboxes + ''' + + if lb.parent is None: + print('LayoutBox Tree\n') + print('==============\n') + print_children(lb) + print('\n') + else: + print_tree(lb.parent) + + +def plot_children(fig, box, level=0, printit=True): + ''' + Simple plotting to show where boxes are + ''' + import matplotlib + import matplotlib.pyplot as plt + + if isinstance(fig, matplotlib.figure.Figure): + ax = fig.add_axes([0., 0., 1., 1.]) + ax.set_facecolor([1., 1., 1., 0.7]) + ax.set_alpha(0.3) + fig.draw(fig.canvas.get_renderer()) + else: + ax = fig + + import matplotlib.patches as patches + colors = plt.rcParams["axes.prop_cycle"].by_key()["color"] + if printit: + print("Level:", level) + for child in box.children: + if printit: + print(child) + ax.add_patch( + patches.Rectangle( + (child.left.value(), child.bottom.value()), # (x,y) + child.width.value(), # width + child.height.value(), # height + fc='none', + alpha=0.8, + ec=colors[level] + ) + ) + if level > 0: + name = child.name.split('.')[-1] + if level % 2 == 0: + ax.text(child.left.value(), child.bottom.value(), name, + size=12-level, color=colors[level]) + else: + ax.text(child.right.value(), child.top.value(), name, + ha='right', va='top', size=12-level, + color=colors[level]) + + plot_children(ax, child, level=level+1, printit=printit) diff --git a/venv/lib/python3.6/site-packages/matplotlib/_mathtext_data.py b/venv/lib/python3.6/site-packages/matplotlib/_mathtext_data.py new file mode 100644 index 0000000..baefe1b --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_mathtext_data.py @@ -0,0 +1,2544 @@ +""" +font data tables for truetype and afm computer modern fonts +""" + +latex_to_bakoma = { + '\\__sqrt__' : ('cmex10', 0x70), + '\\bigcap' : ('cmex10', 0x5c), + '\\bigcup' : ('cmex10', 0x5b), + '\\bigodot' : ('cmex10', 0x4b), + '\\bigoplus' : ('cmex10', 0x4d), + '\\bigotimes' : ('cmex10', 0x4f), + '\\biguplus' : ('cmex10', 0x5d), + '\\bigvee' : ('cmex10', 0x5f), + '\\bigwedge' : ('cmex10', 0x5e), + '\\coprod' : ('cmex10', 0x61), + '\\int' : ('cmex10', 0x5a), + '\\langle' : ('cmex10', 0xad), + '\\leftangle' : ('cmex10', 0xad), + '\\leftbrace' : ('cmex10', 0xa9), + '\\oint' : ('cmex10', 0x49), + '\\prod' : ('cmex10', 0x59), + '\\rangle' : ('cmex10', 0xae), + '\\rightangle' : ('cmex10', 0xae), + '\\rightbrace' : ('cmex10', 0xaa), + '\\sum' : ('cmex10', 0x58), + '\\widehat' : ('cmex10', 0x62), + '\\widetilde' : ('cmex10', 0x65), + '\\{' : ('cmex10', 0xa9), + '\\}' : ('cmex10', 0xaa), + '{' : ('cmex10', 0xa9), + '}' : ('cmex10', 0xaa), + + ',' : ('cmmi10', 0x3b), + '.' : ('cmmi10', 0x3a), + '/' : ('cmmi10', 0x3d), + '<' : ('cmmi10', 0x3c), + '>' : ('cmmi10', 0x3e), + '\\alpha' : ('cmmi10', 0xae), + '\\beta' : ('cmmi10', 0xaf), + '\\chi' : ('cmmi10', 0xc2), + '\\combiningrightarrowabove' : ('cmmi10', 0x7e), + '\\delta' : ('cmmi10', 0xb1), + '\\ell' : ('cmmi10', 0x60), + '\\epsilon' : ('cmmi10', 0xb2), + '\\eta' : ('cmmi10', 0xb4), + '\\flat' : ('cmmi10', 0x5b), + '\\frown' : ('cmmi10', 0x5f), + '\\gamma' : ('cmmi10', 0xb0), + '\\imath' : ('cmmi10', 0x7b), + '\\iota' : ('cmmi10', 0xb6), + '\\jmath' : ('cmmi10', 0x7c), + '\\kappa' : ('cmmi10', 0x2219), + '\\lambda' : ('cmmi10', 0xb8), + '\\leftharpoondown' : ('cmmi10', 0x29), + '\\leftharpoonup' : ('cmmi10', 0x28), + '\\mu' : ('cmmi10', 0xb9), + '\\natural' : ('cmmi10', 0x5c), + '\\nu' : ('cmmi10', 0xba), + '\\omega' : ('cmmi10', 0x21), + '\\phi' : ('cmmi10', 0xc1), + '\\pi' : ('cmmi10', 0xbc), + '\\psi' : ('cmmi10', 0xc3), + '\\rho' : ('cmmi10', 0xbd), + '\\rightharpoondown' : ('cmmi10', 0x2b), + '\\rightharpoonup' : ('cmmi10', 0x2a), + '\\sharp' : ('cmmi10', 0x5d), + '\\sigma' : ('cmmi10', 0xbe), + '\\smile' : ('cmmi10', 0x5e), + '\\tau' : ('cmmi10', 0xbf), + '\\theta' : ('cmmi10', 0xb5), + '\\triangleleft' : ('cmmi10', 0x2f), + '\\triangleright' : ('cmmi10', 0x2e), + '\\upsilon' : ('cmmi10', 0xc0), + '\\varepsilon' : ('cmmi10', 0x22), + '\\varphi' : ('cmmi10', 0x27), + '\\varrho' : ('cmmi10', 0x25), + '\\varsigma' : ('cmmi10', 0x26), + '\\vartheta' : ('cmmi10', 0x23), + '\\wp' : ('cmmi10', 0x7d), + '\\xi' : ('cmmi10', 0xbb), + '\\zeta' : ('cmmi10', 0xb3), + + '!' : ('cmr10', 0x21), + '%' : ('cmr10', 0x25), + '&' : ('cmr10', 0x26), + '(' : ('cmr10', 0x28), + ')' : ('cmr10', 0x29), + '+' : ('cmr10', 0x2b), + '0' : ('cmr10', 0x30), + '1' : ('cmr10', 0x31), + '2' : ('cmr10', 0x32), + '3' : ('cmr10', 0x33), + '4' : ('cmr10', 0x34), + '5' : ('cmr10', 0x35), + '6' : ('cmr10', 0x36), + '7' : ('cmr10', 0x37), + '8' : ('cmr10', 0x38), + '9' : ('cmr10', 0x39), + ':' : ('cmr10', 0x3a), + ';' : ('cmr10', 0x3b), + '=' : ('cmr10', 0x3d), + '?' : ('cmr10', 0x3f), + '@' : ('cmr10', 0x40), + '[' : ('cmr10', 0x5b), + '\\#' : ('cmr10', 0x23), + '\\$' : ('cmr10', 0x24), + '\\%' : ('cmr10', 0x25), + '\\Delta' : ('cmr10', 0xa2), + '\\Gamma' : ('cmr10', 0xa1), + '\\Lambda' : ('cmr10', 0xa4), + '\\Omega' : ('cmr10', 0xad), + '\\Phi' : ('cmr10', 0xa9), + '\\Pi' : ('cmr10', 0xa6), + '\\Psi' : ('cmr10', 0xaa), + '\\Sigma' : ('cmr10', 0xa7), + '\\Theta' : ('cmr10', 0xa3), + '\\Upsilon' : ('cmr10', 0xa8), + '\\Xi' : ('cmr10', 0xa5), + '\\circumflexaccent' : ('cmr10', 0x5e), + '\\combiningacuteaccent' : ('cmr10', 0xb6), + '\\combiningbreve' : ('cmr10', 0xb8), + '\\combiningdiaeresis' : ('cmr10', 0xc4), + '\\combiningdotabove' : ('cmr10', 0x5f), + '\\combininggraveaccent' : ('cmr10', 0xb5), + '\\combiningoverline' : ('cmr10', 0xb9), + '\\combiningtilde' : ('cmr10', 0x7e), + '\\leftbracket' : ('cmr10', 0x5b), + '\\leftparen' : ('cmr10', 0x28), + '\\rightbracket' : ('cmr10', 0x5d), + '\\rightparen' : ('cmr10', 0x29), + '\\widebar' : ('cmr10', 0xb9), + ']' : ('cmr10', 0x5d), + + '*' : ('cmsy10', 0xa4), + '-' : ('cmsy10', 0xa1), + '\\Downarrow' : ('cmsy10', 0x2b), + '\\Im' : ('cmsy10', 0x3d), + '\\Leftarrow' : ('cmsy10', 0x28), + '\\Leftrightarrow' : ('cmsy10', 0x2c), + '\\P' : ('cmsy10', 0x7b), + '\\Re' : ('cmsy10', 0x3c), + '\\Rightarrow' : ('cmsy10', 0x29), + '\\S' : ('cmsy10', 0x78), + '\\Uparrow' : ('cmsy10', 0x2a), + '\\Updownarrow' : ('cmsy10', 0x6d), + '\\Vert' : ('cmsy10', 0x6b), + '\\aleph' : ('cmsy10', 0x40), + '\\approx' : ('cmsy10', 0xbc), + '\\ast' : ('cmsy10', 0xa4), + '\\asymp' : ('cmsy10', 0xb3), + '\\backslash' : ('cmsy10', 0x6e), + '\\bigcirc' : ('cmsy10', 0xb0), + '\\bigtriangledown' : ('cmsy10', 0x35), + '\\bigtriangleup' : ('cmsy10', 0x34), + '\\bot' : ('cmsy10', 0x3f), + '\\bullet' : ('cmsy10', 0xb2), + '\\cap' : ('cmsy10', 0x5c), + '\\cdot' : ('cmsy10', 0xa2), + '\\circ' : ('cmsy10', 0xb1), + '\\clubsuit' : ('cmsy10', 0x7c), + '\\cup' : ('cmsy10', 0x5b), + '\\dag' : ('cmsy10', 0x79), + '\\dashv' : ('cmsy10', 0x61), + '\\ddag' : ('cmsy10', 0x7a), + '\\diamond' : ('cmsy10', 0xa6), + '\\diamondsuit' : ('cmsy10', 0x7d), + '\\div' : ('cmsy10', 0xa5), + '\\downarrow' : ('cmsy10', 0x23), + '\\emptyset' : ('cmsy10', 0x3b), + '\\equiv' : ('cmsy10', 0xb4), + '\\exists' : ('cmsy10', 0x39), + '\\forall' : ('cmsy10', 0x38), + '\\geq' : ('cmsy10', 0xb8), + '\\gg' : ('cmsy10', 0xc0), + '\\heartsuit' : ('cmsy10', 0x7e), + '\\in' : ('cmsy10', 0x32), + '\\infty' : ('cmsy10', 0x31), + '\\lbrace' : ('cmsy10', 0x66), + '\\lceil' : ('cmsy10', 0x64), + '\\leftarrow' : ('cmsy10', 0xc3), + '\\leftrightarrow' : ('cmsy10', 0x24), + '\\leq' : ('cmsy10', 0x2219), + '\\lfloor' : ('cmsy10', 0x62), + '\\ll' : ('cmsy10', 0xbf), + '\\mid' : ('cmsy10', 0x6a), + '\\mp' : ('cmsy10', 0xa8), + '\\nabla' : ('cmsy10', 0x72), + '\\nearrow' : ('cmsy10', 0x25), + '\\neg' : ('cmsy10', 0x3a), + '\\ni' : ('cmsy10', 0x33), + '\\nwarrow' : ('cmsy10', 0x2d), + '\\odot' : ('cmsy10', 0xaf), + '\\ominus' : ('cmsy10', 0xaa), + '\\oplus' : ('cmsy10', 0xa9), + '\\oslash' : ('cmsy10', 0xae), + '\\otimes' : ('cmsy10', 0xad), + '\\pm' : ('cmsy10', 0xa7), + '\\prec' : ('cmsy10', 0xc1), + '\\preceq' : ('cmsy10', 0xb9), + '\\prime' : ('cmsy10', 0x30), + '\\propto' : ('cmsy10', 0x2f), + '\\rbrace' : ('cmsy10', 0x67), + '\\rceil' : ('cmsy10', 0x65), + '\\rfloor' : ('cmsy10', 0x63), + '\\rightarrow' : ('cmsy10', 0x21), + '\\searrow' : ('cmsy10', 0x26), + '\\sim' : ('cmsy10', 0xbb), + '\\simeq' : ('cmsy10', 0x27), + '\\slash' : ('cmsy10', 0x36), + '\\spadesuit' : ('cmsy10', 0xc4), + '\\sqcap' : ('cmsy10', 0x75), + '\\sqcup' : ('cmsy10', 0x74), + '\\sqsubseteq' : ('cmsy10', 0x76), + '\\sqsupseteq' : ('cmsy10', 0x77), + '\\subset' : ('cmsy10', 0xbd), + '\\subseteq' : ('cmsy10', 0xb5), + '\\succ' : ('cmsy10', 0xc2), + '\\succeq' : ('cmsy10', 0xba), + '\\supset' : ('cmsy10', 0xbe), + '\\supseteq' : ('cmsy10', 0xb6), + '\\swarrow' : ('cmsy10', 0x2e), + '\\times' : ('cmsy10', 0xa3), + '\\to' : ('cmsy10', 0x21), + '\\top' : ('cmsy10', 0x3e), + '\\uparrow' : ('cmsy10', 0x22), + '\\updownarrow' : ('cmsy10', 0x6c), + '\\uplus' : ('cmsy10', 0x5d), + '\\vdash' : ('cmsy10', 0x60), + '\\vee' : ('cmsy10', 0x5f), + '\\vert' : ('cmsy10', 0x6a), + '\\wedge' : ('cmsy10', 0x5e), + '\\wr' : ('cmsy10', 0x6f), + '\\|' : ('cmsy10', 0x6b), + '|' : ('cmsy10', 0x6a), + + '\\_' : ('cmtt10', 0x5f) +} + +latex_to_cmex = { + r'\__sqrt__' : 112, + r'\bigcap' : 92, + r'\bigcup' : 91, + r'\bigodot' : 75, + r'\bigoplus' : 77, + r'\bigotimes' : 79, + r'\biguplus' : 93, + r'\bigvee' : 95, + r'\bigwedge' : 94, + r'\coprod' : 97, + r'\int' : 90, + r'\leftangle' : 173, + r'\leftbrace' : 169, + r'\oint' : 73, + r'\prod' : 89, + r'\rightangle' : 174, + r'\rightbrace' : 170, + r'\sum' : 88, + r'\widehat' : 98, + r'\widetilde' : 101, +} + +latex_to_standard = { + r'\cong' : ('psyr', 64), + r'\Delta' : ('psyr', 68), + r'\Phi' : ('psyr', 70), + r'\Gamma' : ('psyr', 89), + r'\alpha' : ('psyr', 97), + r'\beta' : ('psyr', 98), + r'\chi' : ('psyr', 99), + r'\delta' : ('psyr', 100), + r'\varepsilon' : ('psyr', 101), + r'\phi' : ('psyr', 102), + r'\gamma' : ('psyr', 103), + r'\eta' : ('psyr', 104), + r'\iota' : ('psyr', 105), + r'\varpsi' : ('psyr', 106), + r'\kappa' : ('psyr', 108), + r'\nu' : ('psyr', 110), + r'\pi' : ('psyr', 112), + r'\theta' : ('psyr', 113), + r'\rho' : ('psyr', 114), + r'\sigma' : ('psyr', 115), + r'\tau' : ('psyr', 116), + r'\upsilon' : ('psyr', 117), + r'\varpi' : ('psyr', 118), + r'\omega' : ('psyr', 119), + r'\xi' : ('psyr', 120), + r'\psi' : ('psyr', 121), + r'\zeta' : ('psyr', 122), + r'\sim' : ('psyr', 126), + r'\leq' : ('psyr', 163), + r'\infty' : ('psyr', 165), + r'\clubsuit' : ('psyr', 167), + r'\diamondsuit' : ('psyr', 168), + r'\heartsuit' : ('psyr', 169), + r'\spadesuit' : ('psyr', 170), + r'\leftrightarrow' : ('psyr', 171), + r'\leftarrow' : ('psyr', 172), + r'\uparrow' : ('psyr', 173), + r'\rightarrow' : ('psyr', 174), + r'\downarrow' : ('psyr', 175), + r'\pm' : ('psyr', 176), + r'\geq' : ('psyr', 179), + r'\times' : ('psyr', 180), + r'\propto' : ('psyr', 181), + r'\partial' : ('psyr', 182), + r'\bullet' : ('psyr', 183), + r'\div' : ('psyr', 184), + r'\neq' : ('psyr', 185), + r'\equiv' : ('psyr', 186), + r'\approx' : ('psyr', 187), + r'\ldots' : ('psyr', 188), + r'\aleph' : ('psyr', 192), + r'\Im' : ('psyr', 193), + r'\Re' : ('psyr', 194), + r'\wp' : ('psyr', 195), + r'\otimes' : ('psyr', 196), + r'\oplus' : ('psyr', 197), + r'\oslash' : ('psyr', 198), + r'\cap' : ('psyr', 199), + r'\cup' : ('psyr', 200), + r'\supset' : ('psyr', 201), + r'\supseteq' : ('psyr', 202), + r'\subset' : ('psyr', 204), + r'\subseteq' : ('psyr', 205), + r'\in' : ('psyr', 206), + r'\notin' : ('psyr', 207), + r'\angle' : ('psyr', 208), + r'\nabla' : ('psyr', 209), + r'\textregistered' : ('psyr', 210), + r'\copyright' : ('psyr', 211), + r'\texttrademark' : ('psyr', 212), + r'\Pi' : ('psyr', 213), + r'\prod' : ('psyr', 213), + r'\surd' : ('psyr', 214), + r'\__sqrt__' : ('psyr', 214), + r'\cdot' : ('psyr', 215), + r'\urcorner' : ('psyr', 216), + r'\vee' : ('psyr', 217), + r'\wedge' : ('psyr', 218), + r'\Leftrightarrow' : ('psyr', 219), + r'\Leftarrow' : ('psyr', 220), + r'\Uparrow' : ('psyr', 221), + r'\Rightarrow' : ('psyr', 222), + r'\Downarrow' : ('psyr', 223), + r'\Diamond' : ('psyr', 224), + r'\Sigma' : ('psyr', 229), + r'\sum' : ('psyr', 229), + r'\forall' : ('psyr', 34), + r'\exists' : ('psyr', 36), + r'\lceil' : ('psyr', 233), + r'\lbrace' : ('psyr', 123), + r'\Psi' : ('psyr', 89), + r'\bot' : ('psyr', 0o136), + r'\Omega' : ('psyr', 0o127), + r'\leftbracket' : ('psyr', 0o133), + r'\rightbracket' : ('psyr', 0o135), + r'\leftbrace' : ('psyr', 123), + r'\leftparen' : ('psyr', 0o50), + r'\prime' : ('psyr', 0o242), + r'\sharp' : ('psyr', 0o43), + r'\slash' : ('psyr', 0o57), + r'\Lamda' : ('psyr', 0o114), + r'\neg' : ('psyr', 0o330), + r'\Upsilon' : ('psyr', 0o241), + r'\rightbrace' : ('psyr', 0o175), + r'\rfloor' : ('psyr', 0o373), + r'\lambda' : ('psyr', 0o154), + r'\to' : ('psyr', 0o256), + r'\Xi' : ('psyr', 0o130), + r'\emptyset' : ('psyr', 0o306), + r'\lfloor' : ('psyr', 0o353), + r'\rightparen' : ('psyr', 0o51), + r'\rceil' : ('psyr', 0o371), + r'\ni' : ('psyr', 0o47), + r'\epsilon' : ('psyr', 0o145), + r'\Theta' : ('psyr', 0o121), + r'\langle' : ('psyr', 0o341), + r'\leftangle' : ('psyr', 0o341), + r'\rangle' : ('psyr', 0o361), + r'\rightangle' : ('psyr', 0o361), + r'\rbrace' : ('psyr', 0o175), + r'\circ' : ('psyr', 0o260), + r'\diamond' : ('psyr', 0o340), + r'\mu' : ('psyr', 0o155), + r'\mid' : ('psyr', 0o352), + r'\imath' : ('pncri8a', 105), + r'\%' : ('pncr8a', 37), + r'\$' : ('pncr8a', 36), + r'\{' : ('pncr8a', 123), + r'\}' : ('pncr8a', 125), + r'\backslash' : ('pncr8a', 92), + r'\ast' : ('pncr8a', 42), + r'\#' : ('pncr8a', 35), + + r'\circumflexaccent' : ('pncri8a', 124), # for \hat + r'\combiningbreve' : ('pncri8a', 81), # for \breve + r'\combininggraveaccent' : ('pncri8a', 114), # for \grave + r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute + r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot + r'\combiningtilde' : ('pncri8a', 75), # for \tilde + r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec + r'\combiningdotabove' : ('pncri8a', 26), # for \dot +} + +# Automatically generated. + +type12uni = { + 'uni24C8' : 9416, + 'aring' : 229, + 'uni22A0' : 8864, + 'uni2292' : 8850, + 'quotedblright' : 8221, + 'uni03D2' : 978, + 'uni2215' : 8725, + 'uni03D0' : 976, + 'V' : 86, + 'dollar' : 36, + 'uni301E' : 12318, + 'uni03D5' : 981, + 'four' : 52, + 'uni25A0' : 9632, + 'uni013C' : 316, + 'uni013B' : 315, + 'uni013E' : 318, + 'Yacute' : 221, + 'uni25DE' : 9694, + 'uni013F' : 319, + 'uni255A' : 9562, + 'uni2606' : 9734, + 'uni0180' : 384, + 'uni22B7' : 8887, + 'uni044F' : 1103, + 'uni22B5' : 8885, + 'uni22B4' : 8884, + 'uni22AE' : 8878, + 'uni22B2' : 8882, + 'uni22B1' : 8881, + 'uni22B0' : 8880, + 'uni25CD' : 9677, + 'uni03CE' : 974, + 'uni03CD' : 973, + 'uni03CC' : 972, + 'uni03CB' : 971, + 'uni03CA' : 970, + 'uni22B8' : 8888, + 'uni22C9' : 8905, + 'uni0449' : 1097, + 'uni20DD' : 8413, + 'uni20DC' : 8412, + 'uni20DB' : 8411, + 'uni2231' : 8753, + 'uni25CF' : 9679, + 'uni306E' : 12398, + 'uni03D1' : 977, + 'uni01A1' : 417, + 'uni20D7' : 8407, + 'uni03D6' : 982, + 'uni2233' : 8755, + 'uni20D2' : 8402, + 'uni20D1' : 8401, + 'uni20D0' : 8400, + 'P' : 80, + 'uni22BE' : 8894, + 'uni22BD' : 8893, + 'uni22BC' : 8892, + 'uni22BB' : 8891, + 'underscore' : 95, + 'uni03C8' : 968, + 'uni03C7' : 967, + 'uni0328' : 808, + 'uni03C5' : 965, + 'uni03C4' : 964, + 'uni03C3' : 963, + 'uni03C2' : 962, + 'uni03C1' : 961, + 'uni03C0' : 960, + 'uni2010' : 8208, + 'uni0130' : 304, + 'uni0133' : 307, + 'uni0132' : 306, + 'uni0135' : 309, + 'uni0134' : 308, + 'uni0137' : 311, + 'uni0136' : 310, + 'uni0139' : 313, + 'uni0138' : 312, + 'uni2244' : 8772, + 'uni229A' : 8858, + 'uni2571' : 9585, + 'uni0278' : 632, + 'uni2239' : 8761, + 'p' : 112, + 'uni3019' : 12313, + 'uni25CB' : 9675, + 'uni03DB' : 987, + 'uni03DC' : 988, + 'uni03DA' : 986, + 'uni03DF' : 991, + 'uni03DD' : 989, + 'uni013D' : 317, + 'uni220A' : 8714, + 'uni220C' : 8716, + 'uni220B' : 8715, + 'uni220E' : 8718, + 'uni220D' : 8717, + 'uni220F' : 8719, + 'uni22CC' : 8908, + 'Otilde' : 213, + 'uni25E5' : 9701, + 'uni2736' : 10038, + 'perthousand' : 8240, + 'zero' : 48, + 'uni279B' : 10139, + 'dotlessi' : 305, + 'uni2279' : 8825, + 'Scaron' : 352, + 'zcaron' : 382, + 'uni21D8' : 8664, + 'egrave' : 232, + 'uni0271' : 625, + 'uni01AA' : 426, + 'uni2332' : 9010, + 'section' : 167, + 'uni25E4' : 9700, + 'Icircumflex' : 206, + 'ntilde' : 241, + 'uni041E' : 1054, + 'ampersand' : 38, + 'uni041C' : 1052, + 'uni041A' : 1050, + 'uni22AB' : 8875, + 'uni21DB' : 8667, + 'dotaccent' : 729, + 'uni0416' : 1046, + 'uni0417' : 1047, + 'uni0414' : 1044, + 'uni0415' : 1045, + 'uni0412' : 1042, + 'uni0413' : 1043, + 'degree' : 176, + 'uni0411' : 1041, + 'K' : 75, + 'uni25EB' : 9707, + 'uni25EF' : 9711, + 'uni0418' : 1048, + 'uni0419' : 1049, + 'uni2263' : 8803, + 'uni226E' : 8814, + 'uni2251' : 8785, + 'uni02C8' : 712, + 'uni2262' : 8802, + 'acircumflex' : 226, + 'uni22B3' : 8883, + 'uni2261' : 8801, + 'uni2394' : 9108, + 'Aring' : 197, + 'uni2260' : 8800, + 'uni2254' : 8788, + 'uni0436' : 1078, + 'uni2267' : 8807, + 'k' : 107, + 'uni22C8' : 8904, + 'uni226A' : 8810, + 'uni231F' : 8991, + 'smalltilde' : 732, + 'uni2201' : 8705, + 'uni2200' : 8704, + 'uni2203' : 8707, + 'uni02BD' : 701, + 'uni2205' : 8709, + 'uni2204' : 8708, + 'Agrave' : 192, + 'uni2206' : 8710, + 'uni2209' : 8713, + 'uni2208' : 8712, + 'uni226D' : 8813, + 'uni2264' : 8804, + 'uni263D' : 9789, + 'uni2258' : 8792, + 'uni02D3' : 723, + 'uni02D2' : 722, + 'uni02D1' : 721, + 'uni02D0' : 720, + 'uni25E1' : 9697, + 'divide' : 247, + 'uni02D5' : 725, + 'uni02D4' : 724, + 'ocircumflex' : 244, + 'uni2524' : 9508, + 'uni043A' : 1082, + 'uni24CC' : 9420, + 'asciitilde' : 126, + 'uni22B9' : 8889, + 'uni24D2' : 9426, + 'uni211E' : 8478, + 'uni211D' : 8477, + 'uni24DD' : 9437, + 'uni211A' : 8474, + 'uni211C' : 8476, + 'uni211B' : 8475, + 'uni25C6' : 9670, + 'uni017F' : 383, + 'uni017A' : 378, + 'uni017C' : 380, + 'uni017B' : 379, + 'uni0346' : 838, + 'uni22F1' : 8945, + 'uni22F0' : 8944, + 'two' : 50, + 'uni2298' : 8856, + 'uni24D1' : 9425, + 'E' : 69, + 'uni025D' : 605, + 'scaron' : 353, + 'uni2322' : 8994, + 'uni25E3' : 9699, + 'uni22BF' : 8895, + 'F' : 70, + 'uni0440' : 1088, + 'uni255E' : 9566, + 'uni22BA' : 8890, + 'uni0175' : 373, + 'uni0174' : 372, + 'uni0177' : 375, + 'uni0176' : 374, + 'bracketleft' : 91, + 'uni0170' : 368, + 'uni0173' : 371, + 'uni0172' : 370, + 'asciicircum' : 94, + 'uni0179' : 377, + 'uni2590' : 9616, + 'uni25E2' : 9698, + 'uni2119' : 8473, + 'uni2118' : 8472, + 'uni25CC' : 9676, + 'f' : 102, + 'ordmasculine' : 186, + 'uni229B' : 8859, + 'uni22A1' : 8865, + 'uni2111' : 8465, + 'uni2110' : 8464, + 'uni2113' : 8467, + 'uni2112' : 8466, + 'mu' : 181, + 'uni2281' : 8833, + 'paragraph' : 182, + 'nine' : 57, + 'uni25EC' : 9708, + 'v' : 118, + 'uni040C' : 1036, + 'uni0113' : 275, + 'uni22D0' : 8912, + 'uni21CC' : 8652, + 'uni21CB' : 8651, + 'uni21CA' : 8650, + 'uni22A5' : 8869, + 'uni21CF' : 8655, + 'uni21CE' : 8654, + 'uni21CD' : 8653, + 'guilsinglleft' : 8249, + 'backslash' : 92, + 'uni2284' : 8836, + 'uni224E' : 8782, + 'uni224D' : 8781, + 'uni224F' : 8783, + 'uni224A' : 8778, + 'uni2287' : 8839, + 'uni224C' : 8780, + 'uni224B' : 8779, + 'uni21BD' : 8637, + 'uni2286' : 8838, + 'uni030F' : 783, + 'uni030D' : 781, + 'uni030E' : 782, + 'uni030B' : 779, + 'uni030C' : 780, + 'uni030A' : 778, + 'uni026E' : 622, + 'uni026D' : 621, + 'six' : 54, + 'uni026A' : 618, + 'uni026C' : 620, + 'uni25C1' : 9665, + 'uni20D6' : 8406, + 'uni045B' : 1115, + 'uni045C' : 1116, + 'uni256B' : 9579, + 'uni045A' : 1114, + 'uni045F' : 1119, + 'uni045E' : 1118, + 'A' : 65, + 'uni2569' : 9577, + 'uni0458' : 1112, + 'uni0459' : 1113, + 'uni0452' : 1106, + 'uni0453' : 1107, + 'uni2562' : 9570, + 'uni0451' : 1105, + 'uni0456' : 1110, + 'uni0457' : 1111, + 'uni0454' : 1108, + 'uni0455' : 1109, + 'icircumflex' : 238, + 'uni0307' : 775, + 'uni0304' : 772, + 'uni0305' : 773, + 'uni0269' : 617, + 'uni0268' : 616, + 'uni0300' : 768, + 'uni0301' : 769, + 'uni0265' : 613, + 'uni0264' : 612, + 'uni0267' : 615, + 'uni0266' : 614, + 'uni0261' : 609, + 'uni0260' : 608, + 'uni0263' : 611, + 'uni0262' : 610, + 'a' : 97, + 'uni2207' : 8711, + 'uni2247' : 8775, + 'uni2246' : 8774, + 'uni2241' : 8769, + 'uni2240' : 8768, + 'uni2243' : 8771, + 'uni2242' : 8770, + 'uni2312' : 8978, + 'ogonek' : 731, + 'uni2249' : 8777, + 'uni2248' : 8776, + 'uni3030' : 12336, + 'q' : 113, + 'uni21C2' : 8642, + 'uni21C1' : 8641, + 'uni21C0' : 8640, + 'uni21C7' : 8647, + 'uni21C6' : 8646, + 'uni21C5' : 8645, + 'uni21C4' : 8644, + 'uni225F' : 8799, + 'uni212C' : 8492, + 'uni21C8' : 8648, + 'uni2467' : 9319, + 'oacute' : 243, + 'uni028F' : 655, + 'uni028E' : 654, + 'uni026F' : 623, + 'uni028C' : 652, + 'uni028B' : 651, + 'uni028A' : 650, + 'uni2510' : 9488, + 'ograve' : 242, + 'edieresis' : 235, + 'uni22CE' : 8910, + 'uni22CF' : 8911, + 'uni219F' : 8607, + 'comma' : 44, + 'uni22CA' : 8906, + 'uni0429' : 1065, + 'uni03C6' : 966, + 'uni0427' : 1063, + 'uni0426' : 1062, + 'uni0425' : 1061, + 'uni0424' : 1060, + 'uni0423' : 1059, + 'uni0422' : 1058, + 'uni0421' : 1057, + 'uni0420' : 1056, + 'uni2465' : 9317, + 'uni24D0' : 9424, + 'uni2464' : 9316, + 'uni0430' : 1072, + 'otilde' : 245, + 'uni2661' : 9825, + 'uni24D6' : 9430, + 'uni2466' : 9318, + 'uni24D5' : 9429, + 'uni219A' : 8602, + 'uni2518' : 9496, + 'uni22B6' : 8886, + 'uni2461' : 9313, + 'uni24D4' : 9428, + 'uni2460' : 9312, + 'uni24EA' : 9450, + 'guillemotright' : 187, + 'ecircumflex' : 234, + 'greater' : 62, + 'uni2011' : 8209, + 'uacute' : 250, + 'uni2462' : 9314, + 'L' : 76, + 'bullet' : 8226, + 'uni02A4' : 676, + 'uni02A7' : 679, + 'cedilla' : 184, + 'uni02A2' : 674, + 'uni2015' : 8213, + 'uni22C4' : 8900, + 'uni22C5' : 8901, + 'uni22AD' : 8877, + 'uni22C7' : 8903, + 'uni22C0' : 8896, + 'uni2016' : 8214, + 'uni22C2' : 8898, + 'uni22C3' : 8899, + 'uni24CF' : 9423, + 'uni042F' : 1071, + 'uni042E' : 1070, + 'uni042D' : 1069, + 'ydieresis' : 255, + 'l' : 108, + 'logicalnot' : 172, + 'uni24CA' : 9418, + 'uni0287' : 647, + 'uni0286' : 646, + 'uni0285' : 645, + 'uni0284' : 644, + 'uni0283' : 643, + 'uni0282' : 642, + 'uni0281' : 641, + 'uni027C' : 636, + 'uni2664' : 9828, + 'exclamdown' : 161, + 'uni25C4' : 9668, + 'uni0289' : 649, + 'uni0288' : 648, + 'uni039A' : 922, + 'endash' : 8211, + 'uni2640' : 9792, + 'uni20E4' : 8420, + 'uni0473' : 1139, + 'uni20E1' : 8417, + 'uni2642' : 9794, + 'uni03B8' : 952, + 'uni03B9' : 953, + 'agrave' : 224, + 'uni03B4' : 948, + 'uni03B5' : 949, + 'uni03B6' : 950, + 'uni03B7' : 951, + 'uni03B0' : 944, + 'uni03B1' : 945, + 'uni03B2' : 946, + 'uni03B3' : 947, + 'uni2555' : 9557, + 'Adieresis' : 196, + 'germandbls' : 223, + 'Odieresis' : 214, + 'space' : 32, + 'uni0126' : 294, + 'uni0127' : 295, + 'uni0124' : 292, + 'uni0125' : 293, + 'uni0122' : 290, + 'uni0123' : 291, + 'uni0120' : 288, + 'uni0121' : 289, + 'quoteright' : 8217, + 'uni2560' : 9568, + 'uni2556' : 9558, + 'ucircumflex' : 251, + 'uni2561' : 9569, + 'uni2551' : 9553, + 'uni25B2' : 9650, + 'uni2550' : 9552, + 'uni2563' : 9571, + 'uni2553' : 9555, + 'G' : 71, + 'uni2564' : 9572, + 'uni2552' : 9554, + 'quoteleft' : 8216, + 'uni2565' : 9573, + 'uni2572' : 9586, + 'uni2568' : 9576, + 'uni2566' : 9574, + 'W' : 87, + 'uni214A' : 8522, + 'uni012F' : 303, + 'uni012D' : 301, + 'uni012E' : 302, + 'uni012B' : 299, + 'uni012C' : 300, + 'uni255C' : 9564, + 'uni012A' : 298, + 'uni2289' : 8841, + 'Q' : 81, + 'uni2320' : 8992, + 'uni2321' : 8993, + 'g' : 103, + 'uni03BD' : 957, + 'uni03BE' : 958, + 'uni03BF' : 959, + 'uni2282' : 8834, + 'uni2285' : 8837, + 'uni03BA' : 954, + 'uni03BB' : 955, + 'uni03BC' : 956, + 'uni2128' : 8488, + 'uni25B7' : 9655, + 'w' : 119, + 'uni0302' : 770, + 'uni03DE' : 990, + 'uni25DA' : 9690, + 'uni0303' : 771, + 'uni0463' : 1123, + 'uni0462' : 1122, + 'uni3018' : 12312, + 'uni2514' : 9492, + 'question' : 63, + 'uni25B3' : 9651, + 'uni24E1' : 9441, + 'one' : 49, + 'uni200A' : 8202, + 'uni2278' : 8824, + 'ring' : 730, + 'uni0195' : 405, + 'figuredash' : 8210, + 'uni22EC' : 8940, + 'uni0339' : 825, + 'uni0338' : 824, + 'uni0337' : 823, + 'uni0336' : 822, + 'uni0335' : 821, + 'uni0333' : 819, + 'uni0332' : 818, + 'uni0331' : 817, + 'uni0330' : 816, + 'uni01C1' : 449, + 'uni01C0' : 448, + 'uni01C3' : 451, + 'uni01C2' : 450, + 'uni2353' : 9043, + 'uni0308' : 776, + 'uni2218' : 8728, + 'uni2219' : 8729, + 'uni2216' : 8726, + 'uni2217' : 8727, + 'uni2214' : 8724, + 'uni0309' : 777, + 'uni2609' : 9737, + 'uni2213' : 8723, + 'uni2210' : 8720, + 'uni2211' : 8721, + 'uni2245' : 8773, + 'B' : 66, + 'uni25D6' : 9686, + 'iacute' : 237, + 'uni02E6' : 742, + 'uni02E7' : 743, + 'uni02E8' : 744, + 'uni02E9' : 745, + 'uni221D' : 8733, + 'uni221E' : 8734, + 'Ydieresis' : 376, + 'uni221C' : 8732, + 'uni22D7' : 8919, + 'uni221A' : 8730, + 'R' : 82, + 'uni24DC' : 9436, + 'uni033F' : 831, + 'uni033E' : 830, + 'uni033C' : 828, + 'uni033B' : 827, + 'uni033A' : 826, + 'b' : 98, + 'uni228A' : 8842, + 'uni22DB' : 8923, + 'uni2554' : 9556, + 'uni046B' : 1131, + 'uni046A' : 1130, + 'r' : 114, + 'uni24DB' : 9435, + 'Ccedilla' : 199, + 'minus' : 8722, + 'uni24DA' : 9434, + 'uni03F0' : 1008, + 'uni03F1' : 1009, + 'uni20AC' : 8364, + 'uni2276' : 8822, + 'uni24C0' : 9408, + 'uni0162' : 354, + 'uni0163' : 355, + 'uni011E' : 286, + 'uni011D' : 285, + 'uni011C' : 284, + 'uni011B' : 283, + 'uni0164' : 356, + 'uni0165' : 357, + 'Lslash' : 321, + 'uni0168' : 360, + 'uni0169' : 361, + 'uni25C9' : 9673, + 'uni02E5' : 741, + 'uni21C3' : 8643, + 'uni24C4' : 9412, + 'uni24E2' : 9442, + 'uni2277' : 8823, + 'uni013A' : 314, + 'uni2102' : 8450, + 'Uacute' : 218, + 'uni2317' : 8983, + 'uni2107' : 8455, + 'uni221F' : 8735, + 'yacute' : 253, + 'uni3012' : 12306, + 'Ucircumflex' : 219, + 'uni015D' : 349, + 'quotedbl' : 34, + 'uni25D9' : 9689, + 'uni2280' : 8832, + 'uni22AF' : 8879, + 'onehalf' : 189, + 'uni221B' : 8731, + 'Thorn' : 222, + 'uni2226' : 8742, + 'M' : 77, + 'uni25BA' : 9658, + 'uni2463' : 9315, + 'uni2336' : 9014, + 'eight' : 56, + 'uni2236' : 8758, + 'multiply' : 215, + 'uni210C' : 8460, + 'uni210A' : 8458, + 'uni21C9' : 8649, + 'grave' : 96, + 'uni210E' : 8462, + 'uni0117' : 279, + 'uni016C' : 364, + 'uni0115' : 277, + 'uni016A' : 362, + 'uni016F' : 367, + 'uni0112' : 274, + 'uni016D' : 365, + 'uni016E' : 366, + 'Ocircumflex' : 212, + 'uni2305' : 8965, + 'm' : 109, + 'uni24DF' : 9439, + 'uni0119' : 281, + 'uni0118' : 280, + 'uni20A3' : 8355, + 'uni20A4' : 8356, + 'uni20A7' : 8359, + 'uni2288' : 8840, + 'uni24C3' : 9411, + 'uni251C' : 9500, + 'uni228D' : 8845, + 'uni222F' : 8751, + 'uni222E' : 8750, + 'uni222D' : 8749, + 'uni222C' : 8748, + 'uni222B' : 8747, + 'uni222A' : 8746, + 'uni255B' : 9563, + 'Ugrave' : 217, + 'uni24DE' : 9438, + 'guilsinglright' : 8250, + 'uni250A' : 9482, + 'Ntilde' : 209, + 'uni0279' : 633, + 'questiondown' : 191, + 'uni256C' : 9580, + 'Atilde' : 195, + 'uni0272' : 626, + 'uni0273' : 627, + 'uni0270' : 624, + 'ccedilla' : 231, + 'uni0276' : 630, + 'uni0277' : 631, + 'uni0274' : 628, + 'uni0275' : 629, + 'uni2252' : 8786, + 'uni041F' : 1055, + 'uni2250' : 8784, + 'Z' : 90, + 'uni2256' : 8790, + 'uni2257' : 8791, + 'copyright' : 169, + 'uni2255' : 8789, + 'uni043D' : 1085, + 'uni043E' : 1086, + 'uni043F' : 1087, + 'yen' : 165, + 'uni041D' : 1053, + 'uni043B' : 1083, + 'uni043C' : 1084, + 'uni21B0' : 8624, + 'uni21B1' : 8625, + 'uni21B2' : 8626, + 'uni21B3' : 8627, + 'uni21B4' : 8628, + 'uni21B5' : 8629, + 'uni21B6' : 8630, + 'uni21B7' : 8631, + 'uni21B8' : 8632, + 'Eacute' : 201, + 'uni2311' : 8977, + 'uni2310' : 8976, + 'uni228F' : 8847, + 'uni25DB' : 9691, + 'uni21BA' : 8634, + 'uni21BB' : 8635, + 'uni21BC' : 8636, + 'uni2017' : 8215, + 'uni21BE' : 8638, + 'uni21BF' : 8639, + 'uni231C' : 8988, + 'H' : 72, + 'uni0293' : 659, + 'uni2202' : 8706, + 'uni22A4' : 8868, + 'uni231E' : 8990, + 'uni2232' : 8754, + 'uni225B' : 8795, + 'uni225C' : 8796, + 'uni24D9' : 9433, + 'uni225A' : 8794, + 'uni0438' : 1080, + 'uni0439' : 1081, + 'uni225D' : 8797, + 'uni225E' : 8798, + 'uni0434' : 1076, + 'X' : 88, + 'uni007F' : 127, + 'uni0437' : 1079, + 'Idieresis' : 207, + 'uni0431' : 1073, + 'uni0432' : 1074, + 'uni0433' : 1075, + 'uni22AC' : 8876, + 'uni22CD' : 8909, + 'uni25A3' : 9635, + 'bar' : 124, + 'uni24BB' : 9403, + 'uni037E' : 894, + 'uni027B' : 635, + 'h' : 104, + 'uni027A' : 634, + 'uni027F' : 639, + 'uni027D' : 637, + 'uni027E' : 638, + 'uni2227' : 8743, + 'uni2004' : 8196, + 'uni2225' : 8741, + 'uni2224' : 8740, + 'uni2223' : 8739, + 'uni2222' : 8738, + 'uni2221' : 8737, + 'uni2220' : 8736, + 'x' : 120, + 'uni2323' : 8995, + 'uni2559' : 9561, + 'uni2558' : 9560, + 'uni2229' : 8745, + 'uni2228' : 8744, + 'udieresis' : 252, + 'uni029D' : 669, + 'ordfeminine' : 170, + 'uni22CB' : 8907, + 'uni233D' : 9021, + 'uni0428' : 1064, + 'uni24C6' : 9414, + 'uni22DD' : 8925, + 'uni24C7' : 9415, + 'uni015C' : 348, + 'uni015B' : 347, + 'uni015A' : 346, + 'uni22AA' : 8874, + 'uni015F' : 351, + 'uni015E' : 350, + 'braceleft' : 123, + 'uni24C5' : 9413, + 'uni0410' : 1040, + 'uni03AA' : 938, + 'uni24C2' : 9410, + 'uni03AC' : 940, + 'uni03AB' : 939, + 'macron' : 175, + 'uni03AD' : 941, + 'uni03AF' : 943, + 'uni0294' : 660, + 'uni0295' : 661, + 'uni0296' : 662, + 'uni0297' : 663, + 'uni0290' : 656, + 'uni0291' : 657, + 'uni0292' : 658, + 'atilde' : 227, + 'Acircumflex' : 194, + 'uni2370' : 9072, + 'uni24C1' : 9409, + 'uni0298' : 664, + 'uni0299' : 665, + 'Oslash' : 216, + 'uni029E' : 670, + 'C' : 67, + 'quotedblleft' : 8220, + 'uni029B' : 667, + 'uni029C' : 668, + 'uni03A9' : 937, + 'uni03A8' : 936, + 'S' : 83, + 'uni24C9' : 9417, + 'uni03A1' : 929, + 'uni03A0' : 928, + 'exclam' : 33, + 'uni03A5' : 933, + 'uni03A4' : 932, + 'uni03A7' : 935, + 'Zcaron' : 381, + 'uni2133' : 8499, + 'uni2132' : 8498, + 'uni0159' : 345, + 'uni0158' : 344, + 'uni2137' : 8503, + 'uni2005' : 8197, + 'uni2135' : 8501, + 'uni2134' : 8500, + 'uni02BA' : 698, + 'uni2033' : 8243, + 'uni0151' : 337, + 'uni0150' : 336, + 'uni0157' : 343, + 'equal' : 61, + 'uni0155' : 341, + 'uni0154' : 340, + 's' : 115, + 'uni233F' : 9023, + 'eth' : 240, + 'uni24BE' : 9406, + 'uni21E9' : 8681, + 'uni2060' : 8288, + 'Egrave' : 200, + 'uni255D' : 9565, + 'uni24CD' : 9421, + 'uni21E1' : 8673, + 'uni21B9' : 8633, + 'hyphen' : 45, + 'uni01BE' : 446, + 'uni01BB' : 443, + 'period' : 46, + 'igrave' : 236, + 'uni01BA' : 442, + 'uni2296' : 8854, + 'uni2297' : 8855, + 'uni2294' : 8852, + 'uni2295' : 8853, + 'colon' : 58, + 'uni2293' : 8851, + 'uni2290' : 8848, + 'uni2291' : 8849, + 'uni032D' : 813, + 'uni032E' : 814, + 'uni032F' : 815, + 'uni032A' : 810, + 'uni032B' : 811, + 'uni032C' : 812, + 'uni231D' : 8989, + 'Ecircumflex' : 202, + 'uni24D7' : 9431, + 'uni25DD' : 9693, + 'trademark' : 8482, + 'Aacute' : 193, + 'cent' : 162, + 'uni0445' : 1093, + 'uni266E' : 9838, + 'uni266D' : 9837, + 'uni266B' : 9835, + 'uni03C9' : 969, + 'uni2003' : 8195, + 'uni2047' : 8263, + 'lslash' : 322, + 'uni03A6' : 934, + 'uni2043' : 8259, + 'uni250C' : 9484, + 'uni2040' : 8256, + 'uni255F' : 9567, + 'uni24CB' : 9419, + 'uni0472' : 1138, + 'uni0446' : 1094, + 'uni0474' : 1140, + 'uni0475' : 1141, + 'uni2508' : 9480, + 'uni2660' : 9824, + 'uni2506' : 9478, + 'uni2502' : 9474, + 'c' : 99, + 'uni2500' : 9472, + 'N' : 78, + 'uni22A6' : 8870, + 'uni21E7' : 8679, + 'uni2130' : 8496, + 'uni2002' : 8194, + 'breve' : 728, + 'uni0442' : 1090, + 'Oacute' : 211, + 'uni229F' : 8863, + 'uni25C7' : 9671, + 'uni229D' : 8861, + 'uni229E' : 8862, + 'guillemotleft' : 171, + 'uni0329' : 809, + 'uni24E5' : 9445, + 'uni011F' : 287, + 'uni0324' : 804, + 'uni0325' : 805, + 'uni0326' : 806, + 'uni0327' : 807, + 'uni0321' : 801, + 'uni0322' : 802, + 'n' : 110, + 'uni2032' : 8242, + 'uni2269' : 8809, + 'uni2268' : 8808, + 'uni0306' : 774, + 'uni226B' : 8811, + 'uni21EA' : 8682, + 'uni0166' : 358, + 'uni203B' : 8251, + 'uni01B5' : 437, + 'idieresis' : 239, + 'uni02BC' : 700, + 'uni01B0' : 432, + 'braceright' : 125, + 'seven' : 55, + 'uni02BB' : 699, + 'uni011A' : 282, + 'uni29FB' : 10747, + 'brokenbar' : 166, + 'uni2036' : 8246, + 'uni25C0' : 9664, + 'uni0156' : 342, + 'uni22D5' : 8917, + 'uni0258' : 600, + 'ugrave' : 249, + 'uni22D6' : 8918, + 'uni22D1' : 8913, + 'uni2034' : 8244, + 'uni22D3' : 8915, + 'uni22D2' : 8914, + 'uni203C' : 8252, + 'uni223E' : 8766, + 'uni02BF' : 703, + 'uni22D9' : 8921, + 'uni22D8' : 8920, + 'uni25BD' : 9661, + 'uni25BE' : 9662, + 'uni25BF' : 9663, + 'uni041B' : 1051, + 'periodcentered' : 183, + 'uni25BC' : 9660, + 'uni019E' : 414, + 'uni019B' : 411, + 'uni019A' : 410, + 'uni2007' : 8199, + 'uni0391' : 913, + 'uni0390' : 912, + 'uni0393' : 915, + 'uni0392' : 914, + 'uni0395' : 917, + 'uni0394' : 916, + 'uni0397' : 919, + 'uni0396' : 918, + 'uni0399' : 921, + 'uni0398' : 920, + 'uni25C8' : 9672, + 'uni2468' : 9320, + 'sterling' : 163, + 'uni22EB' : 8939, + 'uni039C' : 924, + 'uni039B' : 923, + 'uni039E' : 926, + 'uni039D' : 925, + 'uni039F' : 927, + 'I' : 73, + 'uni03E1' : 993, + 'uni03E0' : 992, + 'uni2319' : 8985, + 'uni228B' : 8843, + 'uni25B5' : 9653, + 'uni25B6' : 9654, + 'uni22EA' : 8938, + 'uni24B9' : 9401, + 'uni044E' : 1102, + 'uni0199' : 409, + 'uni2266' : 8806, + 'Y' : 89, + 'uni22A2' : 8866, + 'Eth' : 208, + 'uni266F' : 9839, + 'emdash' : 8212, + 'uni263B' : 9787, + 'uni24BD' : 9405, + 'uni22DE' : 8926, + 'uni0360' : 864, + 'uni2557' : 9559, + 'uni22DF' : 8927, + 'uni22DA' : 8922, + 'uni22DC' : 8924, + 'uni0361' : 865, + 'i' : 105, + 'uni24BF' : 9407, + 'uni0362' : 866, + 'uni263E' : 9790, + 'uni028D' : 653, + 'uni2259' : 8793, + 'uni0323' : 803, + 'uni2265' : 8805, + 'daggerdbl' : 8225, + 'y' : 121, + 'uni010A' : 266, + 'plusminus' : 177, + 'less' : 60, + 'uni21AE' : 8622, + 'uni0315' : 789, + 'uni230B' : 8971, + 'uni21AF' : 8623, + 'uni21AA' : 8618, + 'uni21AC' : 8620, + 'uni21AB' : 8619, + 'uni01FB' : 507, + 'uni01FC' : 508, + 'uni223A' : 8762, + 'uni01FA' : 506, + 'uni01FF' : 511, + 'uni01FD' : 509, + 'uni01FE' : 510, + 'uni2567' : 9575, + 'uni25E0' : 9696, + 'uni0104' : 260, + 'uni0105' : 261, + 'uni0106' : 262, + 'uni0107' : 263, + 'uni0100' : 256, + 'uni0101' : 257, + 'uni0102' : 258, + 'uni0103' : 259, + 'uni2038' : 8248, + 'uni2009' : 8201, + 'uni2008' : 8200, + 'uni0108' : 264, + 'uni0109' : 265, + 'uni02A1' : 673, + 'uni223B' : 8763, + 'uni226C' : 8812, + 'uni25AC' : 9644, + 'uni24D3' : 9427, + 'uni21E0' : 8672, + 'uni21E3' : 8675, + 'Udieresis' : 220, + 'uni21E2' : 8674, + 'D' : 68, + 'uni21E5' : 8677, + 'uni2621' : 9761, + 'uni21D1' : 8657, + 'uni203E' : 8254, + 'uni22C6' : 8902, + 'uni21E4' : 8676, + 'uni010D' : 269, + 'uni010E' : 270, + 'uni010F' : 271, + 'five' : 53, + 'T' : 84, + 'uni010B' : 267, + 'uni010C' : 268, + 'uni2605' : 9733, + 'uni2663' : 9827, + 'uni21E6' : 8678, + 'uni24B6' : 9398, + 'uni22C1' : 8897, + 'oslash' : 248, + 'acute' : 180, + 'uni01F0' : 496, + 'd' : 100, + 'OE' : 338, + 'uni22E3' : 8931, + 'Igrave' : 204, + 'uni2308' : 8968, + 'uni2309' : 8969, + 'uni21A9' : 8617, + 't' : 116, + 'uni2313' : 8979, + 'uni03A3' : 931, + 'uni21A4' : 8612, + 'uni21A7' : 8615, + 'uni21A6' : 8614, + 'uni21A1' : 8609, + 'uni21A0' : 8608, + 'uni21A3' : 8611, + 'uni21A2' : 8610, + 'parenright' : 41, + 'uni256A' : 9578, + 'uni25DC' : 9692, + 'uni24CE' : 9422, + 'uni042C' : 1068, + 'uni24E0' : 9440, + 'uni042B' : 1067, + 'uni0409' : 1033, + 'uni0408' : 1032, + 'uni24E7' : 9447, + 'uni25B4' : 9652, + 'uni042A' : 1066, + 'uni228E' : 8846, + 'uni0401' : 1025, + 'adieresis' : 228, + 'uni0403' : 1027, + 'quotesingle' : 39, + 'uni0405' : 1029, + 'uni0404' : 1028, + 'uni0407' : 1031, + 'uni0406' : 1030, + 'uni229C' : 8860, + 'uni2306' : 8966, + 'uni2253' : 8787, + 'twodotenleader' : 8229, + 'uni2131' : 8497, + 'uni21DA' : 8666, + 'uni2234' : 8756, + 'uni2235' : 8757, + 'uni01A5' : 421, + 'uni2237' : 8759, + 'uni2230' : 8752, + 'uni02CC' : 716, + 'slash' : 47, + 'uni01A0' : 416, + 'ellipsis' : 8230, + 'uni2299' : 8857, + 'uni2238' : 8760, + 'numbersign' : 35, + 'uni21A8' : 8616, + 'uni223D' : 8765, + 'uni01AF' : 431, + 'uni223F' : 8767, + 'uni01AD' : 429, + 'uni01AB' : 427, + 'odieresis' : 246, + 'uni223C' : 8764, + 'uni227D' : 8829, + 'uni0280' : 640, + 'O' : 79, + 'uni227E' : 8830, + 'uni21A5' : 8613, + 'uni22D4' : 8916, + 'uni25D4' : 9684, + 'uni227F' : 8831, + 'uni0435' : 1077, + 'uni2302' : 8962, + 'uni2669' : 9833, + 'uni24E3' : 9443, + 'uni2720' : 10016, + 'uni22A8' : 8872, + 'uni22A9' : 8873, + 'uni040A' : 1034, + 'uni22A7' : 8871, + 'oe' : 339, + 'uni040B' : 1035, + 'uni040E' : 1038, + 'uni22A3' : 8867, + 'o' : 111, + 'uni040F' : 1039, + 'Edieresis' : 203, + 'uni25D5' : 9685, + 'plus' : 43, + 'uni044D' : 1101, + 'uni263C' : 9788, + 'uni22E6' : 8934, + 'uni2283' : 8835, + 'uni258C' : 9612, + 'uni219E' : 8606, + 'uni24E4' : 9444, + 'uni2136' : 8502, + 'dagger' : 8224, + 'uni24B7' : 9399, + 'uni219B' : 8603, + 'uni22E5' : 8933, + 'three' : 51, + 'uni210B' : 8459, + 'uni2534' : 9524, + 'uni24B8' : 9400, + 'uni230A' : 8970, + 'hungarumlaut' : 733, + 'parenleft' : 40, + 'uni0148' : 328, + 'uni0149' : 329, + 'uni2124' : 8484, + 'uni2125' : 8485, + 'uni2126' : 8486, + 'uni2127' : 8487, + 'uni0140' : 320, + 'uni2129' : 8489, + 'uni25C5' : 9669, + 'uni0143' : 323, + 'uni0144' : 324, + 'uni0145' : 325, + 'uni0146' : 326, + 'uni0147' : 327, + 'uni210D' : 8461, + 'fraction' : 8260, + 'uni2031' : 8241, + 'uni2196' : 8598, + 'uni2035' : 8245, + 'uni24E6' : 9446, + 'uni016B' : 363, + 'uni24BA' : 9402, + 'uni266A' : 9834, + 'uni0116' : 278, + 'uni2115' : 8469, + 'registered' : 174, + 'J' : 74, + 'uni25DF' : 9695, + 'uni25CE' : 9678, + 'uni273D' : 10045, + 'dieresis' : 168, + 'uni212B' : 8491, + 'uni0114' : 276, + 'uni212D' : 8493, + 'uni212E' : 8494, + 'uni212F' : 8495, + 'uni014A' : 330, + 'uni014B' : 331, + 'uni014C' : 332, + 'uni014D' : 333, + 'uni014E' : 334, + 'uni014F' : 335, + 'uni025E' : 606, + 'uni24E8' : 9448, + 'uni0111' : 273, + 'uni24E9' : 9449, + 'Ograve' : 210, + 'j' : 106, + 'uni2195' : 8597, + 'uni2194' : 8596, + 'uni2197' : 8599, + 'uni2037' : 8247, + 'uni2191' : 8593, + 'uni2190' : 8592, + 'uni2193' : 8595, + 'uni2192' : 8594, + 'uni29FA' : 10746, + 'uni2713' : 10003, + 'z' : 122, + 'uni2199' : 8601, + 'uni2198' : 8600, + 'uni2667' : 9831, + 'ae' : 230, + 'uni0448' : 1096, + 'semicolon' : 59, + 'uni2666' : 9830, + 'uni038F' : 911, + 'uni0444' : 1092, + 'uni0447' : 1095, + 'uni038E' : 910, + 'uni0441' : 1089, + 'uni038C' : 908, + 'uni0443' : 1091, + 'uni038A' : 906, + 'uni0250' : 592, + 'uni0251' : 593, + 'uni0252' : 594, + 'uni0253' : 595, + 'uni0254' : 596, + 'at' : 64, + 'uni0256' : 598, + 'uni0257' : 599, + 'uni0167' : 359, + 'uni0259' : 601, + 'uni228C' : 8844, + 'uni2662' : 9826, + 'uni0319' : 793, + 'uni0318' : 792, + 'uni24BC' : 9404, + 'uni0402' : 1026, + 'uni22EF' : 8943, + 'Iacute' : 205, + 'uni22ED' : 8941, + 'uni22EE' : 8942, + 'uni0311' : 785, + 'uni0310' : 784, + 'uni21E8' : 8680, + 'uni0312' : 786, + 'percent' : 37, + 'uni0317' : 791, + 'uni0316' : 790, + 'uni21D6' : 8662, + 'uni21D7' : 8663, + 'uni21D4' : 8660, + 'uni21D5' : 8661, + 'uni21D2' : 8658, + 'uni21D3' : 8659, + 'uni21D0' : 8656, + 'uni2138' : 8504, + 'uni2270' : 8816, + 'uni2271' : 8817, + 'uni2272' : 8818, + 'uni2273' : 8819, + 'uni2274' : 8820, + 'uni2275' : 8821, + 'bracketright' : 93, + 'uni21D9' : 8665, + 'uni21DF' : 8671, + 'uni21DD' : 8669, + 'uni21DE' : 8670, + 'AE' : 198, + 'uni03AE' : 942, + 'uni227A' : 8826, + 'uni227B' : 8827, + 'uni227C' : 8828, + 'asterisk' : 42, + 'aacute' : 225, + 'uni226F' : 8815, + 'uni22E2' : 8930, + 'uni0386' : 902, + 'uni22E0' : 8928, + 'uni22E1' : 8929, + 'U' : 85, + 'uni22E7' : 8935, + 'uni22E4' : 8932, + 'uni0387' : 903, + 'uni031A' : 794, + 'eacute' : 233, + 'uni22E8' : 8936, + 'uni22E9' : 8937, + 'uni24D8' : 9432, + 'uni025A' : 602, + 'uni025B' : 603, + 'uni025C' : 604, + 'e' : 101, + 'uni0128' : 296, + 'uni025F' : 607, + 'uni2665' : 9829, + 'thorn' : 254, + 'uni0129' : 297, + 'uni253C' : 9532, + 'uni25D7' : 9687, + 'u' : 117, + 'uni0388' : 904, + 'uni0389' : 905, + 'uni0255' : 597, + 'uni0171' : 369, + 'uni0384' : 900, + 'uni0385' : 901, + 'uni044A' : 1098, + 'uni252C' : 9516, + 'uni044C' : 1100, + 'uni044B' : 1099 +} + +uni2type1 = {v: k for k, v in type12uni.items()} + +tex2uni = { + 'widehat' : 0x0302, + 'widetilde' : 0x0303, + 'widebar' : 0x0305, + 'langle' : 0x27e8, + 'rangle' : 0x27e9, + 'perp' : 0x27c2, + 'neq' : 0x2260, + 'Join' : 0x2a1d, + 'leqslant' : 0x2a7d, + 'geqslant' : 0x2a7e, + 'lessapprox' : 0x2a85, + 'gtrapprox' : 0x2a86, + 'lesseqqgtr' : 0x2a8b, + 'gtreqqless' : 0x2a8c, + 'triangleeq' : 0x225c, + 'eqslantless' : 0x2a95, + 'eqslantgtr' : 0x2a96, + 'backepsilon' : 0x03f6, + 'precapprox' : 0x2ab7, + 'succapprox' : 0x2ab8, + 'fallingdotseq' : 0x2252, + 'subseteqq' : 0x2ac5, + 'supseteqq' : 0x2ac6, + 'varpropto' : 0x221d, + 'precnapprox' : 0x2ab9, + 'succnapprox' : 0x2aba, + 'subsetneqq' : 0x2acb, + 'supsetneqq' : 0x2acc, + 'lnapprox' : 0x2ab9, + 'gnapprox' : 0x2aba, + 'longleftarrow' : 0x27f5, + 'longrightarrow' : 0x27f6, + 'longleftrightarrow' : 0x27f7, + 'Longleftarrow' : 0x27f8, + 'Longrightarrow' : 0x27f9, + 'Longleftrightarrow' : 0x27fa, + 'longmapsto' : 0x27fc, + 'leadsto' : 0x21dd, + 'dashleftarrow' : 0x290e, + 'dashrightarrow' : 0x290f, + 'circlearrowleft' : 0x21ba, + 'circlearrowright' : 0x21bb, + 'leftrightsquigarrow' : 0x21ad, + 'leftsquigarrow' : 0x219c, + 'rightsquigarrow' : 0x219d, + 'Game' : 0x2141, + 'hbar' : 0x0127, + 'hslash' : 0x210f, + 'ldots' : 0x2026, + 'vdots' : 0x22ee, + 'doteqdot' : 0x2251, + 'doteq' : 8784, + 'partial' : 8706, + 'gg' : 8811, + 'asymp' : 8781, + 'blacktriangledown' : 9662, + 'otimes' : 8855, + 'nearrow' : 8599, + 'varpi' : 982, + 'vee' : 8744, + 'vec' : 8407, + 'smile' : 8995, + 'succnsim' : 8937, + 'gimel' : 8503, + 'vert' : 124, + '|' : 124, + 'varrho' : 1009, + 'P' : 182, + 'approxident' : 8779, + 'Swarrow' : 8665, + 'textasciicircum' : 94, + 'imageof' : 8887, + 'ntriangleleft' : 8938, + 'nleq' : 8816, + 'div' : 247, + 'nparallel' : 8742, + 'Leftarrow' : 8656, + 'lll' : 8920, + 'oiint' : 8751, + 'ngeq' : 8817, + 'Theta' : 920, + 'origof' : 8886, + 'blacksquare' : 9632, + 'solbar' : 9023, + 'neg' : 172, + 'sum' : 8721, + 'Vdash' : 8873, + 'coloneq' : 8788, + 'degree' : 176, + 'bowtie' : 8904, + 'blacktriangleright' : 9654, + 'varsigma' : 962, + 'leq' : 8804, + 'ggg' : 8921, + 'lneqq' : 8808, + 'scurel' : 8881, + 'stareq' : 8795, + 'BbbN' : 8469, + 'nLeftarrow' : 8653, + 'nLeftrightarrow' : 8654, + 'k' : 808, + 'bot' : 8869, + 'BbbC' : 8450, + 'Lsh' : 8624, + 'leftleftarrows' : 8647, + 'BbbZ' : 8484, + 'digamma' : 989, + 'BbbR' : 8477, + 'BbbP' : 8473, + 'BbbQ' : 8474, + 'vartriangleright' : 8883, + 'succsim' : 8831, + 'wedge' : 8743, + 'lessgtr' : 8822, + 'veebar' : 8891, + 'mapsdown' : 8615, + 'Rsh' : 8625, + 'chi' : 967, + 'prec' : 8826, + 'nsubseteq' : 8840, + 'therefore' : 8756, + 'eqcirc' : 8790, + 'textexclamdown' : 161, + 'nRightarrow' : 8655, + 'flat' : 9837, + 'notin' : 8713, + 'llcorner' : 8990, + 'varepsilon' : 949, + 'bigtriangleup' : 9651, + 'aleph' : 8501, + 'dotminus' : 8760, + 'upsilon' : 965, + 'Lambda' : 923, + 'cap' : 8745, + 'barleftarrow' : 8676, + 'mu' : 956, + 'boxplus' : 8862, + 'mp' : 8723, + 'circledast' : 8859, + 'tau' : 964, + 'in' : 8712, + 'backslash' : 92, + 'varnothing' : 8709, + 'sharp' : 9839, + 'eqsim' : 8770, + 'gnsim' : 8935, + 'Searrow' : 8664, + 'updownarrows' : 8645, + 'heartsuit' : 9825, + 'trianglelefteq' : 8884, + 'ddag' : 8225, + 'sqsubseteq' : 8849, + 'mapsfrom' : 8612, + 'boxbar' : 9707, + 'sim' : 8764, + 'Nwarrow' : 8662, + 'nequiv' : 8802, + 'succ' : 8827, + 'vdash' : 8866, + 'Leftrightarrow' : 8660, + 'parallel' : 8741, + 'invnot' : 8976, + 'natural' : 9838, + 'ss' : 223, + 'uparrow' : 8593, + 'nsim' : 8769, + 'hookrightarrow' : 8618, + 'Equiv' : 8803, + 'approx' : 8776, + 'Vvdash' : 8874, + 'nsucc' : 8833, + 'leftrightharpoons' : 8651, + 'Re' : 8476, + 'boxminus' : 8863, + 'equiv' : 8801, + 'Lleftarrow' : 8666, + 'll' : 8810, + 'Cup' : 8915, + 'measeq' : 8798, + 'upharpoonleft' : 8639, + 'lq' : 8216, + 'Upsilon' : 933, + 'subsetneq' : 8842, + 'greater' : 62, + 'supsetneq' : 8843, + 'Cap' : 8914, + 'L' : 321, + 'spadesuit' : 9824, + 'lrcorner' : 8991, + 'not' : 824, + 'bar' : 772, + 'rightharpoonaccent' : 8401, + 'boxdot' : 8865, + 'l' : 322, + 'leftharpoondown' : 8637, + 'bigcup' : 8899, + 'iint' : 8748, + 'bigwedge' : 8896, + 'downharpoonleft' : 8643, + 'textasciitilde' : 126, + 'subset' : 8834, + 'leqq' : 8806, + 'mapsup' : 8613, + 'nvDash' : 8877, + 'looparrowleft' : 8619, + 'nless' : 8814, + 'rightarrowbar' : 8677, + 'Vert' : 8214, + 'downdownarrows' : 8650, + 'uplus' : 8846, + 'simeq' : 8771, + 'napprox' : 8777, + 'ast' : 8727, + 'twoheaduparrow' : 8607, + 'doublebarwedge' : 8966, + 'Sigma' : 931, + 'leftharpoonaccent' : 8400, + 'ntrianglelefteq' : 8940, + 'nexists' : 8708, + 'times' : 215, + 'measuredangle' : 8737, + 'bumpeq' : 8783, + 'carriagereturn' : 8629, + 'adots' : 8944, + 'checkmark' : 10003, + 'lambda' : 955, + 'xi' : 958, + 'rbrace' : 125, + 'rbrack' : 93, + 'Nearrow' : 8663, + 'maltese' : 10016, + 'clubsuit' : 9827, + 'top' : 8868, + 'overarc' : 785, + 'varphi' : 966, + 'Delta' : 916, + 'iota' : 953, + 'nleftarrow' : 8602, + 'candra' : 784, + 'supset' : 8835, + 'triangleleft' : 9665, + 'gtreqless' : 8923, + 'ntrianglerighteq' : 8941, + 'quad' : 8195, + 'Xi' : 926, + 'gtrdot' : 8919, + 'leftthreetimes' : 8907, + 'minus' : 8722, + 'preccurlyeq' : 8828, + 'nleftrightarrow' : 8622, + 'lambdabar' : 411, + 'blacktriangle' : 9652, + 'kernelcontraction' : 8763, + 'Phi' : 934, + 'angle' : 8736, + 'spadesuitopen' : 9828, + 'eqless' : 8924, + 'mid' : 8739, + 'varkappa' : 1008, + 'Ldsh' : 8626, + 'updownarrow' : 8597, + 'beta' : 946, + 'textquotedblleft' : 8220, + 'rho' : 961, + 'alpha' : 945, + 'intercal' : 8890, + 'beth' : 8502, + 'grave' : 768, + 'acwopencirclearrow' : 8634, + 'nmid' : 8740, + 'nsupset' : 8837, + 'sigma' : 963, + 'dot' : 775, + 'Rightarrow' : 8658, + 'turnednot' : 8985, + 'backsimeq' : 8909, + 'leftarrowtail' : 8610, + 'approxeq' : 8778, + 'curlyeqsucc' : 8927, + 'rightarrowtail' : 8611, + 'Psi' : 936, + 'copyright' : 169, + 'yen' : 165, + 'vartriangleleft' : 8882, + 'rasp' : 700, + 'triangleright' : 9655, + 'precsim' : 8830, + 'infty' : 8734, + 'geq' : 8805, + 'updownarrowbar' : 8616, + 'precnsim' : 8936, + 'H' : 779, + 'ulcorner' : 8988, + 'looparrowright' : 8620, + 'ncong' : 8775, + 'downarrow' : 8595, + 'circeq' : 8791, + 'subseteq' : 8838, + 'bigstar' : 9733, + 'prime' : 8242, + 'lceil' : 8968, + 'Rrightarrow' : 8667, + 'oiiint' : 8752, + 'curlywedge' : 8911, + 'vDash' : 8872, + 'lfloor' : 8970, + 'ddots' : 8945, + 'exists' : 8707, + 'underbar' : 817, + 'Pi' : 928, + 'leftrightarrows' : 8646, + 'sphericalangle' : 8738, + 'coprod' : 8720, + 'circledcirc' : 8858, + 'gtrsim' : 8819, + 'gneqq' : 8809, + 'between' : 8812, + 'theta' : 952, + 'complement' : 8705, + 'arceq' : 8792, + 'nVdash' : 8878, + 'S' : 167, + 'wr' : 8768, + 'wp' : 8472, + 'backcong' : 8780, + 'lasp' : 701, + 'c' : 807, + 'nabla' : 8711, + 'dotplus' : 8724, + 'eta' : 951, + 'forall' : 8704, + 'eth' : 240, + 'colon' : 58, + 'sqcup' : 8852, + 'rightrightarrows' : 8649, + 'sqsupset' : 8848, + 'mapsto' : 8614, + 'bigtriangledown' : 9661, + 'sqsupseteq' : 8850, + 'propto' : 8733, + 'pi' : 960, + 'pm' : 177, + 'dots' : 0x2026, + 'nrightarrow' : 8603, + 'textasciiacute' : 180, + 'Doteq' : 8785, + 'breve' : 774, + 'sqcap' : 8851, + 'twoheadrightarrow' : 8608, + 'kappa' : 954, + 'vartriangle' : 9653, + 'diamondsuit' : 9826, + 'pitchfork' : 8916, + 'blacktriangleleft' : 9664, + 'nprec' : 8832, + 'curvearrowright' : 8631, + 'barwedge' : 8892, + 'multimap' : 8888, + 'textquestiondown' : 191, + 'cong' : 8773, + 'rtimes' : 8906, + 'rightzigzagarrow' : 8669, + 'rightarrow' : 8594, + 'leftarrow' : 8592, + '__sqrt__' : 8730, + 'twoheaddownarrow' : 8609, + 'oint' : 8750, + 'bigvee' : 8897, + 'eqdef' : 8797, + 'sterling' : 163, + 'phi' : 981, + 'Updownarrow' : 8661, + 'backprime' : 8245, + 'emdash' : 8212, + 'Gamma' : 915, + 'i' : 305, + 'rceil' : 8969, + 'leftharpoonup' : 8636, + 'Im' : 8465, + 'curvearrowleft' : 8630, + 'wedgeq' : 8793, + 'curlyeqprec' : 8926, + 'questeq' : 8799, + 'less' : 60, + 'upuparrows' : 8648, + 'tilde' : 771, + 'textasciigrave' : 96, + 'smallsetminus' : 8726, + 'ell' : 8467, + 'cup' : 8746, + 'danger' : 9761, + 'nVDash' : 8879, + 'cdotp' : 183, + 'cdots' : 8943, + 'hat' : 770, + 'eqgtr' : 8925, + 'psi' : 968, + 'frown' : 8994, + 'acute' : 769, + 'downzigzagarrow' : 8623, + 'ntriangleright' : 8939, + 'cupdot' : 8845, + 'circleddash' : 8861, + 'oslash' : 8856, + 'mho' : 8487, + 'd' : 803, + 'sqsubset' : 8847, + 'cdot' : 8901, + 'Omega' : 937, + 'OE' : 338, + 'veeeq' : 8794, + 'Finv' : 8498, + 't' : 865, + 'leftrightarrow' : 8596, + 'swarrow' : 8601, + 'rightthreetimes' : 8908, + 'rightleftharpoons' : 8652, + 'lesssim' : 8818, + 'searrow' : 8600, + 'because' : 8757, + 'gtrless' : 8823, + 'star' : 8902, + 'nsubset' : 8836, + 'zeta' : 950, + 'dddot' : 8411, + 'bigcirc' : 9675, + 'Supset' : 8913, + 'circ' : 8728, + 'slash' : 8725, + 'ocirc' : 778, + 'prod' : 8719, + 'twoheadleftarrow' : 8606, + 'daleth' : 8504, + 'upharpoonright' : 8638, + 'odot' : 8857, + 'Uparrow' : 8657, + 'O' : 216, + 'hookleftarrow' : 8617, + 'trianglerighteq' : 8885, + 'nsime' : 8772, + 'oe' : 339, + 'nwarrow' : 8598, + 'o' : 248, + 'ddddot' : 8412, + 'downharpoonright' : 8642, + 'succcurlyeq' : 8829, + 'gamma' : 947, + 'scrR' : 8475, + 'dag' : 8224, + 'thickspace' : 8197, + 'frakZ' : 8488, + 'lessdot' : 8918, + 'triangledown' : 9663, + 'ltimes' : 8905, + 'scrB' : 8492, + 'endash' : 8211, + 'scrE' : 8496, + 'scrF' : 8497, + 'scrH' : 8459, + 'scrI' : 8464, + 'rightharpoondown' : 8641, + 'scrL' : 8466, + 'scrM' : 8499, + 'frakC' : 8493, + 'nsupseteq' : 8841, + 'circledR' : 174, + 'circledS' : 9416, + 'ngtr' : 8815, + 'bigcap' : 8898, + 'scre' : 8495, + 'Downarrow' : 8659, + 'scrg' : 8458, + 'overleftrightarrow' : 8417, + 'scro' : 8500, + 'lnsim' : 8934, + 'eqcolon' : 8789, + 'curlyvee' : 8910, + 'urcorner' : 8989, + 'lbrace' : 123, + 'Bumpeq' : 8782, + 'delta' : 948, + 'boxtimes' : 8864, + 'overleftarrow' : 8406, + 'prurel' : 8880, + 'clubsuitopen' : 9831, + 'cwopencirclearrow' : 8635, + 'geqq' : 8807, + 'rightleftarrows' : 8644, + 'ac' : 8766, + 'ae' : 230, + 'int' : 8747, + 'rfloor' : 8971, + 'risingdotseq' : 8787, + 'nvdash' : 8876, + 'diamond' : 8900, + 'ddot' : 776, + 'backsim' : 8765, + 'oplus' : 8853, + 'triangleq' : 8796, + 'check' : 780, + 'ni' : 8715, + 'iiint' : 8749, + 'ne' : 8800, + 'lesseqgtr' : 8922, + 'obar' : 9021, + 'supseteq' : 8839, + 'nu' : 957, + 'AA' : 197, + 'AE' : 198, + 'models' : 8871, + 'ominus' : 8854, + 'dashv' : 8867, + 'omega' : 969, + 'rq' : 8217, + 'Subset' : 8912, + 'rightharpoonup' : 8640, + 'Rdsh' : 8627, + 'bullet' : 8729, + 'divideontimes' : 8903, + 'lbrack' : 91, + 'textquotedblright' : 8221, + 'Colon' : 8759, + '%' : 37, + '$' : 36, + '{' : 123, + '}' : 125, + '_' : 95, + '#' : 35, + 'imath' : 0x131, + 'circumflexaccent' : 770, + 'combiningbreve' : 774, + 'combiningoverline' : 772, + 'combininggraveaccent' : 768, + 'combiningacuteaccent' : 769, + 'combiningdiaeresis' : 776, + 'combiningtilde' : 771, + 'combiningrightarrowabove' : 8407, + 'combiningdotabove' : 775, + 'to' : 8594, + 'succeq' : 8829, + 'emptyset' : 8709, + 'leftparen' : 40, + 'rightparen' : 41, + 'bigoplus' : 10753, + 'leftangle' : 10216, + 'rightangle' : 10217, + 'leftbrace' : 124, + 'rightbrace' : 125, + 'jmath' : 567, + 'bigodot' : 10752, + 'preceq' : 8828, + 'biguplus' : 10756, + 'epsilon' : 949, + 'vartheta' : 977, + 'bigotimes' : 10754, + 'guillemotleft' : 171, + 'ring' : 730, + 'Thorn' : 222, + 'guilsinglright' : 8250, + 'perthousand' : 8240, + 'macron' : 175, + 'cent' : 162, + 'guillemotright' : 187, + 'equal' : 61, + 'asterisk' : 42, + 'guilsinglleft' : 8249, + 'plus' : 43, + 'thorn' : 254, + 'dagger' : 8224 +} + +# Each element is a 4-tuple of the form: +# src_start, src_end, dst_font, dst_start +# +stix_virtual_fonts = { + 'bb': + { + 'rm': + [ + (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9 + (0x0041, 0x0042, 'rm', 0x1d538), # A-B + (0x0043, 0x0043, 'rm', 0x2102), # C + (0x0044, 0x0047, 'rm', 0x1d53b), # D-G + (0x0048, 0x0048, 'rm', 0x210d), # H + (0x0049, 0x004d, 'rm', 0x1d540), # I-M + (0x004e, 0x004e, 'rm', 0x2115), # N + (0x004f, 0x004f, 'rm', 0x1d546), # O + (0x0050, 0x0051, 'rm', 0x2119), # P-Q + (0x0052, 0x0052, 'rm', 0x211d), # R + (0x0053, 0x0059, 'rm', 0x1d54a), # S-Y + (0x005a, 0x005a, 'rm', 0x2124), # Z + (0x0061, 0x007a, 'rm', 0x1d552), # a-z + (0x0393, 0x0393, 'rm', 0x213e), # \Gamma + (0x03a0, 0x03a0, 'rm', 0x213f), # \Pi + (0x03a3, 0x03a3, 'rm', 0x2140), # \Sigma + (0x03b3, 0x03b3, 'rm', 0x213d), # \gamma + (0x03c0, 0x03c0, 'rm', 0x213c), # \pi + ], + 'it': + [ + (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9 + (0x0041, 0x0042, 'it', 0xe154), # A-B + (0x0043, 0x0043, 'it', 0x2102), # C + (0x0044, 0x0044, 'it', 0x2145), # D + (0x0045, 0x0047, 'it', 0xe156), # E-G + (0x0048, 0x0048, 'it', 0x210d), # H + (0x0049, 0x004d, 'it', 0xe159), # I-M + (0x004e, 0x004e, 'it', 0x2115), # N + (0x004f, 0x004f, 'it', 0xe15e), # O + (0x0050, 0x0051, 'it', 0x2119), # P-Q + (0x0052, 0x0052, 'it', 0x211d), # R + (0x0053, 0x0059, 'it', 0xe15f), # S-Y + (0x005a, 0x005a, 'it', 0x2124), # Z + (0x0061, 0x0063, 'it', 0xe166), # a-c + (0x0064, 0x0065, 'it', 0x2146), # d-e + (0x0066, 0x0068, 'it', 0xe169), # f-h + (0x0069, 0x006a, 'it', 0x2148), # i-j + (0x006b, 0x007a, 'it', 0xe16c), # k-z + (0x0393, 0x0393, 'it', 0x213e), # \Gamma (not in beta STIX fonts) + (0x03a0, 0x03a0, 'it', 0x213f), # \Pi + (0x03a3, 0x03a3, 'it', 0x2140), # \Sigma (not in beta STIX fonts) + (0x03b3, 0x03b3, 'it', 0x213d), # \gamma (not in beta STIX fonts) + (0x03c0, 0x03c0, 'it', 0x213c), # \pi + ], + 'bf': + [ + (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9 + (0x0041, 0x0042, 'bf', 0xe38a), # A-B + (0x0043, 0x0043, 'bf', 0x2102), # C + (0x0044, 0x0044, 'bf', 0x2145), # D + (0x0045, 0x0047, 'bf', 0xe38d), # E-G + (0x0048, 0x0048, 'bf', 0x210d), # H + (0x0049, 0x004d, 'bf', 0xe390), # I-M + (0x004e, 0x004e, 'bf', 0x2115), # N + (0x004f, 0x004f, 'bf', 0xe395), # O + (0x0050, 0x0051, 'bf', 0x2119), # P-Q + (0x0052, 0x0052, 'bf', 0x211d), # R + (0x0053, 0x0059, 'bf', 0xe396), # S-Y + (0x005a, 0x005a, 'bf', 0x2124), # Z + (0x0061, 0x0063, 'bf', 0xe39d), # a-c + (0x0064, 0x0065, 'bf', 0x2146), # d-e + (0x0066, 0x0068, 'bf', 0xe3a2), # f-h + (0x0069, 0x006a, 'bf', 0x2148), # i-j + (0x006b, 0x007a, 'bf', 0xe3a7), # k-z + (0x0393, 0x0393, 'bf', 0x213e), # \Gamma + (0x03a0, 0x03a0, 'bf', 0x213f), # \Pi + (0x03a3, 0x03a3, 'bf', 0x2140), # \Sigma + (0x03b3, 0x03b3, 'bf', 0x213d), # \gamma + (0x03c0, 0x03c0, 'bf', 0x213c), # \pi + ], + }, + 'cal': + [ + (0x0041, 0x005a, 'it', 0xe22d), # A-Z + ], + 'circled': + { + 'rm': + [ + (0x0030, 0x0030, 'rm', 0x24ea), # 0 + (0x0031, 0x0039, 'rm', 0x2460), # 1-9 + (0x0041, 0x005a, 'rm', 0x24b6), # A-Z + (0x0061, 0x007a, 'rm', 0x24d0) # a-z + ], + 'it': + [ + (0x0030, 0x0030, 'rm', 0x24ea), # 0 + (0x0031, 0x0039, 'rm', 0x2460), # 1-9 + (0x0041, 0x005a, 'it', 0x24b6), # A-Z + (0x0061, 0x007a, 'it', 0x24d0) # a-z + ], + 'bf': + [ + (0x0030, 0x0030, 'bf', 0x24ea), # 0 + (0x0031, 0x0039, 'bf', 0x2460), # 1-9 + (0x0041, 0x005a, 'bf', 0x24b6), # A-Z + (0x0061, 0x007a, 'bf', 0x24d0) # a-z + ], + }, + 'frak': + { + 'rm': + [ + (0x0041, 0x0042, 'rm', 0x1d504), # A-B + (0x0043, 0x0043, 'rm', 0x212d), # C + (0x0044, 0x0047, 'rm', 0x1d507), # D-G + (0x0048, 0x0048, 'rm', 0x210c), # H + (0x0049, 0x0049, 'rm', 0x2111), # I + (0x004a, 0x0051, 'rm', 0x1d50d), # J-Q + (0x0052, 0x0052, 'rm', 0x211c), # R + (0x0053, 0x0059, 'rm', 0x1d516), # S-Y + (0x005a, 0x005a, 'rm', 0x2128), # Z + (0x0061, 0x007a, 'rm', 0x1d51e), # a-z + ], + 'it': + [ + (0x0041, 0x0042, 'rm', 0x1d504), # A-B + (0x0043, 0x0043, 'rm', 0x212d), # C + (0x0044, 0x0047, 'rm', 0x1d507), # D-G + (0x0048, 0x0048, 'rm', 0x210c), # H + (0x0049, 0x0049, 'rm', 0x2111), # I + (0x004a, 0x0051, 'rm', 0x1d50d), # J-Q + (0x0052, 0x0052, 'rm', 0x211c), # R + (0x0053, 0x0059, 'rm', 0x1d516), # S-Y + (0x005a, 0x005a, 'rm', 0x2128), # Z + (0x0061, 0x007a, 'rm', 0x1d51e), # a-z + ], + 'bf': + [ + (0x0041, 0x005a, 'bf', 0x1d56c), # A-Z + (0x0061, 0x007a, 'bf', 0x1d586), # a-z + ], + }, + 'scr': + [ + (0x0041, 0x0041, 'it', 0x1d49c), # A + (0x0042, 0x0042, 'it', 0x212c), # B + (0x0043, 0x0044, 'it', 0x1d49e), # C-D + (0x0045, 0x0046, 'it', 0x2130), # E-F + (0x0047, 0x0047, 'it', 0x1d4a2), # G + (0x0048, 0x0048, 'it', 0x210b), # H + (0x0049, 0x0049, 'it', 0x2110), # I + (0x004a, 0x004b, 'it', 0x1d4a5), # J-K + (0x004c, 0x004c, 'it', 0x2112), # L + (0x004d, 0x004d, 'it', 0x2133), # M + (0x004e, 0x0051, 'it', 0x1d4a9), # N-Q + (0x0052, 0x0052, 'it', 0x211b), # R + (0x0053, 0x005a, 'it', 0x1d4ae), # S-Z + (0x0061, 0x0064, 'it', 0x1d4b6), # a-d + (0x0065, 0x0065, 'it', 0x212f), # e + (0x0066, 0x0066, 'it', 0x1d4bb), # f + (0x0067, 0x0067, 'it', 0x210a), # g + (0x0068, 0x006e, 'it', 0x1d4bd), # h-n + (0x006f, 0x006f, 'it', 0x2134), # o + (0x0070, 0x007a, 'it', 0x1d4c5), # p-z + ], + 'sf': + { + 'rm': + [ + (0x0030, 0x0039, 'rm', 0x1d7e2), # 0-9 + (0x0041, 0x005a, 'rm', 0x1d5a0), # A-Z + (0x0061, 0x007a, 'rm', 0x1d5ba), # a-z + (0x0391, 0x03a9, 'rm', 0xe17d), # \Alpha-\Omega + (0x03b1, 0x03c9, 'rm', 0xe196), # \alpha-\omega + (0x03d1, 0x03d1, 'rm', 0xe1b0), # theta variant + (0x03d5, 0x03d5, 'rm', 0xe1b1), # phi variant + (0x03d6, 0x03d6, 'rm', 0xe1b3), # pi variant + (0x03f1, 0x03f1, 'rm', 0xe1b2), # rho variant + (0x03f5, 0x03f5, 'rm', 0xe1af), # lunate epsilon + (0x2202, 0x2202, 'rm', 0xe17c), # partial differential + ], + 'it': + [ + # These numerals are actually upright. We don't actually + # want italic numerals ever. + (0x0030, 0x0039, 'rm', 0x1d7e2), # 0-9 + (0x0041, 0x005a, 'it', 0x1d608), # A-Z + (0x0061, 0x007a, 'it', 0x1d622), # a-z + (0x0391, 0x03a9, 'rm', 0xe17d), # \Alpha-\Omega + (0x03b1, 0x03c9, 'it', 0xe1d8), # \alpha-\omega + (0x03d1, 0x03d1, 'it', 0xe1f2), # theta variant + (0x03d5, 0x03d5, 'it', 0xe1f3), # phi variant + (0x03d6, 0x03d6, 'it', 0xe1f5), # pi variant + (0x03f1, 0x03f1, 'it', 0xe1f4), # rho variant + (0x03f5, 0x03f5, 'it', 0xe1f1), # lunate epsilon + ], + 'bf': + [ + (0x0030, 0x0039, 'bf', 0x1d7ec), # 0-9 + (0x0041, 0x005a, 'bf', 0x1d5d4), # A-Z + (0x0061, 0x007a, 'bf', 0x1d5ee), # a-z + (0x0391, 0x03a9, 'bf', 0x1d756), # \Alpha-\Omega + (0x03b1, 0x03c9, 'bf', 0x1d770), # \alpha-\omega + (0x03d1, 0x03d1, 'bf', 0x1d78b), # theta variant + (0x03d5, 0x03d5, 'bf', 0x1d78d), # phi variant + (0x03d6, 0x03d6, 'bf', 0x1d78f), # pi variant + (0x03f0, 0x03f0, 'bf', 0x1d78c), # kappa variant + (0x03f1, 0x03f1, 'bf', 0x1d78e), # rho variant + (0x03f5, 0x03f5, 'bf', 0x1d78a), # lunate epsilon + (0x2202, 0x2202, 'bf', 0x1d789), # partial differential + (0x2207, 0x2207, 'bf', 0x1d76f), # \Nabla + ], + }, + 'tt': + [ + (0x0030, 0x0039, 'rm', 0x1d7f6), # 0-9 + (0x0041, 0x005a, 'rm', 0x1d670), # A-Z + (0x0061, 0x007a, 'rm', 0x1d68a) # a-z + ], + } diff --git a/venv/lib/python3.6/site-packages/matplotlib/_path.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/matplotlib/_path.cpython-36m-x86_64-linux-gnu.so new file mode 100644 index 0000000..9476585 Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/_path.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_png.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/matplotlib/_png.cpython-36m-x86_64-linux-gnu.so new file mode 100644 index 0000000..c41273f Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/_png.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_pylab_helpers.py b/venv/lib/python3.6/site-packages/matplotlib/_pylab_helpers.py new file mode 100644 index 0000000..45574b5 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_pylab_helpers.py @@ -0,0 +1,130 @@ +""" +Manage figures for pyplot interface. +""" + +import atexit +import gc + + +class Gcf(object): + """ + Singleton to manage a set of integer-numbered figures. + + This class is never instantiated; it consists of two class + attributes (a list and a dictionary), and a set of static + methods that operate on those attributes, accessing them + directly as class attributes. + + Attributes: + + *figs*: + dictionary of the form {*num*: *manager*, ...} + + *_activeQue*: + list of *managers*, with active one at the end + + """ + _activeQue = [] + figs = {} + + @classmethod + def get_fig_manager(cls, num): + """ + If figure manager *num* exists, make it the active + figure and return the manager; otherwise return *None*. + """ + manager = cls.figs.get(num, None) + if manager is not None: + cls.set_active(manager) + return manager + + @classmethod + def destroy(cls, num): + """ + Try to remove all traces of figure *num*. + + In the interactive backends, this is bound to the + window "destroy" and "delete" events. + """ + if not cls.has_fignum(num): + return + manager = cls.figs[num] + manager.canvas.mpl_disconnect(manager._cidgcf) + cls._activeQue.remove(manager) + del cls.figs[num] + manager.destroy() + gc.collect(1) + + @classmethod + def destroy_fig(cls, fig): + "*fig* is a Figure instance" + num = next((manager.num for manager in cls.figs.values() + if manager.canvas.figure == fig), None) + if num is not None: + cls.destroy(num) + + @classmethod + def destroy_all(cls): + # this is need to ensure that gc is available in corner cases + # where modules are being torn down after install with easy_install + import gc # noqa + for manager in list(cls.figs.values()): + manager.canvas.mpl_disconnect(manager._cidgcf) + manager.destroy() + + cls._activeQue = [] + cls.figs.clear() + gc.collect(1) + + @classmethod + def has_fignum(cls, num): + """ + Return *True* if figure *num* exists. + """ + return num in cls.figs + + @classmethod + def get_all_fig_managers(cls): + """ + Return a list of figure managers. + """ + return list(cls.figs.values()) + + @classmethod + def get_num_fig_managers(cls): + """ + Return the number of figures being managed. + """ + return len(cls.figs) + + @classmethod + def get_active(cls): + """ + Return the manager of the active figure, or *None*. + """ + if len(cls._activeQue) == 0: + return None + else: + return cls._activeQue[-1] + + @classmethod + def set_active(cls, manager): + """ + Make the figure corresponding to *manager* the active one. + """ + oldQue = cls._activeQue[:] + cls._activeQue = [m for m in oldQue if m != manager] + cls._activeQue.append(manager) + cls.figs[manager.num] = manager + + @classmethod + def draw_all(cls, force=False): + """ + Redraw all figures registered with the pyplot + state machine. + """ + for f_mgr in cls.get_all_fig_managers(): + if force or f_mgr.canvas.figure.stale: + f_mgr.canvas.draw_idle() + +atexit.register(Gcf.destroy_all) diff --git a/venv/lib/python3.6/site-packages/matplotlib/_qhull.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/matplotlib/_qhull.cpython-36m-x86_64-linux-gnu.so new file mode 100644 index 0000000..2683a0d Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/_qhull.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_tri.cpython-36m-x86_64-linux-gnu.so b/venv/lib/python3.6/site-packages/matplotlib/_tri.cpython-36m-x86_64-linux-gnu.so new file mode 100644 index 0000000..22787aa Binary files /dev/null and b/venv/lib/python3.6/site-packages/matplotlib/_tri.cpython-36m-x86_64-linux-gnu.so differ diff --git a/venv/lib/python3.6/site-packages/matplotlib/_version.py b/venv/lib/python3.6/site-packages/matplotlib/_version.py new file mode 100644 index 0000000..9858f0e --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/_version.py @@ -0,0 +1,21 @@ + +# This file was generated by 'versioneer.py' (0.15) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +import json +import sys + +version_json = ''' +{ + "dirty": false, + "error": null, + "full-revisionid": "bed022902c04af827d24d86d161eaf401041dbe3", + "version": "3.1.1" +} +''' # END VERSION_JSON + + +def get_versions(): + return json.loads(version_json) diff --git a/venv/lib/python3.6/site-packages/matplotlib/afm.py b/venv/lib/python3.6/site-packages/matplotlib/afm.py new file mode 100644 index 0000000..c2b0090 --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/afm.py @@ -0,0 +1,573 @@ +""" +This is a python interface to Adobe Font Metrics Files. Although a +number of other python implementations exist, and may be more complete +than this, it was decided not to go with them because they were +either: + + 1) copyrighted or used a non-BSD compatible license + + 2) had too many dependencies and a free standing lib was needed + + 3) Did more than needed and it was easier to write afresh rather than + figure out how to get just what was needed. + +It is pretty easy to use, and requires only built-in python libs: + + >>> from matplotlib import rcParams + >>> import os.path + >>> afm_fname = os.path.join(rcParams['datapath'], + ... 'fonts', 'afm', 'ptmr8a.afm') + >>> + >>> from matplotlib.afm import AFM + >>> with open(afm_fname, 'rb') as fh: + ... afm = AFM(fh) + >>> afm.string_width_height('What the heck?') + (6220.0, 694) + >>> afm.get_fontname() + 'Times-Roman' + >>> afm.get_kern_dist('A', 'f') + 0 + >>> afm.get_kern_dist('A', 'y') + -92.0 + >>> afm.get_bbox_char('!') + [130, -9, 238, 676] + +As in the Adobe Font Metrics File Format Specification, all dimensions +are given in units of 1/1000 of the scale factor (point size) of the font +being used. +""" + +from collections import namedtuple +import logging +import re + + +from ._mathtext_data import uni2type1 +from matplotlib.cbook import deprecated + + +_log = logging.getLogger(__name__) + + +def _to_int(x): + # Some AFM files have floats where we are expecting ints -- there is + # probably a better way to handle this (support floats, round rather + # than truncate). But I don't know what the best approach is now and + # this change to _to_int should at least prevent mpl from crashing on + # these JDH (2009-11-06) + return int(float(x)) + + +def _to_float(x): + # Some AFM files use "," instead of "." as decimal separator -- this + # shouldn't be ambiguous (unless someone is wicked enough to use "," as + # thousands separator...). + if isinstance(x, bytes): + # Encoding doesn't really matter -- if we have codepoints >127 the call + # to float() will error anyways. + x = x.decode('latin-1') + return float(x.replace(',', '.')) + + +def _to_str(x): + return x.decode('utf8') + + +def _to_list_of_ints(s): + s = s.replace(b',', b' ') + return [_to_int(val) for val in s.split()] + + +def _to_list_of_floats(s): + return [_to_float(val) for val in s.split()] + + +def _to_bool(s): + if s.lower().strip() in (b'false', b'0', b'no'): + return False + else: + return True + + +def _sanity_check(fh): + """ + Check if the file looks like AFM; if it doesn't, raise `RuntimeError`. + """ + # Remember the file position in case the caller wants to + # do something else with the file. + pos = fh.tell() + try: + line = next(fh) + finally: + fh.seek(pos, 0) + # AFM spec, Section 4: The StartFontMetrics keyword [followed by a + # version number] must be the first line in the file, and the + # EndFontMetrics keyword must be the last non-empty line in the + # file. We just check the first line. + if not line.startswith(b'StartFontMetrics'): + raise RuntimeError('Not an AFM file') + + +def _parse_header(fh): + """ + Reads the font metrics header (up to the char metrics) and returns + a dictionary mapping *key* to *val*. *val* will be converted to the + appropriate python type as necessary; e.g.: + + * 'False'->False + * '0'->0 + * '-168 -218 1000 898'-> [-168, -218, 1000, 898] + + Dictionary keys are + + StartFontMetrics, FontName, FullName, FamilyName, Weight, + ItalicAngle, IsFixedPitch, FontBBox, UnderlinePosition, + UnderlineThickness, Version, Notice, EncodingScheme, CapHeight, + XHeight, Ascender, Descender, StartCharMetrics + + """ + header_converters = { + b'StartFontMetrics': _to_float, + b'FontName': _to_str, + b'FullName': _to_str, + b'FamilyName': _to_str, + b'Weight': _to_str, + b'ItalicAngle': _to_float, + b'IsFixedPitch': _to_bool, + b'FontBBox': _to_list_of_ints, + b'UnderlinePosition': _to_float, + b'UnderlineThickness': _to_float, + b'Version': _to_str, + # Some AFM files have non-ASCII characters (which are not allowed by + # the spec). Given that there is actually no public API to even access + # this field, just return it as straight bytes. + b'Notice': lambda x: x, + b'EncodingScheme': _to_str, + b'CapHeight': _to_float, # Is the second version a mistake, or + b'Capheight': _to_float, # do some AFM files contain 'Capheight'? -JKS + b'XHeight': _to_float, + b'Ascender': _to_float, + b'Descender': _to_float, + b'StdHW': _to_float, + b'StdVW': _to_float, + b'StartCharMetrics': _to_int, + b'CharacterSet': _to_str, + b'Characters': _to_int, + } + + d = {} + for line in fh: + line = line.rstrip() + if line.startswith(b'Comment'): + continue + lst = line.split(b' ', 1) + + key = lst[0] + if len(lst) == 2: + val = lst[1] + else: + val = b'' + + try: + converter = header_converters[key] + except KeyError: + _log.error('Found an unknown keyword in AFM header (was %r)' % key) + continue + try: + d[key] = converter(val) + except ValueError: + _log.error('Value error parsing header in AFM: %s, %s', key, val) + continue + if key == b'StartCharMetrics': + return d + raise RuntimeError('Bad parse') + + +CharMetrics = namedtuple('CharMetrics', 'width, name, bbox') +CharMetrics.__doc__ = """ + Represents the character metrics of a single character. + + Notes + ----- + The fields do currently only describe a subset of character metrics + information defined in the AFM standard. + """ +CharMetrics.width.__doc__ = """The character width (WX).""" +CharMetrics.name.__doc__ = """The character name (N).""" +CharMetrics.bbox.__doc__ = """ + The bbox of the character (B) as a tuple (*llx*, *lly*, *urx*, *ury*).""" + + +def _parse_char_metrics(fh): + """ + Parse the given filehandle for character metrics information and return + the information as dicts. + + It is assumed that the file cursor is on the line behind + 'StartCharMetrics'. + + Returns + ------- + ascii_d : dict + A mapping "ASCII num of the character" to `.CharMetrics`. + name_d : dict + A mapping "character name" to `.CharMetrics`. + + Notes + ----- + This function is incomplete per the standard, but thus far parses + all the sample afm files tried. + """ + required_keys = {'C', 'WX', 'N', 'B'} + + ascii_d = {} + name_d = {} + for line in fh: + # We are defensively letting values be utf8. The spec requires + # ascii, but there are non-compliant fonts in circulation + line = _to_str(line.rstrip()) # Convert from byte-literal + if line.startswith('EndCharMetrics'): + return ascii_d, name_d + # Split the metric line into a dictionary, keyed by metric identifiers + vals = dict(s.strip().split(' ', 1) for s in line.split(';') if s) + # There may be other metrics present, but only these are needed + if not required_keys.issubset(vals): + raise RuntimeError('Bad char metrics line: %s' % line) + num = _to_int(vals['C']) + wx = _to_float(vals['WX']) + name = vals['N'] + bbox = _to_list_of_floats(vals['B']) + bbox = list(map(int, bbox)) + metrics = CharMetrics(wx, name, bbox) + # Workaround: If the character name is 'Euro', give it the + # corresponding character code, according to WinAnsiEncoding (see PDF + # Reference). + if name == 'Euro': + num = 128 + if num != -1: + ascii_d[num] = metrics + name_d[name] = metrics + raise RuntimeError('Bad parse') + + +def _parse_kern_pairs(fh): + """ + Return a kern pairs dictionary; keys are (*char1*, *char2*) tuples and + values are the kern pair value. For example, a kern pairs line like + ``KPX A y -50`` + + will be represented as:: + + d[ ('A', 'y') ] = -50 + + """ + + line = next(fh) + if not line.startswith(b'StartKernPairs'): + raise RuntimeError('Bad start of kern pairs data: %s' % line) + + d = {} + for line in fh: + line = line.rstrip() + if not line: + continue + if line.startswith(b'EndKernPairs'): + next(fh) # EndKernData + return d + vals = line.split() + if len(vals) != 4 or vals[0] != b'KPX': + raise RuntimeError('Bad kern pairs line: %s' % line) + c1, c2, val = _to_str(vals[1]), _to_str(vals[2]), _to_float(vals[3]) + d[(c1, c2)] = val + raise RuntimeError('Bad kern pairs parse') + + +CompositePart = namedtuple('CompositePart', 'name, dx, dy') +CompositePart.__doc__ = """ + Represents the information on a composite element of a composite char.""" +CompositePart.name.__doc__ = """Name of the part, e.g. 'acute'.""" +CompositePart.dx.__doc__ = """x-displacement of the part from the origin.""" +CompositePart.dy.__doc__ = """y-displacement of the part from the origin.""" + + +def _parse_composites(fh): + """ + Parse the given filehandle for composites information return them as a + dict. + + It is assumed that the file cursor is on the line behind 'StartComposites'. + + Returns + ------- + composites : dict + A dict mapping composite character names to a parts list. The parts + list is a list of `.CompositePart` entries describing the parts of + the composite. + + Example + ------- + A composite definition line:: + + CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 170 ; + + will be represented as:: + + composites['Aacute'] = [CompositePart(name='A', dx=0, dy=0), + CompositePart(name='acute', dx=160, dy=170)] + + """ + composites = {} + for line in fh: + line = line.rstrip() + if not line: + continue + if line.startswith(b'EndComposites'): + return composites + vals = line.split(b';') + cc = vals[0].split() + name, numParts = cc[1], _to_int(cc[2]) + pccParts = [] + for s in vals[1:-1]: + pcc = s.split() + part = CompositePart(pcc[1], _to_float(pcc[2]), _to_float(pcc[3])) + pccParts.append(part) + composites[name] = pccParts + + raise RuntimeError('Bad composites parse') + + +def _parse_optional(fh): + """ + Parse the optional fields for kern pair data and composites. + + Returns + ------- + kern_data : dict + A dict containing kerning information. May be empty. + See `._parse_kern_pairs`. + composites : dict + A dict containing composite information. May be empty. + See `._parse_composites`. + """ + optional = { + b'StartKernData': _parse_kern_pairs, + b'StartComposites': _parse_composites, + } + + d = {b'StartKernData': {}, + b'StartComposites': {}} + for line in fh: + line = line.rstrip() + if not line: + continue + key = line.split()[0] + + if key in optional: + d[key] = optional[key](fh) + + return d[b'StartKernData'], d[b'StartComposites'] + + +@deprecated("3.0", alternative="the AFM class") +def parse_afm(fh): + return _parse_afm(fh) + + +def _parse_afm(fh): + """ + Parse the Adobe Font Metrics file in file handle *fh*. + + Returns + ------- + header : dict + A header dict. See :func:`_parse_header`. + cmetrics_by_ascii : dict + From :func:`_parse_char_metrics`. + cmetrics_by_name : dict + From :func:`_parse_char_metrics`. + kernpairs : dict + From :func:`_parse_kern_pairs`. + composites : dict + From :func:`_parse_composites` + + """ + _sanity_check(fh) + header = _parse_header(fh) + cmetrics_by_ascii, cmetrics_by_name = _parse_char_metrics(fh) + kernpairs, composites = _parse_optional(fh) + return header, cmetrics_by_ascii, cmetrics_by_name, kernpairs, composites + + +class AFM(object): + + def __init__(self, fh): + """Parse the AFM file in file object *fh*.""" + (self._header, + self._metrics, + self._metrics_by_name, + self._kern, + self._composite) = _parse_afm(fh) + + def get_bbox_char(self, c, isord=False): + if not isord: + c = ord(c) + return self._metrics[c].bbox + + def string_width_height(self, s): + """ + Return the string width (including kerning) and string height + as a (*w*, *h*) tuple. + """ + if not len(s): + return 0, 0 + total_width = 0 + namelast = None + miny = 1e9 + maxy = 0 + for c in s: + if c == '\n': + continue + wx, name, bbox = self._metrics[ord(c)] + + total_width += wx + self._kern.get((namelast, name), 0) + l, b, w, h = bbox + miny = min(miny, b) + maxy = max(maxy, b + h) + + namelast = name + + return total_width, maxy - miny + + def get_str_bbox_and_descent(self, s): + """Return the string bounding box and the maximal descent.""" + if not len(s): + return 0, 0, 0, 0, 0 + total_width = 0 + namelast = None + miny = 1e9 + maxy = 0 + left = 0 + if not isinstance(s, str): + s = _to_str(s) + for c in s: + if c == '\n': + continue + name = uni2type1.get(ord(c), 'question') + try: + wx, _, bbox = self._metrics_by_name[name] + except KeyError: + name = 'question' + wx, _, bbox = self._metrics_by_name[name] + total_width += wx + self._kern.get((namelast, name), 0) + l, b, w, h = bbox + left = min(left, l) + miny = min(miny, b) + maxy = max(maxy, b + h) + + namelast = name + + return left, miny, total_width, maxy - miny, -miny + + def get_str_bbox(self, s): + """Return the string bounding box.""" + return self.get_str_bbox_and_descent(s)[:4] + + def get_name_char(self, c, isord=False): + """Get the name of the character, i.e., ';' is 'semicolon'.""" + if not isord: + c = ord(c) + return self._metrics[c].name + + def get_width_char(self, c, isord=False): + """ + Get the width of the character from the character metric WX field. + """ + if not isord: + c = ord(c) + return self._metrics[c].width + + def get_width_from_char_name(self, name): + """Get the width of the character from a type1 character name.""" + return self._metrics_by_name[name].width + + def get_height_char(self, c, isord=False): + """Get the bounding box (ink) height of character *c* (space is 0).""" + if not isord: + c = ord(c) + return self._metrics[c].bbox[-1] + + def get_kern_dist(self, c1, c2): + """ + Return the kerning pair distance (possibly 0) for chars *c1* and *c2*. + """ + name1, name2 = self.get_name_char(c1), self.get_name_char(c2) + return self.get_kern_dist_from_name(name1, name2) + + def get_kern_dist_from_name(self, name1, name2): + """ + Return the kerning pair distance (possibly 0) for chars + *name1* and *name2*. + """ + return self._kern.get((name1, name2), 0) + + def get_fontname(self): + """Return the font name, e.g., 'Times-Roman'.""" + return self._header[b'FontName'] + + def get_fullname(self): + """Return the font full name, e.g., 'Times-Roman'.""" + name = self._header.get(b'FullName') + if name is None: # use FontName as a substitute + name = self._header[b'FontName'] + return name + + def get_familyname(self): + """Return the font family name, e.g., 'Times'.""" + name = self._header.get(b'FamilyName') + if name is not None: + return name + + # FamilyName not specified so we'll make a guess + name = self.get_fullname() + extras = (r'(?i)([ -](regular|plain|italic|oblique|bold|semibold|' + r'light|ultralight|extra|condensed))+$') + return re.sub(extras, '', name) + + @property + def family_name(self): + """The font family name, e.g., 'Times'.""" + return self.get_familyname() + + def get_weight(self): + """Return the font weight, e.g., 'Bold' or 'Roman'.""" + return self._header[b'Weight'] + + def get_angle(self): + """Return the fontangle as float.""" + return self._header[b'ItalicAngle'] + + def get_capheight(self): + """Return the cap height as float.""" + return self._header[b'CapHeight'] + + def get_xheight(self): + """Return the xheight as float.""" + return self._header[b'XHeight'] + + def get_underline_thickness(self): + """Return the underline thickness as float.""" + return self._header[b'UnderlineThickness'] + + def get_horizontal_stem_width(self): + """ + Return the standard horizontal stem width as float, or *None* if + not specified in AFM file. + """ + return self._header.get(b'StdHW', None) + + def get_vertical_stem_width(self): + """ + Return the standard vertical stem width as float, or *None* if + not specified in AFM file. + """ + return self._header.get(b'StdVW', None) diff --git a/venv/lib/python3.6/site-packages/matplotlib/animation.py b/venv/lib/python3.6/site-packages/matplotlib/animation.py new file mode 100644 index 0000000..8346a4e --- /dev/null +++ b/venv/lib/python3.6/site-packages/matplotlib/animation.py @@ -0,0 +1,1764 @@ +# TODO: +# * Documentation -- this will need a new section of the User's Guide. +# Both for Animations and just timers. +# - Also need to update http://www.scipy.org/Cookbook/Matplotlib/Animations +# * Blit +# * Currently broken with Qt4 for widgets that don't start on screen +# * Still a few edge cases that aren't working correctly +# * Can this integrate better with existing matplotlib animation artist flag? +# - If animated removes from default draw(), perhaps we could use this to +# simplify initial draw. +# * Example +# * Frameless animation - pure procedural with no loop +# * Need example that uses something like inotify or subprocess +# * Complex syncing examples +# * Movies +# * Can blit be enabled for movies? +# * Need to consider event sources to allow clicking through multiple figures + +import abc +import base64 +import contextlib +from io import BytesIO, TextIOWrapper +import itertools +import logging +import os +from pathlib import Path +import platform +import shutil +import subprocess +import sys +from tempfile import TemporaryDirectory +import uuid + +import numpy as np + +import matplotlib as mpl +from matplotlib._animation_data import ( + DISPLAY_TEMPLATE, INCLUDED_FRAMES, JS_INCLUDE, STYLE_INCLUDE) +from matplotlib import cbook, rcParams, rcParamsDefault, rc_context + + +_log = logging.getLogger(__name__) + +# Process creation flag for subprocess to prevent it raising a terminal +# window. See for example: +# https://stackoverflow.com/questions/24130623/using-python-subprocess-popen-cant-prevent-exe-stopped-working-prompt +if platform.system() == 'Windows': + subprocess_creation_flags = CREATE_NO_WINDOW = 0x08000000 +else: + # Apparently None won't work here + subprocess_creation_flags = 0 + +# Other potential writing methods: +# * http://pymedia.org/ +# * libming (produces swf) python wrappers: https://github.com/libming/libming +# * Wrap x264 API: + +# (http://stackoverflow.com/questions/2940671/ +# how-to-encode-series-of-images-into-h264-using-x264-api-c-c ) + + +def adjusted_figsize(w, h, dpi, n): + '''Compute figure size so that pixels are a multiple of n + + Parameters + ---------- + w, h : float + Size in inches + + dpi : float + The dpi + + n : int + The target multiple + + Returns + ------- + wnew, hnew : float + The new figure size in inches. + ''' + + # this maybe simplified if / when we adopt consistent rounding for + # pixel size across the whole library + def correct_roundoff(x, dpi, n): + if int(x*dpi) % n != 0: + if int(np.nextafter(x, np.inf)*dpi) % n == 0: + x = np.nextafter(x, np.inf) + elif int(np.nextafter(x, -np.inf)*dpi) % n == 0: + x = np.nextafter(x, -np.inf) + return x + + wnew = int(w * dpi / n) * n / dpi + hnew = int(h * dpi / n) * n / dpi + return (correct_roundoff(wnew, dpi, n), correct_roundoff(hnew, dpi, n)) + + +# A registry for available MovieWriter classes +class MovieWriterRegistry(object): + '''Registry of available writer classes by human readable name.''' + def __init__(self): + self.avail = dict() + self._registered = dict() + self._dirty = False + + def set_dirty(self): + """Sets a flag to re-setup the writers.""" + self._dirty = True + + def register(self, name): + """Decorator for registering a class under a name. + + Example use:: + + @registry.register(name) + class Foo: + pass + """ + def wrapper(writerClass): + self._registered[name] = writerClass + if writerClass.isAvailable(): + self.avail[name] = writerClass + return writerClass + return wrapper + + def ensure_not_dirty(self): + """If dirty, reasks the writers if they are available""" + if self._dirty: + self.reset_available_writers() + + def reset_available_writers(self): + """Reset the available state of all registered writers""" + self.avail = {name: writerClass + for name, writerClass in self._registered.items() + if writerClass.isAvailable()} + self._dirty = False + + def list(self): + '''Get a list of available MovieWriters.''' + self.ensure_not_dirty() + return list(self.avail) + + def is_available(self, name): + '''Check if given writer is available by name. + + Parameters + ---------- + name : str + + Returns + ------- + available : bool + ''' + self.ensure_not_dirty() + return name in self.avail + + def __getitem__(self, name): + self.ensure_not_dirty() + if not self.avail: + raise RuntimeError("No MovieWriters available!") + try: + return self.avail[name] + except KeyError: + raise RuntimeError( + 'Requested MovieWriter ({}) not available'.format(name)) + + +writers = MovieWriterRegistry() + + +class AbstractMovieWriter(abc.ABC): + ''' + Abstract base class for writing movies. Fundamentally, what a MovieWriter + does is provide is a way to grab frames by calling grab_frame(). + + setup() is called to start the process and finish() is called afterwards. + + This class is set up to provide for writing movie frame data to a pipe. + saving() is provided as a context manager to facilitate this process as:: + + with moviewriter.saving(fig, outfile='myfile.mp4', dpi=100): + # Iterate over frames + moviewriter.grab_frame(**savefig_kwargs) + + The use of the context manager ensures that setup() and finish() are + performed as necessary. + + An instance of a concrete subclass of this class can be given as the + ``writer`` argument of `Animation.save()`. + ''' + + @abc.abstractmethod + def setup(self, fig, outfile, dpi=None): + ''' + Perform setup for writing the movie file. + + Parameters + ---------- + fig : `matplotlib.figure.Figure` instance + The figure object that contains the information for frames + outfile : string + The filename of the resulting movie file + dpi : int, optional + The DPI (or resolution) for the file. This controls the size + in pixels of the resulting movie file. Default is ``fig.dpi``. + ''' + + @abc.abstractmethod + def grab_frame(self, **savefig_kwargs): + ''' + Grab the image information from the figure and save as a movie frame. + + All keyword arguments in savefig_kwargs are passed on to the `savefig` + command that saves the figure. + ''' + + @abc.abstractmethod + def finish(self): + '''Finish any processing for writing the movie.''' + + @contextlib.contextmanager + def saving(self, fig, outfile, dpi, *args, **kwargs): + ''' + Context manager to facilitate writing the movie file. + + ``*args, **kw`` are any parameters that should be passed to `setup`. + ''' + # This particular sequence is what contextlib.contextmanager wants + self.setup(fig, outfile, dpi, *args, **kwargs) + try: + yield self + finally: + self.finish() + + +class MovieWriter(AbstractMovieWriter): + '''Base class for writing movies. + + This is a base class for MovieWriter subclasses that write a movie frame + data to a pipe. You cannot instantiate this class directly. + See examples for how to use its subclasses. + + Attributes + ---------- + frame_format : str + The format used in writing frame data, defaults to 'rgba' + fig : `~matplotlib.figure.Figure` + The figure to capture data from. + This must be provided by the sub-classes. + + ''' + + def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None, + metadata=None): + '''MovieWriter + + Parameters + ---------- + fps : int + Framerate for movie. + codec : string or None, optional + The codec to use. If ``None`` (the default) the ``animation.codec`` + rcParam is used. + bitrate : int or None, optional + The bitrate for the saved movie file, which is one way to control + the output file size and quality. The default value is ``None``, + which uses the ``animation.bitrate`` rcParam. A value of -1 + implies that the bitrate should be determined automatically by the + underlying utility. + extra_args : list of strings or None, optional + A list of extra string arguments to be passed to the underlying + movie utility. The default is ``None``, which passes the additional + arguments in the ``animation.extra_args`` rcParam. + metadata : Dict[str, str] or None + A dictionary of keys and values for metadata to include in the + output file. Some keys that may be of use include: + title, artist, genre, subject, copyright, srcform, comment. + ''' + if self.__class__ is MovieWriter: + # TODO MovieWriter is still an abstract class and needs to be + # extended with a mixin. This should be clearer in naming + # and description. For now, just give a reasonable error + # message to users. + raise TypeError( + 'MovieWriter cannot be instantiated directly. Please use one ' + 'of its subclasses.') + + self.fps = fps + self.frame_format = 'rgba' + + if codec is None: + self.codec = rcParams['animation.codec'] + else: + self.codec = codec + + if bitrate is None: + self.bitrate = rcParams['animation.bitrate'] + else: + self.bitrate = bitrate + + if extra_args is None: + self.extra_args = list(rcParams[self.args_key]) + else: + self.extra_args = extra_args + + if metadata is None: + self.metadata = dict() + else: + self.metadata = metadata + + @property + def frame_size(self): + '''A tuple ``(width, height)`` in pixels of a movie frame.''' + w, h = self.fig.get_size_inches() + return int(w * self.dpi), int(h * self.dpi) + + def _adjust_frame_size(self): + if self.codec == 'h264': + wo, ho = self.fig.get_size_inches() + w, h = adjusted_figsize(wo, ho, self.dpi, 2) + if not (wo, ho) == (w, h): + self.fig.set_size_inches(w, h, forward=True) + _log.info('figure size (inches) has been adjusted ' + 'from %s x %s to %s x %s', wo, ho, w, h) + else: + w, h = self.fig.get_size_inches() + _log.debug('frame size in pixels is %s x %s', *self.frame_size) + return w, h + + def setup(self, fig, outfile, dpi=None): + ''' + Perform setup for writing the movie file. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that contains the information for frames + outfile : string + The filename of the resulting movie file + dpi : int, optional + The DPI (or resolution) for the file. This controls the size + in pixels of the resulting movie file. Default is fig.dpi. + ''' + self.outfile = outfile + self.fig = fig + if dpi is None: + dpi = self.fig.dpi + self.dpi = dpi + self._w, self._h = self._adjust_frame_size() + + # Run here so that grab_frame() can write the data to a pipe. This + # eliminates the need for temp files. + self._run() + + def _run(self): + # Uses subprocess to call the program for assembling frames into a + # movie file. *args* returns the sequence of command line arguments + # from a few configuration options. + command = self._args() + _log.info('MovieWriter.run: running command: %s', command) + PIPE = subprocess.PIPE + self._proc = subprocess.Popen( + command, stdin=PIPE, stdout=PIPE, stderr=PIPE, + creationflags=subprocess_creation_flags) + + def finish(self): + '''Finish any processing for writing the movie.''' + self.cleanup() + + def grab_frame(self, **savefig_kwargs): + ''' + Grab the image information from the figure and save as a movie frame. + + All keyword arguments in savefig_kwargs are passed on to the `savefig` + command that saves the figure. + ''' + _log.debug('MovieWriter.grab_frame: Grabbing frame.') + # re-adjust the figure size in case it has been changed by the + # user. We must ensure that every frame is the same size or + # the movie will not save correctly. + self.fig.set_size_inches(self._w, self._h) + # Tell the figure to save its data to the sink, using the + # frame format and dpi. + self.fig.savefig(self._frame_sink(), format=self.frame_format, + dpi=self.dpi, **savefig_kwargs) + + def _frame_sink(self): + '''Return the place to which frames should be written.''' + return self._proc.stdin + + def _args(self): + '''Assemble list of utility-specific command-line arguments.''' + return NotImplementedError("args needs to be implemented by subclass.") + + def cleanup(self): + '''Clean-up and collect the process used to write the movie file.''' + out, err = self._proc.communicate() + self._frame_sink().close() + # Use the encoding/errors that universal_newlines would use. + out = TextIOWrapper(BytesIO(out)).read() + err = TextIOWrapper(BytesIO(err)).read() + if out: + _log.log( + logging.WARNING if self._proc.returncode else logging.DEBUG, + "MovieWriter stdout:\n%s", out) + if err: + _log.log( + logging.WARNING if self._proc.returncode else logging.DEBUG, + "MovieWriter stderr:\n%s", err) + if self._proc.returncode: + raise subprocess.CalledProcessError( + self._proc.returncode, self._proc.args, out, err) + + @classmethod + def bin_path(cls): + ''' + Return the binary path to the commandline tool used by a specific + subclass. This is a class method so that the tool can be looked for + before making a particular MovieWriter subclass available. + ''' + return str(rcParams[cls.exec_key]) + + @classmethod + def isAvailable(cls): + ''' + Check to see if a MovieWriter subclass is actually available. + ''' + return shutil.which(cls.bin_path()) is not None + + +class FileMovieWriter(MovieWriter): + '''`MovieWriter` for writing to individual files and stitching at the end. + + This must be sub-classed to be useful. + ''' + def __init__(self, *args, **kwargs): + MovieWriter.__init__(self, *args, **kwargs) + self.frame_format = rcParams['animation.frame_format'] + + def setup(self, fig, outfile, dpi=None, frame_prefix='_tmp', + clear_temp=True): + '''Perform setup for writing the movie file. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure to grab the rendered frames from. + outfile : str + The filename of the resulting movie file. + dpi : number, optional + The dpi of the output file. This, with the figure size, + controls the size in pixels of the resulting movie file. + Default is fig.dpi. + frame_prefix : str, optional + The filename prefix to use for temporary files. Defaults to + ``'_tmp'``. + clear_temp : bool, optional + If the temporary files should be deleted after stitching + the final result. Setting this to ``False`` can be useful for + debugging. Defaults to ``True``. + + ''' + self.fig = fig + self.outfile = outfile + if dpi is None: + dpi = self.fig.dpi + self.dpi = dpi + self._adjust_frame_size() + + self.clear_temp = clear_temp + self.temp_prefix = frame_prefix + self._frame_counter = 0 # used for generating sequential file names + self._temp_names = list() + self.fname_format_str = '%s%%07d.%s' + + @property + def frame_format(self): + ''' + Format (png, jpeg, etc.) to use for saving the frames, which can be + decided by the individual subclasses. + ''' + return self._frame_format + + @frame_format.setter + def frame_format(self, frame_format): + if frame_format in self.supported_formats: + self._frame_format = frame_format + else: + self._frame_format = self.supported_formats[0] + + def _base_temp_name(self): + # Generates a template name (without number) given the frame format + # for extension and the prefix. + return self.fname_format_str % (self.temp_prefix, self.frame_format) + + def _frame_sink(self): + # Creates a filename for saving using the basename and the current + # counter. + fname = self._base_temp_name() % self._frame_counter + + # Save the filename so we can delete it later if necessary + self._temp_names.append(fname) + _log.debug('FileMovieWriter.frame_sink: saving frame %d to fname=%s', + self._frame_counter, fname) + self._frame_counter += 1 # Ensures each created name is 'unique' + + # This file returned here will be closed once it's used by savefig() + # because it will no longer be referenced and will be gc-ed. + return open(fname, 'wb') + + def grab_frame(self, **savefig_kwargs): + ''' + Grab the image information from the figure and save as a movie frame. + All keyword arguments in savefig_kwargs are passed on to the `savefig` + command that saves the figure. + ''' + # Overloaded to explicitly close temp file. + _log.debug('MovieWriter.grab_frame: Grabbing frame.') + # Tell the figure to save its data to the sink, using the + # frame format and dpi. + with self._frame_sink() as myframesink: + self.fig.savefig(myframesink, format=self.frame_format, + dpi=self.dpi, **savefig_kwargs) + + def finish(self): + # Call run here now that all frame grabbing is done. All temp files + # are available to be assembled. + self._run() + MovieWriter.finish(self) # Will call clean-up + + def cleanup(self): + MovieWriter.cleanup(self) + + # Delete temporary files + if self.clear_temp: + _log.debug('MovieWriter: clearing temporary fnames=%s', + self._temp_names) + for fname in self._temp_names: + os.remove(fname) + + +@writers.register('pillow') +class PillowWriter(MovieWriter): + @classmethod + def isAvailable(cls): + try: + import PIL + except ImportError: + return False + return True + + def __init__(self, *args, **kwargs): + if kwargs.get("extra_args") is None: + kwargs["extra_args"] = () + super().__init__(*args, **kwargs) + + def setup(self, fig, outfile, dpi=None): + self._frames = [] + self._outfile = outfile + self._dpi = dpi + self._fig = fig + + def grab_frame(self, **savefig_kwargs): + from PIL import Image + buf = BytesIO() + self._fig.savefig(buf, **dict(savefig_kwargs, format="rgba")) + renderer = self._fig.canvas.get_renderer() + # Using frombuffer / getbuffer may be slightly more efficient, but + # Py3-only. + self._frames.append(Image.frombytes( + "RGBA", + (int(renderer.width), int(renderer.height)), + buf.getvalue())) + + def finish(self): + self._frames[0].save( + self._outfile, save_all=True, append_images=self._frames[1:], + duration=int(1000 / self.fps), loop=0) + + +# Base class of ffmpeg information. Has the config keys and the common set +# of arguments that controls the *output* side of things. +class FFMpegBase(object): + '''Mixin class for FFMpeg output. + + To be useful this must be multiply-inherited from with a + `MovieWriterBase` sub-class. + ''' + + exec_key = 'animation.ffmpeg_path' + args_key = 'animation.ffmpeg_args' + + @property + def output_args(self): + args = ['-vcodec', self.codec] + # For h264, the default format is yuv444p, which is not compatible + # with quicktime (and others). Specifying yuv420p fixes playback on + # iOS,as well as HTML5 video in firefox and safari (on both Win and + # OSX). Also fixes internet explorer. This is as of 2015/10/29. + if self.codec == 'h264' and '-pix_fmt' not in self.extra_args: + args.extend(['-pix_fmt', 'yuv420p']) + # The %dk adds 'k' as a suffix so that ffmpeg treats our bitrate as in + # kbps + if self.bitrate > 0: + args.extend(['-b', '%dk' % self.bitrate]) + if self.extra_args: + args.extend(self.extra_args) + for k, v in self.metadata.items(): + args.extend(['-metadata', '%s=%s' % (k, v)]) + + return args + ['-y', self.outfile] + + @classmethod + def isAvailable(cls): + return ( + super().isAvailable() + # Ubuntu 12.04 ships a broken ffmpeg binary which we shouldn't use. + # NOTE: when removed, remove the same method in AVConvBase. + and b'LibAv' not in subprocess.run( + [cls.bin_path()], creationflags=subprocess_creation_flags, + stdout=subprocess.DEVNULL, stderr=subprocess.PIPE).stderr) + + +# Combine FFMpeg options with pipe-based writing +@writers.register('ffmpeg') +class FFMpegWriter(FFMpegBase, MovieWriter): + '''Pipe-based ffmpeg writer. + + Frames are streamed directly to ffmpeg via a pipe and written in a single + pass. + ''' + def _args(self): + # Returns the command line parameters for subprocess to use + # ffmpeg to create a movie using a pipe. + args = [self.bin_path(), '-f', 'rawvideo', '-vcodec', 'rawvideo', + '-s', '%dx%d' % self.frame_size, '-pix_fmt', self.frame_format, + '-r', str(self.fps)] + # Logging is quieted because subprocess.PIPE has limited buffer size. + # If you have a lot of frames in your animation and set logging to + # DEBUG, you will have a buffer overrun. + if _log.getEffectiveLevel() > logging.DEBUG: + args += ['-loglevel', 'error'] + args += ['-i', 'pipe:'] + self.output_args + return args + + +# Combine FFMpeg options with temp file-based writing +@writers.register('ffmpeg_file') +class FFMpegFileWriter(FFMpegBase, FileMovieWriter): + '''File-based ffmpeg writer. + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' + supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp', + 'pbm', 'raw', 'rgba'] + + def _args(self): + # Returns the command line parameters for subprocess to use + # ffmpeg to create a movie using a collection of temp images + return [self.bin_path(), '-r', str(self.fps), + '-i', self._base_temp_name(), + '-vframes', str(self._frame_counter)] + self.output_args + + +# Base class of avconv information. AVConv has identical arguments to FFMpeg. +class AVConvBase(FFMpegBase): + '''Mixin class for avconv output. + + To be useful this must be multiply-inherited from with a + `MovieWriterBase` sub-class. + ''' + + exec_key = 'animation.avconv_path' + args_key = 'animation.avconv_args' + + # NOTE : should be removed when the same method is removed in FFMpegBase. + isAvailable = classmethod(MovieWriter.isAvailable.__func__) + + +# Combine AVConv options with pipe-based writing +@writers.register('avconv') +class AVConvWriter(AVConvBase, FFMpegWriter): + '''Pipe-based avconv writer. + + Frames are streamed directly to avconv via a pipe and written in a single + pass. + ''' + + +# Combine AVConv options with file-based writing +@writers.register('avconv_file') +class AVConvFileWriter(AVConvBase, FFMpegFileWriter): + '''File-based avconv writer. + + Frames are written to temporary files on disk and then stitched + together at the end. + ''' + + +# Base class for animated GIFs with ImageMagick +class ImageMagickBase(object): + '''Mixin class for ImageMagick output. + + To be useful this must be multiply-inherited from with a + `MovieWriterBase` sub-class. + ''' + + exec_key = 'animation.convert_path' + args_key = 'animation.convert_args' + + @property + def delay(self): + return 100. / self.fps + + @property + def output_args(self): + return [self.outfile] + + @classmethod + def bin_path(cls): + binpath = super().bin_path() + if binpath == 'convert': + binpath = mpl._get_executable_info('magick').executable + return binpath + + @classmethod + def isAvailable(cls): + try: + return super().isAvailable() + except FileNotFoundError: # May be raised by get_executable_info. + return False + + +# Combine ImageMagick options with pipe-based writing +@writers.register('imagemagick') +class ImageMagickWriter(ImageMagickBase, MovieWriter): + '''Pipe-based animated gif. + + Frames are streamed directly to ImageMagick via a pipe and written + in a single pass. + + ''' + def _args(self): + return ([self.bin_path(), + '-size', '%ix%i' % self.frame_size, '-depth', '8', + '-delay', str(self.delay), '-loop', '0', + '%s:-' % self.frame_format] + + self.output_args) + + +# Combine ImageMagick options with temp file-based writing +@writers.register('imagemagick_file') +class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter): + '''File-based animated gif writer. + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' + + supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp', + 'pbm', 'raw', 'rgba'] + + def _args(self): + return ([self.bin_path(), '-delay', str(self.delay), '-loop', '0', + '%s*.%s' % (self.temp_prefix, self.frame_format)] + + self.output_args) + + +# Taken directly from jakevdp's JSAnimation package at +# http://github.com/jakevdp/JSAnimation +def _included_frames(frame_list, frame_format): + """frame_list should be a list of filenames""" + return INCLUDED_FRAMES.format(Nframes=len(frame_list), + frame_dir=os.path.dirname(frame_list[0]), + frame_format=frame_format) + + +def _embedded_frames(frame_list, frame_format): + """frame_list should be a list of base64-encoded png files""" + template = ' frames[{0}] = "data:image/{1};base64,{2}"\n' + return "\n" + "".join( + template.format(i, frame_format, frame_data.replace('\n', '\\\n')) + for i, frame_data in enumerate(frame_list)) + + +@writers.register('html') +class HTMLWriter(FileMovieWriter): + supported_formats = ['png', 'jpeg', 'tiff', 'svg'] + args_key = 'animation.html_args' + + @classmethod + def isAvailable(cls): + return True + + def __init__(self, fps=30, codec=None, bitrate=None, extra_args=None, + metadata=None, embed_frames=False, default_mode='loop', + embed_limit=None): + self.embed_frames = embed_frames + self.default_mode = default_mode.lower() + + # Save embed limit, which is given in MB + if embed_limit is None: + self._bytes_limit = rcParams['animation.embed_limit'] + else: + self._bytes_limit = embed_limit + + # Convert from MB to bytes + self._bytes_limit *= 1024 * 1024 + + if self.default_mode not in ['loop', 'once', 'reflect']: + raise ValueError( + "unrecognized default_mode {!r}".format(self.default_mode)) + + super().__init__(fps, codec, bitrate, extra_args, metadata) + + def setup(self, fig, outfile, dpi, frame_dir=None): + root, ext = os.path.splitext(outfile) + if ext not in ['.html', '.htm']: + raise ValueError("outfile must be *.htm or *.html") + + self._saved_frames = [] + self._total_bytes = 0 + self._hit_limit = False + + if not self.embed_frames: + if frame_dir is None: + frame_dir = root + '_frames' + if not os.path.exists(frame_dir): + os.makedirs(frame_dir) + frame_prefix = os.path.join(frame_dir, 'frame') + else: + frame_prefix = None + + super().setup(fig, outfile, dpi, frame_prefix, clear_temp=False) + + def grab_frame(self, **savefig_kwargs): + if self.embed_frames: + # Just stop processing if we hit the limit + if self._hit_limit: + return + f = BytesIO() + self.fig.savefig(f, format=self.frame_format, + dpi=self.dpi, **savefig_kwargs) + imgdata64 = base64.encodebytes(f.getvalue()).decode('ascii') + self._total_bytes += len(imgdata64) + if self._total_bytes >= self._bytes_limit: + _log.warning( + "Animation size has reached %s bytes, exceeding the limit " + "of %s. If you're sure you want a larger animation " + "embedded, set the animation.embed_limit rc parameter to " + "a larger value (in MB). This and further frames will be " + "dropped.", self._total_bytes, self._bytes_limit) + self._hit_limit = True + else: + self._saved_frames.append(imgdata64) + else: + return super().grab_frame(**savefig_kwargs) + + def finish(self): + # save the frames to an html file + if self.embed_frames: + fill_frames = _embedded_frames(self._saved_frames, + self.frame_format) + Nframes = len(self._saved_frames) + else: + # temp names is filled by FileMovieWriter + fill_frames = _included_frames(self._temp_names, + self.frame_format) + Nframes = len(self._temp_names) + mode_dict = dict(once_checked='', + loop_checked='', + reflect_checked='') + mode_dict[self.default_mode + '_checked'] = 'checked' + + interval = 1000 // self.fps + + with open(self.outfile, 'w') as of: + of.write(JS_INCLUDE + STYLE_INCLUDE) + of.write(DISPLAY_TEMPLATE.format(id=uuid.uuid4().hex, + Nframes=Nframes, + fill_frames=fill_frames, + interval=interval, + **mode_dict)) + + +class Animation(object): + '''This class wraps the creation of an animation using matplotlib. + + It is only a base class which should be subclassed to provide + needed behavior. + + This class is not typically used directly. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that is used to get draw, resize, and any + other needed events. + + event_source : object, optional + A class that can run a callback when desired events + are generated, as well as be stopped and started. + + Examples include timers (see :class:`TimedAnimation`) and file + system notifications. + + blit : bool, optional + controls whether blitting is used to optimize drawing. Defaults + to ``False``. + + See Also + -------- + FuncAnimation, ArtistAnimation + + ''' + def __init__(self, fig, event_source=None, blit=False): + self._fig = fig + # Disables blitting for backends that don't support it. This + # allows users to request it if available, but still have a + # fallback that works if it is not. + self._blit = blit and fig.canvas.supports_blit + + # These are the basics of the animation. The frame sequence represents + # information for each frame of the animation and depends on how the + # drawing is handled by the subclasses. The event source fires events + # that cause the frame sequence to be iterated. + self.frame_seq = self.new_frame_seq() + self.event_source = event_source + + # Instead of starting the event source now, we connect to the figure's + # draw_event, so that we only start once the figure has been drawn. + self._first_draw_id = fig.canvas.mpl_connect('draw_event', self._start) + + # Connect to the figure's close_event so that we don't continue to + # fire events and try to draw to a deleted figure. + self._close_id = self._fig.canvas.mpl_connect('close_event', + self._stop) + if self._blit: + self._setup_blit() + + def _start(self, *args): + ''' + Starts interactive animation. Adds the draw frame command to the GUI + handler, calls show to start the event loop. + ''' + # First disconnect our draw event handler + self._fig.canvas.mpl_disconnect(self._first_draw_id) + self._first_draw_id = None # So we can check on save + + # Now do any initial draw + self._init_draw() + + # Add our callback for stepping the animation and + # actually start the event_source. + self.event_source.add_callback(self._step) + self.event_source.start() + + def _stop(self, *args): + # On stop we disconnect all of our events. + if self._blit: + self._fig.canvas.mpl_disconnect(self._resize_id) + self._fig.canvas.mpl_disconnect(self._close_id) + self.event_source.remove_callback(self._step) + self.event_source = None + + def save(self, filename, writer=None, fps=None, dpi=None, codec=None, + bitrate=None, extra_args=None, metadata=None, extra_anim=None, + savefig_kwargs=None, *, progress_callback=None): + """ + Save the animation as a movie file by drawing every frame. + + Parameters + ---------- + + filename : str + The output filename, e.g., :file:`mymovie.mp4`. + + writer : :class:`MovieWriter` or str, optional + A `MovieWriter` instance to use or a key that identifies a + class to use, such as 'ffmpeg'. If ``None``, defaults to + :rc:`animation.writer` = 'ffmpeg'. + + fps : number, optional + Frames per second in the movie. Defaults to ``None``, which will use + the animation's specified interval to set the frames per second. + + dpi : number, optional + Controls the dots per inch for the movie frames. This combined with + the figure's size in inches controls the size of the movie. If + ``None``, defaults to :rc:`savefig.dpi`. + + codec : str, optional + The video codec to be used. Not all codecs are supported + by a given :class:`MovieWriter`. If ``None``, default to + :rc:`animation.codec` = 'h264'. + + bitrate : number, optional + Specifies the number of bits used per second in the compressed + movie, in kilobits per second. A higher number means a higher + quality movie, but at the cost of increased file size. If ``None``, + defaults to :rc:`animation.bitrate` = -1. + + extra_args : list, optional + List of extra string arguments to be passed to the underlying movie + utility. If ``None``, defaults to :rc:`animation.extra_args`. + + metadata : Dict[str, str], optional + Dictionary of keys and values for metadata to include in + the output file. Some keys that may be of use include: + title, artist, genre, subject, copyright, srcform, comment. + + extra_anim : list, optional + Additional `Animation` objects that should be included + in the saved movie file. These need to be from the same + `matplotlib.figure.Figure` instance. Also, animation frames will + just be simply combined, so there should be a 1:1 correspondence + between the frames from the different animations. + + savefig_kwargs : dict, optional + Is a dictionary containing keyword arguments to be passed + on to the `savefig` command which is called repeatedly to + save the individual frames. + + progress_callback : function, optional + A callback function that will be called for every frame to notify + the saving progress. It must have the signature :: + + def func(current_frame: int, total_frames: int) -> Any + + where *current_frame* is the current frame number and + *total_frames* is the total number of frames to be saved. + *total_frames* is set to None, if the total number of frames can + not be determined. Return values may exist but are ignored. + + Example code to write the progress to stdout:: + + progress_callback =\ + lambda i, n: print(f'Saving frame {i} of {n}') + + Notes + ----- + *fps*, *codec*, *bitrate*, *extra_args* and *metadata* are used to + construct a `.MovieWriter` instance and can only be passed if + *writer* is a string. If they are passed as non-*None* and *writer* + is a `.MovieWriter`, a `RuntimeError` will be raised. + + """ + # If the writer is None, use the rc param to find the name of the one + # to use + if writer is None: + writer = rcParams['animation.writer'] + elif (not isinstance(writer, str) and + any(arg is not None + for arg in (fps, codec, bitrate, extra_args, metadata))): + raise RuntimeError('Passing in values for arguments ' + 'fps, codec, bitrate, extra_args, or metadata ' + 'is not supported when writer is an existing ' + 'MovieWriter instance. These should instead be ' + 'passed as arguments when creating the ' + 'MovieWriter instance.') + + if savefig_kwargs is None: + savefig_kwargs = {} + + # Need to disconnect the first draw callback, since we'll be doing + # draws. Otherwise, we'll end up starting the animation. + if self._first_draw_id is not None: + self._fig.canvas.mpl_disconnect(self._first_draw_id) + reconnect_first_draw = True + else: + reconnect_first_draw = False + + if fps is None and hasattr(self, '_interval'): + # Convert interval in ms to frames per second + fps = 1000. / self._interval + + # Re-use the savefig DPI for ours if none is given + if dpi is None: + dpi = rcParams['savefig.dpi'] + if dpi == 'figure': + dpi = self._fig.dpi + + if codec is None: + codec = rcParams['animation.codec'] + + if bitrate is None: + bitrate = rcParams['animation.bitrate'] + + all_anim = [self] + if extra_anim is not None: + all_anim.extend(anim + for anim + in extra_anim if anim._fig is self._fig) + + # If we have the name of a writer, instantiate an instance of the + # registered class. + if isinstance(writer, str): + if writer in writers.avail: + writer = writers[writer](fps, codec, bitrate, + extra_args=extra_args, + metadata=metadata) + else: + if writers.list(): + alt_writer = writers[writers.list()[0]] + _log.warning("MovieWriter %s unavailable; trying to use " + "%s instead.", writer, alt_writer) + writer = alt_writer( + fps, codec, bitrate, + extra_args=extra_args, metadata=metadata) + else: + raise ValueError("Cannot save animation: no writers are " + "available. Please install ffmpeg to " + "save animations.") + _log.info('Animation.save using %s', type(writer)) + + if 'bbox_inches' in savefig_kwargs: + _log.warning("Warning: discarding the 'bbox_inches' argument in " + "'savefig_kwargs' as it may cause frame size " + "to vary, which is inappropriate for animation.") + savefig_kwargs.pop('bbox_inches') + + # Create a new sequence of frames for saved data. This is different + # from new_frame_seq() to give the ability to save 'live' generated + # frame information to be saved later. + # TODO: Right now, after closing the figure, saving a movie won't work + # since GUI widgets are gone. Either need to remove extra code to + # allow for this non-existent use case or find a way to make it work. + with rc_context(): + if rcParams['savefig.bbox'] == 'tight': + _log.info("Disabling savefig.bbox = 'tight', as it may cause " + "frame size to vary, which is inappropriate for " + "animation.") + rcParams['savefig.bbox'] = None + with writer.saving(self._fig, filename, dpi): + for anim in all_anim: + # Clear the initial frame + anim._init_draw() + frame_number = 0 + # TODO: Currently only FuncAnimation has a save_count + # attribute. Can we generalize this to all Animations? + save_count_list = [getattr(a, 'save_count', None) + for a in all_anim] + if None in save_count_list: + total_frames = None + else: + total_frames = sum(save_count_list) + for data in zip(*[a.new_saved_frame_seq() for a in all_anim]): + for anim, d in zip(all_anim, data): + # TODO: See if turning off blit is really necessary + anim._draw_next_frame(d, blit=False) + if progress_callback is not None: + progress_callback(frame_number, total_frames) + frame_number += 1 + writer.grab_frame(**savefig_kwargs) + + # Reconnect signal for first draw if necessary + if reconnect_first_draw: + self._first_draw_id = self._fig.canvas.mpl_connect('draw_event', + self._start) + + def _step(self, *args): + ''' + Handler for getting events. By default, gets the next frame in the + sequence and hands the data off to be drawn. + ''' + # Returns True to indicate that the event source should continue to + # call _step, until the frame sequence reaches the end of iteration, + # at which point False will be returned. + try: + framedata = next(self.frame_seq) + self._draw_next_frame(framedata, self._blit) + return True + except StopIteration: + return False + + def new_frame_seq(self): + """Return a new sequence of frame information.""" + # Default implementation is just an iterator over self._framedata + return iter(self._framedata) + + def new_saved_frame_seq(self): + """Return a new sequence of saved/cached frame information.""" + # Default is the same as the regular frame sequence + return self.new_frame_seq() + + def _draw_next_frame(self, framedata, blit): + # Breaks down the drawing of the next frame into steps of pre- and + # post- draw, as well as the drawing of the frame itself. + self._pre_draw(framedata, blit) + self._draw_frame(framedata) + self._post_draw(framedata, blit) + + def _init_draw(self): + # Initial draw to clear the frame. Also used by the blitting code + # when a clean base is required. + pass + + def _pre_draw(self, framedata, blit): + # Perform any cleaning or whatnot before the drawing of the frame. + # This default implementation allows blit to clear the frame. + if blit: + self._blit_clear(self._drawn_artists, self._blit_cache) + + def _draw_frame(self, framedata): + # Performs actual drawing of the frame. + raise NotImplementedError('Needs to be implemented by subclasses to' + ' actually make an animation.') + + def _post_draw(self, framedata, blit): + # After the frame is rendered, this handles the actual flushing of + # the draw, which can be a direct draw_idle() or make use of the + # blitting. + if blit and self._drawn_artists: + self._blit_draw(self._drawn_artists, self._blit_cache) + else: + self._fig.canvas.draw_idle() + + # The rest of the code in this class is to facilitate easy blitting + def _blit_draw(self, artists, bg_cache): + # Handles blitted drawing, which renders only the artists given instead + # of the entire figure. + updated_ax = [] + for a in artists: + # If we haven't cached the background for this axes object, do + # so now. This might not always be reliable, but it's an attempt + # to automate the process. + if a.axes not in bg_cache: + bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox) + a.axes.draw_artist(a) + updated_ax.append(a.axes) + + # After rendering all the needed artists, blit each axes individually. + for ax in set(updated_ax): + ax.figure.canvas.blit(ax.bbox) + + def _blit_clear(self, artists, bg_cache): + # Get a list of the axes that need clearing from the artists that + # have been drawn. Grab the appropriate saved background from the + # cache and restore. + axes = {a.axes for a in artists} + for a in axes: + if a in bg_cache: + a.figure.canvas.restore_region(bg_cache[a]) + + def _setup_blit(self): + # Setting up the blit requires: a cache of the background for the + # axes + self._blit_cache = dict() + self._drawn_artists = [] + for ax in self._fig.axes: + ax.callbacks.connect('xlim_changed', + lambda ax: self._blit_cache.pop(ax, None)) + ax.callbacks.connect('ylim_changed', + lambda ax: self._blit_cache.pop(ax, None)) + self._resize_id = self._fig.canvas.mpl_connect('resize_event', + self._handle_resize) + self._post_draw(None, self._blit) + + def _handle_resize(self, *args): + # On resize, we need to disable the resize event handling so we don't + # get too many events. Also stop the animation events, so that + # we're paused. Reset the cache and re-init. Set up an event handler + # to catch once the draw has actually taken place. + self._fig.canvas.mpl_disconnect(self._resize_id) + self.event_source.stop() + self._blit_cache.clear() + self._init_draw() + self._resize_id = self._fig.canvas.mpl_connect('draw_event', + self._end_redraw) + + def _end_redraw(self, evt): + # Now that the redraw has happened, do the post draw flushing and + # blit handling. Then re-enable all of the original events. + self._post_draw(None, False) + self.event_source.start() + self._fig.canvas.mpl_disconnect(self._resize_id) + self._resize_id = self._fig.canvas.mpl_connect('resize_event', + self._handle_resize) + + def to_html5_video(self, embed_limit=None): + """ + Convert the animation to an HTML5 ``