Codebase list jsonpickle / 4b6fe8f
New upstream version 3.0.0+dfsg1 Louis-Philippe Véronneau 1 year, 5 months ago
60 changed file(s) with 5258 addition(s) and 1750 deletion(s). Raw diff Collapse all Expand all
0 name: Lint
1
2 permissions:
3 contents: write
4
5 on:
6 push:
7 branches:
8 - main
9
10 jobs:
11 lint:
12 runs-on: ubuntu-latest
13 steps:
14 - name: Checkout code
15 uses: actions/checkout@v3
16
17 - uses: actions/setup-python@v3
18 with:
19 python-version: "3.10"
20
21 - name: Run isort check
22 uses: isort/isort-action@master
23 with:
24 configuration: "--check-only --diff --profile black"
25
26 - name: Run isort
27 if: failure()
28 uses: isort/isort-action@master
29 with:
30 configuration: "--profile black"
31
32 - name: Run black check
33 uses: psf/black@stable
34 with:
35 options: "--check --diff"
36
37 - name: Run black format
38 if: failure()
39 uses: psf/black@stable
40 with:
41 options: ""
42
43 - name: Commit isort+black format
44 if: failure()
45 uses: stefanzweifel/git-auto-commit-action@v4
46 with:
47 commit_message: "Apply black to code"
48
0 name: Test
1
2 on: [push, pull_request]
3
4 env:
5 FORCE_COLOR: 1
6
7 jobs:
8 build:
9 runs-on: ${{ matrix.os }}
10 strategy:
11 fail-fast: false
12 matrix:
13 python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
14 os: [ubuntu-22.04]
15 env:
16 - TOXENV: libs
17 - TOXENV: sa12
18 - TOXENV: sa13
19
20 steps:
21 - uses: actions/checkout@v2
22
23 - name: Set up Python ${{ matrix.python-version }}
24 uses: actions/setup-python@v4
25 with:
26 python-version: ${{ matrix.python-version }}
27
28 - name: Get pip cache dir
29 id: pip-cache
30 run: |
31 echo "::set-output name=dir::$(pip cache dir)"
32
33 - name: Cache
34 uses: actions/cache@v3
35 with:
36 path: ${{ steps.pip-cache.outputs.dir }}
37 key:
38 ${{ matrix.os }}-${{ matrix.python-version }}-v1-${{
39 hashFiles('**/setup.py') }}
40 restore-keys: |
41 ${{ matrix.os }}-${{ matrix.python-version }}-v1-
42
43 - name: Install dependencies
44 run: |
45 python -m pip install -U pip
46 python -m pip install -U tox tox-venv
47
48 - name: Install gmpy2 dependencies
49 if: matrix.python-version == '3.11'
50 run: |
51 sudo apt-get -y update
52 sudo apt-get install -y libmpfr-dev libmpc-dev
53
54 - name: Tox tests
55 run: |
56 tox
57 env: ${{ matrix.env }}
11 /build
22 /dist
33 /docs/build
4 /images/benchmark-*.svg
45 /.eggs
56 /env*
67 /tags
1415 *#*
1516 *~
1617 *.tar.gz
18
19 # Local benchmarking files for Theelx
20 kern*.py
21 *.lprof
0 [tool.isort]
1 profile = "black"
00 repos:
11 - repo: https://github.com/psf/black
2 rev: 19.10b0
2 rev: 22.3.0
33 hooks:
44 - id: black
55
+0
-28
.travis.yml less more
0 dist: bionic
1 language: python
2
3 python:
4 - 2.7
5 - 3.6
6 - 3.7
7 - 3.8
8 - &latest_py3 3.9
9
10 env:
11 - TOXENV=libs
12 - TOXENV=sa10
13 - TOXENV=sa11
14 - TOXENV=sa12
15 - TOXENV=sa13
16
17 cache: pip
18
19 install:
20 - pip install tox tox-venv
21
22 before_script:
23 # Enable IPv6. Ref travis-ci/travis-ci#8361
24 - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
25 sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6';
26 fi
27 script: tox
0 ***WARNING: CERTAIN BENCHMARKS WILL SHOW VERY HIGH OUTLIER VALUES, TAKE ALL BENCHMARKS WITH A GRAIN OF SALT.***
1
2 **TL;DR**
3
4 jsonpickle 2.0.0 shows significant improvement in encoding/decoding speeds for virtually every test, the main benefits come in class encoding/decoding, but there are more minor speedups for other common use cases also. Onto the raw data!
5
6 Environment:
7 - Python 3.9.13
8 - 8-core Intel i7-11800H CPU (laptop)
9 - Ubuntu 20.04, Linux kernel 5.17.9 (kernel mainline ppa)
10 - Turbo boost disabled, plugged in + on battery
11
12 Make note of:
13 - If a benchmark ends with `_e`, it's an encode benchmark, if it ends with `_d` then it's a decode benchmark
14 - `homog` is short for homogenous, and `heterog` is short for heterogenous
15
16 jsonpickle 3.0.0-dev (drops support for python <3.7)
17
18 <figure><img src="images/jsonpickle-3.0.0-dev.svg"></figure>
19
20 jsonpickle 2.2.0 (latest release of writing)
21
22 <figure><img src="images/jsonpickle-2.2.0.svg"></figure>
23
24 jsonpickle 1.5.2 (major performance increases reverted due to accidental breaking change)
25
26 <figure><img src="images/jsonpickle-1.5.2.svg"></figure>
27
28 jsonpickle 1.5.1 (major performance increases in this version)
29
30 <figure><img src="images/jsonpickle-1.5.1.svg"></figure>
31
32 jsonpickle 0.9.6 (please upgrade from this!)
33
34 <figure><img src="images/jsonpickle-0.9.6.svg"></figure>
0 .. warning::
1 The next major release of jsonpickle (v3.0.0) will drop support for
2 Python 3.6 and earlier (including Python 2.7).
3
4 .. note::
5 Users on older Python versions should pin requirements to ``jsonpickle<3.0.0``.
6
7 v3.0.0
8 ======
9 * Drop support for CPython<3.7. CPython 3.6 and below have reached EOL
10 and no longer receieve security updates. (#375)
11 * Add support for CPython 3.11. (#395) (+396)
12 * Remove jsonlib and yajl backends (py2 only)
13 * Add ``include_properties`` option to the pickler. This should only
14 be used if analyzing generated json outside of Python. (#297) (+387)
15 * Allow the ``classes`` argument to ``jsonpickle.decode`` to be a dict
16 of class name to class object. This lets you decode arbitrary dumps
17 into different classes. (#148) (+392)
18 * Fix bug with deserializing `numpy.poly1d`. (#391)
19 * Allow frozen dataclasses to be deserialized. (#240)
20 * Fixed a bug where pickling a function could return a ``None`` module. (#399)
21 * Removed old bytes/quopri and ref decoding abaility from the unpickler.
22 These were last used in jsonpickle<1. Removing them causes a slight speedup
23 in unpickling lists (~5%). (+403)
24 * Fixed a bug with namedtuples encoding on CPython 3.11. (#411)
25 * When using the ``sort_keys`` option for the ``simplejson`` backend,
26 jsonpickle now produces correct object references with py/id tags. (#408)
27 * Speed up the internal method ``_restore_tags`` by ~10%. This should speed
28 up unpickling of almost every object.
29
30 v2.2.0
31 ======
32
33 * Classes with a custom ``__getitem__()`` and ``append()``
34 now pickle properly. (#362) (+379)
35 * Remove the demjson backend, as demjson hasn't been maintained
36 for 5 years. (+379)
37 * Added new handler for numpy objects when using unpickleable=False.
38 (#381) (+382)
39 * Added exception handling for class attributes that can't be accessed.
40 (#301) (+383)
41 * Added a long-requested on_missing attribute to the Unpickler class.
42 This lets you choose behavior for when jsonpickle can't find a class
43 to deserialize to. (#190) (#193) (+384)
44 * Private members of ``__slots__`` are no longer skipped when encoding.
45 Any objects encoded with versions prior to 2.2.0 should still decode
46 properly. (#318) (+385)
47
48 v2.1.0
49 ======
50
51 * Python 3.10 is now officially supported. (+376)
52 * Benchmarks were added to aid in optimization efforts. (#350) (+352)
53 * ``is_reducible()`` was sped up by ~80%. (+353) (+354)
54 * ``_restore_tags()`` was sped up by ~100%. Unpickling items
55 with a lot of tuples and sets will benefit most. Python 2 users
56 and users deserializing pickles from jsonpickle <= 0.9.6 may see
57 a slight performance decrease if using a lot of bytes, ref,
58 and/or repr objects. (+354)
59 * ``is_iterator()`` was sped up by ~20% by removing an unnecessary
60 variable assignment. (+354)
61 * ``jsonpickle.decode`` has a new option, ``v1_decode`` to assist in
62 decoding objects created in jsonpickle version 1. (#364)
63 * The ``encode()`` documentation has been updated to help sklearn users.
64 * ``demjson`` has been removed from the test suite. (+374)
65 * ``SQLALchemy<1.2`` is no longer being tested by jsonpickle.
66 Users of sqlalchemy + jsonpickle can always use 1.2 or 1.3.
67 When jsonpickle v3 is released we will add SQLAlchemy 1.4 to
68 the test suite alongside removal of support for Python 3.5 and earlier.
69
070 v2.0.0
171 ======
272 * Major release: the serialized JSON format now preserves dictionary
575 dictionary appears twice in a list, the reconstituted list
676 will now contain two references to the same dictionary. (#255) (+332)
777
8 v1.5.3
78 v1.5.2
979 ======
1080 * Patch release to avoid the change in behavior from the preservation
1181 of dict identity. The next release will be v2.0.0. (#351)
12 * This relese does *not* include the performance improvements
82 * This release does *not* include the performance improvements
1383 from v1.5.1.
1484 * Pandas DataFrame objects with multilevel columns are now supported.
1585 (#346) (+347)
296366 (#16).
297367 * Experimental support for `jsonlib <http://pypi.python.org/pypi/jsonlib/>`_
298368 and `py-yajl <http://github.com/rtyler/py-yajl/>`_ backends.
299 * New contributers David K. Hess and Alec Thomas
369 * New contributors David K. Hess and Alec Thomas
300370
301371 .. warning::
302372
00 Copyright (C) 2008 John Paulett (john -at- paulett.org)
1 Copyright (C) 2009-2018 David Aguilar (davvid -at- gmail.com)
2 All rights reserved.
1 Copyright (C) 2009-2021 David Aguilar (davvid -at- gmail.com)
32
43 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
4 modification, are permitted provided that the following conditions are met:
75
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in
12 the documentation and/or other materials provided with the
13 distribution.
14 3. The name of the author may not be used to endorse or promote
15 products derived from this software without specific prior
16 written permission.
6 1. Redistributions of source code must retain the above copyright notice,
7 this list of conditions and the following disclaimer.
178
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9 2. Redistributions in binary form must reproduce the above copyright notice,
10 this list of conditions and the following disclaimer in the documentation
11 and/or other materials provided with the distribution.
12
13 3. Neither the name of the copyright holder nor the names of its
14 contributors may be used to endorse or promote products derived from this
15 software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00 #!/usr/bin/env make
1
2 DATEANDTIME=$(shell date +%Y-%m-%dT%T%z)
13
24 # External commands
35 BLACK ?= black
57 FIND ?= find
68 PYTHON ?= python
79 PYTEST ?= $(PYTHON) -m pytest
10 SPHINX ?= $(PYTHON) -m sphinx
11 BENCHMARK ?= py.test
812 RM_R ?= rm -fr
913 SH ?= sh
1014 TOX ?= tox
3337 NUM_JOBS := $(shell printf %s "$(DASH_J)" | sed -e 's/-j//')
3438
3539 TESTCMD ?= $(PYTEST)
40 BENCHMARKCMD ?= $(BENCHMARK)
3641 TOXCMD ?= $(TOX)
3742 TOXCMD += --develop --skip-missing-interpreters
3843 ifdef multi
3944 TOXCMD += --parallel $(NUM_JOBS)
4045 TOXCMD += -e
41 TOXCMD += 'clean,py{27,36,37,38,39},py{27,38,39}-sa{10,11,12,13},py{27,38,39}-libs'
46 TOXCMD += 'clean,py{37,38,39,310},py{38,39,310}-sa{12,13},py{38,39,310}-libs'
4247 # Disable coverage when running in parallel
4348 TOXCMD += -- --no-cov
4449 endif
4550 ifdef V
4651 TESTCMD += --verbose
4752 TOXCMD += -v
53 BENCHMARKCMD += --benchmark-verbose
4854 endif
4955
5056 # Coverage
51 COVERAGE_ENV ?= py39
57 COVERAGE_ENV ?= py310
5258
5359 # Data
5460 ARTIFACTS := build
6369 # The default target of this makefile is....
6470 all:: help
6571
66 help:
72 help::
6773 @echo "---- Makefile Targets ----"
68 @echo "make help - print this message"
69 @echo "make test - run unit tests"
70 @echo "make tox - run unit tests using tox"
71 @echo "make tox multi=1 - run unit tests on multiple pythons using tox"
72 @echo "make clean - remove cruft"
74 @echo "make help - print this message"
75 @echo "make test - run unit tests"
76 @echo "make tox - run unit tests using tox"
77 @echo "make tox multi=1 - run unit tests on multiple pythons using tox"
78 @echo "make clean - remove cruft"
79 @echo "make benchmark - run pytest benchmarking"
80 @echo "make doc - generate documentation using sphinx"
7381 .PHONY: help
7482
75 test:
83 test::
7684 $(TESTCMD) $(flags)
7785 .PHONY: test
7886
79 tox:
87 tox::
8088 $(TOXCMD) $(flags)
8189 .PHONY: tox
8290
83 tags:
91 benchmark::
92 $(BENCHMARKCMD) --benchmark-only --benchmark-histogram=./images/benchmark-$(DATEANDTIME) ./jsonpickle_benchmarks.py
93 .PHONY: benchmark
94
95 doc::
96 $(SPHINX) docs build/html
97
98 tags::
8499 $(FIND) $(PYTHON_DIRS) -name '*.py' -print0 | xargs -0 $(CTAGS) -f tags
85100
86 clean:
101 clean::
87102 $(FIND) $(PYTHON_DIRS) -name '*.py[cod]' -print0 | xargs -0 rm -f
88103 $(FIND) $(PYTHON_DIRS) -name '__pycache__' -print0 | xargs -0 rm -fr
89104 $(RM_R) $(ARTIFACTS)
90105 .PHONY: clean
91106
92107 format::
93 $(BLACK) --skip-string-normalization --target-version py27 $(PYTHON_DIRS)
108 $(BLACK) --skip-string-normalization --target-version py310 $(PYTHON_DIRS)
94109 .PHONY: format
+161
-133
PKG-INFO less more
00 Metadata-Version: 2.1
11 Name: jsonpickle
2 Version: 2.0.0
2 Version: 3.0.0
33 Summary: Python library for serializing any arbitrary object graph into JSON
44 Home-page: https://github.com/jsonpickle/jsonpickle
55 Author: David Aguilar
66 Author-email: davvid@gmail.com
77 License: UNKNOWN
8 Description: .. image:: https://img.shields.io/pypi/v/jsonpickle.svg
9 :target: `PyPI link`_
10
11 .. image:: https://img.shields.io/pypi/pyversions/jsonpickle.svg
12 :target: `PyPI link`_
13
14 .. _PyPI link: https://pypi.org/project/jsonpickle
15
16 .. image:: https://dev.azure.com/jaraco/jsonpickle/_apis/build/status/jaraco.jsonpickle?branchName=master
17 :target: https://dev.azure.com/jaraco/jsonpickle/_build/latest?definitionId=1&branchName=master
18
19 .. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest
20 :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest
21
22 .. image:: https://travis-ci.org/jsonpickle/jsonpickle.svg?branch=master
23 :target: https://travis-ci.org/jsonpickle/jsonpickle
24 :alt: travis
25
26 .. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
27 :target: https://github.com/jsonpickle/jsonpickle/blob/master/COPYING
28 :alt: BSD
29
30
31 jsonpickle
32 ==========
33 jsonpickle is a library for the two-way conversion of complex Python objects
34 and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON
35 encoders, such as simplejson, json, and demjson.
36
37 For complete documentation, please visit the
38 `jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_.
39
40 Bug reports and merge requests are encouraged at the
41 `jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_.
42
43 jsonpickle supports Python 2.7 and Python 3.4 or greater.
44
45 **WARNING**:
46 jsonpickle can execute arbitrary Python code. Do not load jsonpickles from untrusted / unauthenticated sources.
47
48 Why jsonpickle?
49 ===============
50 Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena.
51
52 Install
53 =======
54
55 Install from pip for the latest stable release:
56
57 ::
58
59 pip install jsonpickle
60
61 Install from github for the latest changes:
62
63 ::
64
65 pip install git+https://github.com/jsonpickle/jsonpickle.git
66
67 If you have the files checked out for development:
68
69 ::
70
71 git clone https://github.com/jsonpickle/jsonpickle.git
72 cd jsonpickle
73 python setup.py develop
74
75
76 Numpy Support
77 =============
78 jsonpickle includes a built-in numpy extension. If would like to encode
79 sklearn models, numpy arrays, and other numpy-based data then you must
80 enable the numpy extension by registering its handlers::
81
82 >>> import jsonpickle.ext.numpy as jsonpickle_numpy
83 >>> jsonpickle_numpy.register_handlers()
84
85 Pandas Support
86 ==============
87 jsonpickle includes a built-in pandas extension. If would like to encode
88 pandas DataFrame or Series objects then you must enable the pandas extension
89 by registering its handlers::
90
91 >>> import jsonpickle.ext.pandas as jsonpickle_pandas
92 >>> jsonpickle_pandas.register_handlers()
93
94 jsonpickleJS
95 ============
96 `jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_
97 is a javascript implementation of jsonpickle by Michael Scott Cuthbert.
98 jsonpickleJS can be extremely useful for projects that have parallel data
99 structures between Python and Javascript.
100
101 License
102 =======
103 Licensed under the BSD License. See COPYING for details.
104 See jsonpickleJS/LICENSE for details about the jsonpickleJS license.
105
106 Development
107 ===========
108
109 Use `make` to run the unit tests::
110
111 make test
112
113 `pytest` is used to run unit tests internally.
114
115 A `tox` target is provided to run tests using tox.
116 Setting ``multi=1`` tests using all installed and supported Python versions::
117
118 make tox
119 make tox multi=1
120
121 `jsonpickle` itself has no dependencies beyond the Python stdlib.
122 `tox` is required for testing when using the `tox` test runner only.
123
124 The testing requirements are specified in `requirements-dev.txt`.
125 It is recommended to create a virtualenv and run tests from within the
126 virtualenv, or use a tool such as `vx <https://github.com/davvid/vx/>`_
127 to activate the virtualenv without polluting the shell environment::
128
129 python3 -mvenv env3x
130 vx env3x pip install --requirement requirements-dev.txt
131 vx env3x make test
132
133 `jsonpickle` supports multiple Python versions, so using a combination of
134 multiple virtualenvs and `tox` is useful in order to catch compatibility
135 issues when developing.
136
1378 Keywords: json pickle,json,pickle,marshal,serialization,JavaScript Object Notation
1389 Platform: POSIX
13910 Platform: Windows
14112 Classifier: Intended Audience :: Developers
14213 Classifier: License :: OSI Approved :: BSD License
14314 Classifier: Programming Language :: Python
144 Classifier: Programming Language :: Python :: 2
145 Classifier: Programming Language :: Python :: 2.7
14615 Classifier: Programming Language :: Python :: 3
16 Classifier: Programming Language :: Python :: 3.7
17 Classifier: Programming Language :: Python :: 3.8
18 Classifier: Programming Language :: Python :: 3.9
19 Classifier: Programming Language :: Python :: 3.10
14720 Classifier: Programming Language :: JavaScript
14821 Classifier: Operating System :: OS Independent
14922 Classifier: Topic :: Software Development :: Libraries :: Python Modules
150 Requires-Python: >=2.7
23 Requires-Python: >=3.7
15124 Provides-Extra: testing
15225 Provides-Extra: testing.libs
15326 Provides-Extra: docs
27 License-File: LICENSE
28
29 .. image:: https://img.shields.io/pypi/v/jsonpickle.svg
30 :target: `PyPI link`_
31
32 .. image:: https://img.shields.io/pypi/pyversions/jsonpickle.svg
33 :target: `PyPI link`_
34
35 .. _PyPI link: https://pypi.org/project/jsonpickle
36
37 .. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest
38 :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest
39
40 .. image:: https://github.com/jsonpickle/jsonpickle/actions/workflows/test.yml/badge.svg
41 :target: https://github.com/jsonpickle/jsonpickle/actions
42 :alt: Github Actions
43
44 .. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
45 :target: https://github.com/jsonpickle/jsonpickle/blob/main/COPYING
46 :alt: BSD
47
48
49 jsonpickle
50 ==========
51 jsonpickle is a library for the two-way conversion of complex Python objects
52 and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON
53 encoders, such as simplejson, json, and ujson.
54
55 .. warning::
56
57 jsonpickle can execute arbitrary Python code.
58
59 Please see the Security section for more details.
60
61
62 For complete documentation, please visit the
63 `jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_.
64
65 Bug reports and merge requests are encouraged at the
66 `jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_.
67
68 jsonpickle officially supports CPython 2.7 and CPython 3.6 or greater. Version support below CPython 3.7 will be dropped upon release of jsonpickle 3.0.
69
70 Why jsonpickle?
71 ===============
72 Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena.
73
74 Security
75 ========
76
77 jsonpickle should be treated the same as the
78 `Python stdlib pickle module <https://docs.python.org/3/library/pickle.html>`_
79 from a security perspective.
80
81 .. warning::
82
83 The jsonpickle module **is not secure**. Only unpickle data you trust.
84
85 It is possible to construct malicious pickle data which will **execute
86 arbitrary code during unpickling**. Never unpickle data that could have come
87 from an untrusted source, or that could have been tampered with.
88
89 Consider signing data with an HMAC if you need to ensure that it has not
90 been tampered with.
91
92 Safer deserialization approaches, such as reading JSON directly,
93 may be more appropriate if you are processing untrusted data.
94
95
96 Install
97 =======
98
99 Install from pip for the latest stable release:
100
101 ::
102
103 pip install jsonpickle
104
105 Install from github for the latest changes:
106
107 ::
108
109 pip install git+https://github.com/jsonpickle/jsonpickle.git
110
111 If you have the files checked out for development:
112
113 ::
114
115 git clone https://github.com/jsonpickle/jsonpickle.git
116 cd jsonpickle
117 python setup.py develop
118
119
120 Numpy Support
121 =============
122 jsonpickle includes a built-in numpy extension. If would like to encode
123 sklearn models, numpy arrays, and other numpy-based data then you must
124 enable the numpy extension by registering its handlers::
125
126 >>> import jsonpickle.ext.numpy as jsonpickle_numpy
127 >>> jsonpickle_numpy.register_handlers()
128
129 Pandas Support
130 ==============
131 jsonpickle includes a built-in pandas extension. If would like to encode
132 pandas DataFrame or Series objects then you must enable the pandas extension
133 by registering its handlers::
134
135 >>> import jsonpickle.ext.pandas as jsonpickle_pandas
136 >>> jsonpickle_pandas.register_handlers()
137
138 jsonpickleJS
139 ============
140 `jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_
141 is a javascript implementation of jsonpickle by Michael Scott Cuthbert.
142 jsonpickleJS can be extremely useful for projects that have parallel data
143 structures between Python and Javascript.
144
145 License
146 =======
147 Licensed under the BSD License. See COPYING for details.
148 See jsonpickleJS/LICENSE for details about the jsonpickleJS license.
149
150 Development
151 ===========
152
153 Use `make` to run the unit tests::
154
155 make test
156
157 `pytest` is used to run unit tests internally.
158
159 A `tox` target is provided to run tests using tox.
160 Setting ``multi=1`` tests using all installed and supported Python versions::
161
162 make tox
163 make tox multi=1
164
165 `jsonpickle` itself has no dependencies beyond the Python stdlib.
166 `tox` is required for testing when using the `tox` test runner only.
167
168 The testing requirements are specified in `requirements-dev.txt`.
169 It is recommended to create a virtualenv and run tests from within the
170 virtualenv, or use a tool such as `vx <https://github.com/davvid/vx/>`_
171 to activate the virtualenv without polluting the shell environment::
172
173 python3 -mvenv env3x
174 vx env3x pip install --requirement requirements-dev.txt
175 vx env3x make test
176
177 `jsonpickle` supports multiple Python versions, so using a combination of
178 multiple virtualenvs and `tox` is useful in order to catch compatibility
179 issues when developing.
180
181
55
66 .. _PyPI link: https://pypi.org/project/jsonpickle
77
8 .. image:: https://dev.azure.com/jaraco/jsonpickle/_apis/build/status/jaraco.jsonpickle?branchName=master
9 :target: https://dev.azure.com/jaraco/jsonpickle/_build/latest?definitionId=1&branchName=master
10
118 .. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest
129 :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest
1310
14 .. image:: https://travis-ci.org/jsonpickle/jsonpickle.svg?branch=master
15 :target: https://travis-ci.org/jsonpickle/jsonpickle
16 :alt: travis
11 .. image:: https://github.com/jsonpickle/jsonpickle/actions/workflows/test.yml/badge.svg
12 :target: https://github.com/jsonpickle/jsonpickle/actions
13 :alt: Github Actions
1714
1815 .. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
19 :target: https://github.com/jsonpickle/jsonpickle/blob/master/COPYING
16 :target: https://github.com/jsonpickle/jsonpickle/blob/main/COPYING
2017 :alt: BSD
2118
2219
2421 ==========
2522 jsonpickle is a library for the two-way conversion of complex Python objects
2623 and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON
27 encoders, such as simplejson, json, and demjson.
24 encoders, such as simplejson, json, and ujson.
25
26 .. warning::
27
28 jsonpickle can execute arbitrary Python code.
29
30 Please see the Security section for more details.
31
2832
2933 For complete documentation, please visit the
3034 `jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_.
3236 Bug reports and merge requests are encouraged at the
3337 `jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_.
3438
35 jsonpickle supports Python 2.7 and Python 3.4 or greater.
36
37 **WARNING**:
38 jsonpickle can execute arbitrary Python code. Do not load jsonpickles from untrusted / unauthenticated sources.
39 jsonpickle officially supports CPython 2.7 and CPython 3.6 or greater. Version support below CPython 3.7 will be dropped upon release of jsonpickle 3.0.
3940
4041 Why jsonpickle?
4142 ===============
4243 Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena.
44
45 Security
46 ========
47
48 jsonpickle should be treated the same as the
49 `Python stdlib pickle module <https://docs.python.org/3/library/pickle.html>`_
50 from a security perspective.
51
52 .. warning::
53
54 The jsonpickle module **is not secure**. Only unpickle data you trust.
55
56 It is possible to construct malicious pickle data which will **execute
57 arbitrary code during unpickling**. Never unpickle data that could have come
58 from an untrusted source, or that could have been tampered with.
59
60 Consider signing data with an HMAC if you need to ensure that it has not
61 been tampered with.
62
63 Safer deserialization approaches, such as reading JSON directly,
64 may be more appropriate if you are processing untrusted data.
65
4366
4467 Install
4568 =======
4949 - script: |
5050 tox -- --junit-xml=test-results.xml
5151 env:
52 TOXENV: {libs,sa10,sa11,sa12,sa13}
52 TOXENV: {libs,sa12,sa13}
5353 displayName: 'run tests'
5454
5555 - task: PublishTestResults@2
00 collect_ignore = ['contrib']
1
2
3 def pytest_addoption(parser):
4 parser.addoption(
5 '--repeat', action='store', help='Number of times to repeat each test'
6 )
7
8
9 def pytest_generate_tests(metafunc):
10 if metafunc.config.option.repeat is not None:
11 count = int(metafunc.config.option.repeat)
12
13 # We're going to duplicate these tests by parametrizing them,
14 # which requires that each test has a fixture to accept the parameter.
15 # We can add a new fixture like so:
16 metafunc.fixturenames.append('tmp_ct')
17
18 # Now we parametrize. This is what happens when we do e.g.,
19 # @pytest.mark.parametrize('tmp_ct', range(count))
20 # def test_foo(): pass
21 metafunc.parametrize('tmp_ct', range(count))
3636
3737 jsonpickle allows the user to specify what JSON backend to use
3838 when encoding and decoding. By default, jsonpickle will try to use, in
39 the following order: :mod:`simplejson`, :mod:`json`, and :mod:`demjson`.
40 The prefered backend can be set via :func:`jsonpickle.set_preferred_backend`.
39 the following order: :mod:`simplejson` and :mod:`json`.
40 The preferred backend can be set via :func:`jsonpickle.set_preferred_backend`.
4141 Additional JSON backends can be used via :func:`jsonpickle.load_backend`.
4242
4343 For example, users of `Django <http://www.djangoproject.com/>`_ can use the
5050
5151 * :mod:`json`
5252 * `simplejson <http://undefined.org/python/#simplejson>`_
53 * `demjson <https://deron.meranda.us/python/demjson/>`_
5453
5554 Experimental backends:
5655
7271 -----------------------
7372
7473 jsonpickle supports the standard :mod:`pickle` `__getstate__` and `__setstate__`
75 protocol for representating object instances.
74 protocol for representing object instances.
7675
7776 .. method:: object.__getstate__()
7877
1111
1212 ::
1313
14 git clone git://github.com/jsonpickle/jsonpickle.git
14 git clone https://github.com/jsonpickle/jsonpickle.git
1515
1616 Run the Test Suite
1717 ==================
1818
19 Before code is pulled into the master jsonpickle branch, all tests should pass.
19 All tests should pass before before code is merged into the main repository.
2020 If you are contributing an addition or a change in behavior, we ask that you
2121 document the change in the form of test cases.
2222
4242
4343 tox -e py37-libs
4444
45 To create the enivornment without running tests::
45 To create the environment without running tests::
4646
4747 tox -e libs --notest
4848
99
1010 >>> import jsonpickle.ext.numpy as jsonpickle_numpy
1111 >>> jsonpickle_numpy.register_handlers()
12
13 Ecdsa
14 -----
15 For the ecdsa module's keys, when trying to serialize them with
16 ``gmpy2`` installed, jsonpickle will error unless the ``gmpy``
17 handlers are registered:
18
19 >>> import jsonpickle.ext.gmpy as jsonpickle_gmpy
20 >>> jsonpickle_gmpy.register_handlers()
44 ``jsonpickle`` is a Python library for
55 serialization and deserialization of complex Python objects to and from
66 JSON. The standard Python libraries for encoding Python into JSON, such as
7 the stdlib's json, simplejson, and demjson, can only handle Python
7 the stdlib's json and simplejson can only handle Python
88 primitives that have a direct JSON equivalent (e.g. dicts, lists, strings,
99 ints, etc.). jsonpickle builds on top of these libraries and allows more
1010 complex data structures to be serialized to JSON. jsonpickle is highly
1515
1616 jsonpickle Usage
1717 ================
18
19 .. note::
20
21 Please see the note in the :ref:`api-docs` when serializing dictionaries
22 that contain non-string dictionary keys.
2318
2419 .. automodule:: jsonpickle
2520
7873
7974 * John Paulett - john -at- paulett.org - https://github.com/johnpaulett
8075 * David Aguilar - davvid -at- gmail.com - https://github.com/davvid
76 * Theelx - https://github.com/Theelx
8177 * Dan Buch - https://github.com/meatballhat
8278 * Ian Schenck - https://github.com/ianschenck
8379 * David K. Hess - https://github.com/davidkhess
9894 =======
9995
10096 jsonpickle is provided under a
101 `New BSD license <https://github.com/jsonpickle/jsonpickle/raw/master/COPYING>`_,
97 `New BSD license <https://github.com/jsonpickle/jsonpickle/raw/main/COPYING>`_,
10298
10399 Copyright (C) 2008-2011 John Paulett (john -at- paulett.org)
104 Copyright (C) 2009-2016 David Aguilar (davvid -at- gmail.com)
100 Copyright (C) 2009-2021 David Aguilar (davvid -at- gmail.com)
0 <?xml version='1.0' encoding='utf-8'?>
1 <svg xmlns="http://www.w3.org/2000/svg" id="chart-83417b21-d81c-43db-a314-e3e737f00e1e" class="pygal-chart" viewBox="0 0 800 600"><!--Generated with pygal 3.0.0 (etree) ©Kozea 2012-2016 on 2022-06-20--><!--http://pygal.org--><!--http://github.com/Kozea/pygal--><defs><style type="text/css">#chart-83417b21-d81c-43db-a314-e3e737f00e1e{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .title{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .legends .legend text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis text.major{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay text.value{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay text.label{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e text.no_data{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:64px}
2 #chart-83417b21-d81c-43db-a314-e3e737f00e1e{background-color:rgba(249,249,249,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e path,#chart-83417b21-d81c-43db-a314-e3e737f00e1e line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e rect,#chart-83417b21-d81c-43db-a314-e3e737f00e1e circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .graph &gt; .background{fill:rgba(249,249,249,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .plot &gt; .background{fill:rgba(255,255,255,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .graph{fill:rgba(0,0,0,.87)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e text.no_data{fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .title{fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .legends .legend text{fill:rgba(0,0,0,.87)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .line{stroke:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis text.major{fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y .guides:hover .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .line-graph .axis.x .guides:hover .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .stackedline-graph .axis.x .guides:hover .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .reactive{fill-opacity:.7;stroke-opacity:.8;stroke-width:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .ci{stroke:rgba(0,0,0,.87)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .reactive.active,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .ci .reactive.active{stroke-width:1.5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .series text{fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip .label{fill:rgba(0,0,0,.87)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip .label{fill:rgba(0,0,0,.87)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip .value{font-size:1.5em}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .bound{font-size:.5em}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-0,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-0 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-1,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-2,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-2 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-3,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-3 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-4,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-4 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-5,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-5 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-6,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-6 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-7,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-7 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-8,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-8 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-9,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-9 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-10,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-10 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-11,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-11 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-12,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-12 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-13,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-13 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-14,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-14 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-15,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-15 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-16,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-16 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-17,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-17 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-18,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-18 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-19,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-19 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-20,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-20 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-21,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-21 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-22,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-22 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-23,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-23 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-24,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-24 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-25,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-25 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-26,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-26 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-27,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-27 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-28,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-28 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-29,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .color-29 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-0 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-1 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-2 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-3 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-4 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-5 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-6 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-7 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-8 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-9 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-10 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-11 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-12 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-13 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-14 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-15 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-16 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-17 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-18 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-19 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-20 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-21 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-22 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-23 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-24 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-25 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-26 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-27 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-28 text{fill:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .text-overlay .color-29 text{fill:black}
3 #chart-83417b21-d81c-43db-a314-e3e737f00e1e text.no_data{text-anchor:middle}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .guide.line{fill:none}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .centered{text-anchor:middle}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .title{text-anchor:middle}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .legends .legend text{fill-opacity:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.x text{text-anchor:middle}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.x:not(.web) text[transform]{text-anchor:start}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y text{text-anchor:end}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y text[transform].backwards{text-anchor:start}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y2 text{text-anchor:start}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y2 text[transform].backwards{text-anchor:end}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .guide.line{stroke-dasharray:4,4;stroke:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .major.guide.line{stroke-dasharray:6,6;stroke:black}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .horizontal .axis.y .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .horizontal .axis.y2 .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .vertical .axis.x .guide.line{opacity:0}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .horizontal .axis.always_show .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y .guides:hover .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.y2 .guides:hover .guide.line,#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis.x .guides:hover .guide.line{opacity:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .axis .guides:hover text{opacity:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .nofill{fill:none}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .subtle-fill{fill-opacity:.2}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .dot{stroke-width:1px;fill-opacity:1;stroke-opacity:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .dot.active{stroke-width:5px}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .dot.negative{fill:transparent}#chart-83417b21-d81c-43db-a314-e3e737f00e1e text,#chart-83417b21-d81c-43db-a314-e3e737f00e1e tspan{stroke:none !important}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .series text.active{opacity:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .tooltip text{fill-opacity:1}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .showable{visibility:hidden}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .showable.shown{visibility:visible}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-83417b21-d81c-43db-a314-e3e737f00e1e .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}
4 .tooltip .value{font-size:1em !important}.axis text{font-size:9px !important}</style><script type="text/javascript">window.pygal = window.pygal || {};window.pygal.config = window.pygal.config || {};window.pygal.config['83417b21-d81c-43db-a314-e3e737f00e1e'] = {"allow_interruptions": false, "box_mode": "tukey", "classes": ["pygal-chart"], "css": ["file://style.css", "file://graph.css", "inline:\n .tooltip .value {\n font-size: 1em !important;\n }\n .axis text {\n font-size: 9px !important;\n }\n "], "defs": [], "disable_xml_declaration": false, "dots_size": 2.5, "dynamic_print_values": false, "explicit_size": false, "fill": false, "force_uri_protocol": "https", "formatter": null, "half_pie": false, "height": 600, "include_x_axis": false, "inner_radius": 0, "interpolate": null, "interpolation_parameters": {}, "interpolation_precision": 250, "inverse_y_axis": false, "js": ["file:///home/theel/.pyenv/versions/3.9.13/lib/python3.9/site-packages/pygaljs/static/2.0.x/pygal-tooltips.js"], "legend_at_bottom": false, "legend_at_bottom_columns": null, "legend_box_size": 12, "logarithmic": false, "margin": 20, "margin_bottom": null, "margin_left": null, "margin_right": null, "margin_top": null, "max_scale": 20, "min_scale": 20, "missing_value_fill_truncation": "x", "no_data_text": "No data", "no_prefix": false, "order_min": null, "pretty_print": false, "print_labels": false, "print_values": false, "print_values_position": "center", "print_zeroes": true, "range": [15, 344], "rounded_bars": null, "secondary_range": null, "show_dots": true, "show_legend": false, "show_minor_x_labels": true, "show_minor_y_labels": true, "show_only_major_dots": false, "show_x_guides": false, "show_x_labels": true, "show_y_guides": true, "show_y_labels": true, "spacing": 10, "stack_from_top": false, "strict": false, "stroke": true, "stroke_style": null, "style": {"background": "rgba(249, 249, 249, 1)", "ci_colors": [], "colors": ["#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5"], "dot_opacity": "1", "font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "foreground": "rgba(0, 0, 0, .87)", "foreground_strong": "rgba(0, 0, 0, 1)", "foreground_subtle": "rgba(0, 0, 0, .54)", "guide_stroke_color": "black", "guide_stroke_dasharray": "4,4", "label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "label_font_size": 10, "legend_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "legend_font_size": 14, "major_guide_stroke_color": "black", "major_guide_stroke_dasharray": "6,6", "major_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "major_label_font_size": 10, "no_data_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "no_data_font_size": 64, "opacity": ".7", "opacity_hover": ".8", "plot_background": "rgba(255, 255, 255, 1)", "stroke_opacity": ".8", "stroke_opacity_hover": ".9", "stroke_width": "1", "stroke_width_hover": "4", "title_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "title_font_size": 16, "tooltip_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "tooltip_font_size": 14, "transition": "150ms", "value_background": "rgba(229, 229, 229, 1)", "value_colors": [], "value_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_font_size": 16, "value_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_label_font_size": 10}, "title": "Speed in Microseconds (us)", "tooltip_border_radius": 0, "tooltip_fancy_mode": true, "truncate_label": 50, "truncate_legend": null, "width": 800, "x_label_rotation": 270, "x_labels": ["simple_list_e", "simple_tuple_e", "simple_set_e", "simple_dict_e", "simple_dict_d", "simple_tuple_d", "simple_set_d", "simple_list_d", "complex_homog_list_e", "complex_homog_dict_d", "complex_homog_set_e", "complex_homog_tuple_e", "complex_heterog_set_e", "complex_heterog_dict_d", "complex_homog_tuple_d", "complex_homog_set_d", "complex_heterog_set_d", "simple_cls_d", "complex_heterog_list_e", "complex_heterog_tuple_e", "complex_heterog_tuple_d", "complex_heterog_list_d", "complex_homog_list_d", "complex_homog_dict_e", "complex_heterog_dict_e", "simple_cls_e", "complex_cls_d", "state_cls_d", "complex_cls_e", "state_cls_e"], "x_labels_major": null, "x_labels_major_count": null, "x_labels_major_every": null, "x_title": "Trial", "xrange": null, "y_label_rotation": 0, "y_labels": null, "y_labels_major": null, "y_labels_major_count": null, "y_labels_major_every": null, "y_title": "Duration", "zero": 15, "legends": ["jsonpickle_benchmarks.py::simple_list_e - 15376 rounds", "jsonpickle_benchmarks.py::simple_tuple_e - 15926 rounds", "jsonpickle_benchmarks.py::simple_set_e - 13633 rounds", "jsonpickle_benchmarks.py::simple_dict_e - 6871 rounds", "jsonpickle_benchmarks.py::simple_dict_d - 9429 rounds", "jsonpickle_benchmarks.py::simple_tuple_d - 16865 rounds", "jsonpickle_benchmarks.py::simple_set_d - 12822 rounds", "jsonpickle_benchmarks.py::simple_list_d - 12937 rounds", "jsonpickle_benchmarks.py::complex_homog_list_e - 10564 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_d - 8157 rounds", "jsonpickle_benchmarks.py::complex_homog_set_e - 9634 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_e - 657 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_e - 8602 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_d - 8509 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_d - 9192 rounds", "jsonpickle_benchmarks.py::complex_homog_set_d - 9693 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_d - 9429 rounds", "jsonpickle_benchmarks.py::simple_cls_d - 6749 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_e - 8148 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_e - 8061 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_d - 7751 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_d - 8824 rounds", "jsonpickle_benchmarks.py::complex_homog_list_d - 8567 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_e - 6835 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_e - 6758 rounds", "jsonpickle_benchmarks.py::simple_cls_e - 5437 rounds", "jsonpickle_benchmarks.py::complex_cls_d - 2588 rounds", "jsonpickle_benchmarks.py::state_cls_d - 2439 rounds", "jsonpickle_benchmarks.py::complex_cls_e - 2161 rounds", "jsonpickle_benchmarks.py::state_cls_e - 2262 rounds"]}</script><script type="text/javascript">(function() {
5 var $, get_translation, init, init_svg, matches, padding, r_translation, sibl, svg_ns, tooltip_timeout, xlink_ns;
6
7 svg_ns = 'http://www.w3.org/2000/svg';
8
9 xlink_ns = 'http://www.w3.org/1999/xlink';
10
11 $ = function(sel, ctx) {
12 if (ctx == null) {
13 ctx = null;
14 }
15 ctx = ctx || document;
16 return Array.prototype.slice.call(ctx.querySelectorAll(sel), 0).filter(function(e) {
17 return e !== ctx;
18 });
19 };
20
21 matches = function(el, selector) {
22 return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
23 };
24
25 sibl = function(el, match) {
26 if (match == null) {
27 match = null;
28 }
29 return Array.prototype.filter.call(el.parentElement.children, function(child) {
30 return child !== el &amp;&amp; (!match || matches(child, match));
31 });
32 };
33
34 Array.prototype.one = function() {
35 return this.length &gt; 0 &amp;&amp; this[0] || {};
36 };
37
38 padding = 5;
39
40 tooltip_timeout = null;
41
42 r_translation = /translate\((\d+)[ ,]+(\d+)\)/;
43
44 get_translation = function(el) {
45 return (r_translation.exec(el.getAttribute('transform')) || []).slice(1).map(function(x) {
46 return +x;
47 });
48 };
49
50 init = function(ctx) {
51 var bbox, box, config, el, graph, inner_svg, num, parent, tooltip, tooltip_el, tt, uid, untooltip, xconvert, yconvert, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
52 if ($('svg', ctx).length) {
53 inner_svg = $('svg', ctx).one();
54 parent = inner_svg.parentElement;
55 box = inner_svg.viewBox.baseVal;
56 bbox = parent.getBBox();
57 xconvert = function(x) {
58 return ((x - box.x) / box.width) * bbox.width;
59 };
60 yconvert = function(y) {
61 return ((y - box.y) / box.height) * bbox.height;
62 };
63 } else {
64 xconvert = yconvert = function(x) {
65 return x;
66 };
67 }
68 if (((_ref = window.pygal) != null ? _ref.config : void 0) != null) {
69 if (window.pygal.config.no_prefix != null) {
70 config = window.pygal.config;
71 } else {
72 uid = ctx.id.replace('chart-', '');
73 config = window.pygal.config[uid];
74 }
75 } else {
76 config = window.config;
77 }
78 tooltip_el = null;
79 graph = $('.graph').one();
80 tt = $('.tooltip', ctx).one();
81 _ref1 = $('.reactive', ctx);
82 for (_i = 0, _len = _ref1.length; _i &lt; _len; _i++) {
83 el = _ref1[_i];
84 el.addEventListener('mouseenter', (function(el) {
85 return function() {
86 return el.classList.add('active');
87 };
88 })(el));
89 el.addEventListener('mouseleave', (function(el) {
90 return function() {
91 return el.classList.remove('active');
92 };
93 })(el));
94 }
95 _ref2 = $('.activate-serie', ctx);
96 for (_j = 0, _len1 = _ref2.length; _j &lt; _len1; _j++) {
97 el = _ref2[_j];
98 num = el.id.replace('activate-serie-', '');
99 el.addEventListener('mouseenter', (function(num) {
100 return function() {
101 var re, _k, _len2, _ref3, _results;
102 _ref3 = $('.serie-' + num + ' .reactive', ctx);
103 _results = [];
104 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
105 re = _ref3[_k];
106 _results.push(re.classList.add('active'));
107 }
108 return _results;
109 };
110 })(num));
111 el.addEventListener('mouseleave', (function(num) {
112 return function() {
113 var re, _k, _len2, _ref3, _results;
114 _ref3 = $('.serie-' + num + ' .reactive', ctx);
115 _results = [];
116 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
117 re = _ref3[_k];
118 _results.push(re.classList.remove('active'));
119 }
120 return _results;
121 };
122 })(num));
123 el.addEventListener('click', (function(el, num) {
124 return function() {
125 var ov, re, rect, show, _k, _l, _len2, _len3, _ref3, _ref4, _results;
126 rect = $('rect', el).one();
127 show = rect.style.fill !== '';
128 rect.style.fill = show ? '' : 'transparent';
129 _ref3 = $('.serie-' + num + ' .reactive', ctx);
130 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
131 re = _ref3[_k];
132 re.style.display = show ? '' : 'none';
133 }
134 _ref4 = $('.text-overlay .serie-' + num, ctx);
135 _results = [];
136 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
137 ov = _ref4[_l];
138 _results.push(ov.style.display = show ? '' : 'none');
139 }
140 return _results;
141 };
142 })(el, num));
143 }
144 _ref3 = $('.tooltip-trigger', ctx);
145 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
146 el = _ref3[_k];
147 el.addEventListener('mouseenter', (function(el) {
148 return function() {
149 return tooltip_el = tooltip(el);
150 };
151 })(el));
152 }
153 tt.addEventListener('mouseenter', function() {
154 return tooltip_el != null ? tooltip_el.classList.add('active') : void 0;
155 });
156 tt.addEventListener('mouseleave', function() {
157 return tooltip_el != null ? tooltip_el.classList.remove('active') : void 0;
158 });
159 ctx.addEventListener('mouseleave', function() {
160 if (tooltip_timeout) {
161 clearTimeout(tooltip_timeout);
162 }
163 return untooltip(0);
164 });
165 graph.addEventListener('mousemove', function(el) {
166 if (tooltip_timeout) {
167 return;
168 }
169 if (!matches(el.target, '.background')) {
170 return;
171 }
172 return untooltip(1000);
173 });
174 tooltip = function(el) {
175 var a, baseline, cls, current_x, current_y, dy, h, i, key, keys, label, legend, name, plot_x, plot_y, rect, serie_index, subval, text, text_group, texts, traversal, value, w, x, x_elt, x_label, xlink, y, y_elt, _l, _len3, _len4, _len5, _m, _n, _ref4, _ref5, _ref6, _ref7, _ref8;
176 clearTimeout(tooltip_timeout);
177 tooltip_timeout = null;
178 tt.style.opacity = 1;
179 tt.style.display = '';
180 text_group = $('g.text', tt).one();
181 rect = $('rect', tt).one();
182 text_group.innerHTML = '';
183 label = sibl(el, '.label').one().textContent;
184 x_label = sibl(el, '.x_label').one().textContent;
185 value = sibl(el, '.value').one().textContent;
186 xlink = sibl(el, '.xlink').one().textContent;
187 serie_index = null;
188 parent = el;
189 traversal = [];
190 while (parent) {
191 traversal.push(parent);
192 if (parent.classList.contains('series')) {
193 break;
194 }
195 parent = parent.parentElement;
196 }
197 if (parent) {
198 _ref4 = parent.classList;
199 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
200 cls = _ref4[_l];
201 if (cls.indexOf('serie-') === 0) {
202 serie_index = +cls.replace('serie-', '');
203 break;
204 }
205 }
206 }
207 legend = null;
208 if (serie_index !== null) {
209 legend = config.legends[serie_index];
210 }
211 dy = 0;
212 keys = [[label, 'label']];
213 _ref5 = value.split('\n');
214 for (i = _m = 0, _len4 = _ref5.length; _m &lt; _len4; i = ++_m) {
215 subval = _ref5[i];
216 keys.push([subval, 'value-' + i]);
217 }
218 if (config.tooltip_fancy_mode) {
219 keys.push([xlink, 'xlink']);
220 keys.unshift([x_label, 'x_label']);
221 keys.unshift([legend, 'legend']);
222 }
223 texts = {};
224 for (_n = 0, _len5 = keys.length; _n &lt; _len5; _n++) {
225 _ref6 = keys[_n], key = _ref6[0], name = _ref6[1];
226 if (key) {
227 text = document.createElementNS(svg_ns, 'text');
228 text.textContent = key;
229 text.setAttribute('x', padding);
230 text.setAttribute('dy', dy);
231 text.classList.add(name.indexOf('value') === 0 ? 'value' : name);
232 if (name.indexOf('value') === 0 &amp;&amp; config.tooltip_fancy_mode) {
233 text.classList.add('color-' + serie_index);
234 }
235 if (name === 'xlink') {
236 a = document.createElementNS(svg_ns, 'a');
237 a.setAttributeNS(xlink_ns, 'href', key);
238 a.textContent = void 0;
239 a.appendChild(text);
240 text.textContent = 'Link &gt;';
241 text_group.appendChild(a);
242 } else {
243 text_group.appendChild(text);
244 }
245 dy += text.getBBox().height + padding / 2;
246 baseline = padding;
247 if (text.style.dominantBaseline !== void 0) {
248 text.style.dominantBaseline = 'text-before-edge';
249 } else {
250 baseline += text.getBBox().height * .8;
251 }
252 text.setAttribute('y', baseline);
253 texts[name] = text;
254 }
255 }
256 w = text_group.getBBox().width + 2 * padding;
257 h = text_group.getBBox().height + 2 * padding;
258 rect.setAttribute('width', w);
259 rect.setAttribute('height', h);
260 if (texts.value) {
261 texts.value.setAttribute('dx', (w - texts.value.getBBox().width) / 2 - padding);
262 }
263 if (texts.x_label) {
264 texts.x_label.setAttribute('dx', w - texts.x_label.getBBox().width - 2 * padding);
265 }
266 if (texts.xlink) {
267 texts.xlink.setAttribute('dx', w - texts.xlink.getBBox().width - 2 * padding);
268 }
269 x_elt = sibl(el, '.x').one();
270 y_elt = sibl(el, '.y').one();
271 x = parseInt(x_elt.textContent);
272 if (x_elt.classList.contains('centered')) {
273 x -= w / 2;
274 } else if (x_elt.classList.contains('left')) {
275 x -= w;
276 } else if (x_elt.classList.contains('auto')) {
277 x = xconvert(el.getBBox().x + el.getBBox().width / 2) - w / 2;
278 }
279 y = parseInt(y_elt.textContent);
280 if (y_elt.classList.contains('centered')) {
281 y -= h / 2;
282 } else if (y_elt.classList.contains('top')) {
283 y -= h;
284 } else if (y_elt.classList.contains('auto')) {
285 y = yconvert(el.getBBox().y + el.getBBox().height / 2) - h / 2;
286 }
287 _ref7 = get_translation(tt.parentElement), plot_x = _ref7[0], plot_y = _ref7[1];
288 if (x + w + plot_x &gt; config.width) {
289 x = config.width - w - plot_x;
290 }
291 if (y + h + plot_y &gt; config.height) {
292 y = config.height - h - plot_y;
293 }
294 if (x + plot_x &lt; 0) {
295 x = -plot_x;
296 }
297 if (y + plot_y &lt; 0) {
298 y = -plot_y;
299 }
300 _ref8 = get_translation(tt), current_x = _ref8[0], current_y = _ref8[1];
301 if (current_x === x &amp;&amp; current_y === y) {
302 return el;
303 }
304 tt.setAttribute('transform', "translate(" + x + " " + y + ")");
305 return el;
306 };
307 return untooltip = function(ms) {
308 return tooltip_timeout = setTimeout(function() {
309 tt.style.display = 'none';
310 tt.style.opacity = 0;
311 if (tooltip_el != null) {
312 tooltip_el.classList.remove('active');
313 }
314 return tooltip_timeout = null;
315 }, ms);
316 };
317 };
318
319 init_svg = function() {
320 var chart, charts, _i, _len, _results;
321 charts = $('.pygal-chart');
322 if (charts.length) {
323 _results = [];
324 for (_i = 0, _len = charts.length; _i &lt; _len; _i++) {
325 chart = charts[_i];
326 _results.push(init(chart));
327 }
328 return _results;
329 }
330 };
331
332 if (document.readyState !== 'loading') {
333 init_svg();
334 } else {
335 document.addEventListener('DOMContentLoaded', function() {
336 return init_svg();
337 });
338 }
339
340 window.pygal = window.pygal || {};
341
342 window.pygal.init = init;
343
344 window.pygal.init_svg = init_svg;
345
346 }).call(this);
347 </script></defs><title>Speed in Microseconds (us)</title><g class="graph custombox-graph vertical"><rect x="0" y="0" width="800" height="600" class="background" /><g transform="translate(74, 46)" class="plot"><rect x="0" y="0" width="706.0" height="360.0" class="background" /><g class="axis y always_show"><path d="M0.000000 360.000000 h706.000000" class="line" /><g class="guides"><path d="M0.000000 347.816226 h706.000000" class="guide line" /><text x="-5" y="351.31622632686464" class="">20</text><title>20</title></g><g class="guides"><path d="M0.000000 326.773439 h706.000000" class="guide line" /><text x="-5" y="330.2734393266308" class="">40</text><title>40</title></g><g class="guides"><path d="M0.000000 305.730652 h706.000000" class="guide line" /><text x="-5" y="309.23065232639703" class="">60</text><title>60</title></g><g class="guides"><path d="M0.000000 284.687865 h706.000000" class="guide line" /><text x="-5" y="288.1878653261632" class="">80</text><title>80</title></g><g class="guides"><path d="M0.000000 263.645078 h706.000000" class="major guide line" /><text x="-5" y="267.1450783259294" class="major">100</text><title>100</title></g><g class="guides"><path d="M0.000000 242.602291 h706.000000" class="guide line" /><text x="-5" y="246.10229132569555" class="">120</text><title>120</title></g><g class="guides"><path d="M0.000000 221.559504 h706.000000" class="guide line" /><text x="-5" y="225.05950432546175" class="">140</text><title>140</title></g><g class="guides"><path d="M0.000000 200.516717 h706.000000" class="guide line" /><text x="-5" y="204.01671732522794" class="">160</text><title>160</title></g><g class="guides"><path d="M0.000000 179.473930 h706.000000" class="guide line" /><text x="-5" y="182.97393032499414" class="">180</text><title>180</title></g><g class="guides"><path d="M0.000000 158.431143 h706.000000" class="major guide line" /><text x="-5" y="161.9311433247603" class="major">200</text><title>200</title></g><g class="guides"><path d="M0.000000 137.388356 h706.000000" class="guide line" /><text x="-5" y="140.8883563245265" class="">220</text><title>220</title></g><g class="guides"><path d="M0.000000 116.345569 h706.000000" class="guide line" /><text x="-5" y="119.84556932429271" class="">240</text><title>240</title></g><g class="guides"><path d="M0.000000 95.302782 h706.000000" class="guide line" /><text x="-5" y="98.80278232405891" class="">260</text><title>260</title></g><g class="guides"><path d="M0.000000 74.259995 h706.000000" class="guide line" /><text x="-5" y="77.75999532382514" class="">280</text><title>280</title></g><g class="guides"><path d="M0.000000 53.217208 h706.000000" class="major guide line" /><text x="-5" y="56.71720832359131" class="major">300</text><title>300</title></g><g class="guides"><path d="M0.000000 32.174421 h706.000000" class="guide line" /><text x="-5" y="35.67442132335748" class="">320</text><title>320</title></g><g class="guides"><path d="M0.000000 11.131634 h706.000000" class="guide line" /><text x="-5" y="14.631634323123706" class="">340</text><title>340</title></g></g><g class="axis x"><path d="M0.000000 0.000000 v360.000000" class="line" /><g class="guides"><path d="M24.891026 0.000000 v360.000000" class="guide line" /><text x="24.89102564102564" y="375.0" class="backwards" transform="rotate(270 24.891026 375.000000)">simple_list_e</text></g><g class="guides"><path d="M47.519231 0.000000 v360.000000" class="guide line" /><text x="47.51923076923077" y="375.0" class="backwards" transform="rotate(270 47.519231 375.000000)">simple_tuple_e</text></g><g class="guides"><path d="M70.147436 0.000000 v360.000000" class="guide line" /><text x="70.1474358974359" y="375.0" class="backwards" transform="rotate(270 70.147436 375.000000)">simple_set_e</text></g><g class="guides"><path d="M92.775641 0.000000 v360.000000" class="guide line" /><text x="92.77564102564102" y="375.0" class="backwards" transform="rotate(270 92.775641 375.000000)">simple_dict_e</text></g><g class="guides"><path d="M115.403846 0.000000 v360.000000" class="guide line" /><text x="115.40384615384615" y="375.0" class="backwards" transform="rotate(270 115.403846 375.000000)">simple_dict_d</text></g><g class="guides"><path d="M138.032051 0.000000 v360.000000" class="guide line" /><text x="138.03205128205127" y="375.0" class="backwards" transform="rotate(270 138.032051 375.000000)">simple_tuple_d</text></g><g class="guides"><path d="M160.660256 0.000000 v360.000000" class="guide line" /><text x="160.6602564102564" y="375.0" class="backwards" transform="rotate(270 160.660256 375.000000)">simple_set_d</text></g><g class="guides"><path d="M183.288462 0.000000 v360.000000" class="guide line" /><text x="183.28846153846155" y="375.0" class="backwards" transform="rotate(270 183.288462 375.000000)">simple_list_d</text></g><g class="guides"><path d="M205.916667 0.000000 v360.000000" class="guide line" /><text x="205.91666666666666" y="375.0" class="backwards" transform="rotate(270 205.916667 375.000000)">complex_homog_list_e</text></g><g class="guides"><path d="M228.544872 0.000000 v360.000000" class="guide line" /><text x="228.5448717948718" y="375.0" class="backwards" transform="rotate(270 228.544872 375.000000)">complex_homog_dict_d</text></g><g class="guides"><path d="M251.173077 0.000000 v360.000000" class="guide line" /><text x="251.17307692307688" y="375.0" class="backwards" transform="rotate(270 251.173077 375.000000)">complex_homog_set_e</text></g><g class="guides"><path d="M273.801282 0.000000 v360.000000" class="guide line" /><text x="273.8012820512821" y="375.0" class="backwards" transform="rotate(270 273.801282 375.000000)">complex_homog_tuple_e</text></g><g class="guides"><path d="M296.429487 0.000000 v360.000000" class="guide line" /><text x="296.4294871794872" y="375.0" class="backwards" transform="rotate(270 296.429487 375.000000)">complex_heterog_set_e</text></g><g class="guides"><path d="M319.057692 0.000000 v360.000000" class="guide line" /><text x="319.05769230769226" y="375.0" class="backwards" transform="rotate(270 319.057692 375.000000)">complex_heterog_dict_d</text></g><g class="guides"><path d="M341.685897 0.000000 v360.000000" class="guide line" /><text x="341.6858974358974" y="375.0" class="backwards" transform="rotate(270 341.685897 375.000000)">complex_homog_tuple_d</text></g><g class="guides"><path d="M364.314103 0.000000 v360.000000" class="guide line" /><text x="364.3141025641026" y="375.0" class="backwards" transform="rotate(270 364.314103 375.000000)">complex_homog_set_d</text></g><g class="guides"><path d="M386.942308 0.000000 v360.000000" class="guide line" /><text x="386.9423076923077" y="375.0" class="backwards" transform="rotate(270 386.942308 375.000000)">complex_heterog_set_d</text></g><g class="guides"><path d="M409.570513 0.000000 v360.000000" class="guide line" /><text x="409.5705128205129" y="375.0" class="backwards" transform="rotate(270 409.570513 375.000000)">simple_cls_d</text></g><g class="guides"><path d="M432.198718 0.000000 v360.000000" class="guide line" /><text x="432.19871794871796" y="375.0" class="backwards" transform="rotate(270 432.198718 375.000000)">complex_heterog_list_e</text></g><g class="guides"><path d="M454.826923 0.000000 v360.000000" class="guide line" /><text x="454.8269230769231" y="375.0" class="backwards" transform="rotate(270 454.826923 375.000000)">complex_heterog_tuple_e</text></g><g class="guides"><path d="M477.455128 0.000000 v360.000000" class="guide line" /><text x="477.4551282051282" y="375.0" class="backwards" transform="rotate(270 477.455128 375.000000)">complex_heterog_tuple_d</text></g><g class="guides"><path d="M500.083333 0.000000 v360.000000" class="guide line" /><text x="500.08333333333337" y="375.0" class="backwards" transform="rotate(270 500.083333 375.000000)">complex_heterog_list_d</text></g><g class="guides"><path d="M522.711538 0.000000 v360.000000" class="guide line" /><text x="522.7115384615385" y="375.0" class="backwards" transform="rotate(270 522.711538 375.000000)">complex_homog_list_d</text></g><g class="guides"><path d="M545.339744 0.000000 v360.000000" class="guide line" /><text x="545.3397435897435" y="375.0" class="backwards" transform="rotate(270 545.339744 375.000000)">complex_homog_dict_e</text></g><g class="guides"><path d="M567.967949 0.000000 v360.000000" class="guide line" /><text x="567.9679487179487" y="375.0" class="backwards" transform="rotate(270 567.967949 375.000000)">complex_heterog_dict_e</text></g><g class="guides"><path d="M590.596154 0.000000 v360.000000" class="guide line" /><text x="590.5961538461538" y="375.0" class="backwards" transform="rotate(270 590.596154 375.000000)">simple_cls_e</text></g><g class="guides"><path d="M613.224359 0.000000 v360.000000" class="guide line" /><text x="613.224358974359" y="375.0" class="backwards" transform="rotate(270 613.224359 375.000000)">complex_cls_d</text></g><g class="guides"><path d="M635.852564 0.000000 v360.000000" class="guide line" /><text x="635.8525641025641" y="375.0" class="backwards" transform="rotate(270 635.852564 375.000000)">state_cls_d</text></g><g class="guides"><path d="M658.480769 0.000000 v360.000000" class="guide line" /><text x="658.4807692307692" y="375.0" class="backwards" transform="rotate(270 658.480769 375.000000)">complex_cls_e</text></g><g class="guides"><path d="M681.108974 0.000000 v360.000000" class="guide line" /><text x="681.1089743589743" y="375.0" class="backwards" transform="rotate(270 681.108974 375.000000)">state_cls_e</text></g></g><g class="series serie-0 color-0"><g class="boxes"><g class="box"><path stroke-width="3" d="M19.912821 352.294131 L29.869231 352.294131" class="reactive tooltip-trigger" /><path stroke-width="3" d="M14.934615 351.603931 L34.847436 351.603931" class="reactive tooltip-trigger" /><path stroke-width="3" d="M19.912821 350.886371 L29.869231 350.886371" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 352.294131 L24.891026 351.768061" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 350.886371 L24.891026 351.415594" class="reactive tooltip-trigger" /><rect x="14.934615384615384" y="351.4155943513076" height="0.35246630398063417" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="352.4193371161533" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="71.16144256592486" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.6250
348 Q1-1.5IQR: 15.7440
349 Q1: 16.2440
350 Median: 16.4000
351 Q3: 16.5790
352 Q3+1.5IQR: 17.0820
353 Max: 282.9450</desc><desc class="x centered">24.891025641025642</desc><desc class="y centered">351.5936173174214</desc><desc class="x_label" /></g></g></g><g class="series serie-1 color-1"><g class="boxes"><g class="box"><path stroke-width="3" d="M42.541026 351.494505 L52.497436 351.494505" class="reactive tooltip-trigger" /><path stroke-width="3" d="M37.562821 350.944237 L57.475641 350.944237" class="reactive tooltip-trigger" /><path stroke-width="3" d="M42.541026 350.366612 L52.497436 350.366612" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 351.494505 L47.519231 351.074703" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 350.366612 L47.519231 350.791678" class="reactive tooltip-trigger" /><rect x="37.562820512820515" y="350.79167800882203" height="0.28302488433314466" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="351.6491696876072" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="334.39092910676317" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.3570
354 Q1-1.5IQR: 16.5040
355 Q1: 16.9030
356 Median: 17.0270
357 Q3: 17.1720
358 Q3+1.5IQR: 17.5760
359 Max: 32.7600</desc><desc class="x centered">47.519230769230774</desc><desc class="y centered">350.93434717003925</desc><desc class="x_label" /></g></g></g><g class="series serie-2 color-2"><g class="boxes"><g class="box"><path stroke-width="3" d="M65.169231 351.309331 L75.125641 351.309331" class="reactive tooltip-trigger" /><path stroke-width="3" d="M60.191026 350.753799 L80.103846 350.753799" class="reactive tooltip-trigger" /><path stroke-width="3" d="M65.169231 350.179333 L75.125641 350.179333" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 351.309331 L70.147436 350.888472" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 350.179333 L70.147436 350.605447" class="reactive tooltip-trigger" /><rect x="60.19102564102564" y="350.60544700719447" height="0.28302488433314466" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="351.42190999139245" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="331.6595755318382" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.5730
360 Q1-1.5IQR: 16.6800
361 Q1: 17.0800
362 Median: 17.2080
363 Q3: 17.3490
364 Q3+1.5IQR: 17.7540
365 Max: 35.3560</desc><desc class="x centered">70.1474358974359</desc><desc class="y centered">350.74727637966345</desc><desc class="x_label" /></g></g></g><g class="series serie-3 color-3"><g class="boxes"><g class="box"><path stroke-width="3" d="M87.797436 349.709024 L97.753846 349.709024" class="reactive tooltip-trigger" /><path stroke-width="3" d="M82.819231 348.872573 L102.732051 348.872573" class="reactive tooltip-trigger" /><path stroke-width="3" d="M87.797436 347.682607 L97.753846 347.682607" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 349.709024 L92.775641 349.072480" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 347.682607 L92.775641 348.516950" class="reactive tooltip-trigger" /><rect x="82.81923076923077" y="348.51694999660333" height="0.5555304002644448" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="349.70902419186234" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="121.51367929534689" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 18.2010
366 Q1-1.5IQR: 18.2010
367 Q1: 18.8060
368 Median: 18.9960
369 Q3: 19.3340
370 Q3+1.5IQR: 20.1270
371 Max: 235.0880</desc><desc class="x centered">92.77564102564102</desc><desc class="y centered">348.77072696032076</desc><desc class="x_label" /></g></g></g><g class="series serie-4 color-4"><g class="boxes"><g class="box"><path stroke-width="3" d="M110.425641 343.922260 L120.382051 343.922260" class="reactive tooltip-trigger" /><path stroke-width="3" d="M105.447436 343.263619 L125.360256 343.263619" class="reactive tooltip-trigger" /><path stroke-width="3" d="M110.425641 342.555528 L120.382051 342.555528" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 343.922260 L115.403846 343.413024" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 342.555528 L115.403846 343.070027" class="reactive tooltip-trigger" /><rect x="105.4474358974359" y="343.0700271623895" height="0.3429966715140722" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="343.9222596354314" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="323.53600500573083" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 23.7010
372 Q1-1.5IQR: 23.7010
373 Q1: 24.1850
374 Median: 24.3270
375 Q3: 24.5110
376 Q3+1.5IQR: 25.0000
377 Max: 43.0770</desc><desc class="x centered">115.40384615384615</desc><desc class="y centered">343.2448915429287</desc><desc class="x_label" /></g></g></g><g class="series serie-5 color-5"><g class="boxes"><g class="box"><path stroke-width="3" d="M133.053846 339.908349 L143.010256 339.908349" class="reactive tooltip-trigger" /><path stroke-width="3" d="M128.075641 339.200255 L147.988462 339.200255" class="reactive tooltip-trigger" /><path stroke-width="3" d="M133.053846 338.478492 L143.010256 338.478492" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 339.908349 L138.032051 339.373862" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 338.478492 L138.032051 339.017185" class="reactive tooltip-trigger" /><rect x="128.07564102564103" y="339.0171852284619" height="0.356676730703839" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="340.0861589862319" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="120.16904124468806" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 27.3470
378 Q1-1.5IQR: 27.5160
379 Q1: 28.0240
380 Median: 28.1890
381 Q3: 28.3630
382 Q3+1.5IQR: 28.8750
383 Max: 236.3660</desc><desc class="x centered">138.0320512820513</desc><desc class="y centered">339.19562847171585</desc><desc class="x_label" /></g></g></g><g class="series serie-6 color-6"><g class="boxes"><g class="box"><path stroke-width="3" d="M155.682051 339.137129 L165.638462 339.137129" class="reactive tooltip-trigger" /><path stroke-width="3" d="M150.703846 338.421674 L170.616667 338.421674" class="reactive tooltip-trigger" /><path stroke-width="3" d="M155.682051 337.693595 L165.638462 337.693595" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 339.137129 L160.660256 338.599484" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 337.693595 L160.660256 338.237548" class="reactive tooltip-trigger" /><rect x="150.70384615384614" y="338.2375481674493" height="0.3619359364471393" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="339.28337606122363" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="72.87853496451748" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 28.1100
384 Q1-1.5IQR: 28.2490
385 Q1: 28.7600
386 Median: 28.9290
387 Q3: 29.1040
388 Q3+1.5IQR: 29.6210
389 Max: 281.3130</desc><desc class="x centered">160.6602564102564</desc><desc class="y centered">338.41788610272863</desc><desc class="x_label" /></g></g></g><g class="series serie-7 color-7"><g class="boxes"><g class="box"><path stroke-width="3" d="M178.310256 337.842997 L188.266667 337.842997" class="reactive tooltip-trigger" /><path stroke-width="3" d="M173.332051 337.019169 L193.244872 337.019169" class="reactive tooltip-trigger" /><path stroke-width="3" d="M178.310256 336.149054 L188.266667 336.149054" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 337.842997 L183.288462 337.210660" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 336.149054 L183.288462 336.787703" class="reactive tooltip-trigger" /><rect x="173.33205128205125" y="336.7877030359598" height="0.42295650264821916" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="337.9345314115023" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="122.70680322654121" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 29.3920
390 Q1-1.5IQR: 29.4790
391 Q1: 30.0800
392 Median: 30.2620
393 Q3: 30.4820
394 Q3+1.5IQR: 31.0890
395 Max: 233.9540</desc><desc class="x centered">183.28846153846152</desc><desc class="y centered">337.00191653358974</desc><desc class="x_label" /></g></g></g><g class="series serie-8 color-8"><g class="boxes"><g class="box"><path stroke-width="3" d="M200.938462 320.043954 L210.894872 320.043954" class="reactive tooltip-trigger" /><path stroke-width="3" d="M195.960256 318.446809 L215.873077 318.446809" class="reactive tooltip-trigger" /><path stroke-width="3" d="M200.938462 316.764437 L210.894872 316.764437" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 320.043954 L205.916667 318.830838" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 316.764437 L205.916667 318.005435" class="reactive tooltip-trigger" /><rect x="195.9602564102564" y="318.00543534625456" height="0.8254024856635169" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="320.0439536347262" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="36.15571364666221" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 46.3960
396 Q1-1.5IQR: 46.3960
397 Q1: 47.5490
398 Median: 47.9140
399 Q3: 48.3335
400 Q3+1.5IQR: 49.5130
401 Max: 316.2160</desc><desc class="x centered">205.91666666666666</desc><desc class="y centered">318.41829448008843</desc><desc class="x_label" /></g></g></g><g class="series serie-9 color-9"><g class="boxes"><g class="box"><path stroke-width="3" d="M223.566667 319.699904 L233.523077 319.699904" class="reactive tooltip-trigger" /><path stroke-width="3" d="M218.588462 318.779283 L238.501282 318.779283" class="reactive tooltip-trigger" /><path stroke-width="3" d="M223.566667 317.782909 L233.523077 317.782909" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 319.699904 L228.544872 318.990765" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 317.782909 L228.544872 318.507833" class="reactive tooltip-trigger" /><rect x="218.58846153846153" y="318.50783303201786" height="0.4829321174897814" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="319.78092062200693" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="38.68926902945282" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 46.6460
402 Q1-1.5IQR: 46.7230
403 Q1: 47.3970
404 Median: 47.5980
405 Q3: 47.8560
406 Q3+1.5IQR: 48.5450
407 Max: 313.8080</desc><desc class="x centered">228.5448717948718</desc><desc class="y centered">318.7521388322045</desc><desc class="x_label" /></g></g></g><g class="series serie-10 color-10"><g class="boxes"><g class="box"><path stroke-width="3" d="M246.194872 316.825461 L256.151282 316.825461" class="reactive tooltip-trigger" /><path stroke-width="3" d="M241.216667 315.421908 L261.129487 315.421908" class="reactive tooltip-trigger" /><path stroke-width="3" d="M246.194872 313.916294 L256.151282 313.916294" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 316.825461 L251.173077 315.768059" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 313.916294 L251.173077 315.029462" class="reactive tooltip-trigger" /><rect x="241.21666666666664" y="315.02946172020296" height="0.7385968834435062" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="317.2431586401538" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="151.76794548514488" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 49.0580
408 Q1-1.5IQR: 49.4550
409 Q1: 50.4600
410 Median: 50.7890
411 Q3: 51.1620
412 Q3+1.5IQR: 52.2200
413 Max: 206.3330</desc><desc class="x centered">251.1730769230769</desc><desc class="y centered">315.39223667986624</desc><desc class="x_label" /></g></g></g><g class="series serie-11 color-11"><g class="boxes"><g class="box"><path stroke-width="3" d="M268.823077 317.085340 L278.779487 317.085340" class="reactive tooltip-trigger" /><path stroke-width="3" d="M263.844872 315.614451 L283.757692 315.614451" class="reactive tooltip-trigger" /><path stroke-width="3" d="M268.823077 314.020460 L278.779487 314.020460" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 317.085340 L273.801282 315.952711" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 314.020460 L273.801282 315.195435" class="reactive tooltip-trigger" /><rect x="263.84487179487184" y="315.19543482780097" height="0.7572758674518241" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="317.17582243386795" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="293.9698411999832" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 49.1220
414 Q1-1.5IQR: 49.2080
415 Q1: 50.2845
416 Median: 50.6060
417 Q3: 51.0043
418 Q3+1.5IQR: 52.1210
419 Max: 71.1780</desc><desc class="x centered">273.8012820512821</desc><desc class="y centered">315.5736792780113</desc><desc class="x_label" /></g></g></g><g class="series serie-12 color-12"><g class="boxes"><g class="box"><path stroke-width="3" d="M291.451282 314.157234 L301.407692 314.157234" class="reactive tooltip-trigger" /><path stroke-width="3" d="M286.473077 312.689504 L306.385897 312.689504" class="reactive tooltip-trigger" /><path stroke-width="3" d="M291.451282 311.163900 L301.407692 311.163900" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 314.157234 L296.429487 313.036705" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 311.163900 L296.429487 312.287586" class="reactive tooltip-trigger" /><rect x="286.473076923077" y="312.28758590613063" height="0.7491191225908551" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="314.25297865157205" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="166.53998267319162" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 51.9000
420 Q1-1.5IQR: 51.9910
421 Q1: 53.0560
422 Median: 53.3860
423 Q3: 53.7680
424 Q3+1.5IQR: 54.8360
425 Max: 192.2930</desc><desc class="x centered">296.42948717948724</desc><desc class="y centered">312.6669855443274</desc><desc class="x_label" /></g></g></g><g class="series serie-13 color-13"><g class="boxes"><g class="box"><path stroke-width="3" d="M314.079487 310.134910 L324.035897 310.134910" class="reactive tooltip-trigger" /><path stroke-width="3" d="M309.101282 308.377837 L329.014103 308.377837" class="reactive tooltip-trigger" /><path stroke-width="3" d="M314.079487 306.556583 L324.035897 306.556583" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 310.134910 L319.057692 308.795535" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 306.556583 L319.057692 307.900164" class="reactive tooltip-trigger" /><rect x="309.1012820512821" y="307.90016432647474" height="0.8953702086513431" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="310.63888232050465" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="173.65138958100692" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 55.3350
426 Q1-1.5IQR: 55.8140
427 Q1: 57.0870
428 Median: 57.4840
429 Q3: 57.9380
430 Q3+1.5IQR: 59.2150
431 Max: 185.5340</desc><desc class="x centered">319.0576923076924</desc><desc class="y centered">308.3530056724721</desc><desc class="x_label" /></g></g></g><g class="series serie-14 color-14"><g class="boxes"><g class="box"><path stroke-width="3" d="M336.707692 308.566166 L346.664103 308.566166" class="reactive tooltip-trigger" /><path stroke-width="3" d="M331.729487 307.531913 L351.642308 307.531913" class="reactive tooltip-trigger" /><path stroke-width="3" d="M336.707692 306.446109 L346.664103 306.446109" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 308.566166 L341.685897 307.786533" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 306.446109 L341.685897 307.250467" class="reactive tooltip-trigger" /><rect x="331.7294871794872" y="307.25046677563085" height="0.5360657889061713" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="308.9102189037446" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="172.1373622356133" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 56.9780
432 Q1-1.5IQR: 57.3050
433 Q1: 58.0460
434 Median: 58.2880
435 Q3: 58.5555
436 Q3+1.5IQR: 59.3200
437 Max: 186.9730</desc><desc class="x centered">341.68589743589746</desc><desc class="y centered">307.5162373312524</desc><desc class="x_label" /></g></g></g><g class="series serie-15 color-15"><g class="boxes"><g class="box"><path stroke-width="3" d="M359.335897 307.552957 L369.292308 307.552957" class="reactive tooltip-trigger" /><path stroke-width="3" d="M354.357692 306.421906 L374.270513 306.421906" class="reactive tooltip-trigger" /><path stroke-width="3" d="M359.335897 305.224572 L369.292308 305.224572" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 307.552957 L364.314103 306.693357" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 305.224572 L364.314103 306.106266" class="reactive tooltip-trigger" /><rect x="354.35769230769233" y="306.10626608912975" height="0.5870913762154828" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="307.9148931646846" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="205.57856165476795" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 57.9240
438 Q1-1.5IQR: 58.2680
439 Q1: 59.0850
440 Median: 59.3430
441 Q3: 59.6430
442 Q3+1.5IQR: 60.4810
443 Max: 155.1890</desc><desc class="x centered">364.3141025641026</desc><desc class="y centered">306.399811872929</desc><desc class="x_label" /></g></g></g><g class="series serie-16 color-16"><g class="boxes"><g class="box"><path stroke-width="3" d="M381.964103 307.046879 L391.920513 307.046879" class="reactive tooltip-trigger" /><path stroke-width="3" d="M376.985897 305.812719 L396.898718 305.812719" class="reactive tooltip-trigger" /><path stroke-width="3" d="M381.964103 304.538579 L391.920513 304.538579" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 307.046879 L386.942308 306.108633" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 304.538579 L386.942308 305.481293" class="reactive tooltip-trigger" /><rect x="376.98589743589747" y="305.4812933123027" height="0.627340184943705" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="307.18891607842875" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="234.8911620802628" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 58.6140
444 Q1-1.5IQR: 58.7490
445 Q1: 59.6407
446 Median: 59.9220
447 Q3: 60.2370
448 Q3+1.5IQR: 61.1330
449 Max: 127.3290</desc><desc class="x centered">386.94230769230774</desc><desc class="y centered">305.79762075818593</desc><desc class="x_label" /></g></g></g><g class="series serie-17 color-17"><g class="boxes"><g class="box"><path stroke-width="3" d="M404.592308 306.305121 L414.548718 306.305121" class="reactive tooltip-trigger" /><path stroke-width="3" d="M399.614103 304.230299 L419.526923 304.230299" class="reactive tooltip-trigger" /><path stroke-width="3" d="M404.592308 302.112347 L414.548718 302.112347" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 306.305121 L409.570513 304.749268" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 302.112347 L409.570513 303.695550" class="reactive tooltip-trigger" /><rect x="399.6141025641026" y="303.69554990598834" height="1.053717659304482" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="307.14157174375674" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="281.7471370119571" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 58.6590
450 Q1-1.5IQR: 59.4540
451 Q1: 60.9328
452 Median: 61.4260
453 Q3: 61.9343
454 Q3+1.5IQR: 63.4390
455 Max: 82.7950</desc><desc class="x centered">409.5705128205129</desc><desc class="y centered">304.21851686597563</desc><desc class="x_label" /></g></g></g><g class="series serie-18 color-18"><g class="boxes"><g class="box"><path stroke-width="3" d="M427.220513 306.211477 L437.176923 306.211477" class="reactive tooltip-trigger" /><path stroke-width="3" d="M422.242308 303.826280 L442.155128 303.826280" class="reactive tooltip-trigger" /><path stroke-width="3" d="M427.220513 301.335864 L437.176923 301.335864" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 306.211477 L432.198718 304.388649" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 301.335864 L432.198718 303.173428" class="reactive tooltip-trigger" /><rect x="422.24230769230775" y="303.17342828485727" height="1.215221016169778" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="306.8543364327004" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="70.42705228154392" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 58.9320
456 Q1-1.5IQR: 59.5430
457 Q1: 61.2755
458 Median: 61.8100
459 Q3: 62.4305
460 Q3+1.5IQR: 64.1770
461 Max: 283.6430</desc><desc class="x centered">432.198717948718</desc><desc class="y centered">303.78713970126404</desc><desc class="x_label" /></g></g></g><g class="series serie-19 color-19"><g class="boxes"><g class="box"><path stroke-width="3" d="M449.848718 305.209843 L459.805128 305.209843" class="reactive tooltip-trigger" /><path stroke-width="3" d="M444.870513 303.121345 L464.783333 303.121345" class="reactive tooltip-trigger" /><path stroke-width="3" d="M449.848718 300.953940 L459.805128 300.953940" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 305.209843 L454.826923 303.618221" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 300.953940 L454.826923 302.557138" class="reactive tooltip-trigger" /><rect x="444.87051282051283" y="302.55713759931643" height="1.0610830353246001" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="305.65384808240117" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="197.03518861839413" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 60.0730
462 Q1-1.5IQR: 60.4950
463 Q1: 62.0077
464 Median: 62.4800
465 Q3: 63.0162
466 Q3+1.5IQR: 64.5400
467 Max: 163.3090</desc><desc class="x centered">454.8269230769231</desc><desc class="y centered">303.09209738567563</desc><desc class="x_label" /></g></g></g><g class="series serie-20 color-20"><g class="boxes"><g class="box"><path stroke-width="3" d="M472.476923 304.609069 L482.433333 304.609069" class="reactive tooltip-trigger" /><path stroke-width="3" d="M467.498718 303.138183 L487.411538 303.138183" class="reactive tooltip-trigger" /><path stroke-width="3" d="M472.476923 301.594691 L482.433333 301.594691" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 304.609069 L477.455128 303.495909" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 301.594691 L477.455128 302.739421" class="reactive tooltip-trigger" /><rect x="467.49871794871797" y="302.739421325891" height="0.7564873693564209" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="304.83949031156476" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="209.16845568749827" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 60.8470
468 Q1-1.5IQR: 61.0660
469 Q1: 62.1240
470 Median: 62.4640
471 Q3: 62.8430
472 Q3+1.5IQR: 63.9310
473 Max: 151.7770</desc><desc class="x centered">477.45512820512823</desc><desc class="y centered">303.1154545365395</desc><desc class="x_label" /></g></g></g><g class="series serie-21 color-21"><g class="boxes"><g class="box"><path stroke-width="3" d="M495.105128 302.476384 L505.061538 302.476384" class="reactive tooltip-trigger" /><path stroke-width="3" d="M490.126923 300.710895 L510.039744 300.710895" class="reactive tooltip-trigger" /><path stroke-width="3" d="M495.105128 298.868600 L505.061538 298.868600" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 302.476384 L500.083333 301.135432" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 298.868600 L500.083333 300.229016" class="reactive tooltip-trigger" /><rect x="490.1269230769231" y="300.22901563475665" height="0.9064168373087114" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="302.734158292487" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="117.16729023793886" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 62.8480
474 Q1-1.5IQR: 63.0930
475 Q1: 64.3675
476 Median: 64.7710
477 Q3: 65.2290
478 Q3+1.5IQR: 66.5220
479 Max: 239.2190</desc><desc class="x centered">500.08333333333337</desc><desc class="y centered">300.68406554095327</desc><desc class="x_label" /></g></g></g><g class="series serie-22 color-22"><g class="boxes"><g class="box"><path stroke-width="3" d="M517.733333 302.208092 L527.689744 302.208092" class="reactive tooltip-trigger" /><path stroke-width="3" d="M512.755128 300.832944 L532.667949 300.832944" class="reactive tooltip-trigger" /><path stroke-width="3" d="M517.733333 299.324176 L527.689744 299.324176" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 302.208092 L522.711538 301.165418" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 299.324176 L522.711538 300.429185" class="reactive tooltip-trigger" /><rect x="512.7551282051282" y="300.4291850626683" height="0.7362333029875003" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="302.4395585623257" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="-27.67863097392467" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 63.1280
480 Q1-1.5IQR: 63.3480
481 Q1: 64.3390
482 Median: 64.6550
483 Q3: 65.0388
484 Q3+1.5IQR: 66.0890
485 Max: 376.8870</desc><desc class="x centered">522.7115384615385</desc><desc class="y centered">300.79196308446006</desc><desc class="x_label" /></g></g></g><g class="series serie-23 color-23"><g class="boxes"><g class="box"><path stroke-width="3" d="M540.361538 300.234275 L550.317949 300.234275" class="reactive tooltip-trigger" /><path stroke-width="3" d="M535.383333 297.865910 L555.296154 297.865910" class="reactive tooltip-trigger" /><path stroke-width="3" d="M540.361538 295.472294 L550.317949 295.472294" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 300.234275 L545.339744 298.455896" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 295.472294 L545.339744 297.266192" class="reactive tooltip-trigger" /><rect x="535.3833333333333" y="297.2661919368937" height="1.1897039163969225" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="301.0833533211601" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="251.80851120295435" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 64.4170
486 Q1-1.5IQR: 65.2240
487 Q1: 66.9143
488 Median: 67.4750
489 Q3: 68.0450
490 Q3+1.5IQR: 69.7500
491 Max: 111.2500</desc><desc class="x centered">545.3397435897435</desc><desc class="y centered">297.8589132277872</desc><desc class="x_label" /></g></g></g><g class="series serie-24 color-24"><g class="boxes"><g class="box"><path stroke-width="3" d="M562.989744 297.604982 L572.946154 297.604982" class="reactive tooltip-trigger" /><path stroke-width="3" d="M558.011538 295.098785 L577.924359 295.098785" class="reactive tooltip-trigger" /><path stroke-width="3" d="M562.989744 292.597847 L572.946154 292.597847" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 297.604982 L567.967949 295.744800" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 292.597847 L567.967949 294.487490" class="reactive tooltip-trigger" /><rect x="558.0115384615385" y="294.48749019963606" height="1.257309972759117" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="298.4256477649451" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="266.24281092523034" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 66.9430
492 Q1-1.5IQR: 67.7230
493 Q1: 69.4910
494 Median: 70.1050
495 Q3: 70.6860
496 Q3+1.5IQR: 72.4820
497 Max: 97.5310</desc><desc class="x centered">567.9679487179487</desc><desc class="y centered">295.10678081421713</desc><desc class="x_label" /></g></g></g><g class="series serie-25 color-25"><g class="boxes"><g class="box"><path stroke-width="3" d="M585.617949 285.832594 L595.574359 285.832594" class="reactive tooltip-trigger" /><path stroke-width="3" d="M580.639744 283.334812 L600.552564 283.334812" class="reactive tooltip-trigger" /><path stroke-width="3" d="M585.617949 280.710779 L595.574359 280.710779" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 285.832594 L590.596154 283.932429" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 280.710779 L590.596154 282.649872" class="reactive tooltip-trigger" /><rect x="580.6397435897436" y="282.64987163971335" height="1.2825572224556367" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="285.88099138369955" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="157.19382671180955" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 78.8660
498 Q1-1.5IQR: 78.9120
499 Q1: 80.7180
500 Median: 81.2860
501 Q3: 81.9370
502 Q3+1.5IQR: 83.7800
503 Max: 201.1760</desc><desc class="x centered">590.5961538461538</desc><desc class="y centered">283.29209721418783</desc><desc class="x_label" /></g></g></g><g class="series serie-26 color-26"><g class="boxes"><g class="box"><path stroke-width="3" d="M608.246154 57.653027 L618.202564 57.653027" class="reactive tooltip-trigger" /><path stroke-width="3" d="M603.267949 53.035188 L623.180769 53.035188" class="reactive tooltip-trigger" /><path stroke-width="3" d="M608.246154 48.265839 L618.202564 48.265839" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 57.653027 L613.224359 54.149403" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 48.265839 L613.224359 51.799451" class="reactive tooltip-trigger" /><rect x="603.2679487179488" y="51.799450789854575" height="2.349952070204381" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="59.18915159343044" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="-218.04220087924796" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 294.3240
504 Q1-1.5IQR: 295.7840
505 Q1: 299.1140
506 Median: 300.1730
507 Q3: 301.3475
508 Q3+1.5IQR: 304.7060
509 Max: 557.8170</desc><desc class="x centered">613.224358974359</desc><desc class="y centered">52.98058151191094</desc><desc class="x_label" /></g></g></g><g class="series serie-27 color-27"><g class="boxes"><g class="box"><path stroke-width="3" d="M630.874359 50.724690 L640.830769 50.724690" class="reactive tooltip-trigger" /><path stroke-width="3" d="M625.896154 45.601821 L645.808974 45.601821" class="reactive tooltip-trigger" /><path stroke-width="3" d="M630.874359 39.336335 L640.830769 39.336335" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 50.724690 L635.852564 46.765752" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 39.336335 L635.852564 43.798719" class="reactive tooltip-trigger" /><rect x="625.8961538461539" y="43.798719463396424" height="2.9670322107558036" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="50.72468960917058" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="-311.24806893349046" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 302.3690
510 Q1-1.5IQR: 302.3690
511 Q1: 306.1318
512 Median: 307.2380
513 Q3: 308.9518
514 Q3+1.5IQR: 313.1930
515 Max: 646.4040</desc><desc class="x centered">635.8525641025641</desc><desc class="y centered">45.24546342422127</desc><desc class="x_label" /></g></g></g><g class="series serie-28 color-28"><g class="boxes"><g class="box"><path stroke-width="3" d="M653.502564 28.092123 L663.458974 28.092123" class="reactive tooltip-trigger" /><path stroke-width="3" d="M648.524359 22.547347 L668.437179 22.547347" class="reactive tooltip-trigger" /><path stroke-width="3" d="M653.502564 16.595395 L663.458974 16.595395" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 28.092123 L658.480769 23.802024" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 16.595395 L658.480769 20.930210" class="reactive tooltip-trigger" /><rect x="648.524358974359" y="20.930209672866738" height="2.8718143673259533" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="28.092122563057103" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="-208.7981056616361" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 323.8800
516 Q1-1.5IQR: 323.8800
517 Q1: 327.9575
518 Median: 329.1500
519 Q3: 330.6870
520 Q3+1.5IQR: 334.8070
521 Max: 549.0310</desc><desc class="x centered">658.4807692307692</desc><desc class="y centered">22.39341965569082</desc><desc class="x_label" /></g></g></g><g class="series serie-29 color-29"><g class="boxes"><g class="box"><path stroke-width="3" d="M676.130769 17.980010 L686.087179 17.980010" class="reactive tooltip-trigger" /><path stroke-width="3" d="M671.152564 12.853459 L691.065385 12.853459" class="reactive tooltip-trigger" /><path stroke-width="3" d="M676.130769 7.089316 L686.087179 7.089316" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 17.980010 L681.108974 14.104978" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 7.089316 L681.108974 11.311547" class="reactive tooltip-trigger" /><rect x="671.1525641025642" y="11.311547238638184" height="2.7934305754675393" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="18.467148316404405" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="-252.52291255209218" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 333.0280
522 Q1-1.5IQR: 333.4910
523 Q1: 337.1740
524 Median: 338.3635
525 Q3: 339.8290
526 Q3+1.5IQR: 343.8420
527 Max: 590.5890</desc><desc class="x centered">681.1089743589744</desc><desc class="y centered">12.667861950898612</desc><desc class="x_label" /></g></g></g></g><g class="titles"><text x="400.0" y="26" class="title plot_title">Speed in Microseconds (us)</text><text x="427.0" y="580.0" class="title">Trial</text><text x="0" y="252.0" class="title" transform="rotate(-90 0.000000 226.000000)">Duration</text></g><g transform="translate(74, 46)" class="plot overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot text-overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot tooltip-overlay"><g transform="translate(0 0)" style="opacity: 0" class="tooltip"><rect rx="0" ry="0" width="0" height="0" class="tooltip-box" /><g class="text" /></g></g></g></svg>
0 <?xml version='1.0' encoding='utf-8'?>
1 <svg xmlns="http://www.w3.org/2000/svg" id="chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969" class="pygal-chart" viewBox="0 0 800 600"><!--Generated with pygal 3.0.0 (etree) ©Kozea 2012-2016 on 2022-06-20--><!--http://pygal.org--><!--http://github.com/Kozea/pygal--><defs><style type="text/css">#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .title{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .legends .legend text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis text.major{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay text.value{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay text.label{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 text.no_data{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:64px}
2 #chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969{background-color:rgba(249,249,249,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 path,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 rect,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .graph &gt; .background{fill:rgba(249,249,249,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .plot &gt; .background{fill:rgba(255,255,255,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .graph{fill:rgba(0,0,0,.87)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 text.no_data{fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .title{fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .legends .legend text{fill:rgba(0,0,0,.87)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .line{stroke:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis text.major{fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y .guides:hover .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .line-graph .axis.x .guides:hover .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .stackedline-graph .axis.x .guides:hover .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .reactive{fill-opacity:.7;stroke-opacity:.8;stroke-width:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .ci{stroke:rgba(0,0,0,.87)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .reactive.active,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .ci .reactive.active{stroke-width:1.5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .series text{fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip .value{font-size:1.5em}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .bound{font-size:.5em}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-0,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-0 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-1,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-2,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-2 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-3,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-3 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-4,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-4 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-5,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-5 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-6,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-6 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-7,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-7 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-8,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-8 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-9,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-9 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-10,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-10 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-11,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-11 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-12,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-12 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-13,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-13 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-14,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-14 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-15,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-15 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-16,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-16 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-17,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-17 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-18,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-18 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-19,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-19 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-20,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-20 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-21,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-21 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-22,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-22 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-23,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-23 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-24,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-24 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-25,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-25 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-26,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-26 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-27,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-27 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-28,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-28 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-29,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .color-29 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-0 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-1 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-2 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-3 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-4 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-5 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-6 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-7 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-8 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-9 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-10 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-11 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-12 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-13 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-14 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-15 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-16 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-17 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-18 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-19 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-20 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-21 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-22 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-23 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-24 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-25 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-26 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-27 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-28 text{fill:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .text-overlay .color-29 text{fill:black}
3 #chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 text.no_data{text-anchor:middle}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .guide.line{fill:none}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .centered{text-anchor:middle}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .title{text-anchor:middle}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .legends .legend text{fill-opacity:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.x text{text-anchor:middle}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.x:not(.web) text[transform]{text-anchor:start}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y text{text-anchor:end}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y text[transform].backwards{text-anchor:start}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y2 text{text-anchor:start}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y2 text[transform].backwards{text-anchor:end}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .guide.line{stroke-dasharray:4,4;stroke:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .major.guide.line{stroke-dasharray:6,6;stroke:black}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .horizontal .axis.y .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .horizontal .axis.y2 .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .vertical .axis.x .guide.line{opacity:0}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .horizontal .axis.always_show .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y .guides:hover .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.y2 .guides:hover .guide.line,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis.x .guides:hover .guide.line{opacity:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .axis .guides:hover text{opacity:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .nofill{fill:none}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .subtle-fill{fill-opacity:.2}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .dot{stroke-width:1px;fill-opacity:1;stroke-opacity:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .dot.active{stroke-width:5px}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .dot.negative{fill:transparent}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 text,#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 tspan{stroke:none !important}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .series text.active{opacity:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .tooltip text{fill-opacity:1}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .showable{visibility:hidden}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .showable.shown{visibility:visible}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-3d1f86d5-6953-4507-b5f9-1ad1b0395969 .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}
4 .tooltip .value{font-size:1em !important}.axis text{font-size:9px !important}</style><script type="text/javascript">window.pygal = window.pygal || {};window.pygal.config = window.pygal.config || {};window.pygal.config['3d1f86d5-6953-4507-b5f9-1ad1b0395969'] = {"allow_interruptions": false, "box_mode": "tukey", "classes": ["pygal-chart"], "css": ["file://style.css", "file://graph.css", "inline:\n .tooltip .value {\n font-size: 1em !important;\n }\n .axis text {\n font-size: 9px !important;\n }\n "], "defs": [], "disable_xml_declaration": false, "dots_size": 2.5, "dynamic_print_values": false, "explicit_size": false, "fill": false, "force_uri_protocol": "https", "formatter": null, "half_pie": false, "height": 600, "include_x_axis": false, "inner_radius": 0, "interpolate": null, "interpolation_parameters": {}, "interpolation_precision": 250, "inverse_y_axis": false, "js": ["file:///home/theel/.pyenv/versions/3.9.13/lib/python3.9/site-packages/pygaljs/static/2.0.x/pygal-tooltips.js"], "legend_at_bottom": false, "legend_at_bottom_columns": null, "legend_box_size": 12, "logarithmic": false, "margin": 20, "margin_bottom": null, "margin_left": null, "margin_right": null, "margin_top": null, "max_scale": 20, "min_scale": 20, "missing_value_fill_truncation": "x", "no_data_text": "No data", "no_prefix": false, "order_min": null, "pretty_print": false, "print_labels": false, "print_values": false, "print_values_position": "center", "print_zeroes": true, "range": [14, 155], "rounded_bars": null, "secondary_range": null, "show_dots": true, "show_legend": false, "show_minor_x_labels": true, "show_minor_y_labels": true, "show_only_major_dots": false, "show_x_guides": false, "show_x_labels": true, "show_y_guides": true, "show_y_labels": true, "spacing": 10, "stack_from_top": false, "strict": false, "stroke": true, "stroke_style": null, "style": {"background": "rgba(249, 249, 249, 1)", "ci_colors": [], "colors": ["#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5"], "dot_opacity": "1", "font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "foreground": "rgba(0, 0, 0, .87)", "foreground_strong": "rgba(0, 0, 0, 1)", "foreground_subtle": "rgba(0, 0, 0, .54)", "guide_stroke_color": "black", "guide_stroke_dasharray": "4,4", "label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "label_font_size": 10, "legend_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "legend_font_size": 14, "major_guide_stroke_color": "black", "major_guide_stroke_dasharray": "6,6", "major_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "major_label_font_size": 10, "no_data_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "no_data_font_size": 64, "opacity": ".7", "opacity_hover": ".8", "plot_background": "rgba(255, 255, 255, 1)", "stroke_opacity": ".8", "stroke_opacity_hover": ".9", "stroke_width": "1", "stroke_width_hover": "4", "title_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "title_font_size": 16, "tooltip_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "tooltip_font_size": 14, "transition": "150ms", "value_background": "rgba(229, 229, 229, 1)", "value_colors": [], "value_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_font_size": 16, "value_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_label_font_size": 10}, "title": "Speed in Microseconds (us)", "tooltip_border_radius": 0, "tooltip_fancy_mode": true, "truncate_label": 50, "truncate_legend": null, "width": 800, "x_label_rotation": 270, "x_labels": ["simple_list_e", "simple_tuple_e", "simple_set_e", "simple_tuple_d", "simple_set_d", "simple_dict_d", "simple_dict_e", "simple_list_d", "complex_homog_list_e", "complex_homog_tuple_d", "complex_homog_set_d", "complex_homog_tuple_e", "complex_homog_set_e", "complex_heterog_set_d", "complex_homog_dict_d", "complex_heterog_set_e", "complex_homog_list_d", "complex_heterog_tuple_d", "complex_heterog_dict_d", "complex_heterog_list_e", "complex_heterog_tuple_e", "complex_heterog_list_d", "complex_homog_dict_e", "simple_cls_d", "complex_heterog_dict_e", "simple_cls_e", "complex_cls_e", "complex_cls_d", "state_cls_d", "state_cls_e"], "x_labels_major": null, "x_labels_major_count": null, "x_labels_major_every": null, "x_title": "Trial", "xrange": null, "y_label_rotation": 0, "y_labels": null, "y_labels_major": null, "y_labels_major_count": null, "y_labels_major_every": null, "y_title": "Duration", "zero": 14, "legends": ["jsonpickle_benchmarks.py::simple_list_e - 16106 rounds", "jsonpickle_benchmarks.py::simple_tuple_e - 14375 rounds", "jsonpickle_benchmarks.py::simple_set_e - 15376 rounds", "jsonpickle_benchmarks.py::simple_tuple_d - 15959 rounds", "jsonpickle_benchmarks.py::simple_set_d - 15954 rounds", "jsonpickle_benchmarks.py::simple_dict_d - 11231 rounds", "jsonpickle_benchmarks.py::simple_dict_e - 7872 rounds", "jsonpickle_benchmarks.py::simple_list_d - 15533 rounds", "jsonpickle_benchmarks.py::complex_homog_list_e - 10981 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_d - 10620 rounds", "jsonpickle_benchmarks.py::complex_homog_set_d - 10385 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_e - 8312 rounds", "jsonpickle_benchmarks.py::complex_homog_set_e - 10361 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_d - 11168 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_d - 9421 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_e - 10165 rounds", "jsonpickle_benchmarks.py::complex_homog_list_d - 9762 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_d - 8956 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_d - 8725 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_e - 7798 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_e - 8356 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_d - 9295 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_e - 6419 rounds", "jsonpickle_benchmarks.py::simple_cls_d - 6577 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_e - 7613 rounds", "jsonpickle_benchmarks.py::simple_cls_e - 6312 rounds", "jsonpickle_benchmarks.py::complex_cls_e - 3978 rounds", "jsonpickle_benchmarks.py::complex_cls_d - 4349 rounds", "jsonpickle_benchmarks.py::state_cls_d - 4188 rounds", "jsonpickle_benchmarks.py::state_cls_e - 4007 rounds"]}</script><script type="text/javascript">(function() {
5 var $, get_translation, init, init_svg, matches, padding, r_translation, sibl, svg_ns, tooltip_timeout, xlink_ns;
6
7 svg_ns = 'http://www.w3.org/2000/svg';
8
9 xlink_ns = 'http://www.w3.org/1999/xlink';
10
11 $ = function(sel, ctx) {
12 if (ctx == null) {
13 ctx = null;
14 }
15 ctx = ctx || document;
16 return Array.prototype.slice.call(ctx.querySelectorAll(sel), 0).filter(function(e) {
17 return e !== ctx;
18 });
19 };
20
21 matches = function(el, selector) {
22 return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
23 };
24
25 sibl = function(el, match) {
26 if (match == null) {
27 match = null;
28 }
29 return Array.prototype.filter.call(el.parentElement.children, function(child) {
30 return child !== el &amp;&amp; (!match || matches(child, match));
31 });
32 };
33
34 Array.prototype.one = function() {
35 return this.length &gt; 0 &amp;&amp; this[0] || {};
36 };
37
38 padding = 5;
39
40 tooltip_timeout = null;
41
42 r_translation = /translate\((\d+)[ ,]+(\d+)\)/;
43
44 get_translation = function(el) {
45 return (r_translation.exec(el.getAttribute('transform')) || []).slice(1).map(function(x) {
46 return +x;
47 });
48 };
49
50 init = function(ctx) {
51 var bbox, box, config, el, graph, inner_svg, num, parent, tooltip, tooltip_el, tt, uid, untooltip, xconvert, yconvert, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
52 if ($('svg', ctx).length) {
53 inner_svg = $('svg', ctx).one();
54 parent = inner_svg.parentElement;
55 box = inner_svg.viewBox.baseVal;
56 bbox = parent.getBBox();
57 xconvert = function(x) {
58 return ((x - box.x) / box.width) * bbox.width;
59 };
60 yconvert = function(y) {
61 return ((y - box.y) / box.height) * bbox.height;
62 };
63 } else {
64 xconvert = yconvert = function(x) {
65 return x;
66 };
67 }
68 if (((_ref = window.pygal) != null ? _ref.config : void 0) != null) {
69 if (window.pygal.config.no_prefix != null) {
70 config = window.pygal.config;
71 } else {
72 uid = ctx.id.replace('chart-', '');
73 config = window.pygal.config[uid];
74 }
75 } else {
76 config = window.config;
77 }
78 tooltip_el = null;
79 graph = $('.graph').one();
80 tt = $('.tooltip', ctx).one();
81 _ref1 = $('.reactive', ctx);
82 for (_i = 0, _len = _ref1.length; _i &lt; _len; _i++) {
83 el = _ref1[_i];
84 el.addEventListener('mouseenter', (function(el) {
85 return function() {
86 return el.classList.add('active');
87 };
88 })(el));
89 el.addEventListener('mouseleave', (function(el) {
90 return function() {
91 return el.classList.remove('active');
92 };
93 })(el));
94 }
95 _ref2 = $('.activate-serie', ctx);
96 for (_j = 0, _len1 = _ref2.length; _j &lt; _len1; _j++) {
97 el = _ref2[_j];
98 num = el.id.replace('activate-serie-', '');
99 el.addEventListener('mouseenter', (function(num) {
100 return function() {
101 var re, _k, _len2, _ref3, _results;
102 _ref3 = $('.serie-' + num + ' .reactive', ctx);
103 _results = [];
104 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
105 re = _ref3[_k];
106 _results.push(re.classList.add('active'));
107 }
108 return _results;
109 };
110 })(num));
111 el.addEventListener('mouseleave', (function(num) {
112 return function() {
113 var re, _k, _len2, _ref3, _results;
114 _ref3 = $('.serie-' + num + ' .reactive', ctx);
115 _results = [];
116 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
117 re = _ref3[_k];
118 _results.push(re.classList.remove('active'));
119 }
120 return _results;
121 };
122 })(num));
123 el.addEventListener('click', (function(el, num) {
124 return function() {
125 var ov, re, rect, show, _k, _l, _len2, _len3, _ref3, _ref4, _results;
126 rect = $('rect', el).one();
127 show = rect.style.fill !== '';
128 rect.style.fill = show ? '' : 'transparent';
129 _ref3 = $('.serie-' + num + ' .reactive', ctx);
130 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
131 re = _ref3[_k];
132 re.style.display = show ? '' : 'none';
133 }
134 _ref4 = $('.text-overlay .serie-' + num, ctx);
135 _results = [];
136 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
137 ov = _ref4[_l];
138 _results.push(ov.style.display = show ? '' : 'none');
139 }
140 return _results;
141 };
142 })(el, num));
143 }
144 _ref3 = $('.tooltip-trigger', ctx);
145 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
146 el = _ref3[_k];
147 el.addEventListener('mouseenter', (function(el) {
148 return function() {
149 return tooltip_el = tooltip(el);
150 };
151 })(el));
152 }
153 tt.addEventListener('mouseenter', function() {
154 return tooltip_el != null ? tooltip_el.classList.add('active') : void 0;
155 });
156 tt.addEventListener('mouseleave', function() {
157 return tooltip_el != null ? tooltip_el.classList.remove('active') : void 0;
158 });
159 ctx.addEventListener('mouseleave', function() {
160 if (tooltip_timeout) {
161 clearTimeout(tooltip_timeout);
162 }
163 return untooltip(0);
164 });
165 graph.addEventListener('mousemove', function(el) {
166 if (tooltip_timeout) {
167 return;
168 }
169 if (!matches(el.target, '.background')) {
170 return;
171 }
172 return untooltip(1000);
173 });
174 tooltip = function(el) {
175 var a, baseline, cls, current_x, current_y, dy, h, i, key, keys, label, legend, name, plot_x, plot_y, rect, serie_index, subval, text, text_group, texts, traversal, value, w, x, x_elt, x_label, xlink, y, y_elt, _l, _len3, _len4, _len5, _m, _n, _ref4, _ref5, _ref6, _ref7, _ref8;
176 clearTimeout(tooltip_timeout);
177 tooltip_timeout = null;
178 tt.style.opacity = 1;
179 tt.style.display = '';
180 text_group = $('g.text', tt).one();
181 rect = $('rect', tt).one();
182 text_group.innerHTML = '';
183 label = sibl(el, '.label').one().textContent;
184 x_label = sibl(el, '.x_label').one().textContent;
185 value = sibl(el, '.value').one().textContent;
186 xlink = sibl(el, '.xlink').one().textContent;
187 serie_index = null;
188 parent = el;
189 traversal = [];
190 while (parent) {
191 traversal.push(parent);
192 if (parent.classList.contains('series')) {
193 break;
194 }
195 parent = parent.parentElement;
196 }
197 if (parent) {
198 _ref4 = parent.classList;
199 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
200 cls = _ref4[_l];
201 if (cls.indexOf('serie-') === 0) {
202 serie_index = +cls.replace('serie-', '');
203 break;
204 }
205 }
206 }
207 legend = null;
208 if (serie_index !== null) {
209 legend = config.legends[serie_index];
210 }
211 dy = 0;
212 keys = [[label, 'label']];
213 _ref5 = value.split('\n');
214 for (i = _m = 0, _len4 = _ref5.length; _m &lt; _len4; i = ++_m) {
215 subval = _ref5[i];
216 keys.push([subval, 'value-' + i]);
217 }
218 if (config.tooltip_fancy_mode) {
219 keys.push([xlink, 'xlink']);
220 keys.unshift([x_label, 'x_label']);
221 keys.unshift([legend, 'legend']);
222 }
223 texts = {};
224 for (_n = 0, _len5 = keys.length; _n &lt; _len5; _n++) {
225 _ref6 = keys[_n], key = _ref6[0], name = _ref6[1];
226 if (key) {
227 text = document.createElementNS(svg_ns, 'text');
228 text.textContent = key;
229 text.setAttribute('x', padding);
230 text.setAttribute('dy', dy);
231 text.classList.add(name.indexOf('value') === 0 ? 'value' : name);
232 if (name.indexOf('value') === 0 &amp;&amp; config.tooltip_fancy_mode) {
233 text.classList.add('color-' + serie_index);
234 }
235 if (name === 'xlink') {
236 a = document.createElementNS(svg_ns, 'a');
237 a.setAttributeNS(xlink_ns, 'href', key);
238 a.textContent = void 0;
239 a.appendChild(text);
240 text.textContent = 'Link &gt;';
241 text_group.appendChild(a);
242 } else {
243 text_group.appendChild(text);
244 }
245 dy += text.getBBox().height + padding / 2;
246 baseline = padding;
247 if (text.style.dominantBaseline !== void 0) {
248 text.style.dominantBaseline = 'text-before-edge';
249 } else {
250 baseline += text.getBBox().height * .8;
251 }
252 text.setAttribute('y', baseline);
253 texts[name] = text;
254 }
255 }
256 w = text_group.getBBox().width + 2 * padding;
257 h = text_group.getBBox().height + 2 * padding;
258 rect.setAttribute('width', w);
259 rect.setAttribute('height', h);
260 if (texts.value) {
261 texts.value.setAttribute('dx', (w - texts.value.getBBox().width) / 2 - padding);
262 }
263 if (texts.x_label) {
264 texts.x_label.setAttribute('dx', w - texts.x_label.getBBox().width - 2 * padding);
265 }
266 if (texts.xlink) {
267 texts.xlink.setAttribute('dx', w - texts.xlink.getBBox().width - 2 * padding);
268 }
269 x_elt = sibl(el, '.x').one();
270 y_elt = sibl(el, '.y').one();
271 x = parseInt(x_elt.textContent);
272 if (x_elt.classList.contains('centered')) {
273 x -= w / 2;
274 } else if (x_elt.classList.contains('left')) {
275 x -= w;
276 } else if (x_elt.classList.contains('auto')) {
277 x = xconvert(el.getBBox().x + el.getBBox().width / 2) - w / 2;
278 }
279 y = parseInt(y_elt.textContent);
280 if (y_elt.classList.contains('centered')) {
281 y -= h / 2;
282 } else if (y_elt.classList.contains('top')) {
283 y -= h;
284 } else if (y_elt.classList.contains('auto')) {
285 y = yconvert(el.getBBox().y + el.getBBox().height / 2) - h / 2;
286 }
287 _ref7 = get_translation(tt.parentElement), plot_x = _ref7[0], plot_y = _ref7[1];
288 if (x + w + plot_x &gt; config.width) {
289 x = config.width - w - plot_x;
290 }
291 if (y + h + plot_y &gt; config.height) {
292 y = config.height - h - plot_y;
293 }
294 if (x + plot_x &lt; 0) {
295 x = -plot_x;
296 }
297 if (y + plot_y &lt; 0) {
298 y = -plot_y;
299 }
300 _ref8 = get_translation(tt), current_x = _ref8[0], current_y = _ref8[1];
301 if (current_x === x &amp;&amp; current_y === y) {
302 return el;
303 }
304 tt.setAttribute('transform', "translate(" + x + " " + y + ")");
305 return el;
306 };
307 return untooltip = function(ms) {
308 return tooltip_timeout = setTimeout(function() {
309 tt.style.display = 'none';
310 tt.style.opacity = 0;
311 if (tooltip_el != null) {
312 tooltip_el.classList.remove('active');
313 }
314 return tooltip_timeout = null;
315 }, ms);
316 };
317 };
318
319 init_svg = function() {
320 var chart, charts, _i, _len, _results;
321 charts = $('.pygal-chart');
322 if (charts.length) {
323 _results = [];
324 for (_i = 0, _len = charts.length; _i &lt; _len; _i++) {
325 chart = charts[_i];
326 _results.push(init(chart));
327 }
328 return _results;
329 }
330 };
331
332 if (document.readyState !== 'loading') {
333 init_svg();
334 } else {
335 document.addEventListener('DOMContentLoaded', function() {
336 return init_svg();
337 });
338 }
339
340 window.pygal = window.pygal || {};
341
342 window.pygal.init = init;
343
344 window.pygal.init_svg = init_svg;
345
346 }).call(this);
347 </script></defs><title>Speed in Microseconds (us)</title><g class="graph custombox-graph vertical"><rect x="0" y="0" width="800" height="600" class="background" /><g transform="translate(74, 46)" class="plot"><rect x="0" y="0" width="706.0" height="360.0" class="background" /><g class="axis y always_show"><path d="M0.000000 360.000000 h706.000000" class="line" /><g class="guides"><path d="M0.000000 348.166939 h706.000000" class="guide line" /><text x="-5" y="351.66693944353517" class="">16</text><title>16</title></g><g class="guides"><path d="M0.000000 328.527005 h706.000000" class="guide line" /><text x="-5" y="332.02700490998365" class="">24</text><title>24</title></g><g class="guides"><path d="M0.000000 308.887070 h706.000000" class="guide line" /><text x="-5" y="312.38707037643206" class="">32</text><title>32</title></g><g class="guides"><path d="M0.000000 289.247136 h706.000000" class="guide line" /><text x="-5" y="292.74713584288054" class="">40</text><title>40</title></g><g class="guides"><path d="M0.000000 269.607201 h706.000000" class="guide line" /><text x="-5" y="273.10720130932896" class="">48</text><title>48</title></g><g class="guides"><path d="M0.000000 249.967267 h706.000000" class="guide line" /><text x="-5" y="253.4672667757774" class="">56</text><title>56</title></g><g class="guides"><path d="M0.000000 230.327332 h706.000000" class="guide line" /><text x="-5" y="233.82733224222585" class="">64</text><title>64</title></g><g class="guides"><path d="M0.000000 210.687398 h706.000000" class="guide line" /><text x="-5" y="214.1873977086743" class="">72</text><title>72</title></g><g class="guides"><path d="M0.000000 191.047463 h706.000000" class="guide line" /><text x="-5" y="194.54746317512274" class="">80</text><title>80</title></g><g class="guides"><path d="M0.000000 171.407529 h706.000000" class="guide line" /><text x="-5" y="174.9075286415712" class="">88</text><title>88</title></g><g class="guides"><path d="M0.000000 151.767594 h706.000000" class="guide line" /><text x="-5" y="155.26759410801964" class="">96</text><title>96</title></g><g class="guides"><path d="M0.000000 132.127660 h706.000000" class="guide line" /><text x="-5" y="135.62765957446808" class="">104</text><title>104</title></g><g class="guides"><path d="M0.000000 112.487725 h706.000000" class="guide line" /><text x="-5" y="115.98772504091653" class="">112</text><title>112</title></g><g class="guides"><path d="M0.000000 92.847791 h706.000000" class="guide line" /><text x="-5" y="96.34779050736495" class="">120</text><title>120</title></g><g class="guides"><path d="M0.000000 73.207856 h706.000000" class="guide line" /><text x="-5" y="76.70785597381342" class="">128</text><title>128</title></g><g class="guides"><path d="M0.000000 53.567921 h706.000000" class="guide line" /><text x="-5" y="57.06792144026184" class="">136</text><title>136</title></g><g class="guides"><path d="M0.000000 33.927987 h706.000000" class="guide line" /><text x="-5" y="37.427986906710316" class="">144</text><title>144</title></g><g class="guides"><path d="M0.000000 14.288052 h706.000000" class="guide line" /><text x="-5" y="17.788052373158735" class="">152</text><title>152</title></g></g><g class="axis x"><path d="M0.000000 0.000000 v360.000000" class="line" /><g class="guides"><path d="M24.891026 0.000000 v360.000000" class="guide line" /><text x="24.89102564102564" y="375.0" class="backwards" transform="rotate(270 24.891026 375.000000)">simple_list_e</text></g><g class="guides"><path d="M47.519231 0.000000 v360.000000" class="guide line" /><text x="47.51923076923077" y="375.0" class="backwards" transform="rotate(270 47.519231 375.000000)">simple_tuple_e</text></g><g class="guides"><path d="M70.147436 0.000000 v360.000000" class="guide line" /><text x="70.1474358974359" y="375.0" class="backwards" transform="rotate(270 70.147436 375.000000)">simple_set_e</text></g><g class="guides"><path d="M92.775641 0.000000 v360.000000" class="guide line" /><text x="92.77564102564102" y="375.0" class="backwards" transform="rotate(270 92.775641 375.000000)">simple_tuple_d</text></g><g class="guides"><path d="M115.403846 0.000000 v360.000000" class="guide line" /><text x="115.40384615384615" y="375.0" class="backwards" transform="rotate(270 115.403846 375.000000)">simple_set_d</text></g><g class="guides"><path d="M138.032051 0.000000 v360.000000" class="guide line" /><text x="138.03205128205127" y="375.0" class="backwards" transform="rotate(270 138.032051 375.000000)">simple_dict_d</text></g><g class="guides"><path d="M160.660256 0.000000 v360.000000" class="guide line" /><text x="160.6602564102564" y="375.0" class="backwards" transform="rotate(270 160.660256 375.000000)">simple_dict_e</text></g><g class="guides"><path d="M183.288462 0.000000 v360.000000" class="guide line" /><text x="183.28846153846155" y="375.0" class="backwards" transform="rotate(270 183.288462 375.000000)">simple_list_d</text></g><g class="guides"><path d="M205.916667 0.000000 v360.000000" class="guide line" /><text x="205.91666666666666" y="375.0" class="backwards" transform="rotate(270 205.916667 375.000000)">complex_homog_list_e</text></g><g class="guides"><path d="M228.544872 0.000000 v360.000000" class="guide line" /><text x="228.5448717948718" y="375.0" class="backwards" transform="rotate(270 228.544872 375.000000)">complex_homog_tuple_d</text></g><g class="guides"><path d="M251.173077 0.000000 v360.000000" class="guide line" /><text x="251.17307692307688" y="375.0" class="backwards" transform="rotate(270 251.173077 375.000000)">complex_homog_set_d</text></g><g class="guides"><path d="M273.801282 0.000000 v360.000000" class="guide line" /><text x="273.8012820512821" y="375.0" class="backwards" transform="rotate(270 273.801282 375.000000)">complex_homog_tuple_e</text></g><g class="guides"><path d="M296.429487 0.000000 v360.000000" class="guide line" /><text x="296.4294871794872" y="375.0" class="backwards" transform="rotate(270 296.429487 375.000000)">complex_homog_set_e</text></g><g class="guides"><path d="M319.057692 0.000000 v360.000000" class="guide line" /><text x="319.05769230769226" y="375.0" class="backwards" transform="rotate(270 319.057692 375.000000)">complex_heterog_set_d</text></g><g class="guides"><path d="M341.685897 0.000000 v360.000000" class="guide line" /><text x="341.6858974358974" y="375.0" class="backwards" transform="rotate(270 341.685897 375.000000)">complex_homog_dict_d</text></g><g class="guides"><path d="M364.314103 0.000000 v360.000000" class="guide line" /><text x="364.3141025641026" y="375.0" class="backwards" transform="rotate(270 364.314103 375.000000)">complex_heterog_set_e</text></g><g class="guides"><path d="M386.942308 0.000000 v360.000000" class="guide line" /><text x="386.9423076923077" y="375.0" class="backwards" transform="rotate(270 386.942308 375.000000)">complex_homog_list_d</text></g><g class="guides"><path d="M409.570513 0.000000 v360.000000" class="guide line" /><text x="409.5705128205129" y="375.0" class="backwards" transform="rotate(270 409.570513 375.000000)">complex_heterog_tuple_d</text></g><g class="guides"><path d="M432.198718 0.000000 v360.000000" class="guide line" /><text x="432.19871794871796" y="375.0" class="backwards" transform="rotate(270 432.198718 375.000000)">complex_heterog_dict_d</text></g><g class="guides"><path d="M454.826923 0.000000 v360.000000" class="guide line" /><text x="454.8269230769231" y="375.0" class="backwards" transform="rotate(270 454.826923 375.000000)">complex_heterog_list_e</text></g><g class="guides"><path d="M477.455128 0.000000 v360.000000" class="guide line" /><text x="477.4551282051282" y="375.0" class="backwards" transform="rotate(270 477.455128 375.000000)">complex_heterog_tuple_e</text></g><g class="guides"><path d="M500.083333 0.000000 v360.000000" class="guide line" /><text x="500.08333333333337" y="375.0" class="backwards" transform="rotate(270 500.083333 375.000000)">complex_heterog_list_d</text></g><g class="guides"><path d="M522.711538 0.000000 v360.000000" class="guide line" /><text x="522.7115384615385" y="375.0" class="backwards" transform="rotate(270 522.711538 375.000000)">complex_homog_dict_e</text></g><g class="guides"><path d="M545.339744 0.000000 v360.000000" class="guide line" /><text x="545.3397435897435" y="375.0" class="backwards" transform="rotate(270 545.339744 375.000000)">simple_cls_d</text></g><g class="guides"><path d="M567.967949 0.000000 v360.000000" class="guide line" /><text x="567.9679487179487" y="375.0" class="backwards" transform="rotate(270 567.967949 375.000000)">complex_heterog_dict_e</text></g><g class="guides"><path d="M590.596154 0.000000 v360.000000" class="guide line" /><text x="590.5961538461538" y="375.0" class="backwards" transform="rotate(270 590.596154 375.000000)">simple_cls_e</text></g><g class="guides"><path d="M613.224359 0.000000 v360.000000" class="guide line" /><text x="613.224358974359" y="375.0" class="backwards" transform="rotate(270 613.224359 375.000000)">complex_cls_e</text></g><g class="guides"><path d="M635.852564 0.000000 v360.000000" class="guide line" /><text x="635.8525641025641" y="375.0" class="backwards" transform="rotate(270 635.852564 375.000000)">complex_cls_d</text></g><g class="guides"><path d="M658.480769 0.000000 v360.000000" class="guide line" /><text x="658.4807692307692" y="375.0" class="backwards" transform="rotate(270 658.480769 375.000000)">state_cls_d</text></g><g class="guides"><path d="M681.108974 0.000000 v360.000000" class="guide line" /><text x="681.1089743589743" y="375.0" class="backwards" transform="rotate(270 681.108974 375.000000)">state_cls_e</text></g></g><g class="series serie-0 color-0"><g class="boxes"><g class="box"><path stroke-width="3" d="M19.912821 350.747134 L29.869231 350.747134" class="reactive tooltip-trigger" /><path stroke-width="3" d="M14.934615 349.455807 L34.847436 349.455807" class="reactive tooltip-trigger" /><path stroke-width="3" d="M19.912821 348.135024 L29.869231 348.135024" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 350.747134 L24.891026 349.770051" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 348.135024 L24.891026 349.117019" class="reactive tooltip-trigger" /><rect x="14.934615384615384" y="349.117019143079" height="0.6530320812199761" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="351.0932901001089" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="320.4918180879605" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 14.8080
348 Q1-1.5IQR: 14.9490
349 Q1: 15.3470
350 Median: 15.4750
351 Q3: 15.6130
352 Q3+1.5IQR: 16.0130
353 Max: 27.2730</desc><desc class="x centered">24.891025641025642</desc><desc class="y centered">349.44500704680047</desc><desc class="x_label" /></g></g></g><g class="series serie-1 color-1"><g class="boxes"><g class="box"><path stroke-width="3" d="M42.541026 349.725860 L52.497436 349.725860" class="reactive tooltip-trigger" /><path stroke-width="3" d="M37.562821 348.088385 L57.475641 348.088385" class="reactive tooltip-trigger" /><path stroke-width="3" d="M42.541026 346.360062 L52.497436 346.360062" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 349.725860 L47.519231 348.498363" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 346.360062 L47.519231 347.644031" class="reactive tooltip-trigger" /><rect x="37.562820512820515" y="347.6440306993677" height="0.854332582855875" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="349.94435268354414" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="297.78314056144734" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.2760
354 Q1-1.5IQR: 15.3650
355 Q1: 15.8650
356 Median: 16.0320
357 Q3: 16.2130
358 Q3+1.5IQR: 16.7360
359 Max: 36.5230</desc><desc class="x centered">47.519230769230774</desc><desc class="y centered">348.06334020694146</desc><desc class="x_label" /></g></g></g><g class="series serie-2 color-2"><g class="boxes"><g class="box"><path stroke-width="3" d="M65.169231 349.534375 L75.125641 349.534375" class="reactive tooltip-trigger" /><path stroke-width="3" d="M60.191026 348.112928 L80.103846 348.112928" class="reactive tooltip-trigger" /><path stroke-width="3" d="M65.169231 346.657114 L75.125641 346.657114" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 349.534375 L70.147436 348.456628" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 346.657114 L70.147436 347.737317" class="reactive tooltip-trigger" /><rect x="60.19102564102564" y="347.73731716902415" height="0.719310577277497" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="349.77987555331975" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="299.06464390133533" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.3430
360 Q1-1.5IQR: 15.4430
361 Q1: 15.8820
362 Median: 16.0220
363 Q3: 16.1750
364 Q3+1.5IQR: 16.6150
365 Max: 36.0010</desc><desc class="x centered">70.1474358974359</desc><desc class="y centered">348.099672361902</desc><desc class="x_label" /></g></g></g><g class="series serie-3 color-3"><g class="boxes"><g class="box"><path stroke-width="3" d="M87.797436 346.318327 L97.753846 346.318327" class="reactive tooltip-trigger" /><path stroke-width="3" d="M82.819231 345.380523 L102.732051 345.380523" class="reactive tooltip-trigger" /><path stroke-width="3" d="M87.797436 344.415712 L97.753846 344.415712" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 346.318327 L92.775641 345.605764" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 344.415712 L92.775641 345.130110" class="reactive tooltip-trigger" /><rect x="82.81923076923077" y="345.1301099398629" height="0.4756538207496419" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="346.68413123557934" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="268.3158694723325" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.6040
366 Q1-1.5IQR: 16.7530
367 Q1: 17.0433
368 Median: 17.1350
369 Q3: 17.2370
370 Q3+1.5IQR: 17.5280
371 Max: 48.5260</desc><desc class="x centered">92.77564102564102</desc><desc class="y centered">345.37008703861204</desc><desc class="x_label" /></g></g></g><g class="series serie-4 color-4"><g class="boxes"><g class="box"><path stroke-width="3" d="M110.425641 345.027008 L120.382051 345.027008" class="reactive tooltip-trigger" /><path stroke-width="3" d="M105.447436 344.074468 L125.360256 344.074468" class="reactive tooltip-trigger" /><path stroke-width="3" d="M110.425641 343.112112 L120.382051 343.112112" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 345.027008 L115.403846 344.310145" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 343.112112 L115.403846 343.831423" class="reactive tooltip-trigger" /><rect x="105.4474358974359" y="343.83142295539676" height="0.47872169076657656" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="345.4075311289936" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="297.24058752567026" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.1240
372 Q1-1.5IQR: 17.2790
373 Q1: 17.5710
374 Median: 17.6670
375 Q3: 17.7660
376 Q3+1.5IQR: 18.0590
377 Max: 36.7440</desc><desc class="x centered">115.40384615384615</desc><desc class="y centered">344.0710311952472</desc><desc class="x_label" /></g></g></g><g class="series serie-5 color-5"><g class="boxes"><g class="box"><path stroke-width="3" d="M133.053846 344.992632 L143.010256 344.992632" class="reactive tooltip-trigger" /><path stroke-width="3" d="M128.075641 343.733224 L147.988462 343.733224" class="reactive tooltip-trigger" /><path stroke-width="3" d="M133.053846 342.306866 L143.010256 342.306866" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 344.992632 L138.032051 344.037645" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 342.306866 L138.032051 343.347789" class="reactive tooltip-trigger" /><rect x="128.07564102564103" y="343.34778910011977" height="0.6898554526315479" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="345.20622169614944" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="294.44681628840425" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.2060
378 Q1-1.5IQR: 17.2930
379 Q1: 17.6820
380 Median: 17.8060
381 Q3: 17.9630
382 Q3+1.5IQR: 18.3870
383 Max: 37.8820</desc><desc class="x centered">138.0320512820513</desc><desc class="y centered">343.683631108333</desc><desc class="x_label" /></g></g></g><g class="series serie-6 color-6"><g class="boxes"><g class="box"><path stroke-width="3" d="M155.682051 345.044192 L165.638462 345.044192" class="reactive tooltip-trigger" /><path stroke-width="3" d="M150.703846 343.117025 L170.616667 343.117025" class="reactive tooltip-trigger" /><path stroke-width="3" d="M155.682051 340.504914 L165.638462 340.504914" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 345.044192 L160.660256 343.600654" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 340.504914 L160.660256 342.363338" class="reactive tooltip-trigger" /><rect x="150.70384615384614" y="342.36333774498763" height="1.2373161873149456" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="345.044191716972" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="286.56382826937335" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.2720
384 Q1-1.5IQR: 17.2720
385 Q1: 17.8600
386 Median: 18.0570
387 Q3: 18.3640
388 Q3+1.5IQR: 19.1210
389 Max: 41.0930</desc><desc class="x centered">160.6602564102564</desc><desc class="y centered">342.92602440341165</desc><desc class="x_label" /></g></g></g><g class="series serie-7 color-7"><g class="boxes"><g class="box"><path stroke-width="3" d="M178.310256 340.900156 L188.266667 340.900156" class="reactive tooltip-trigger" /><path stroke-width="3" d="M173.332051 339.584285 L193.244872 339.584285" class="reactive tooltip-trigger" /><path stroke-width="3" d="M178.310256 338.202127 L188.266667 338.202127" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 340.900156 L183.288462 339.891161" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 338.202127 L183.288462 339.216034" class="reactive tooltip-trigger" /><rect x="173.33205128205125" y="339.21603356230446" height="0.6751278903085449" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="341.1505689834124" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="286.01636306908586" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 18.8580
390 Q1-1.5IQR: 18.9600
391 Q1: 19.3710
392 Median: 19.4960
393 Q3: 19.6460
394 Q3+1.5IQR: 20.0590
395 Max: 41.3160</desc><desc class="x centered">183.28846153846152</desc><desc class="y centered">339.55875260083224</desc><desc class="x_label" /></g></g></g><g class="series serie-8 color-8"><g class="boxes"><g class="box"><path stroke-width="3" d="M200.938462 302.717678 L210.894872 302.717678" class="reactive tooltip-trigger" /><path stroke-width="3" d="M195.960256 298.225039 L215.873077 298.225039" class="reactive tooltip-trigger" /><path stroke-width="3" d="M200.938462 293.526187 L210.894872 293.526187" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 302.717678 L205.916667 299.415712" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 293.526187 L205.916667 297.071198" class="reactive tooltip-trigger" /><rect x="195.9602564102564" y="297.07119823093547" height="2.3445136023536293" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="303.058921351317" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="208.63257052338759" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 34.3740
396 Q1-1.5IQR: 34.5130
397 Q1: 35.8580
398 Median: 36.3430
399 Q3: 36.8130
400 Q3+1.5IQR: 38.2570
401 Max: 72.8370</desc><desc class="x centered">205.91666666666666</desc><desc class="y centered">298.1911628080971</desc><desc class="x_label" /></g></g></g><g class="series serie-9 color-9"><g class="boxes"><g class="box"><path stroke-width="3" d="M223.566667 299.835514 L233.523077 299.835514" class="reactive tooltip-trigger" /><path stroke-width="3" d="M218.588462 297.463993 L238.501282 297.463993" class="reactive tooltip-trigger" /><path stroke-width="3" d="M223.566667 294.807691 L233.523077 294.807691" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 299.835514 L228.544872 297.974635" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 294.807691 L228.544872 296.707859" class="reactive tooltip-trigger" /><rect x="218.58846153846153" y="296.70785881891396" height="1.2667757775649875" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="300.0687349833008" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="204.50572715008266" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 35.5920
402 Q1-1.5IQR: 35.6870
403 Q1: 36.4450
404 Median: 36.6530
405 Q3: 36.9610
406 Q3+1.5IQR: 37.7350
407 Max: 74.5180</desc><desc class="x centered">228.5448717948718</desc><desc class="y centered">297.35793824270274</desc><desc class="x_label" /></g></g></g><g class="series serie-10 color-10"><g class="boxes"><g class="box"><path stroke-width="3" d="M246.194872 298.566291 L256.151282 298.566291" class="reactive tooltip-trigger" /><path stroke-width="3" d="M241.216667 296.091659 L261.129487 296.091659" class="reactive tooltip-trigger" /><path stroke-width="3" d="M246.194872 293.364157 L256.151282 293.364157" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 298.566291 L251.173077 296.653843" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 293.364157 L251.173077 295.337972" class="reactive tooltip-trigger" /><rect x="241.21666666666664" y="295.3379722426717" height="1.3158706290442979" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="298.8387825771474" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="203.32487852661677" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.0930
408 Q1-1.5IQR: 36.2040
409 Q1: 36.9830
410 Median: 37.2120
411 Q3: 37.5190
412 Q3+1.5IQR: 38.3230
413 Max: 74.9990</desc><desc class="x centered">251.1730769230769</desc><desc class="y centered">296.0027845875084</desc><desc class="x_label" /></g></g></g><g class="series serie-11 color-11"><g class="boxes"><g class="box"><path stroke-width="3" d="M268.823077 297.525377 L278.779487 297.525377" class="reactive tooltip-trigger" /><path stroke-width="3" d="M263.844872 294.362113 L283.757692 294.362113" class="reactive tooltip-trigger" /><path stroke-width="3" d="M268.823077 290.884613 L278.779487 290.884613" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 297.525377 L273.801282 295.140342" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 290.884613 L273.801282 293.445172" class="reactive tooltip-trigger" /><rect x="263.84487179487184" y="293.4451723574857" height="1.6951701101205572" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="297.5253769615665" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="218.19722466573953" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.6280
414 Q1-1.5IQR: 36.6280
415 Q1: 37.5995
416 Median: 37.9165
417 Q3: 38.2900
418 Q3+1.5IQR: 39.3330
419 Max: 68.9410</desc><desc class="x centered">273.8012820512821</desc><desc class="y centered">294.2715234650488</desc><desc class="x_label" /></g></g></g><g class="series serie-12 color-12"><g class="boxes"><g class="box"><path stroke-width="3" d="M291.451282 296.371527 L301.407692 296.371527" class="reactive tooltip-trigger" /><path stroke-width="3" d="M286.473077 292.404258 L306.385897 292.404258" class="reactive tooltip-trigger" /><path stroke-width="3" d="M291.451282 288.216039 L301.407692 288.216039" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 296.371527 L296.429487 293.373973" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 288.216039 L296.429487 291.311784" class="reactive tooltip-trigger" /><rect x="286.473076923077" y="291.3117835857889" height="2.062189179920722" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="296.7888738085027" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="205.4901785052148" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.9280
420 Q1-1.5IQR: 37.0980
421 Q1: 38.3190
422 Median: 38.7140
423 Q3: 39.1590
424 Q3+1.5IQR: 40.4200
425 Max: 74.1170</desc><desc class="x centered">296.42948717948724</desc><desc class="y centered">292.33551618082936</desc><desc class="x_label" /></g></g></g><g class="series serie-13 color-13"><g class="boxes"><g class="box"><path stroke-width="3" d="M314.079487 289.276593 L324.035897 289.276593" class="reactive tooltip-trigger" /><path stroke-width="3" d="M309.101282 287.275780 L329.014103 287.275780" class="reactive tooltip-trigger" /><path stroke-width="3" d="M314.079487 285.159574 L324.035897 285.159574" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 289.276593 L319.057692 287.744686" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 285.159574 L319.057692 286.711131" class="reactive tooltip-trigger" /><rect x="309.1012820512821" y="286.71113068622776" height="1.0335551378196897" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="289.5147351837228" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="215.9484446840894" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 39.8910
426 Q1-1.5IQR: 39.9880
427 Q1: 40.6120
428 Median: 40.8030
429 Q3: 41.0330
430 Q3+1.5IQR: 41.6650
431 Max: 69.8570</desc><desc class="x centered">319.0576923076924</desc><desc class="y centered">287.2335527787204</desc><desc class="x_label" /></g></g></g><g class="series serie-14 color-14"><g class="boxes"><g class="box"><path stroke-width="3" d="M336.707692 288.095745 L346.664103 288.095745" class="reactive tooltip-trigger" /><path stroke-width="3" d="M331.729487 284.481990 L351.642308 284.481990" class="reactive tooltip-trigger" /><path stroke-width="3" d="M336.707692 280.716039 L346.664103 280.716039" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 288.095745 L341.685897 285.385436" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 280.716039 L341.685897 283.519635" class="reactive tooltip-trigger" /><rect x="331.7294871794872" y="283.51963488536745" height="1.8658008427951813" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="288.2995103398923" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="185.33469226066507" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 40.3860
432 Q1-1.5IQR: 40.4690
433 Q1: 41.5730
434 Median: 41.9410
435 Q3: 42.3330
436 Q3+1.5IQR: 43.4750
437 Max: 82.3270</desc><desc class="x centered">341.68589743589746</desc><desc class="y centered">284.43976903776297</desc><desc class="x_label" /></g></g></g><g class="series serie-15 color-15"><g class="boxes"><g class="box"><path stroke-width="3" d="M359.335897 286.917343 L369.292308 286.917343" class="reactive tooltip-trigger" /><path stroke-width="3" d="M354.357692 282.829788 L374.270513 282.829788" class="reactive tooltip-trigger" /><path stroke-width="3" d="M359.335897 278.575291 L369.292308 278.575291" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 286.917343 L364.314103 283.804415" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 278.575291 L364.314103 281.717063" class="reactive tooltip-trigger" /><rect x="354.35769230769233" y="281.7170625310292" height="2.0873528590262254" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="287.02536631556177" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="225.50573057967577" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 40.9050
438 Q1-1.5IQR: 40.9490
439 Q1: 42.2170
440 Median: 42.6140
441 Q3: 43.0672
442 Q3+1.5IQR: 44.3470
443 Max: 65.9640</desc><desc class="x centered">364.3141025641026</desc><desc class="y centered">282.76878017384587</desc><desc class="x_label" /></g></g></g><g class="series serie-16 color-16"><g class="boxes"><g class="box"><path stroke-width="3" d="M381.964103 279.915714 L391.920513 279.915714" class="reactive tooltip-trigger" /><path stroke-width="3" d="M376.985897 276.036828 L396.898718 276.036828" class="reactive tooltip-trigger" /><path stroke-width="3" d="M381.964103 272.010639 L391.920513 272.010639" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 279.915714 L386.942308 276.957448" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 272.010639 L386.942308 274.981177" class="reactive tooltip-trigger" /><rect x="376.98589743589747" y="274.9811765652778" height="1.9762709570298398" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="280.13911899414717" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="136.93207193534127" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 43.7100
444 Q1-1.5IQR: 43.8010
445 Q1: 45.0060
446 Median: 45.3810
447 Q3: 45.8110
448 Q3+1.5IQR: 47.0210
449 Max: 102.0430</desc><desc class="x centered">386.94230769230774</desc><desc class="y centered">275.9803608414578</desc><desc class="x_label" /></g></g></g><g class="series serie-17 color-17"><g class="boxes"><g class="box"><path stroke-width="3" d="M404.592308 276.336336 L414.548718 276.336336" class="reactive tooltip-trigger" /><path stroke-width="3" d="M399.614103 271.914887 L419.526923 271.914887" class="reactive tooltip-trigger" /><path stroke-width="3" d="M404.592308 267.402627 L414.548718 267.402627" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 276.336336 L409.570513 272.990183" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 267.402627 L409.570513 270.756139" class="reactive tooltip-trigger" /><rect x="399.6141025641026" y="270.75613902341007" height="2.234043488118971" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="276.88133576602115" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="144.6211098370854" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 45.0370
450 Q1-1.5IQR: 45.2590
451 Q1: 46.6220
452 Median: 47.0600
453 Q3: 47.5320
454 Q3+1.5IQR: 48.8980
455 Max: 98.9110</desc><desc class="x centered">409.5705128205129</desc><desc class="y centered">271.88003422530085</desc><desc class="x_label" /></g></g></g><g class="series serie-18 color-18"><g class="boxes"><g class="box"><path stroke-width="3" d="M427.220513 272.756957 L437.176923 272.756957" class="reactive tooltip-trigger" /><path stroke-width="3" d="M422.242308 267.810149 L442.155128 267.810149" class="reactive tooltip-trigger" /><path stroke-width="3" d="M427.220513 262.630111 L437.176923 262.630111" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 272.756957 L432.198718 269.030277" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 262.630111 L432.198718 266.472173" class="reactive tooltip-trigger" /><rect x="422.24230769230775" y="266.4721733698341" height="2.5581034464737513" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="273.0196331705709" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="173.61947463324626" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 46.6100
456 Q1-1.5IQR: 46.7170
457 Q1: 48.2350
458 Median: 48.7320
459 Q3: 49.2770
460 Q3+1.5IQR: 50.8420
461 Max: 87.0990</desc><desc class="x centered">432.198717948718</desc><desc class="y centered">267.7399333665428</desc><desc class="x_label" /></g></g></g><g class="series serie-19 color-19"><g class="boxes"><g class="box"><path stroke-width="3" d="M449.848718 269.450079 L459.805128 269.450079" class="reactive tooltip-trigger" /><path stroke-width="3" d="M444.870513 264.294593 L464.783333 264.294593" class="reactive tooltip-trigger" /><path stroke-width="3" d="M449.848718 258.918166 L459.805128 258.918166" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 269.450079 L454.826923 265.578561" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 258.918166 L454.826923 262.919803" class="reactive tooltip-trigger" /><rect x="444.87051282051283" y="262.91980317041566" height="2.658758162895765" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="271.55401297362516" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="177.260228069019" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 47.2070
462 Q1-1.5IQR: 48.0640
463 Q1: 49.6410
464 Median: 50.1640
465 Q3: 50.7240
466 Q3+1.5IQR: 52.3540
467 Max: 85.6160</desc><desc class="x centered">454.8269230769231</desc><desc class="y centered">264.2322406430276</desc><desc class="x_label" /></g></g></g><g class="series serie-20 color-20"><g class="boxes"><g class="box"><path stroke-width="3" d="M472.476923 268.075290 L482.433333 268.075290" class="reactive tooltip-trigger" /><path stroke-width="3" d="M467.498718 263.285599 L487.411538 263.285599" class="reactive tooltip-trigger" /><path stroke-width="3" d="M472.476923 258.382973 L482.433333 258.382973" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 268.075290 L477.455128 264.451720" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 258.382973 L477.455128 262.026182" class="reactive tooltip-trigger" /><rect x="467.49871794871797" y="262.02618220268477" height="2.4255375231504672" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="269.4132559551627" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="178.24713550640632" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 48.0790
468 Q1-1.5IQR: 48.6240
469 Q1: 50.1000
470 Median: 50.5750
471 Q3: 51.0880
472 Q3+1.5IQR: 52.5720
473 Max: 85.2140</desc><desc class="x centered">477.45512820512823</desc><desc class="y centered">263.2443525589798</desc><desc class="x_label" /></g></g></g><g class="series serie-21 color-21"><g class="boxes"><g class="box"><path stroke-width="3" d="M495.105128 267.591656 L505.061538 267.591656" class="reactive tooltip-trigger" /><path stroke-width="3" d="M490.126923 263.094105 L510.039744 263.094105" class="reactive tooltip-trigger" /><path stroke-width="3" d="M495.105128 258.486083 L505.061538 258.486083" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 267.591656 L500.083333 264.191491" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 258.486083 L500.083333 261.913877" class="reactive tooltip-trigger" /><rect x="490.1269230769231" y="261.91387672516487" height="2.277614387326139" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="268.4091648731972" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="137.7545022425042" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 48.4880
474 Q1-1.5IQR: 48.8210
475 Q1: 50.2060
476 Median: 50.6530
477 Q3: 51.1337
478 Q3+1.5IQR: 52.5300
479 Max: 101.7080</desc><desc class="x centered">500.08333333333337</desc><desc class="y centered">263.05544232248076</desc><desc class="x_label" /></g></g></g><g class="series serie-22 color-22"><g class="boxes"><g class="box"><path stroke-width="3" d="M517.733333 262.225036 L527.689744 262.225036" class="reactive tooltip-trigger" /><path stroke-width="3" d="M512.755128 256.227497 L532.667949 256.227497" class="reactive tooltip-trigger" /><path stroke-width="3" d="M517.733333 250.188223 L527.689744 250.188223" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 262.225036 L522.711538 257.764324" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 250.188223 L522.711538 254.734860" class="reactive tooltip-trigger" /><rect x="512.7551282051282" y="254.73485993332673" height="3.0294635888808443" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="264.1522116588243" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="172.5687358508484" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 50.2220
480 Q1-1.5IQR: 51.0070
481 Q1: 52.8240
482 Median: 53.4500
483 Q3: 54.0580
484 Q3+1.5IQR: 55.9100
485 Max: 87.5270</desc><desc class="x centered">522.7115384615385</desc><desc class="y centered">256.2279878049702</desc><desc class="x_label" /></g></g></g><g class="series serie-23 color-23"><g class="boxes"><g class="box"><path stroke-width="3" d="M540.361538 255.505730 L550.317949 255.505730" class="reactive tooltip-trigger" /><path stroke-width="3" d="M535.383333 249.724220 L555.296154 249.724220" class="reactive tooltip-trigger" /><path stroke-width="3" d="M540.361538 243.606378 L550.317949 243.606378" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 255.505730 L545.339744 251.190470" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 243.606378 L545.339744 248.166526" class="reactive tooltip-trigger" /><rect x="535.3833333333333" y="248.16652566622278" height="3.0239441022128233" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="257.06218989110215" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="84.9328987236301" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 53.1100
486 Q1-1.5IQR: 53.7440
487 Q1: 55.5017
488 Median: 56.0990
489 Q3: 56.7335
490 Q3+1.5IQR: 58.5910
491 Max: 123.2240</desc><desc class="x centered">545.3397435897435</desc><desc class="y centered">249.6386647520342</desc><desc class="x_label" /></g></g></g><g class="series serie-24 color-24"><g class="boxes"><g class="box"><path stroke-width="3" d="M562.989744 253.414077 L572.946154 253.414077" class="reactive tooltip-trigger" /><path stroke-width="3" d="M558.011538 247.477905 L577.924359 247.477905" class="reactive tooltip-trigger" /><path stroke-width="3" d="M562.989744 241.497541 L572.946154 241.497541" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 253.414077 L567.967949 248.955806" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 241.497541 L567.967949 245.977909" class="reactive tooltip-trigger" /><rect x="558.0115384615385" y="245.97790853581472" height="2.977897025532002" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="254.99754462892616" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="157.17348533399013" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 53.9510
492 Q1-1.5IQR: 54.5960
493 Q1: 56.4120
494 Median: 57.0140
495 Q3: 57.6250
496 Q3+1.5IQR: 59.4500
497 Max: 93.7980</desc><desc class="x centered">567.9679487179487</desc><desc class="y centered">247.46464746767185</desc><desc class="x_label" /></g></g></g><g class="series serie-25 color-25"><g class="boxes"><g class="box"><path stroke-width="3" d="M585.617949 244.288865 L595.574359 244.288865" class="reactive tooltip-trigger" /><path stroke-width="3" d="M580.639744 238.318326 L600.552564 238.318326" class="reactive tooltip-trigger" /><path stroke-width="3" d="M585.617949 231.837153 L595.574359 231.837153" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 244.288865 L590.596154 239.709085" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 231.837153 L590.596154 236.563013" class="reactive tooltip-trigger" /><rect x="580.6397435897436" y="236.5630128925724" height="3.146071675951447" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="244.72340423831753" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="167.2659649497962" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 58.1360
498 Q1-1.5IQR: 58.3130
499 Q1: 60.1785
500 Median: 60.7450
501 Q3: 61.4600
502 Q3+1.5IQR: 63.3850
503 Max: 89.6870</desc><desc class="x centered">590.5961538461538</desc><desc class="y centered">238.14328836791563</desc><desc class="x_label" /></g></g></g><g class="series serie-26 color-26"><g class="boxes"><g class="box"><path stroke-width="3" d="M608.246154 44.926355 L618.202564 44.926355" class="reactive tooltip-trigger" /><path stroke-width="3" d="M603.267949 37.608025 L623.180769 37.608025" class="reactive tooltip-trigger" /><path stroke-width="3" d="M608.246154 29.963179 L618.202564 29.963179" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 44.926355 L613.224359 39.400170" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 29.963179 L613.224359 35.629289" class="reactive tooltip-trigger" /><rect x="603.2679487179488" y="35.62928918380982" height="3.770881139257199" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="47.499177474848636" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="-121.4042506026068" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 138.4720
504 Q1-1.5IQR: 139.5200
505 Q1: 141.7710
506 Median: 142.5010
507 Q3: 143.3070
508 Q3+1.5IQR: 145.6150
509 Max: 207.2720</desc><desc class="x centered">613.224358974359</desc><desc class="y centered">37.505403785835256</desc><desc class="x_label" /></g></g></g><g class="series serie-27 color-27"><g class="boxes"><g class="box"><path stroke-width="3" d="M630.874359 43.858424 L640.830769 43.858424" class="reactive tooltip-trigger" /><path stroke-width="3" d="M625.896154 36.694764 L645.808974 36.694764" class="reactive tooltip-trigger" /><path stroke-width="3" d="M630.874359 29.305235 L640.830769 29.305235" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 43.858424 L635.852564 38.455604" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 29.305235 L635.852564 34.816699" class="reactive tooltip-trigger" /><rect x="625.8961538461539" y="34.81669883528201" height="3.638904675675235" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="46.38461627864848" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="-101.24631720701001" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 138.9260
510 Q1-1.5IQR: 139.9550
511 Q1: 142.1558
512 Median: 142.8730
513 Q3: 143.6380
514 Q3+1.5IQR: 145.8830
515 Max: 199.0610</desc><desc class="x centered">635.8525641025641</desc><desc class="y centered">36.626145094011974</desc><desc class="x_label" /></g></g></g><g class="series serie-28 color-28"><g class="boxes"><g class="box"><path stroke-width="3" d="M653.502564 29.140757 L663.458974 29.140757" class="reactive tooltip-trigger" /><path stroke-width="3" d="M648.524359 21.678804 L668.437179 21.678804" class="reactive tooltip-trigger" /><path stroke-width="3" d="M653.502564 13.990999 L663.458974 13.990999" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 29.140757 L658.480769 23.540917" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 13.990999 L658.480769 19.746725" class="reactive tooltip-trigger" /><rect x="648.524358974359" y="19.74672515389591" height="3.7941915926610363" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="30.098200876314536" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="-238.5662869306483" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 145.5600
516 Q1-1.5IQR: 145.9500
517 Q1: 148.2310
518 Median: 148.9895
519 Q3: 149.7765
520 Q3+1.5IQR: 152.1210
521 Max: 254.9960</desc><desc class="x centered">658.4807692307692</desc><desc class="y centered">21.619640597143814</desc><desc class="x_label" /></g></g></g><g class="series serie-29 color-29"><g class="boxes"><g class="box"><path stroke-width="3" d="M676.130769 22.576105 L686.087179 22.576105" class="reactive tooltip-trigger" /><path stroke-width="3" d="M671.152564 15.171848 L691.065385 15.171848" class="reactive tooltip-trigger" /><path stroke-width="3" d="M676.130769 7.274141 L686.087179 7.274141" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 22.576105 L681.108974 17.029052" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 7.274141 L681.108974 13.129298" class="reactive tooltip-trigger" /><rect x="671.1525641025642" y="13.129298268114667" height="3.8997540079894293" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="23.160393689957232" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="-92.4279905467427" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 148.3860
522 Q1-1.5IQR: 148.6240
523 Q1: 150.8835
524 Median: 151.6400
525 Q3: 152.4720
526 Q3+1.5IQR: 154.8570
527 Max: 195.4690</desc><desc class="x centered">681.1089743589744</desc><desc class="y centered">15.036088890947042</desc><desc class="x_label" /></g></g></g></g><g class="titles"><text x="400.0" y="26" class="title plot_title">Speed in Microseconds (us)</text><text x="427.0" y="580.0" class="title">Trial</text><text x="0" y="252.0" class="title" transform="rotate(-90 0.000000 226.000000)">Duration</text></g><g transform="translate(74, 46)" class="plot overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot text-overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot tooltip-overlay"><g transform="translate(0 0)" style="opacity: 0" class="tooltip"><rect rx="0" ry="0" width="0" height="0" class="tooltip-box" /><g class="text" /></g></g></g></svg>
0 <?xml version='1.0' encoding='utf-8'?>
1 <svg xmlns="http://www.w3.org/2000/svg" id="chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7" class="pygal-chart" viewBox="0 0 800 600"><!--Generated with pygal 3.0.0 (etree) ©Kozea 2012-2016 on 2022-06-20--><!--http://pygal.org--><!--http://github.com/Kozea/pygal--><defs><style type="text/css">#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .title{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .legends .legend text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis text.major{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay text.value{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay text.label{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 text.no_data{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:64px}
2 #chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7{background-color:rgba(249,249,249,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 path,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 rect,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .graph &gt; .background{fill:rgba(249,249,249,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .plot &gt; .background{fill:rgba(255,255,255,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .graph{fill:rgba(0,0,0,.87)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 text.no_data{fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .title{fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .legends .legend text{fill:rgba(0,0,0,.87)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .line{stroke:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis text.major{fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y .guides:hover .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .line-graph .axis.x .guides:hover .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .stackedline-graph .axis.x .guides:hover .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .reactive{fill-opacity:.7;stroke-opacity:.8;stroke-width:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .ci{stroke:rgba(0,0,0,.87)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .reactive.active,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .ci .reactive.active{stroke-width:1.5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .series text{fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip .value{font-size:1.5em}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .bound{font-size:.5em}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-0,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-0 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-1,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-2,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-2 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-3,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-3 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-4,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-4 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-5,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-5 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-6,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-6 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-7,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-7 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-8,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-8 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-9,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-9 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-10,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-10 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-11,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-11 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-12,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-12 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-13,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-13 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-14,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-14 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-15,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-15 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-16,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-16 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-17,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-17 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-18,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-18 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-19,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-19 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-20,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-20 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-21,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-21 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-22,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-22 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-23,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-23 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-24,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-24 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-25,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-25 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-26,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-26 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-27,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-27 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-28,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-28 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-29,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .color-29 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-0 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-1 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-2 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-3 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-4 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-5 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-6 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-7 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-8 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-9 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-10 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-11 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-12 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-13 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-14 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-15 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-16 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-17 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-18 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-19 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-20 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-21 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-22 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-23 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-24 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-25 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-26 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-27 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-28 text{fill:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .text-overlay .color-29 text{fill:black}
3 #chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 text.no_data{text-anchor:middle}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .guide.line{fill:none}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .centered{text-anchor:middle}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .title{text-anchor:middle}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .legends .legend text{fill-opacity:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.x text{text-anchor:middle}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.x:not(.web) text[transform]{text-anchor:start}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y text{text-anchor:end}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y text[transform].backwards{text-anchor:start}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y2 text{text-anchor:start}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y2 text[transform].backwards{text-anchor:end}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .guide.line{stroke-dasharray:4,4;stroke:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .major.guide.line{stroke-dasharray:6,6;stroke:black}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .horizontal .axis.y .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .horizontal .axis.y2 .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .vertical .axis.x .guide.line{opacity:0}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .horizontal .axis.always_show .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y .guides:hover .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.y2 .guides:hover .guide.line,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis.x .guides:hover .guide.line{opacity:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .axis .guides:hover text{opacity:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .nofill{fill:none}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .subtle-fill{fill-opacity:.2}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .dot{stroke-width:1px;fill-opacity:1;stroke-opacity:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .dot.active{stroke-width:5px}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .dot.negative{fill:transparent}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 text,#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 tspan{stroke:none !important}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .series text.active{opacity:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .tooltip text{fill-opacity:1}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .showable{visibility:hidden}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .showable.shown{visibility:visible}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-8f9f7849-cd2f-4204-bbbe-15c3a18b94d7 .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}
4 .tooltip .value{font-size:1em !important}.axis text{font-size:9px !important}</style><script type="text/javascript">window.pygal = window.pygal || {};window.pygal.config = window.pygal.config || {};window.pygal.config['8f9f7849-cd2f-4204-bbbe-15c3a18b94d7'] = {"allow_interruptions": false, "box_mode": "tukey", "classes": ["pygal-chart"], "css": ["file://style.css", "file://graph.css", "inline:\n .tooltip .value {\n font-size: 1em !important;\n }\n .axis text {\n font-size: 9px !important;\n }\n "], "defs": [], "disable_xml_declaration": false, "dots_size": 2.5, "dynamic_print_values": false, "explicit_size": false, "fill": false, "force_uri_protocol": "https", "formatter": null, "half_pie": false, "height": 600, "include_x_axis": false, "inner_radius": 0, "interpolate": null, "interpolation_parameters": {}, "interpolation_precision": 250, "inverse_y_axis": false, "js": ["file:///home/theel/.pyenv/versions/3.9.13/lib/python3.9/site-packages/pygaljs/static/2.0.x/pygal-tooltips.js"], "legend_at_bottom": false, "legend_at_bottom_columns": null, "legend_box_size": 12, "logarithmic": false, "margin": 20, "margin_bottom": null, "margin_left": null, "margin_right": null, "margin_top": null, "max_scale": 20, "min_scale": 20, "missing_value_fill_truncation": "x", "no_data_text": "No data", "no_prefix": false, "order_min": null, "pretty_print": false, "print_labels": false, "print_values": false, "print_values_position": "center", "print_zeroes": true, "range": [15, 269], "rounded_bars": null, "secondary_range": null, "show_dots": true, "show_legend": false, "show_minor_x_labels": true, "show_minor_y_labels": true, "show_only_major_dots": false, "show_x_guides": false, "show_x_labels": true, "show_y_guides": true, "show_y_labels": true, "spacing": 10, "stack_from_top": false, "strict": false, "stroke": true, "stroke_style": null, "style": {"background": "rgba(249, 249, 249, 1)", "ci_colors": [], "colors": ["#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5"], "dot_opacity": "1", "font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "foreground": "rgba(0, 0, 0, .87)", "foreground_strong": "rgba(0, 0, 0, 1)", "foreground_subtle": "rgba(0, 0, 0, .54)", "guide_stroke_color": "black", "guide_stroke_dasharray": "4,4", "label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "label_font_size": 10, "legend_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "legend_font_size": 14, "major_guide_stroke_color": "black", "major_guide_stroke_dasharray": "6,6", "major_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "major_label_font_size": 10, "no_data_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "no_data_font_size": 64, "opacity": ".7", "opacity_hover": ".8", "plot_background": "rgba(255, 255, 255, 1)", "stroke_opacity": ".8", "stroke_opacity_hover": ".9", "stroke_width": "1", "stroke_width_hover": "4", "title_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "title_font_size": 16, "tooltip_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "tooltip_font_size": 14, "transition": "150ms", "value_background": "rgba(229, 229, 229, 1)", "value_colors": [], "value_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_font_size": 16, "value_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_label_font_size": 10}, "title": "Speed in Microseconds (us)", "tooltip_border_radius": 0, "tooltip_fancy_mode": true, "truncate_label": 50, "truncate_legend": null, "width": 800, "x_label_rotation": 270, "x_labels": ["simple_list_e", "simple_dict_d", "simple_tuple_e", "simple_set_e", "simple_tuple_d", "simple_dict_e", "simple_set_d", "simple_list_d", "complex_homog_dict_d", "complex_homog_tuple_d", "complex_homog_set_d", "complex_homog_list_e", "complex_heterog_set_d", "complex_homog_tuple_e", "complex_homog_set_e", "complex_heterog_dict_d", "complex_homog_list_d", "complex_heterog_tuple_d", "complex_heterog_set_e", "complex_heterog_list_d", "complex_homog_dict_e", "simple_cls_d", "complex_heterog_list_e", "complex_heterog_tuple_e", "complex_heterog_dict_e", "simple_cls_e", "complex_cls_d", "state_cls_d", "complex_cls_e", "state_cls_e"], "x_labels_major": null, "x_labels_major_count": null, "x_labels_major_every": null, "x_title": "Trial", "xrange": null, "y_label_rotation": 0, "y_labels": null, "y_labels_major": null, "y_labels_major_count": null, "y_labels_major_every": null, "y_title": "Duration", "zero": 15, "legends": ["jsonpickle_benchmarks.py::simple_list_e - 14108 rounds", "jsonpickle_benchmarks.py::simple_dict_d - 14121 rounds", "jsonpickle_benchmarks.py::simple_tuple_e - 15463 rounds", "jsonpickle_benchmarks.py::simple_set_e - 15102 rounds", "jsonpickle_benchmarks.py::simple_tuple_d - 15101 rounds", "jsonpickle_benchmarks.py::simple_dict_e - 7215 rounds", "jsonpickle_benchmarks.py::simple_set_d - 14699 rounds", "jsonpickle_benchmarks.py::simple_list_d - 12255 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_d - 10336 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_d - 12163 rounds", "jsonpickle_benchmarks.py::complex_homog_set_d - 11444 rounds", "jsonpickle_benchmarks.py::complex_homog_list_e - 718 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_d - 9036 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_e - 8484 rounds", "jsonpickle_benchmarks.py::complex_homog_set_e - 9909 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_d - 9757 rounds", "jsonpickle_benchmarks.py::complex_homog_list_d - 10957 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_d - 9166 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_e - 8286 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_d - 9015 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_e - 8195 rounds", "jsonpickle_benchmarks.py::simple_cls_d - 7972 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_e - 6428 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_e - 6701 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_e - 7204 rounds", "jsonpickle_benchmarks.py::simple_cls_e - 5783 rounds", "jsonpickle_benchmarks.py::complex_cls_d - 3008 rounds", "jsonpickle_benchmarks.py::state_cls_d - 3015 rounds", "jsonpickle_benchmarks.py::complex_cls_e - 2652 rounds", "jsonpickle_benchmarks.py::state_cls_e - 2718 rounds"]}</script><script type="text/javascript">(function() {
5 var $, get_translation, init, init_svg, matches, padding, r_translation, sibl, svg_ns, tooltip_timeout, xlink_ns;
6
7 svg_ns = 'http://www.w3.org/2000/svg';
8
9 xlink_ns = 'http://www.w3.org/1999/xlink';
10
11 $ = function(sel, ctx) {
12 if (ctx == null) {
13 ctx = null;
14 }
15 ctx = ctx || document;
16 return Array.prototype.slice.call(ctx.querySelectorAll(sel), 0).filter(function(e) {
17 return e !== ctx;
18 });
19 };
20
21 matches = function(el, selector) {
22 return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
23 };
24
25 sibl = function(el, match) {
26 if (match == null) {
27 match = null;
28 }
29 return Array.prototype.filter.call(el.parentElement.children, function(child) {
30 return child !== el &amp;&amp; (!match || matches(child, match));
31 });
32 };
33
34 Array.prototype.one = function() {
35 return this.length &gt; 0 &amp;&amp; this[0] || {};
36 };
37
38 padding = 5;
39
40 tooltip_timeout = null;
41
42 r_translation = /translate\((\d+)[ ,]+(\d+)\)/;
43
44 get_translation = function(el) {
45 return (r_translation.exec(el.getAttribute('transform')) || []).slice(1).map(function(x) {
46 return +x;
47 });
48 };
49
50 init = function(ctx) {
51 var bbox, box, config, el, graph, inner_svg, num, parent, tooltip, tooltip_el, tt, uid, untooltip, xconvert, yconvert, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
52 if ($('svg', ctx).length) {
53 inner_svg = $('svg', ctx).one();
54 parent = inner_svg.parentElement;
55 box = inner_svg.viewBox.baseVal;
56 bbox = parent.getBBox();
57 xconvert = function(x) {
58 return ((x - box.x) / box.width) * bbox.width;
59 };
60 yconvert = function(y) {
61 return ((y - box.y) / box.height) * bbox.height;
62 };
63 } else {
64 xconvert = yconvert = function(x) {
65 return x;
66 };
67 }
68 if (((_ref = window.pygal) != null ? _ref.config : void 0) != null) {
69 if (window.pygal.config.no_prefix != null) {
70 config = window.pygal.config;
71 } else {
72 uid = ctx.id.replace('chart-', '');
73 config = window.pygal.config[uid];
74 }
75 } else {
76 config = window.config;
77 }
78 tooltip_el = null;
79 graph = $('.graph').one();
80 tt = $('.tooltip', ctx).one();
81 _ref1 = $('.reactive', ctx);
82 for (_i = 0, _len = _ref1.length; _i &lt; _len; _i++) {
83 el = _ref1[_i];
84 el.addEventListener('mouseenter', (function(el) {
85 return function() {
86 return el.classList.add('active');
87 };
88 })(el));
89 el.addEventListener('mouseleave', (function(el) {
90 return function() {
91 return el.classList.remove('active');
92 };
93 })(el));
94 }
95 _ref2 = $('.activate-serie', ctx);
96 for (_j = 0, _len1 = _ref2.length; _j &lt; _len1; _j++) {
97 el = _ref2[_j];
98 num = el.id.replace('activate-serie-', '');
99 el.addEventListener('mouseenter', (function(num) {
100 return function() {
101 var re, _k, _len2, _ref3, _results;
102 _ref3 = $('.serie-' + num + ' .reactive', ctx);
103 _results = [];
104 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
105 re = _ref3[_k];
106 _results.push(re.classList.add('active'));
107 }
108 return _results;
109 };
110 })(num));
111 el.addEventListener('mouseleave', (function(num) {
112 return function() {
113 var re, _k, _len2, _ref3, _results;
114 _ref3 = $('.serie-' + num + ' .reactive', ctx);
115 _results = [];
116 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
117 re = _ref3[_k];
118 _results.push(re.classList.remove('active'));
119 }
120 return _results;
121 };
122 })(num));
123 el.addEventListener('click', (function(el, num) {
124 return function() {
125 var ov, re, rect, show, _k, _l, _len2, _len3, _ref3, _ref4, _results;
126 rect = $('rect', el).one();
127 show = rect.style.fill !== '';
128 rect.style.fill = show ? '' : 'transparent';
129 _ref3 = $('.serie-' + num + ' .reactive', ctx);
130 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
131 re = _ref3[_k];
132 re.style.display = show ? '' : 'none';
133 }
134 _ref4 = $('.text-overlay .serie-' + num, ctx);
135 _results = [];
136 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
137 ov = _ref4[_l];
138 _results.push(ov.style.display = show ? '' : 'none');
139 }
140 return _results;
141 };
142 })(el, num));
143 }
144 _ref3 = $('.tooltip-trigger', ctx);
145 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
146 el = _ref3[_k];
147 el.addEventListener('mouseenter', (function(el) {
148 return function() {
149 return tooltip_el = tooltip(el);
150 };
151 })(el));
152 }
153 tt.addEventListener('mouseenter', function() {
154 return tooltip_el != null ? tooltip_el.classList.add('active') : void 0;
155 });
156 tt.addEventListener('mouseleave', function() {
157 return tooltip_el != null ? tooltip_el.classList.remove('active') : void 0;
158 });
159 ctx.addEventListener('mouseleave', function() {
160 if (tooltip_timeout) {
161 clearTimeout(tooltip_timeout);
162 }
163 return untooltip(0);
164 });
165 graph.addEventListener('mousemove', function(el) {
166 if (tooltip_timeout) {
167 return;
168 }
169 if (!matches(el.target, '.background')) {
170 return;
171 }
172 return untooltip(1000);
173 });
174 tooltip = function(el) {
175 var a, baseline, cls, current_x, current_y, dy, h, i, key, keys, label, legend, name, plot_x, plot_y, rect, serie_index, subval, text, text_group, texts, traversal, value, w, x, x_elt, x_label, xlink, y, y_elt, _l, _len3, _len4, _len5, _m, _n, _ref4, _ref5, _ref6, _ref7, _ref8;
176 clearTimeout(tooltip_timeout);
177 tooltip_timeout = null;
178 tt.style.opacity = 1;
179 tt.style.display = '';
180 text_group = $('g.text', tt).one();
181 rect = $('rect', tt).one();
182 text_group.innerHTML = '';
183 label = sibl(el, '.label').one().textContent;
184 x_label = sibl(el, '.x_label').one().textContent;
185 value = sibl(el, '.value').one().textContent;
186 xlink = sibl(el, '.xlink').one().textContent;
187 serie_index = null;
188 parent = el;
189 traversal = [];
190 while (parent) {
191 traversal.push(parent);
192 if (parent.classList.contains('series')) {
193 break;
194 }
195 parent = parent.parentElement;
196 }
197 if (parent) {
198 _ref4 = parent.classList;
199 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
200 cls = _ref4[_l];
201 if (cls.indexOf('serie-') === 0) {
202 serie_index = +cls.replace('serie-', '');
203 break;
204 }
205 }
206 }
207 legend = null;
208 if (serie_index !== null) {
209 legend = config.legends[serie_index];
210 }
211 dy = 0;
212 keys = [[label, 'label']];
213 _ref5 = value.split('\n');
214 for (i = _m = 0, _len4 = _ref5.length; _m &lt; _len4; i = ++_m) {
215 subval = _ref5[i];
216 keys.push([subval, 'value-' + i]);
217 }
218 if (config.tooltip_fancy_mode) {
219 keys.push([xlink, 'xlink']);
220 keys.unshift([x_label, 'x_label']);
221 keys.unshift([legend, 'legend']);
222 }
223 texts = {};
224 for (_n = 0, _len5 = keys.length; _n &lt; _len5; _n++) {
225 _ref6 = keys[_n], key = _ref6[0], name = _ref6[1];
226 if (key) {
227 text = document.createElementNS(svg_ns, 'text');
228 text.textContent = key;
229 text.setAttribute('x', padding);
230 text.setAttribute('dy', dy);
231 text.classList.add(name.indexOf('value') === 0 ? 'value' : name);
232 if (name.indexOf('value') === 0 &amp;&amp; config.tooltip_fancy_mode) {
233 text.classList.add('color-' + serie_index);
234 }
235 if (name === 'xlink') {
236 a = document.createElementNS(svg_ns, 'a');
237 a.setAttributeNS(xlink_ns, 'href', key);
238 a.textContent = void 0;
239 a.appendChild(text);
240 text.textContent = 'Link &gt;';
241 text_group.appendChild(a);
242 } else {
243 text_group.appendChild(text);
244 }
245 dy += text.getBBox().height + padding / 2;
246 baseline = padding;
247 if (text.style.dominantBaseline !== void 0) {
248 text.style.dominantBaseline = 'text-before-edge';
249 } else {
250 baseline += text.getBBox().height * .8;
251 }
252 text.setAttribute('y', baseline);
253 texts[name] = text;
254 }
255 }
256 w = text_group.getBBox().width + 2 * padding;
257 h = text_group.getBBox().height + 2 * padding;
258 rect.setAttribute('width', w);
259 rect.setAttribute('height', h);
260 if (texts.value) {
261 texts.value.setAttribute('dx', (w - texts.value.getBBox().width) / 2 - padding);
262 }
263 if (texts.x_label) {
264 texts.x_label.setAttribute('dx', w - texts.x_label.getBBox().width - 2 * padding);
265 }
266 if (texts.xlink) {
267 texts.xlink.setAttribute('dx', w - texts.xlink.getBBox().width - 2 * padding);
268 }
269 x_elt = sibl(el, '.x').one();
270 y_elt = sibl(el, '.y').one();
271 x = parseInt(x_elt.textContent);
272 if (x_elt.classList.contains('centered')) {
273 x -= w / 2;
274 } else if (x_elt.classList.contains('left')) {
275 x -= w;
276 } else if (x_elt.classList.contains('auto')) {
277 x = xconvert(el.getBBox().x + el.getBBox().width / 2) - w / 2;
278 }
279 y = parseInt(y_elt.textContent);
280 if (y_elt.classList.contains('centered')) {
281 y -= h / 2;
282 } else if (y_elt.classList.contains('top')) {
283 y -= h;
284 } else if (y_elt.classList.contains('auto')) {
285 y = yconvert(el.getBBox().y + el.getBBox().height / 2) - h / 2;
286 }
287 _ref7 = get_translation(tt.parentElement), plot_x = _ref7[0], plot_y = _ref7[1];
288 if (x + w + plot_x &gt; config.width) {
289 x = config.width - w - plot_x;
290 }
291 if (y + h + plot_y &gt; config.height) {
292 y = config.height - h - plot_y;
293 }
294 if (x + plot_x &lt; 0) {
295 x = -plot_x;
296 }
297 if (y + plot_y &lt; 0) {
298 y = -plot_y;
299 }
300 _ref8 = get_translation(tt), current_x = _ref8[0], current_y = _ref8[1];
301 if (current_x === x &amp;&amp; current_y === y) {
302 return el;
303 }
304 tt.setAttribute('transform', "translate(" + x + " " + y + ")");
305 return el;
306 };
307 return untooltip = function(ms) {
308 return tooltip_timeout = setTimeout(function() {
309 tt.style.display = 'none';
310 tt.style.opacity = 0;
311 if (tooltip_el != null) {
312 tooltip_el.classList.remove('active');
313 }
314 return tooltip_timeout = null;
315 }, ms);
316 };
317 };
318
319 init_svg = function() {
320 var chart, charts, _i, _len, _results;
321 charts = $('.pygal-chart');
322 if (charts.length) {
323 _results = [];
324 for (_i = 0, _len = charts.length; _i &lt; _len; _i++) {
325 chart = charts[_i];
326 _results.push(init(chart));
327 }
328 return _results;
329 }
330 };
331
332 if (document.readyState !== 'loading') {
333 init_svg();
334 } else {
335 document.addEventListener('DOMContentLoaded', function() {
336 return init_svg();
337 });
338 }
339
340 window.pygal = window.pygal || {};
341
342 window.pygal.init = init;
343
344 window.pygal.init_svg = init_svg;
345
346 }).call(this);
347 </script></defs><title>Speed in Microseconds (us)</title><g class="graph custombox-graph vertical"><rect x="0" y="0" width="800" height="600" class="background" /><g transform="translate(74, 46)" class="plot"><rect x="0" y="0" width="706.0" height="360.0" class="background" /><g class="axis y always_show"><path d="M0.000000 360.000000 h706.000000" class="line" /><g class="guides"><path d="M0.000000 346.262871 h706.000000" class="guide line" /><text x="-5" y="349.76287098728045" class="">20</text><title>20</title></g><g class="guides"><path d="M0.000000 319.006663 h706.000000" class="guide line" /><text x="-5" y="322.5066626287099" class="">40</text><title>40</title></g><g class="guides"><path d="M0.000000 291.750454 h706.000000" class="guide line" /><text x="-5" y="295.2504542701393" class="">60</text><title>60</title></g><g class="guides"><path d="M0.000000 264.494246 h706.000000" class="guide line" /><text x="-5" y="267.9942459115687" class="">80</text><title>80</title></g><g class="guides"><path d="M0.000000 237.238038 h706.000000" class="major guide line" /><text x="-5" y="240.73803755299815" class="major">100</text><title>100</title></g><g class="guides"><path d="M0.000000 209.981829 h706.000000" class="guide line" /><text x="-5" y="213.4818291944276" class="">120</text><title>120</title></g><g class="guides"><path d="M0.000000 182.725621 h706.000000" class="guide line" /><text x="-5" y="186.22562083585703" class="">140</text><title>140</title></g><g class="guides"><path d="M0.000000 155.469412 h706.000000" class="guide line" /><text x="-5" y="158.96941247728645" class="">160</text><title>160</title></g><g class="guides"><path d="M0.000000 128.213204 h706.000000" class="guide line" /><text x="-5" y="131.71320411871588" class="">180</text><title>180</title></g><g class="guides"><path d="M0.000000 100.956996 h706.000000" class="major guide line" /><text x="-5" y="104.45699576014533" class="major">200</text><title>200</title></g><g class="guides"><path d="M0.000000 73.700787 h706.000000" class="guide line" /><text x="-5" y="77.20078740157476" class="">220</text><title>220</title></g><g class="guides"><path d="M0.000000 46.444579 h706.000000" class="guide line" /><text x="-5" y="49.94457904300418" class="">240</text><title>240</title></g><g class="guides"><path d="M0.000000 19.188371 h706.000000" class="guide line" /><text x="-5" y="22.688370684433607" class="">260</text><title>260</title></g></g><g class="axis x"><path d="M0.000000 0.000000 v360.000000" class="line" /><g class="guides"><path d="M24.891026 0.000000 v360.000000" class="guide line" /><text x="24.89102564102564" y="375.0" class="backwards" transform="rotate(270 24.891026 375.000000)">simple_list_e</text></g><g class="guides"><path d="M47.519231 0.000000 v360.000000" class="guide line" /><text x="47.51923076923077" y="375.0" class="backwards" transform="rotate(270 47.519231 375.000000)">simple_dict_d</text></g><g class="guides"><path d="M70.147436 0.000000 v360.000000" class="guide line" /><text x="70.1474358974359" y="375.0" class="backwards" transform="rotate(270 70.147436 375.000000)">simple_tuple_e</text></g><g class="guides"><path d="M92.775641 0.000000 v360.000000" class="guide line" /><text x="92.77564102564102" y="375.0" class="backwards" transform="rotate(270 92.775641 375.000000)">simple_set_e</text></g><g class="guides"><path d="M115.403846 0.000000 v360.000000" class="guide line" /><text x="115.40384615384615" y="375.0" class="backwards" transform="rotate(270 115.403846 375.000000)">simple_tuple_d</text></g><g class="guides"><path d="M138.032051 0.000000 v360.000000" class="guide line" /><text x="138.03205128205127" y="375.0" class="backwards" transform="rotate(270 138.032051 375.000000)">simple_dict_e</text></g><g class="guides"><path d="M160.660256 0.000000 v360.000000" class="guide line" /><text x="160.6602564102564" y="375.0" class="backwards" transform="rotate(270 160.660256 375.000000)">simple_set_d</text></g><g class="guides"><path d="M183.288462 0.000000 v360.000000" class="guide line" /><text x="183.28846153846155" y="375.0" class="backwards" transform="rotate(270 183.288462 375.000000)">simple_list_d</text></g><g class="guides"><path d="M205.916667 0.000000 v360.000000" class="guide line" /><text x="205.91666666666666" y="375.0" class="backwards" transform="rotate(270 205.916667 375.000000)">complex_homog_dict_d</text></g><g class="guides"><path d="M228.544872 0.000000 v360.000000" class="guide line" /><text x="228.5448717948718" y="375.0" class="backwards" transform="rotate(270 228.544872 375.000000)">complex_homog_tuple_d</text></g><g class="guides"><path d="M251.173077 0.000000 v360.000000" class="guide line" /><text x="251.17307692307688" y="375.0" class="backwards" transform="rotate(270 251.173077 375.000000)">complex_homog_set_d</text></g><g class="guides"><path d="M273.801282 0.000000 v360.000000" class="guide line" /><text x="273.8012820512821" y="375.0" class="backwards" transform="rotate(270 273.801282 375.000000)">complex_homog_list_e</text></g><g class="guides"><path d="M296.429487 0.000000 v360.000000" class="guide line" /><text x="296.4294871794872" y="375.0" class="backwards" transform="rotate(270 296.429487 375.000000)">complex_heterog_set_d</text></g><g class="guides"><path d="M319.057692 0.000000 v360.000000" class="guide line" /><text x="319.05769230769226" y="375.0" class="backwards" transform="rotate(270 319.057692 375.000000)">complex_homog_tuple_e</text></g><g class="guides"><path d="M341.685897 0.000000 v360.000000" class="guide line" /><text x="341.6858974358974" y="375.0" class="backwards" transform="rotate(270 341.685897 375.000000)">complex_homog_set_e</text></g><g class="guides"><path d="M364.314103 0.000000 v360.000000" class="guide line" /><text x="364.3141025641026" y="375.0" class="backwards" transform="rotate(270 364.314103 375.000000)">complex_heterog_dict_d</text></g><g class="guides"><path d="M386.942308 0.000000 v360.000000" class="guide line" /><text x="386.9423076923077" y="375.0" class="backwards" transform="rotate(270 386.942308 375.000000)">complex_homog_list_d</text></g><g class="guides"><path d="M409.570513 0.000000 v360.000000" class="guide line" /><text x="409.5705128205129" y="375.0" class="backwards" transform="rotate(270 409.570513 375.000000)">complex_heterog_tuple_d</text></g><g class="guides"><path d="M432.198718 0.000000 v360.000000" class="guide line" /><text x="432.19871794871796" y="375.0" class="backwards" transform="rotate(270 432.198718 375.000000)">complex_heterog_set_e</text></g><g class="guides"><path d="M454.826923 0.000000 v360.000000" class="guide line" /><text x="454.8269230769231" y="375.0" class="backwards" transform="rotate(270 454.826923 375.000000)">complex_heterog_list_d</text></g><g class="guides"><path d="M477.455128 0.000000 v360.000000" class="guide line" /><text x="477.4551282051282" y="375.0" class="backwards" transform="rotate(270 477.455128 375.000000)">complex_homog_dict_e</text></g><g class="guides"><path d="M500.083333 0.000000 v360.000000" class="guide line" /><text x="500.08333333333337" y="375.0" class="backwards" transform="rotate(270 500.083333 375.000000)">simple_cls_d</text></g><g class="guides"><path d="M522.711538 0.000000 v360.000000" class="guide line" /><text x="522.7115384615385" y="375.0" class="backwards" transform="rotate(270 522.711538 375.000000)">complex_heterog_list_e</text></g><g class="guides"><path d="M545.339744 0.000000 v360.000000" class="guide line" /><text x="545.3397435897435" y="375.0" class="backwards" transform="rotate(270 545.339744 375.000000)">complex_heterog_tuple_e</text></g><g class="guides"><path d="M567.967949 0.000000 v360.000000" class="guide line" /><text x="567.9679487179487" y="375.0" class="backwards" transform="rotate(270 567.967949 375.000000)">complex_heterog_dict_e</text></g><g class="guides"><path d="M590.596154 0.000000 v360.000000" class="guide line" /><text x="590.5961538461538" y="375.0" class="backwards" transform="rotate(270 590.596154 375.000000)">simple_cls_e</text></g><g class="guides"><path d="M613.224359 0.000000 v360.000000" class="guide line" /><text x="613.224358974359" y="375.0" class="backwards" transform="rotate(270 613.224359 375.000000)">complex_cls_d</text></g><g class="guides"><path d="M635.852564 0.000000 v360.000000" class="guide line" /><text x="635.8525641025641" y="375.0" class="backwards" transform="rotate(270 635.852564 375.000000)">state_cls_d</text></g><g class="guides"><path d="M658.480769 0.000000 v360.000000" class="guide line" /><text x="658.4807692307692" y="375.0" class="backwards" transform="rotate(270 658.480769 375.000000)">complex_cls_e</text></g><g class="guides"><path d="M681.108974 0.000000 v360.000000" class="guide line" /><text x="681.1089743589743" y="375.0" class="backwards" transform="rotate(270 681.108974 375.000000)">state_cls_e</text></g></g><g class="series serie-0 color-0"><g class="boxes"><g class="box"><path stroke-width="3" d="M19.912821 352.203358 L29.869231 352.203358" class="reactive tooltip-trigger" /><path stroke-width="3" d="M14.934615 351.406117 L34.847436 351.406117" class="reactive tooltip-trigger" /><path stroke-width="3" d="M19.912821 350.565266 L29.869231 350.565266" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 352.203358 L24.891026 351.591457" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 350.565266 L24.891026 351.181258" class="reactive tooltip-trigger" /><rect x="14.934615384615384" y="351.1812576166295" height="0.4101997385010918" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="352.3273795928768" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="198.33525347498144" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.5500
348 Q1-1.5IQR: 15.6410
349 Q1: 16.0900
350 Median: 16.2260
351 Q3: 16.3910
352 Q3+1.5IQR: 16.8430
353 Max: 128.5460</desc><desc class="x centered">24.891025641025642</desc><desc class="y centered">351.3894913589321</desc><desc class="x_label" /></g></g></g><g class="series serie-1 color-1"><g class="boxes"><g class="box"><path stroke-width="3" d="M42.541026 351.324347 L52.497436 351.324347" class="reactive tooltip-trigger" /><path stroke-width="3" d="M37.562821 350.664746 L57.475641 350.664746" class="reactive tooltip-trigger" /><path stroke-width="3" d="M42.541026 349.966990 L52.497436 349.966990" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 351.324347 L47.519231 350.816021" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 349.966990 L47.519231 350.476679" class="reactive tooltip-trigger" /><rect x="37.562820512820515" y="350.4766790672791" height="0.33934178301979046" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="351.44699973906154" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="330.9762246506926" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.1960
354 Q1-1.5IQR: 16.2860
355 Q1: 16.6590
356 Median: 16.7700
357 Q3: 16.9080
358 Q3+1.5IQR: 17.2820
359 Max: 31.2170</desc><desc class="x centered">47.519230769230774</desc><desc class="y centered">350.64975651498906</desc><desc class="x_label" /></g></g></g><g class="series serie-2 color-2"><g class="boxes"><g class="box"><path stroke-width="3" d="M65.169231 351.313449 L75.125641 351.313449" class="reactive tooltip-trigger" /><path stroke-width="3" d="M60.191026 350.558449 L80.103846 350.558449" class="reactive tooltip-trigger" /><path stroke-width="3" d="M65.169231 349.773474 L75.125641 349.773474" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 351.313449 L70.147436 350.738341" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 349.773474 L70.147436 350.352663" class="reactive tooltip-trigger" /><rect x="60.19102564102564" y="350.3526627715606" height="0.3856780866811391" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="351.42383654510627" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="279.4633536861007" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.2130
360 Q1-1.5IQR: 16.2940
361 Q1: 16.7160
362 Median: 16.8480
363 Q3: 16.9990
364 Q3+1.5IQR: 17.4240
365 Max: 69.0160</desc><desc class="x centered">70.1474358974359</desc><desc class="y centered">350.54727524693834</desc><desc class="x_label" /></g></g></g><g class="series serie-3 color-3"><g class="boxes"><g class="box"><path stroke-width="3" d="M87.797436 350.978193 L97.753846 350.978193" class="reactive tooltip-trigger" /><path stroke-width="3" d="M82.819231 350.126437 L102.732051 350.126437" class="reactive tooltip-trigger" /><path stroke-width="3" d="M87.797436 349.228346 L97.753846 349.228346" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 350.978193 L92.775641 350.326773" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 349.228346 L92.775641 349.887946" class="reactive tooltip-trigger" /><rect x="82.81923076923077" y="349.8879462349576" height="0.4388265111675196" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="351.1444602652734" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="307.47183466699795" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.4180
366 Q1-1.5IQR: 16.5400
367 Q1: 17.0180
368 Median: 17.1650
369 Q3: 17.3400
370 Q3+1.5IQR: 17.8240
371 Max: 48.4640</desc><desc class="x centered">92.77564102564102</desc><desc class="y centered">350.10953897257536</desc><desc class="x_label" /></g></g></g><g class="series serie-4 color-4"><g class="boxes"><g class="box"><path stroke-width="3" d="M110.425641 350.679739 L120.382051 350.679739" class="reactive tooltip-trigger" /><path stroke-width="3" d="M105.447436 350.063748 L125.360256 350.063748" class="reactive tooltip-trigger" /><path stroke-width="3" d="M110.425641 349.417781 L120.382051 349.417781" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 350.679739 L115.403846 350.208205" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 349.417781 L115.403846 349.892036" class="reactive tooltip-trigger" /><rect x="105.4474358974359" y="349.8920364821779" height="0.31616867331365484" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="350.7247116587163" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="250.69578727350194" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.7260
372 Q1-1.5IQR: 16.7590
373 Q1: 17.1050
374 Median: 17.2110
375 Q3: 17.3370
376 Q3+1.5IQR: 17.6850
377 Max: 90.1250</desc><desc class="x centered">115.40384615384615</desc><desc class="y centered">350.0523017882313</desc><desc class="x_label" /></g></g></g><g class="series serie-5 color-5"><g class="boxes"><g class="box"><path stroke-width="3" d="M133.053846 349.976529 L143.010256 349.976529" class="reactive tooltip-trigger" /><path stroke-width="3" d="M128.075641 348.908087 L147.988462 348.908087" class="reactive tooltip-trigger" /><path stroke-width="3" d="M133.053846 347.610690 L143.010256 347.610690" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 349.976529 L138.032051 349.161568" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 347.610690 L138.032051 348.544213" class="reactive tooltip-trigger" /><rect x="128.07564102564103" y="348.54421326027943" height="0.6173546471126201" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="349.9765285950601" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="314.87461693788697" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.2750
378 Q1-1.5IQR: 17.2750
379 Q1: 17.8730
380 Median: 18.0590
381 Q3: 18.3260
382 Q3+1.5IQR: 19.0110
383 Max: 43.0320</desc><desc class="x centered">138.0320512820513</desc><desc class="y centered">348.84021726269094</desc><desc class="x_label" /></g></g></g><g class="series serie-6 color-6"><g class="boxes"><g class="box"><path stroke-width="3" d="M155.682051 349.810266 L165.638462 349.810266" class="reactive tooltip-trigger" /><path stroke-width="3" d="M150.703846 349.188821 L170.616667 349.188821" class="reactive tooltip-trigger" /><path stroke-width="3" d="M155.682051 348.537401 L165.638462 348.537401" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 349.810266 L160.660256 349.337374" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 348.537401 L160.660256 349.019837" class="reactive tooltip-trigger" /><rect x="150.70384615384614" y="349.01983712280315" height="0.3175370469291465" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="349.94791173814446" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="204.99530634517467" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.2960
384 Q1-1.5IQR: 17.3970
385 Q1: 17.7440
386 Median: 17.8530
387 Q3: 17.9770
388 Q3+1.5IQR: 18.3310
389 Max: 123.6590</desc><desc class="x centered">160.6602564102564</desc><desc class="y centered">349.1787400046916</desc><desc class="x_label" /></g></g></g><g class="series serie-7 color-7"><g class="boxes"><g class="box"><path stroke-width="3" d="M178.310256 347.492122 L188.266667 347.492122" class="reactive tooltip-trigger" /><path stroke-width="3" d="M173.332051 346.750756 L193.244872 346.750756" class="reactive tooltip-trigger" /><path stroke-width="3" d="M178.310256 345.960327 L188.266667 345.960327" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 347.492122 L183.288462 346.926563" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 345.960327 L183.288462 346.540885" class="reactive tooltip-trigger" /><rect x="173.33205128205125" y="346.540884539923" height="0.3856780866811391" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="347.5984241560678" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="306.055875363223" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 19.0200
390 Q1-1.5IQR: 19.0980
391 Q1: 19.5130
392 Median: 19.6420
393 Q3: 19.7960
394 Q3+1.5IQR: 20.2220
395 Max: 49.5030</desc><desc class="x centered">183.28846153846152</desc><desc class="y centered">346.7341306248354</desc><desc class="x_label" /></g></g></g><g class="series serie-8 color-8"><g class="boxes"><g class="box"><path stroke-width="3" d="M200.938462 324.839490 L210.894872 324.839490" class="reactive tooltip-trigger" /><path stroke-width="3" d="M195.960256 323.659295 L215.873077 323.659295" class="reactive tooltip-trigger" /><path stroke-width="3" d="M200.938462 322.439581 L210.894872 322.439581" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 324.839490 L205.916667 323.945486" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 322.439581 L205.916667 323.344488" class="reactive tooltip-trigger" /><rect x="195.9602564102564" y="323.3444876929769" height="0.6009986161068923" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="324.9975772201437" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="181.9883400022189" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 35.6040
396 Q1-1.5IQR: 35.7200
397 Q1: 36.3760
398 Median: 36.5860
399 Q3: 36.8170
400 Q3+1.5IQR: 37.4810
401 Max: 140.5410</desc><desc class="x centered">205.91666666666666</desc><desc class="y centered">323.64566821311286</desc><desc class="x_label" /></g></g></g><g class="series serie-9 color-9"><g class="boxes"><g class="box"><path stroke-width="3" d="M223.566667 324.297094 L233.523077 324.297094" class="reactive tooltip-trigger" /><path stroke-width="3" d="M218.588462 323.437160 L238.501282 323.437160" class="reactive tooltip-trigger" /><path stroke-width="3" d="M223.566667 322.554059 L233.523077 322.554059" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 324.297094 L228.544872 323.648051" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 322.554059 L228.544872 323.210932" class="reactive tooltip-trigger" /><rect x="218.58846153846153" y="323.21093244495313" height="0.4371185230858714" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="324.4769854275741" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="285.4106574282538" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 35.9860
402 Q1-1.5IQR: 36.1180
403 Q1: 36.5943
404 Median: 36.7490
405 Q3: 36.9150
406 Q3+1.5IQR: 37.3970
407 Max: 64.6520</desc><desc class="x centered">228.5448717948718</desc><desc class="y centered">323.42945923241206</desc><desc class="x_label" /></g></g></g><g class="series serie-10 color-10"><g class="boxes"><g class="box"><path stroke-width="3" d="M246.194872 323.164601 L256.151282 323.164601" class="reactive tooltip-trigger" /><path stroke-width="3" d="M241.216667 321.978952 L261.129487 321.978952" class="reactive tooltip-trigger" /><path stroke-width="3" d="M246.194872 320.693824 L256.151282 320.693824" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 323.164601 L251.173077 322.266502" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 320.693824 L251.173077 321.640977" class="reactive tooltip-trigger" /><rect x="241.21666666666664" y="321.6409765728039" height="0.6255252258022779" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="323.2218348129984" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="258.9871249347714" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.9070
408 Q1-1.5IQR: 36.9490
409 Q1: 37.6080
410 Median: 37.8190
411 Q3: 38.0670
412 Q3+1.5IQR: 38.7620
413 Max: 84.0410</desc><desc class="x centered">251.1730769230769</desc><desc class="y centered">321.948971196915</desc><desc class="x_label" /></g></g></g><g class="series serie-11 color-11"><g class="boxes"><g class="box"><path stroke-width="3" d="M268.823077 319.168841 L278.779487 319.168841" class="reactive tooltip-trigger" /><path stroke-width="3" d="M263.844872 317.549822 L283.757692 317.549822" class="reactive tooltip-trigger" /><path stroke-width="3" d="M268.823077 315.189432 L278.779487 315.189432" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 319.168841 L273.801282 318.092219" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 315.189432 L273.801282 316.937916" class="reactive tooltip-trigger" /><rect x="263.84487179487184" y="316.93791611930567" height="1.1543024706878668" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="319.16884106862415" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="279.0558758212044" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 39.8810
414 Q1-1.5IQR: 39.8810
415 Q1: 40.6710
416 Median: 41.0690
417 Q3: 41.5180
418 Q3+1.5IQR: 42.8010
419 Max: 69.3150</desc><desc class="x centered">273.8012820512821</desc><desc class="y centered">317.38764599009363</desc><desc class="x_label" /></g></g></g><g class="series serie-12 color-12"><g class="boxes"><g class="box"><path stroke-width="3" d="M291.451282 318.498333 L301.407692 318.498333" class="reactive tooltip-trigger" /><path stroke-width="3" d="M286.473077 317.369928 L306.385897 317.369928" class="reactive tooltip-trigger" /><path stroke-width="3" d="M291.451282 316.161116 L301.407692 316.161116" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 318.498333 L296.429487 317.643853" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 316.161116 L296.429487 317.051030" class="reactive tooltip-trigger" /><rect x="286.473076923077" y="317.05103004697895" height="0.5928230795418017" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="318.6223493348683" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="-14.31495929252793" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 40.2820
420 Q1-1.5IQR: 40.3730
421 Q1: 41.0000
422 Median: 41.2010
423 Q3: 41.4350
424 Q3+1.5IQR: 42.0880
425 Max: 284.5840</desc><desc class="x centered">296.42948717948724</desc><desc class="y centered">317.34485208841875</desc><desc class="x_label" /></g></g></g><g class="series serie-13 color-13"><g class="boxes"><g class="box"><path stroke-width="3" d="M314.079487 316.428227 L324.035897 316.428227" class="reactive tooltip-trigger" /><path stroke-width="3" d="M309.101282 314.223881 L329.014103 314.223881" class="reactive tooltip-trigger" /><path stroke-width="3" d="M314.079487 311.922772 L324.035897 311.922772" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 316.428227 L319.057692 314.765596" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 311.922772 L319.057692 313.630374" class="reactive tooltip-trigger" /><rect x="309.1012820512821" y="313.630373649232" height="1.1352220871397094" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="316.4895556137084" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="169.07843895820895" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 41.8470
426 Q1-1.5IQR: 41.8920
427 Q1: 43.1120
428 Median: 43.5095
429 Q3: 43.9450
430 Q3+1.5IQR: 45.1980
431 Max: 150.0140</desc><desc class="x centered">319.0576923076924</desc><desc class="y centered">314.1941698555611</desc><desc class="x_label" /></g></g></g><g class="series serie-14 color-14"><g class="boxes"><g class="box"><path stroke-width="3" d="M336.707692 316.008478 L346.664103 316.008478" class="reactive tooltip-trigger" /><path stroke-width="3" d="M331.729487 313.864777 L351.642308 313.864777" class="reactive tooltip-trigger" /><path stroke-width="3" d="M336.707692 311.606604 L346.664103 311.606604" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 316.008478 L341.685897 314.381284" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 311.606604 L341.685897 313.271959" class="reactive tooltip-trigger" /><rect x="331.7294871794872" y="313.27195891947724" height="1.1093246248911441" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="316.2892177837973" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="129.59236731020692" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 41.9940
432 Q1-1.5IQR: 42.2000
433 Q1: 43.3940
434 Median: 43.7730
435 Q3: 44.2080
436 Q3+1.5IQR: 45.4300
437 Max: 178.9880</desc><desc class="x centered">341.68589743589746</desc><desc class="y centered">313.8266202403477</desc><desc class="x_label" /></g></g></g><g class="series serie-15 color-15"><g class="boxes"><g class="box"><path stroke-width="3" d="M359.335897 314.002423 L369.292308 314.002423" class="reactive tooltip-trigger" /><path stroke-width="3" d="M354.357692 311.103726 L374.270513 311.103726" class="reactive tooltip-trigger" /><path stroke-width="3" d="M359.335897 308.124623 L369.292308 308.124623" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 314.002423 L364.314103 311.811022" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 308.124623 L364.314103 310.337824" class="reactive tooltip-trigger" /><rect x="354.35769230769233" y="310.3378237944239" height="1.4731979754816393" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="314.62795272006537" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="240.45699614784263" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 43.2130
438 Q1-1.5IQR: 43.6720
439 Q1: 45.2800
440 Median: 45.7990
441 Q3: 46.3610
442 Q3+1.5IQR: 47.9850
443 Max: 97.6380</desc><desc class="x centered">364.3141025641026</desc><desc class="y centered">311.0759235310539</desc><desc class="x_label" /></g></g></g><g class="series serie-16 color-16"><g class="boxes"><g class="box"><path stroke-width="3" d="M381.964103 313.532252 L391.920513 313.532252" class="reactive tooltip-trigger" /><path stroke-width="3" d="M376.985897 311.425349 L396.898718 311.425349" class="reactive tooltip-trigger" /><path stroke-width="3" d="M381.964103 309.183526 L391.920513 309.183526" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 313.532252 L386.942308 311.945940" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 309.183526 L386.942308 310.841725" class="reactive tooltip-trigger" /><rect x="376.98589743589747" y="310.84172489939704" height="1.1042155342723845" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="313.71350730424956" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="233.25318333324913" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 43.8840
444 Q1-1.5IQR: 44.0170
445 Q1: 45.1810
446 Median: 45.5630
447 Q3: 45.9912
448 Q3+1.5IQR: 47.2080
449 Max: 102.9240</desc><desc class="x centered">386.94230769230774</desc><desc class="y centered">311.38575851852045</desc><desc class="x_label" /></g></g></g><g class="series serie-17 color-17"><g class="boxes"><g class="box"><path stroke-width="3" d="M404.592308 312.890371 L414.548718 312.890371" class="reactive tooltip-trigger" /><path stroke-width="3" d="M399.614103 310.580408 L419.526923 310.580408" class="reactive tooltip-trigger" /><path stroke-width="3" d="M404.592308 308.176408 L414.548718 308.176408" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 312.890371 L409.570513 311.139155" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 308.176408 L409.570513 309.954877" class="reactive tooltip-trigger" /><rect x="399.6141025641026" y="309.9548774970984" height="1.1842777854681117" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="313.2215323685956" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="-191.86735560796" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 44.2450
450 Q1-1.5IQR: 44.4880
451 Q1: 45.7730
452 Median: 46.1830
453 Q3: 46.6420
454 Q3+1.5IQR: 47.9470
455 Max: 414.8680</desc><desc class="x centered">409.5705128205129</desc><desc class="y centered">310.548243959786</desc><desc class="x_label" /></g></g></g><g class="series serie-18 color-18"><g class="boxes"><g class="box"><path stroke-width="3" d="M427.220513 309.381132 L437.176923 309.381132" class="reactive tooltip-trigger" /><path stroke-width="3" d="M422.242308 306.900816 L442.155128 306.900816" class="reactive tooltip-trigger" /><path stroke-width="3" d="M427.220513 304.304665 L437.176923 304.304665" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 309.381132 L432.198718 307.505910" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 304.304665 L432.198718 306.226223" class="reactive tooltip-trigger" /><rect x="422.24230769230775" y="306.22622300472744" height="1.279687140021906" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="309.67550121726543" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="-36.784977811908504" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 46.8470
456 Q1-1.5IQR: 47.0630
457 Q1: 48.4390
458 Median: 48.8830
459 Q3: 49.3780
460 Q3+1.5IQR: 50.7880
461 Max: 301.0720</desc><desc class="x centered">432.198717948718</desc><desc class="y centered">306.8637492637678</desc><desc class="x_label" /></g></g></g><g class="series serie-19 color-19"><g class="boxes"><g class="box"><path stroke-width="3" d="M449.848718 307.963810 L459.805128 307.963810" class="reactive tooltip-trigger" /><path stroke-width="3" d="M444.870513 305.566627 L464.783333 305.566627" class="reactive tooltip-trigger" /><path stroke-width="3" d="M449.848718 303.109479 L459.805128 303.109479" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 307.963810 L454.826923 306.148548" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 303.109479 L454.826923 304.932922" class="reactive tooltip-trigger" /><rect x="444.87051282051283" y="304.93292153880634" height="1.215626431739338" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="308.38900691429393" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="12.462902641364337" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 47.7910
462 Q1-1.5IQR: 48.1030
463 Q1: 49.4350
464 Median: 49.8620
465 Q3: 50.3270
466 Q3+1.5IQR: 51.6650
467 Max: 264.9350</desc><desc class="x centered">454.8269230769231</desc><desc class="y centered">305.54427715666253</desc><desc class="x_label" /></g></g></g><g class="series serie-20 color-20"><g class="boxes"><g class="box"><path stroke-width="3" d="M472.476923 303.938069 L482.433333 303.938069" class="reactive tooltip-trigger" /><path stroke-width="3" d="M467.498718 300.571930 L487.411538 300.571930" class="reactive tooltip-trigger" /><path stroke-width="3" d="M472.476923 297.115839 L482.433333 297.115839" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 303.938069 L477.455128 301.433222" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 297.115839 L477.455128 299.706882" class="reactive tooltip-trigger" /><rect x="467.49871794871797" y="299.7068820757246" height="1.726339657537551" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="304.6549086747135" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="-97.80209099590445" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 50.5310
468 Q1-1.5IQR: 51.0570
469 Q1: 52.8950
470 Median: 53.5270
471 Q3: 54.1618
472 Q3+1.5IQR: 56.0630
473 Max: 345.8450</desc><desc class="x centered">477.45512820512823</desc><desc class="y centered">300.55318843493865</desc><desc class="x_label" /></g></g></g><g class="series serie-21 color-21"><g class="boxes"><g class="box"><path stroke-width="3" d="M495.105128 302.259085 L505.061538 302.259085" class="reactive tooltip-trigger" /><path stroke-width="3" d="M490.126923 299.038082 L510.039744 299.038082" class="reactive tooltip-trigger" /><path stroke-width="3" d="M495.105128 295.646727 L505.061538 295.646727" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 302.259085 L500.083333 299.803982" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 295.646727 L500.083333 298.143399" class="reactive tooltip-trigger" /><rect x="490.1269230769231" y="298.1433987099342" height="1.6605833558618883" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="302.9186854925292" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="153.30935594972263" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 51.8050
474 Q1-1.5IQR: 52.2890
475 Q1: 54.0905
476 Median: 54.6525
477 Q3: 55.3090
478 Q3+1.5IQR: 57.1410
479 Max: 161.5850</desc><desc class="x centered">500.08333333333337</desc><desc class="y centered">298.9782548558692</desc><desc class="x_label" /></g></g></g><g class="series serie-22 color-22"><g class="boxes"><g class="box"><path stroke-width="3" d="M517.733333 302.023323 L527.689744 302.023323" class="reactive tooltip-trigger" /><path stroke-width="3" d="M512.755128 299.243184 L532.667949 299.243184" class="reactive tooltip-trigger" /><path stroke-width="3" d="M517.733333 296.355391 L527.689744 296.355391" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 302.023323 L522.711538 299.910281" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 296.355391 L522.711538 298.491595" class="reactive tooltip-trigger" /><rect x="512.7551282051282" y="298.4915952584514" height="1.4186861352552" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="302.51256608549755" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="142.90021222468343" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 52.1030
480 Q1-1.5IQR: 52.4620
481 Q1: 54.0125
482 Median: 54.5020
483 Q3: 55.0535
484 Q3+1.5IQR: 56.6210
485 Max: 169.2230</desc><desc class="x centered">522.7115384615385</desc><desc class="y centered">299.2047548985762</desc><desc class="x_label" /></g></g></g><g class="series serie-23 color-23"><g class="boxes"><g class="box"><path stroke-width="3" d="M540.361538 301.043458 L550.317949 301.043458" class="reactive tooltip-trigger" /><path stroke-width="3" d="M535.383333 298.281044 L555.296154 298.281044" class="reactive tooltip-trigger" /><path stroke-width="3" d="M540.361538 295.436855 L550.317949 295.436855" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 301.043458 L545.339744 298.949160" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 295.436855 L545.339744 297.545127" class="reactive tooltip-trigger" /><rect x="535.3833333333333" y="297.54512692530744" height="1.4040331344558012" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="302.2154753167943" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="152.15505843691022" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 52.3210
486 Q1-1.5IQR: 53.1810
487 Q1: 54.7177
488 Median: 55.2080
489 Q3: 55.7480
490 Q3+1.5IQR: 57.2950
491 Max: 162.4320</desc><desc class="x centered">545.3397435897435</desc><desc class="y centered">298.25112888069054</desc><desc class="x_label" /></g></g></g><g class="series serie-24 color-24"><g class="boxes"><g class="box"><path stroke-width="3" d="M562.989744 294.826317 L572.946154 294.826317" class="reactive tooltip-trigger" /><path stroke-width="3" d="M558.011538 291.518775 L577.924359 291.518775" class="reactive tooltip-trigger" /><path stroke-width="3" d="M562.989744 288.085858 L572.946154 288.085858" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 294.826317 L567.967949 292.314658" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 288.085858 L567.967949 290.623410" class="reactive tooltip-trigger" /><rect x="558.0115384615385" y="290.62340978521394" height="1.6912478153253687" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="296.1182602956118" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="-139.6471842204129" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 56.7950
492 Q1-1.5IQR: 57.7430
493 Q1: 59.5860
494 Median: 60.1700
495 Q3: 60.8270
496 Q3+1.5IQR: 62.6890
497 Max: 376.5500</desc><desc class="x centered">567.9679487179487</desc><desc class="y centered">291.473803416923</desc><desc class="x_label" /></g></g></g><g class="series serie-25 color-25"><g class="boxes"><g class="box"><path stroke-width="3" d="M585.617949 289.897034 L595.574359 289.897034" class="reactive tooltip-trigger" /><path stroke-width="3" d="M580.639744 286.852517 L600.552564 286.852517" class="reactive tooltip-trigger" /><path stroke-width="3" d="M585.617949 283.538157 L595.574359 283.538157" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 289.897034 L590.596154 287.565266" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 283.538157 L590.596154 285.957144" class="reactive tooltip-trigger" /><rect x="580.6397435897436" y="285.95714420413424" height="1.6081215971209417" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="290.4557864962519" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="248.0124165292413" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 60.9500
498 Q1-1.5IQR: 61.3600
499 Q1: 63.0710
500 Median: 63.5940
501 Q3: 64.2510
502 Q3+1.5IQR: 66.0260
503 Max: 92.0940</desc><desc class="x centered">590.5961538461538</desc><desc class="y centered">286.76202354792633</desc><desc class="x_label" /></g></g></g><g class="series serie-26 color-26"><g class="boxes"><g class="box"><path stroke-width="3" d="M608.246154 79.273318 L618.202564 79.273318" class="reactive tooltip-trigger" /><path stroke-width="3" d="M603.267949 74.949803 L623.180769 74.949803" class="reactive tooltip-trigger" /><path stroke-width="3" d="M608.246154 70.454576 L618.202564 70.454576" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 79.273318 L613.224359 76.006663" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 70.454576 L613.224359 73.796184" class="reactive tooltip-trigger" /><rect x="603.2679487179488" y="73.796184498674" height="2.210478671092517" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="80.47668364709313" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="4.456389965012875" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 215.0280
504 Q1-1.5IQR: 215.9110
505 Q1: 218.3080
506 Median: 219.0835
507 Q3: 219.9300
508 Q3+1.5IQR: 222.3820
509 Max: 270.8100</desc><desc class="x centered">613.224358974359</desc><desc class="y centered">74.8961089917716</desc><desc class="x_label" /></g></g></g><g class="series serie-27 color-27"><g class="boxes"><g class="box"><path stroke-width="3" d="M630.874359 71.577530 L640.830769 71.577530" class="reactive tooltip-trigger" /><path stroke-width="3" d="M625.896154 67.298304 L645.808974 67.298304" class="reactive tooltip-trigger" /><path stroke-width="3" d="M630.874359 62.739701 L640.830769 62.739701" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 71.577530 L635.852564 68.382757" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 62.739701 L635.852564 66.144346" class="reactive tooltip-trigger" /><rect x="625.8961538461539" y="66.14434583507392" height="2.23841134120039" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="72.58191652479928" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="-667.3260167648473" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 220.8210
510 Q1-1.5IQR: 221.5580
511 Q1: 223.9023
512 Median: 224.6980
513 Q3: 225.5447
514 Q3+1.5IQR: 228.0430
515 Max: 763.7490</desc><desc class="x centered">635.8525641025641</desc><desc class="y centered">67.22852758635514</desc><desc class="x_label" /></g></g></g><g class="series serie-28 color-28"><g class="boxes"><g class="box"><path stroke-width="3" d="M653.502564 30.086762 L663.458974 30.086762" class="reactive tooltip-trigger" /><path stroke-width="3" d="M648.524359 24.770442 L668.437179 24.770442" class="reactive tooltip-trigger" /><path stroke-width="3" d="M653.502564 19.131131 L663.458974 19.131131" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 30.086762 L658.480769 26.054212" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 19.131131 L658.480769 23.288386" class="reactive tooltip-trigger" /><rect x="648.524358974359" y="23.28838643361047" height="2.765825170345863" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="30.899000363105642" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="-253.91747188265458" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 251.4070
516 Q1-1.5IQR: 252.0030
517 Q1: 254.9620
518 Median: 255.9040
519 Q3: 256.9915
520 Q3+1.5IQR: 260.0420
521 Max: 460.3990</desc><desc class="x centered">658.4807692307692</desc><desc class="y centered">24.66618645765186</desc><desc class="x_label" /></g></g></g><g class="series serie-29 color-29"><g class="boxes"><g class="box"><path stroke-width="3" d="M676.130769 17.814656 L686.087179 17.814656" class="reactive tooltip-trigger" /><path stroke-width="3" d="M671.152564 12.735462 L691.065385 12.735462" class="reactive tooltip-trigger" /><path stroke-width="3" d="M676.130769 7.158844 L686.087179 7.158844" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 17.814656 L681.108974 13.979710" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 7.158844 L681.108974 11.267718" class="reactive tooltip-trigger" /><rect x="671.1525641025642" y="11.267717529975528" height="2.71199255905168" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="18.27665113549375" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="-300.2884608404562" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 260.6690
522 Q1-1.5IQR: 261.0080
523 Q1: 263.8220
524 Median: 264.7350
525 Q3: 265.8120
526 Q3+1.5IQR: 268.8270
527 Max: 494.4250</desc><desc class="x centered">681.1089743589744</desc><desc class="y centered">12.591277901150875</desc><desc class="x_label" /></g></g></g></g><g class="titles"><text x="400.0" y="26" class="title plot_title">Speed in Microseconds (us)</text><text x="427.0" y="580.0" class="title">Trial</text><text x="0" y="252.0" class="title" transform="rotate(-90 0.000000 226.000000)">Duration</text></g><g transform="translate(74, 46)" class="plot overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot text-overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot tooltip-overlay"><g transform="translate(0 0)" style="opacity: 0" class="tooltip"><rect rx="0" ry="0" width="0" height="0" class="tooltip-box" /><g class="text" /></g></g></g></svg>
0 <?xml version='1.0' encoding='utf-8'?>
1 <svg xmlns="http://www.w3.org/2000/svg" id="chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797" class="pygal-chart" viewBox="0 0 800 600"><!--Generated with pygal 3.0.0 (etree) ©Kozea 2012-2016 on 2022-06-20--><!--http://pygal.org--><!--http://github.com/Kozea/pygal--><defs><style type="text/css">#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .title{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .legends .legend text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis text.major{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay text.value{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay text.label{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 text.no_data{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:64px}
2 #chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797{background-color:rgba(249,249,249,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 path,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 rect,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .graph &gt; .background{fill:rgba(249,249,249,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .plot &gt; .background{fill:rgba(255,255,255,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .graph{fill:rgba(0,0,0,.87)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 text.no_data{fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .title{fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .legends .legend text{fill:rgba(0,0,0,.87)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .line{stroke:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis text.major{fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y .guides:hover .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .line-graph .axis.x .guides:hover .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .stackedline-graph .axis.x .guides:hover .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .reactive{fill-opacity:.7;stroke-opacity:.8;stroke-width:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .ci{stroke:rgba(0,0,0,.87)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .reactive.active,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .ci .reactive.active{stroke-width:1.5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .series text{fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip .value{font-size:1.5em}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .bound{font-size:.5em}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-0,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-0 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-1,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-2,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-2 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-3,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-3 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-4,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-4 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-5,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-5 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-6,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-6 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-7,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-7 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-8,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-8 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-9,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-9 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-10,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-10 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-11,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-11 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-12,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-12 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-13,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-13 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-14,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-14 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-15,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-15 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-16,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-16 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-17,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-17 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-18,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-18 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-19,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-19 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-20,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-20 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-21,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-21 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-22,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-22 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-23,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-23 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-24,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-24 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-25,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-25 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-26,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-26 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-27,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-27 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-28,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-28 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-29,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .color-29 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-0 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-1 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-2 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-3 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-4 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-5 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-6 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-7 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-8 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-9 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-10 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-11 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-12 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-13 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-14 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-15 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-16 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-17 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-18 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-19 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-20 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-21 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-22 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-23 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-24 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-25 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-26 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-27 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-28 text{fill:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .text-overlay .color-29 text{fill:black}
3 #chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 text.no_data{text-anchor:middle}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .guide.line{fill:none}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .centered{text-anchor:middle}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .title{text-anchor:middle}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .legends .legend text{fill-opacity:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.x text{text-anchor:middle}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.x:not(.web) text[transform]{text-anchor:start}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y text{text-anchor:end}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y text[transform].backwards{text-anchor:start}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y2 text{text-anchor:start}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y2 text[transform].backwards{text-anchor:end}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .guide.line{stroke-dasharray:4,4;stroke:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .major.guide.line{stroke-dasharray:6,6;stroke:black}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .horizontal .axis.y .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .horizontal .axis.y2 .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .vertical .axis.x .guide.line{opacity:0}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .horizontal .axis.always_show .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y .guides:hover .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.y2 .guides:hover .guide.line,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis.x .guides:hover .guide.line{opacity:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .axis .guides:hover text{opacity:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .nofill{fill:none}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .subtle-fill{fill-opacity:.2}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .dot{stroke-width:1px;fill-opacity:1;stroke-opacity:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .dot.active{stroke-width:5px}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .dot.negative{fill:transparent}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 text,#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 tspan{stroke:none !important}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .series text.active{opacity:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .tooltip text{fill-opacity:1}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .showable{visibility:hidden}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .showable.shown{visibility:visible}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-be6cdfb8-8c9d-4441-ba08-e1f74ae57797 .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}
4 .tooltip .value{font-size:1em !important}.axis text{font-size:9px !important}</style><script type="text/javascript">window.pygal = window.pygal || {};window.pygal.config = window.pygal.config || {};window.pygal.config['be6cdfb8-8c9d-4441-ba08-e1f74ae57797'] = {"allow_interruptions": false, "box_mode": "tukey", "classes": ["pygal-chart"], "css": ["file://style.css", "file://graph.css", "inline:\n .tooltip .value {\n font-size: 1em !important;\n }\n .axis text {\n font-size: 9px !important;\n }\n "], "defs": [], "disable_xml_declaration": false, "dots_size": 2.5, "dynamic_print_values": false, "explicit_size": false, "fill": false, "force_uri_protocol": "https", "formatter": null, "half_pie": false, "height": 600, "include_x_axis": false, "inner_radius": 0, "interpolate": null, "interpolation_parameters": {}, "interpolation_precision": 250, "inverse_y_axis": false, "js": ["file:///home/theel/.pyenv/versions/3.9.13/lib/python3.9/site-packages/pygaljs/static/2.0.x/pygal-tooltips.js"], "legend_at_bottom": false, "legend_at_bottom_columns": null, "legend_box_size": 12, "logarithmic": false, "margin": 20, "margin_bottom": null, "margin_left": null, "margin_right": null, "margin_top": null, "max_scale": 20, "min_scale": 20, "missing_value_fill_truncation": "x", "no_data_text": "No data", "no_prefix": false, "order_min": null, "pretty_print": false, "print_labels": false, "print_values": false, "print_values_position": "center", "print_zeroes": true, "range": [14, 157], "rounded_bars": null, "secondary_range": null, "show_dots": true, "show_legend": false, "show_minor_x_labels": true, "show_minor_y_labels": true, "show_only_major_dots": false, "show_x_guides": false, "show_x_labels": true, "show_y_guides": true, "show_y_labels": true, "spacing": 10, "stack_from_top": false, "strict": false, "stroke": true, "stroke_style": null, "style": {"background": "rgba(249, 249, 249, 1)", "ci_colors": [], "colors": ["#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5"], "dot_opacity": "1", "font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "foreground": "rgba(0, 0, 0, .87)", "foreground_strong": "rgba(0, 0, 0, 1)", "foreground_subtle": "rgba(0, 0, 0, .54)", "guide_stroke_color": "black", "guide_stroke_dasharray": "4,4", "label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "label_font_size": 10, "legend_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "legend_font_size": 14, "major_guide_stroke_color": "black", "major_guide_stroke_dasharray": "6,6", "major_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "major_label_font_size": 10, "no_data_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "no_data_font_size": 64, "opacity": ".7", "opacity_hover": ".8", "plot_background": "rgba(255, 255, 255, 1)", "stroke_opacity": ".8", "stroke_opacity_hover": ".9", "stroke_width": "1", "stroke_width_hover": "4", "title_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "title_font_size": 16, "tooltip_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "tooltip_font_size": 14, "transition": "150ms", "value_background": "rgba(229, 229, 229, 1)", "value_colors": [], "value_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_font_size": 16, "value_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_label_font_size": 10}, "title": "Speed in Microseconds (us)", "tooltip_border_radius": 0, "tooltip_fancy_mode": true, "truncate_label": 50, "truncate_legend": null, "width": 800, "x_label_rotation": 270, "x_labels": ["simple_tuple_d", "simple_set_d", "simple_list_e", "simple_tuple_e", "simple_set_e", "simple_dict_d", "simple_dict_e", "simple_list_d", "complex_homog_tuple_d", "complex_homog_set_d", "complex_heterog_set_d", "complex_heterog_tuple_d", "complex_homog_list_e", "complex_homog_list_d", "complex_homog_dict_d", "complex_homog_tuple_e", "complex_homog_set_e", "complex_heterog_dict_d", "complex_heterog_list_d", "complex_heterog_set_e", "complex_heterog_list_e", "complex_heterog_tuple_e", "complex_homog_dict_e", "simple_cls_d", "complex_heterog_dict_e", "simple_cls_e", "complex_cls_d", "state_cls_d", "complex_cls_e", "state_cls_e"], "x_labels_major": null, "x_labels_major_count": null, "x_labels_major_every": null, "x_title": "Trial", "xrange": null, "y_label_rotation": 0, "y_labels": null, "y_labels_major": null, "y_labels_major_count": null, "y_labels_major_every": null, "y_title": "Duration", "zero": 14, "legends": ["jsonpickle_benchmarks.py::simple_tuple_d - 17900 rounds", "jsonpickle_benchmarks.py::simple_set_d - 17556 rounds", "jsonpickle_benchmarks.py::simple_list_e - 16356 rounds", "jsonpickle_benchmarks.py::simple_tuple_e - 12546 rounds", "jsonpickle_benchmarks.py::simple_set_e - 14094 rounds", "jsonpickle_benchmarks.py::simple_dict_d - 10888 rounds", "jsonpickle_benchmarks.py::simple_dict_e - 7615 rounds", "jsonpickle_benchmarks.py::simple_list_d - 14743 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_d - 14018 rounds", "jsonpickle_benchmarks.py::complex_homog_set_d - 12033 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_d - 11789 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_d - 10634 rounds", "jsonpickle_benchmarks.py::complex_homog_list_e - 698 rounds", "jsonpickle_benchmarks.py::complex_homog_list_d - 10203 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_d - 10654 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_e - 10067 rounds", "jsonpickle_benchmarks.py::complex_homog_set_e - 9318 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_d - 8547 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_d - 9362 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_e - 8887 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_e - 7869 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_e - 6067 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_e - 7435 rounds", "jsonpickle_benchmarks.py::simple_cls_d - 6070 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_e - 7439 rounds", "jsonpickle_benchmarks.py::simple_cls_e - 6490 rounds", "jsonpickle_benchmarks.py::complex_cls_d - 4682 rounds", "jsonpickle_benchmarks.py::state_cls_d - 4265 rounds", "jsonpickle_benchmarks.py::complex_cls_e - 4047 rounds", "jsonpickle_benchmarks.py::state_cls_e - 3217 rounds"]}</script><script type="text/javascript">(function() {
5 var $, get_translation, init, init_svg, matches, padding, r_translation, sibl, svg_ns, tooltip_timeout, xlink_ns;
6
7 svg_ns = 'http://www.w3.org/2000/svg';
8
9 xlink_ns = 'http://www.w3.org/1999/xlink';
10
11 $ = function(sel, ctx) {
12 if (ctx == null) {
13 ctx = null;
14 }
15 ctx = ctx || document;
16 return Array.prototype.slice.call(ctx.querySelectorAll(sel), 0).filter(function(e) {
17 return e !== ctx;
18 });
19 };
20
21 matches = function(el, selector) {
22 return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
23 };
24
25 sibl = function(el, match) {
26 if (match == null) {
27 match = null;
28 }
29 return Array.prototype.filter.call(el.parentElement.children, function(child) {
30 return child !== el &amp;&amp; (!match || matches(child, match));
31 });
32 };
33
34 Array.prototype.one = function() {
35 return this.length &gt; 0 &amp;&amp; this[0] || {};
36 };
37
38 padding = 5;
39
40 tooltip_timeout = null;
41
42 r_translation = /translate\((\d+)[ ,]+(\d+)\)/;
43
44 get_translation = function(el) {
45 return (r_translation.exec(el.getAttribute('transform')) || []).slice(1).map(function(x) {
46 return +x;
47 });
48 };
49
50 init = function(ctx) {
51 var bbox, box, config, el, graph, inner_svg, num, parent, tooltip, tooltip_el, tt, uid, untooltip, xconvert, yconvert, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
52 if ($('svg', ctx).length) {
53 inner_svg = $('svg', ctx).one();
54 parent = inner_svg.parentElement;
55 box = inner_svg.viewBox.baseVal;
56 bbox = parent.getBBox();
57 xconvert = function(x) {
58 return ((x - box.x) / box.width) * bbox.width;
59 };
60 yconvert = function(y) {
61 return ((y - box.y) / box.height) * bbox.height;
62 };
63 } else {
64 xconvert = yconvert = function(x) {
65 return x;
66 };
67 }
68 if (((_ref = window.pygal) != null ? _ref.config : void 0) != null) {
69 if (window.pygal.config.no_prefix != null) {
70 config = window.pygal.config;
71 } else {
72 uid = ctx.id.replace('chart-', '');
73 config = window.pygal.config[uid];
74 }
75 } else {
76 config = window.config;
77 }
78 tooltip_el = null;
79 graph = $('.graph').one();
80 tt = $('.tooltip', ctx).one();
81 _ref1 = $('.reactive', ctx);
82 for (_i = 0, _len = _ref1.length; _i &lt; _len; _i++) {
83 el = _ref1[_i];
84 el.addEventListener('mouseenter', (function(el) {
85 return function() {
86 return el.classList.add('active');
87 };
88 })(el));
89 el.addEventListener('mouseleave', (function(el) {
90 return function() {
91 return el.classList.remove('active');
92 };
93 })(el));
94 }
95 _ref2 = $('.activate-serie', ctx);
96 for (_j = 0, _len1 = _ref2.length; _j &lt; _len1; _j++) {
97 el = _ref2[_j];
98 num = el.id.replace('activate-serie-', '');
99 el.addEventListener('mouseenter', (function(num) {
100 return function() {
101 var re, _k, _len2, _ref3, _results;
102 _ref3 = $('.serie-' + num + ' .reactive', ctx);
103 _results = [];
104 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
105 re = _ref3[_k];
106 _results.push(re.classList.add('active'));
107 }
108 return _results;
109 };
110 })(num));
111 el.addEventListener('mouseleave', (function(num) {
112 return function() {
113 var re, _k, _len2, _ref3, _results;
114 _ref3 = $('.serie-' + num + ' .reactive', ctx);
115 _results = [];
116 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
117 re = _ref3[_k];
118 _results.push(re.classList.remove('active'));
119 }
120 return _results;
121 };
122 })(num));
123 el.addEventListener('click', (function(el, num) {
124 return function() {
125 var ov, re, rect, show, _k, _l, _len2, _len3, _ref3, _ref4, _results;
126 rect = $('rect', el).one();
127 show = rect.style.fill !== '';
128 rect.style.fill = show ? '' : 'transparent';
129 _ref3 = $('.serie-' + num + ' .reactive', ctx);
130 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
131 re = _ref3[_k];
132 re.style.display = show ? '' : 'none';
133 }
134 _ref4 = $('.text-overlay .serie-' + num, ctx);
135 _results = [];
136 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
137 ov = _ref4[_l];
138 _results.push(ov.style.display = show ? '' : 'none');
139 }
140 return _results;
141 };
142 })(el, num));
143 }
144 _ref3 = $('.tooltip-trigger', ctx);
145 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
146 el = _ref3[_k];
147 el.addEventListener('mouseenter', (function(el) {
148 return function() {
149 return tooltip_el = tooltip(el);
150 };
151 })(el));
152 }
153 tt.addEventListener('mouseenter', function() {
154 return tooltip_el != null ? tooltip_el.classList.add('active') : void 0;
155 });
156 tt.addEventListener('mouseleave', function() {
157 return tooltip_el != null ? tooltip_el.classList.remove('active') : void 0;
158 });
159 ctx.addEventListener('mouseleave', function() {
160 if (tooltip_timeout) {
161 clearTimeout(tooltip_timeout);
162 }
163 return untooltip(0);
164 });
165 graph.addEventListener('mousemove', function(el) {
166 if (tooltip_timeout) {
167 return;
168 }
169 if (!matches(el.target, '.background')) {
170 return;
171 }
172 return untooltip(1000);
173 });
174 tooltip = function(el) {
175 var a, baseline, cls, current_x, current_y, dy, h, i, key, keys, label, legend, name, plot_x, plot_y, rect, serie_index, subval, text, text_group, texts, traversal, value, w, x, x_elt, x_label, xlink, y, y_elt, _l, _len3, _len4, _len5, _m, _n, _ref4, _ref5, _ref6, _ref7, _ref8;
176 clearTimeout(tooltip_timeout);
177 tooltip_timeout = null;
178 tt.style.opacity = 1;
179 tt.style.display = '';
180 text_group = $('g.text', tt).one();
181 rect = $('rect', tt).one();
182 text_group.innerHTML = '';
183 label = sibl(el, '.label').one().textContent;
184 x_label = sibl(el, '.x_label').one().textContent;
185 value = sibl(el, '.value').one().textContent;
186 xlink = sibl(el, '.xlink').one().textContent;
187 serie_index = null;
188 parent = el;
189 traversal = [];
190 while (parent) {
191 traversal.push(parent);
192 if (parent.classList.contains('series')) {
193 break;
194 }
195 parent = parent.parentElement;
196 }
197 if (parent) {
198 _ref4 = parent.classList;
199 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
200 cls = _ref4[_l];
201 if (cls.indexOf('serie-') === 0) {
202 serie_index = +cls.replace('serie-', '');
203 break;
204 }
205 }
206 }
207 legend = null;
208 if (serie_index !== null) {
209 legend = config.legends[serie_index];
210 }
211 dy = 0;
212 keys = [[label, 'label']];
213 _ref5 = value.split('\n');
214 for (i = _m = 0, _len4 = _ref5.length; _m &lt; _len4; i = ++_m) {
215 subval = _ref5[i];
216 keys.push([subval, 'value-' + i]);
217 }
218 if (config.tooltip_fancy_mode) {
219 keys.push([xlink, 'xlink']);
220 keys.unshift([x_label, 'x_label']);
221 keys.unshift([legend, 'legend']);
222 }
223 texts = {};
224 for (_n = 0, _len5 = keys.length; _n &lt; _len5; _n++) {
225 _ref6 = keys[_n], key = _ref6[0], name = _ref6[1];
226 if (key) {
227 text = document.createElementNS(svg_ns, 'text');
228 text.textContent = key;
229 text.setAttribute('x', padding);
230 text.setAttribute('dy', dy);
231 text.classList.add(name.indexOf('value') === 0 ? 'value' : name);
232 if (name.indexOf('value') === 0 &amp;&amp; config.tooltip_fancy_mode) {
233 text.classList.add('color-' + serie_index);
234 }
235 if (name === 'xlink') {
236 a = document.createElementNS(svg_ns, 'a');
237 a.setAttributeNS(xlink_ns, 'href', key);
238 a.textContent = void 0;
239 a.appendChild(text);
240 text.textContent = 'Link &gt;';
241 text_group.appendChild(a);
242 } else {
243 text_group.appendChild(text);
244 }
245 dy += text.getBBox().height + padding / 2;
246 baseline = padding;
247 if (text.style.dominantBaseline !== void 0) {
248 text.style.dominantBaseline = 'text-before-edge';
249 } else {
250 baseline += text.getBBox().height * .8;
251 }
252 text.setAttribute('y', baseline);
253 texts[name] = text;
254 }
255 }
256 w = text_group.getBBox().width + 2 * padding;
257 h = text_group.getBBox().height + 2 * padding;
258 rect.setAttribute('width', w);
259 rect.setAttribute('height', h);
260 if (texts.value) {
261 texts.value.setAttribute('dx', (w - texts.value.getBBox().width) / 2 - padding);
262 }
263 if (texts.x_label) {
264 texts.x_label.setAttribute('dx', w - texts.x_label.getBBox().width - 2 * padding);
265 }
266 if (texts.xlink) {
267 texts.xlink.setAttribute('dx', w - texts.xlink.getBBox().width - 2 * padding);
268 }
269 x_elt = sibl(el, '.x').one();
270 y_elt = sibl(el, '.y').one();
271 x = parseInt(x_elt.textContent);
272 if (x_elt.classList.contains('centered')) {
273 x -= w / 2;
274 } else if (x_elt.classList.contains('left')) {
275 x -= w;
276 } else if (x_elt.classList.contains('auto')) {
277 x = xconvert(el.getBBox().x + el.getBBox().width / 2) - w / 2;
278 }
279 y = parseInt(y_elt.textContent);
280 if (y_elt.classList.contains('centered')) {
281 y -= h / 2;
282 } else if (y_elt.classList.contains('top')) {
283 y -= h;
284 } else if (y_elt.classList.contains('auto')) {
285 y = yconvert(el.getBBox().y + el.getBBox().height / 2) - h / 2;
286 }
287 _ref7 = get_translation(tt.parentElement), plot_x = _ref7[0], plot_y = _ref7[1];
288 if (x + w + plot_x &gt; config.width) {
289 x = config.width - w - plot_x;
290 }
291 if (y + h + plot_y &gt; config.height) {
292 y = config.height - h - plot_y;
293 }
294 if (x + plot_x &lt; 0) {
295 x = -plot_x;
296 }
297 if (y + plot_y &lt; 0) {
298 y = -plot_y;
299 }
300 _ref8 = get_translation(tt), current_x = _ref8[0], current_y = _ref8[1];
301 if (current_x === x &amp;&amp; current_y === y) {
302 return el;
303 }
304 tt.setAttribute('transform', "translate(" + x + " " + y + ")");
305 return el;
306 };
307 return untooltip = function(ms) {
308 return tooltip_timeout = setTimeout(function() {
309 tt.style.display = 'none';
310 tt.style.opacity = 0;
311 if (tooltip_el != null) {
312 tooltip_el.classList.remove('active');
313 }
314 return tooltip_timeout = null;
315 }, ms);
316 };
317 };
318
319 init_svg = function() {
320 var chart, charts, _i, _len, _results;
321 charts = $('.pygal-chart');
322 if (charts.length) {
323 _results = [];
324 for (_i = 0, _len = charts.length; _i &lt; _len; _i++) {
325 chart = charts[_i];
326 _results.push(init(chart));
327 }
328 return _results;
329 }
330 };
331
332 if (document.readyState !== 'loading') {
333 init_svg();
334 } else {
335 document.addEventListener('DOMContentLoaded', function() {
336 return init_svg();
337 });
338 }
339
340 window.pygal = window.pygal || {};
341
342 window.pygal.init = init;
343
344 window.pygal.init_svg = init_svg;
345
346 }).call(this);
347 </script></defs><title>Speed in Microseconds (us)</title><g class="graph custombox-graph vertical"><rect x="0" y="0" width="800" height="600" class="background" /><g transform="translate(74, 46)" class="plot"><rect x="0" y="0" width="706.0" height="360.0" class="background" /><g class="axis y always_show"><path d="M0.000000 360.000000 h706.000000" class="line" /><g class="guides"><path d="M0.000000 348.235611 h706.000000" class="guide line" /><text x="-5" y="351.73561054330287" class="">16</text><title>16</title></g><g class="guides"><path d="M0.000000 328.870360 h706.000000" class="guide line" /><text x="-5" y="332.37036040882197" class="">24</text><title>24</title></g><g class="guides"><path d="M0.000000 309.505110 h706.000000" class="guide line" /><text x="-5" y="313.00511027434106" class="">32</text><title>32</title></g><g class="guides"><path d="M0.000000 290.139860 h706.000000" class="guide line" /><text x="-5" y="293.63986013986016" class="">40</text><title>40</title></g><g class="guides"><path d="M0.000000 270.774610 h706.000000" class="guide line" /><text x="-5" y="274.27461000537926" class="">48</text><title>48</title></g><g class="guides"><path d="M0.000000 251.409360 h706.000000" class="guide line" /><text x="-5" y="254.90935987089836" class="">56</text><title>56</title></g><g class="guides"><path d="M0.000000 232.044110 h706.000000" class="guide line" /><text x="-5" y="235.54410973641745" class="">64</text><title>64</title></g><g class="guides"><path d="M0.000000 212.678860 h706.000000" class="guide line" /><text x="-5" y="216.17885960193655" class="">72</text><title>72</title></g><g class="guides"><path d="M0.000000 193.313609 h706.000000" class="guide line" /><text x="-5" y="196.81360946745565" class="">80</text><title>80</title></g><g class="guides"><path d="M0.000000 173.948359 h706.000000" class="guide line" /><text x="-5" y="177.44835933297477" class="">88</text><title>88</title></g><g class="guides"><path d="M0.000000 154.583109 h706.000000" class="guide line" /><text x="-5" y="158.08310919849387" class="">96</text><title>96</title></g><g class="guides"><path d="M0.000000 135.217859 h706.000000" class="guide line" /><text x="-5" y="138.71785906401297" class="">104</text><title>104</title></g><g class="guides"><path d="M0.000000 115.852609 h706.000000" class="guide line" /><text x="-5" y="119.35260892953207" class="">112</text><title>112</title></g><g class="guides"><path d="M0.000000 96.487359 h706.000000" class="guide line" /><text x="-5" y="99.98735879505114" class="">120</text><title>120</title></g><g class="guides"><path d="M0.000000 77.122109 h706.000000" class="guide line" /><text x="-5" y="80.62210866057023" class="">128</text><title>128</title></g><g class="guides"><path d="M0.000000 57.756859 h706.000000" class="guide line" /><text x="-5" y="61.25685852608939" class="">136</text><title>136</title></g><g class="guides"><path d="M0.000000 38.391608 h706.000000" class="guide line" /><text x="-5" y="41.89160839160843" class="">144</text><title>144</title></g><g class="guides"><path d="M0.000000 19.026358 h706.000000" class="guide line" /><text x="-5" y="22.526358257127526" class="">152</text><title>152</title></g></g><g class="axis x"><path d="M0.000000 0.000000 v360.000000" class="line" /><g class="guides"><path d="M24.891026 0.000000 v360.000000" class="guide line" /><text x="24.89102564102564" y="375.0" class="backwards" transform="rotate(270 24.891026 375.000000)">simple_tuple_d</text></g><g class="guides"><path d="M47.519231 0.000000 v360.000000" class="guide line" /><text x="47.51923076923077" y="375.0" class="backwards" transform="rotate(270 47.519231 375.000000)">simple_set_d</text></g><g class="guides"><path d="M70.147436 0.000000 v360.000000" class="guide line" /><text x="70.1474358974359" y="375.0" class="backwards" transform="rotate(270 70.147436 375.000000)">simple_list_e</text></g><g class="guides"><path d="M92.775641 0.000000 v360.000000" class="guide line" /><text x="92.77564102564102" y="375.0" class="backwards" transform="rotate(270 92.775641 375.000000)">simple_tuple_e</text></g><g class="guides"><path d="M115.403846 0.000000 v360.000000" class="guide line" /><text x="115.40384615384615" y="375.0" class="backwards" transform="rotate(270 115.403846 375.000000)">simple_set_e</text></g><g class="guides"><path d="M138.032051 0.000000 v360.000000" class="guide line" /><text x="138.03205128205127" y="375.0" class="backwards" transform="rotate(270 138.032051 375.000000)">simple_dict_d</text></g><g class="guides"><path d="M160.660256 0.000000 v360.000000" class="guide line" /><text x="160.6602564102564" y="375.0" class="backwards" transform="rotate(270 160.660256 375.000000)">simple_dict_e</text></g><g class="guides"><path d="M183.288462 0.000000 v360.000000" class="guide line" /><text x="183.28846153846155" y="375.0" class="backwards" transform="rotate(270 183.288462 375.000000)">simple_list_d</text></g><g class="guides"><path d="M205.916667 0.000000 v360.000000" class="guide line" /><text x="205.91666666666666" y="375.0" class="backwards" transform="rotate(270 205.916667 375.000000)">complex_homog_tuple_d</text></g><g class="guides"><path d="M228.544872 0.000000 v360.000000" class="guide line" /><text x="228.5448717948718" y="375.0" class="backwards" transform="rotate(270 228.544872 375.000000)">complex_homog_set_d</text></g><g class="guides"><path d="M251.173077 0.000000 v360.000000" class="guide line" /><text x="251.17307692307688" y="375.0" class="backwards" transform="rotate(270 251.173077 375.000000)">complex_heterog_set_d</text></g><g class="guides"><path d="M273.801282 0.000000 v360.000000" class="guide line" /><text x="273.8012820512821" y="375.0" class="backwards" transform="rotate(270 273.801282 375.000000)">complex_heterog_tuple_d</text></g><g class="guides"><path d="M296.429487 0.000000 v360.000000" class="guide line" /><text x="296.4294871794872" y="375.0" class="backwards" transform="rotate(270 296.429487 375.000000)">complex_homog_list_e</text></g><g class="guides"><path d="M319.057692 0.000000 v360.000000" class="guide line" /><text x="319.05769230769226" y="375.0" class="backwards" transform="rotate(270 319.057692 375.000000)">complex_homog_list_d</text></g><g class="guides"><path d="M341.685897 0.000000 v360.000000" class="guide line" /><text x="341.6858974358974" y="375.0" class="backwards" transform="rotate(270 341.685897 375.000000)">complex_homog_dict_d</text></g><g class="guides"><path d="M364.314103 0.000000 v360.000000" class="guide line" /><text x="364.3141025641026" y="375.0" class="backwards" transform="rotate(270 364.314103 375.000000)">complex_homog_tuple_e</text></g><g class="guides"><path d="M386.942308 0.000000 v360.000000" class="guide line" /><text x="386.9423076923077" y="375.0" class="backwards" transform="rotate(270 386.942308 375.000000)">complex_homog_set_e</text></g><g class="guides"><path d="M409.570513 0.000000 v360.000000" class="guide line" /><text x="409.5705128205129" y="375.0" class="backwards" transform="rotate(270 409.570513 375.000000)">complex_heterog_dict_d</text></g><g class="guides"><path d="M432.198718 0.000000 v360.000000" class="guide line" /><text x="432.19871794871796" y="375.0" class="backwards" transform="rotate(270 432.198718 375.000000)">complex_heterog_list_d</text></g><g class="guides"><path d="M454.826923 0.000000 v360.000000" class="guide line" /><text x="454.8269230769231" y="375.0" class="backwards" transform="rotate(270 454.826923 375.000000)">complex_heterog_set_e</text></g><g class="guides"><path d="M477.455128 0.000000 v360.000000" class="guide line" /><text x="477.4551282051282" y="375.0" class="backwards" transform="rotate(270 477.455128 375.000000)">complex_heterog_list_e</text></g><g class="guides"><path d="M500.083333 0.000000 v360.000000" class="guide line" /><text x="500.08333333333337" y="375.0" class="backwards" transform="rotate(270 500.083333 375.000000)">complex_heterog_tuple_e</text></g><g class="guides"><path d="M522.711538 0.000000 v360.000000" class="guide line" /><text x="522.7115384615385" y="375.0" class="backwards" transform="rotate(270 522.711538 375.000000)">complex_homog_dict_e</text></g><g class="guides"><path d="M545.339744 0.000000 v360.000000" class="guide line" /><text x="545.3397435897435" y="375.0" class="backwards" transform="rotate(270 545.339744 375.000000)">simple_cls_d</text></g><g class="guides"><path d="M567.967949 0.000000 v360.000000" class="guide line" /><text x="567.9679487179487" y="375.0" class="backwards" transform="rotate(270 567.967949 375.000000)">complex_heterog_dict_e</text></g><g class="guides"><path d="M590.596154 0.000000 v360.000000" class="guide line" /><text x="590.5961538461538" y="375.0" class="backwards" transform="rotate(270 590.596154 375.000000)">simple_cls_e</text></g><g class="guides"><path d="M613.224359 0.000000 v360.000000" class="guide line" /><text x="613.224358974359" y="375.0" class="backwards" transform="rotate(270 613.224359 375.000000)">complex_cls_d</text></g><g class="guides"><path d="M635.852564 0.000000 v360.000000" class="guide line" /><text x="635.8525641025641" y="375.0" class="backwards" transform="rotate(270 635.852564 375.000000)">state_cls_d</text></g><g class="guides"><path d="M658.480769 0.000000 v360.000000" class="guide line" /><text x="658.4807692307692" y="375.0" class="backwards" transform="rotate(270 658.480769 375.000000)">complex_cls_e</text></g><g class="guides"><path d="M681.108974 0.000000 v360.000000" class="guide line" /><text x="681.1089743589743" y="375.0" class="backwards" transform="rotate(270 681.108974 375.000000)">state_cls_e</text></g></g><g class="series serie-0 color-0"><g class="boxes"><g class="box"><path stroke-width="3" d="M19.912821 351.275962 L29.869231 351.275962" class="reactive tooltip-trigger" /><path stroke-width="3" d="M14.934615 350.387574 L34.847436 350.387574" class="reactive tooltip-trigger" /><path stroke-width="3" d="M19.912821 349.484674 L29.869231 349.484674" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 351.275962 L24.891026 350.605433" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 349.484674 L24.891026 350.157607" class="reactive tooltip-trigger" /><rect x="14.934615384615384" y="350.1576068020221" height="0.44782658055225966" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="351.47686922913465" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="193.76142332748918" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 14.6610
348 Q1-1.5IQR: 14.7440
349 Q1: 15.0210
350 Median: 15.1110
351 Q3: 15.2060
352 Q3+1.5IQR: 15.4840
353 Max: 79.8150</desc><desc class="x centered">24.891025641025642</desc><desc class="y centered">350.382250134253</desc><desc class="x_label" /></g></g></g><g class="series serie-1 color-1"><g class="boxes"><g class="box"><path stroke-width="3" d="M42.541026 350.360944 L52.497436 350.360944" class="reactive tooltip-trigger" /><path stroke-width="3" d="M37.562821 349.499195 L57.475641 349.499195" class="reactive tooltip-trigger" /><path stroke-width="3" d="M42.541026 348.608394 L52.497436 348.608394" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 350.360944 L47.519231 349.704954" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 348.608394 L47.519231 349.266815" class="reactive tooltip-trigger" /><rect x="37.562820512820515" y="349.2668147164188" height="0.43813965473452754" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="350.66352851859193" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="182.07934304319113" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 14.9970
354 Q1-1.5IQR: 15.1220
355 Q1: 15.3930
356 Median: 15.4780
357 Q3: 15.5740
358 Q3+1.5IQR: 15.8460
359 Max: 84.6410</desc><desc class="x centered">47.519230769230774</desc><desc class="y centered">349.4880605795766</desc><desc class="x_label" /></g></g></g><g class="series serie-2 color-2"><g class="boxes"><g class="box"><path stroke-width="3" d="M65.169231 349.961535 L75.125641 349.961535" class="reactive tooltip-trigger" /><path stroke-width="3" d="M60.191026 348.739106 L80.103846 348.739106" class="reactive tooltip-trigger" /><path stroke-width="3" d="M65.169231 347.499735 L75.125641 347.499735" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 349.961535 L70.147436 349.039269" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 347.499735 L70.147436 348.424422" class="reactive tooltip-trigger" /><rect x="60.19102564102564" y="348.4244220347192" height="0.6148467942418279" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="350.2447539091966" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="199.26116665419207" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.1700
360 Q1-1.5IQR: 15.2870
361 Q1: 15.6680
362 Median: 15.7920
363 Q3: 15.9220
364 Q3+1.5IQR: 16.3040
365 Max: 77.5430</desc><desc class="x centered">70.1474358974359</desc><desc class="y centered">348.7328132437923</desc><desc class="x_label" /></g></g></g><g class="series serie-3 color-3"><g class="boxes"><g class="box"><path stroke-width="3" d="M87.797436 348.538191 L97.753846 348.538191" class="reactive tooltip-trigger" /><path stroke-width="3" d="M82.819231 347.335127 L102.732051 347.335127" class="reactive tooltip-trigger" /><path stroke-width="3" d="M87.797436 346.081234 L97.753846 346.081234" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 348.538191 L92.775641 347.620759" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 346.081234 L92.775641 347.005921" class="reactive tooltip-trigger" /><rect x="82.81923076923077" y="347.00592145575246" height="0.6148379879456343" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="348.8867613914056" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="314.83055077596896" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.7310
366 Q1-1.5IQR: 15.8750
367 Q1: 16.2540
368 Median: 16.3720
369 Q3: 16.5080
370 Q3+1.5IQR: 16.8900
371 Max: 29.8000</desc><desc class="x centered">92.77564102564102</desc><desc class="y centered">347.3162465274706</desc><desc class="x_label" /></g></g></g><g class="series serie-4 color-4"><g class="boxes"><g class="box"><path stroke-width="3" d="M110.425641 348.402635 L120.382051 348.402635" class="reactive tooltip-trigger" /><path stroke-width="3" d="M105.447436 347.279445 L125.360256 347.279445" class="reactive tooltip-trigger" /><path stroke-width="3" d="M110.425641 346.107855 L120.382051 346.107855" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 348.402635 L115.403846 347.543308" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 346.107855 L115.403846 346.969613" class="reactive tooltip-trigger" /><rect x="105.4474358974359" y="346.96961309652846" height="0.5736949721089672" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="348.58902051695435" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="287.7216272310626" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.8540
372 Q1-1.5IQR: 15.9310
373 Q1: 16.2860
374 Median: 16.3950
375 Q3: 16.5230
376 Q3+1.5IQR: 16.8790
377 Max: 40.9990</desc><desc class="x centered">115.40384615384615</desc><desc class="y centered">347.26057136164815</desc><desc class="x_label" /></g></g></g><g class="series serie-5 color-5"><g class="boxes"><g class="box"><path stroke-width="3" d="M133.053846 345.831901 L143.010256 345.831901" class="reactive tooltip-trigger" /><path stroke-width="3" d="M128.075641 343.948631 L147.988462 343.948631" class="reactive tooltip-trigger" /><path stroke-width="3" d="M133.053846 341.820871 L143.010256 341.820871" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 345.831901 L138.032051 344.401292" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 341.820871 L138.032051 343.370092" class="reactive tooltip-trigger" /><rect x="128.07564102564103" y="343.3700923634104" height="1.0311996721827654" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="345.831901271832" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="303.39779434962605" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.9930
378 Q1-1.5IQR: 16.9930
379 Q1: 17.5840
380 Median: 17.7710
381 Q3: 18.0100
382 Q3+1.5IQR: 18.6500
383 Max: 34.5230</desc><desc class="x centered">138.0320512820513</desc><desc class="y centered">343.87455751858914</desc><desc class="x_label" /></g></g></g><g class="series serie-6 color-6"><g class="boxes"><g class="box"><path stroke-width="3" d="M155.682051 345.171059 L165.638462 345.171059" class="reactive tooltip-trigger" /><path stroke-width="3" d="M150.703846 342.931953 L170.616667 342.931953" class="reactive tooltip-trigger" /><path stroke-width="3" d="M155.682051 339.850454 L165.638462 339.850454" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 345.171059 L160.660256 343.495961" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 339.850454 L160.660256 342.041152" class="reactive tooltip-trigger" /><rect x="150.70384615384614" y="342.04115181677633" height="1.4548089381907516" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="345.17105919254857" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="286.3200611596844" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.2660
384 Q1-1.5IQR: 17.2660
385 Q1: 17.9580
386 Median: 18.1910
387 Q3: 18.5590
388 Q3+1.5IQR: 19.4640
389 Max: 41.5780</desc><desc class="x centered">160.6602564102564</desc><desc class="y centered">342.69811560321426</desc><desc class="x_label" /></g></g></g><g class="series serie-7 color-7"><g class="boxes"><g class="box"><path stroke-width="3" d="M178.310256 343.924422 L188.266667 343.924422" class="reactive tooltip-trigger" /><path stroke-width="3" d="M173.332051 342.786719 L193.244872 342.786719" class="reactive tooltip-trigger" /><path stroke-width="3" d="M178.310256 341.593334 L188.266667 341.593334" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 343.924422 L183.288462 343.060252" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 341.593334 L183.288462 342.474448" class="reactive tooltip-trigger" /><rect x="173.33205128205125" y="342.47444800860205" height="0.5858036293811324" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="344.47875221694994" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="148.6452444163595" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.5520
390 Q1-1.5IQR: 17.7810
391 Q1: 18.1380
392 Median: 18.2510
393 Q3: 18.3800
394 Q3+1.5IQR: 18.7440
395 Max: 98.4530</desc><desc class="x centered">183.28846153846152</desc><desc class="y centered">342.76783505021314</desc><desc class="x_label" /></g></g></g><g class="series serie-8 color-8"><g class="boxes"><g class="box"><path stroke-width="3" d="M200.938462 322.039262 L210.894872 322.039262" class="reactive tooltip-trigger" /><path stroke-width="3" d="M195.960256 320.819255 L215.873077 320.819255" class="reactive tooltip-trigger" /><path stroke-width="3" d="M200.938462 319.555675 L210.894872 319.555675" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 322.039262 L205.916667 321.124261" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 319.555675 L205.916667 320.497306" class="reactive tooltip-trigger" /><rect x="195.9602564102564" y="320.4973055100652" height="0.6269554515139362" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="322.458044971122" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="125.03415530237399" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 26.6490
396 Q1-1.5IQR: 26.8220
397 Q1: 27.2000
398 Median: 27.3260
399 Q3: 27.4590
400 Q3+1.5IQR: 27.8480
401 Max: 108.2070</desc><desc class="x centered">205.91666666666666</desc><desc class="y centered">320.8071515192701</desc><desc class="x_label" /></g></g></g><g class="series serie-9 color-9"><g class="boxes"><g class="box"><path stroke-width="3" d="M223.566667 320.180200 L233.523077 320.180200" class="reactive tooltip-trigger" /><path stroke-width="3" d="M218.588462 318.747177 L238.501282 318.747177" class="reactive tooltip-trigger" /><path stroke-width="3" d="M223.566667 317.277838 L233.523077 317.277838" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 320.180200 L228.544872 319.095748" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 317.277838 L228.544872 318.369552" class="reactive tooltip-trigger" /><rect x="218.58846153846153" y="318.36955244004093" height="0.7261958049422219" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="320.8386199381037" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="165.27272048799827" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 27.3180
402 Q1-1.5IQR: 27.5900
403 Q1: 28.0380
404 Median: 28.1820
405 Q3: 28.3380
406 Q3+1.5IQR: 28.7890
407 Max: 91.5840</desc><desc class="x centered">228.5448717948718</desc><desc class="y centered">318.7341031612273</desc><desc class="x_label" /></g></g></g><g class="series serie-10 color-10"><g class="boxes"><g class="box"><path stroke-width="3" d="M246.194872 318.149274 L256.151282 318.149274" class="reactive tooltip-trigger" /><path stroke-width="3" d="M241.216667 316.069931 L261.129487 316.069931" class="reactive tooltip-trigger" /><path stroke-width="3" d="M246.194872 314.097101 L256.151282 314.097101" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 318.149274 L251.173077 316.646048" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 314.097101 L251.173077 315.626948" class="reactive tooltip-trigger" /><rect x="241.21666666666664" y="315.62694817262684" height="1.0190998212067939" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="318.5172186162615" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="260.455352785692" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 28.2770
408 Q1-1.5IQR: 28.4290
409 Q1: 29.0500
410 Median: 29.2880
411 Q3: 29.4710
412 Q3+1.5IQR: 30.1030
413 Max: 52.2630</desc><desc class="x centered">251.1730769230769</desc><desc class="y centered">316.117860437957</desc><desc class="x_label" /></g></g></g><g class="series serie-11 color-11"><g class="boxes"><g class="box"><path stroke-width="3" d="M268.823077 299.720822 L278.779487 299.720822" class="reactive tooltip-trigger" /><path stroke-width="3" d="M263.844872 295.586337 L283.757692 295.586337" class="reactive tooltip-trigger" /><path stroke-width="3" d="M268.823077 291.379234 L278.779487 291.379234" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 299.720822 L273.801282 296.600593" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 291.379234 L273.801282 294.513985" class="reactive tooltip-trigger" /><rect x="263.84487179487184" y="294.5139851325831" height="2.086607852613554" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="300.4542810391788" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="232.00295830542507" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 35.7390
414 Q1-1.5IQR: 36.0420
415 Q1: 37.3310
416 Median: 37.7500
417 Q3: 38.1930
418 Q3+1.5IQR: 39.4880
419 Max: 64.0170</desc><desc class="x centered">273.8012820512821</desc><desc class="y centered">295.5601942560056</desc><desc class="x_label" /></g></g></g><g class="series serie-12 color-12"><g class="boxes"><g class="box"><path stroke-width="3" d="M291.451282 299.626419 L301.407692 299.626419" class="reactive tooltip-trigger" /><path stroke-width="3" d="M286.473077 295.809035 L306.385897 295.809035" class="reactive tooltip-trigger" /><path stroke-width="3" d="M291.451282 291.149275 L301.407692 291.149275" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 299.626419 L296.429487 296.973372" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 291.149275 L296.429487 294.714901" class="reactive tooltip-trigger" /><rect x="286.473076923077" y="294.71490078033844" height="2.2584715292119313" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="299.6264187462058" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="210.40586032560515" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.0810
420 Q1-1.5IQR: 36.0810
421 Q1: 37.1770
422 Median: 37.6580
423 Q3: 38.1100
424 Q3+1.5IQR: 39.5830
425 Max: 72.9390</desc><desc class="x centered">296.42948717948724</desc><desc class="y centered">295.65460039313604</desc><desc class="x_label" /></g></g></g><g class="series serie-13 color-13"><g class="boxes"><g class="box"><path stroke-width="3" d="M314.079487 298.779183 L324.035897 298.779183" class="reactive tooltip-trigger" /><path stroke-width="3" d="M309.101282 296.201183 L329.014103 296.201183" class="reactive tooltip-trigger" /><path stroke-width="3" d="M314.079487 293.531202 L324.035897 293.531202" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 298.779183 L319.057692 296.816030" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 293.531202 L319.057692 295.504645" class="reactive tooltip-trigger" /><rect x="309.1012820512821" y="295.5046450202188" height="1.3113851951635525" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="299.09386678993343" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="126.05808978019346" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.3010
426 Q1-1.5IQR: 36.4310
427 Q1: 37.2420
428 Median: 37.4960
429 Q3: 37.7837
430 Q3+1.5IQR: 38.5990
431 Max: 107.7840</desc><desc class="x centered">319.0576923076924</desc><desc class="y centered">296.16644874704707</desc><desc class="x_label" /></g></g></g><g class="series serie-14 color-14"><g class="boxes"><g class="box"><path stroke-width="3" d="M336.707692 297.297743 L346.664103 297.297743" class="reactive tooltip-trigger" /><path stroke-width="3" d="M331.729487 294.037115 L351.642308 294.037115" class="reactive tooltip-trigger" /><path stroke-width="3" d="M336.707692 290.423073 L346.664103 290.423073" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 297.297743 L341.685897 294.775418" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 290.423073 L341.685897 293.037389" class="reactive tooltip-trigger" /><rect x="331.7294871794872" y="293.0373894175988" height="1.7380282302116825" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="297.2977434237041" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="154.82516844879646" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 37.0430
432 Q1-1.5IQR: 37.0430
433 Q1: 38.0850
434 Median: 38.3900
435 Q3: 38.8030
436 Q3+1.5IQR: 39.8830
437 Max: 95.9000</desc><desc class="x centered">341.68589743589746</desc><desc class="y centered">293.9141477895811</desc><desc class="x_label" /></g></g></g><g class="series serie-15 color-15"><g class="boxes"><g class="box"><path stroke-width="3" d="M359.335897 295.816304 L369.292308 295.816304" class="reactive tooltip-trigger" /><path stroke-width="3" d="M354.357692 291.991659 L374.270513 291.991659" class="reactive tooltip-trigger" /><path stroke-width="3" d="M359.335897 288.036303 L369.292308 288.036303" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 295.816304 L364.314103 292.918777" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 288.036303 L364.314103 290.974990" class="reactive tooltip-trigger" /><rect x="354.35769230769233" y="290.9749900732333" height="1.943787340875815" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="295.9857373846587" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="194.93544351140963" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 37.5850
438 Q1-1.5IQR: 37.6550
439 Q1: 38.8520
440 Median: 39.2350
441 Q3: 39.6550
442 Q3+1.5IQR: 40.8690
443 Max: 79.3300</desc><desc class="x centered">364.3141025641026</desc><desc class="y centered">291.94760674058904</desc><desc class="x_label" /></g></g></g><g class="series serie-16 color-16"><g class="boxes"><g class="box"><path stroke-width="3" d="M381.964103 293.163258 L391.920513 293.163258" class="reactive tooltip-trigger" /><path stroke-width="3" d="M376.985897 289.292635 L396.898718 289.292635" class="reactive tooltip-trigger" /><path stroke-width="3" d="M381.964103 285.259818 L391.920513 285.259818" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 293.163258 L386.942308 290.241531" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 285.259818 L386.942308 288.251749" class="reactive tooltip-trigger" /><rect x="376.98589743589747" y="288.25174864958433" height="1.9897826259175417" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="293.7805263348517" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="179.7821326170046" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 38.4960
444 Q1-1.5IQR: 38.7510
445 Q1: 39.9580
446 Median: 40.3500
447 Q3: 40.7800
448 Q3+1.5IQR: 42.0160
449 Max: 85.5900</desc><desc class="x centered">386.94230769230774</desc><desc class="y centered">289.24179826089346</desc><desc class="x_label" /></g></g></g><g class="series serie-17 color-17"><g class="boxes"><g class="box"><path stroke-width="3" d="M404.592308 292.369282 L414.548718 292.369282" class="reactive tooltip-trigger" /><path stroke-width="3" d="M399.614103 287.670788 L419.526923 287.670788" class="reactive tooltip-trigger" /><path stroke-width="3" d="M404.592308 282.621302 L414.548718 282.621302" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 292.369282 L409.570513 288.837552" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 282.621302 L409.570513 286.351535" class="reactive tooltip-trigger" /><rect x="399.6141025641026" y="286.3515348622957" height="2.4860174166697107" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="292.93329899653946" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="107.8305537208756" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 38.8460
450 Q1-1.5IQR: 39.0790
451 Q1: 40.5380
452 Median: 41.0200
453 Q3: 41.5650
454 Q3+1.5IQR: 43.1060
455 Max: 115.3140</desc><desc class="x centered">409.5705128205129</desc><desc class="y centered">287.57009200860745</desc><desc class="x_label" /></g></g></g><g class="series serie-18 color-18"><g class="boxes"><g class="box"><path stroke-width="3" d="M427.220513 291.236414 L437.176923 291.236414" class="reactive tooltip-trigger" /><path stroke-width="3" d="M422.242308 286.398737 L442.155128 286.398737" class="reactive tooltip-trigger" /><path stroke-width="3" d="M427.220513 281.440026 L437.176923 281.440026" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 291.236414 L432.198718 287.576385" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 281.440026 L432.198718 285.129106" class="reactive tooltip-trigger" /><rect x="422.24230769230775" y="285.1291064681754" height="2.4472785196950895" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="291.52205480563975" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="153.3800464364234" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 39.4290
456 Q1-1.5IQR: 39.5470
457 Q1: 41.0590
458 Median: 41.5455
459 Q3: 42.0700
460 Q3+1.5IQR: 43.5940
461 Max: 96.4970</desc><desc class="x centered">432.198717948718</desc><desc class="y centered">286.35613351017025</desc><desc class="x_label" /></g></g></g><g class="series serie-19 color-19"><g class="boxes"><g class="box"><path stroke-width="3" d="M449.848718 283.763849 L459.805128 283.763849" class="reactive tooltip-trigger" /><path stroke-width="3" d="M444.870513 280.033616 L464.783333 280.033616" class="reactive tooltip-trigger" /><path stroke-width="3" d="M449.848718 276.225923 L459.805128 276.225923" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 283.763849 L454.826923 280.951047" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 276.225923 L454.826923 279.070199" class="reactive tooltip-trigger" /><rect x="444.87051282051283" y="279.07019855809006" height="1.8808487419494213" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="284.3738520873541" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="151.81871653942275" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 42.3820
462 Q1-1.5IQR: 42.6340
463 Q1: 43.7960
464 Median: 44.1750
465 Q3: 44.5730
466 Q3+1.5IQR: 45.7480
467 Max: 97.1420</desc><desc class="x centered">454.8269230769231</desc><desc class="y centered">280.00892683641706</desc><desc class="x_label" /></g></g></g><g class="series serie-20 color-20"><g class="boxes"><g class="box"><path stroke-width="3" d="M472.476923 267.995700 L482.433333 267.995700" class="reactive tooltip-trigger" /><path stroke-width="3" d="M467.498718 262.568582 L487.411538 262.568582" class="reactive tooltip-trigger" /><path stroke-width="3" d="M472.476923 257.151160 L482.433333 257.151160" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 267.995700 L477.455128 263.936865" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 257.151160 L477.455128 261.225120" class="reactive tooltip-trigger" /><rect x="467.49871794871797" y="261.22511994264744" height="2.7117448039625742" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="268.8937571536371" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="70.78967797285878" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 48.7770
468 Q1-1.5IQR: 49.1480
469 Q1: 50.8247
470 Median: 51.3900
471 Q3: 51.9450
472 Q3+1.5IQR: 53.6280
473 Max: 130.6160</desc><desc class="x centered">477.45512820512823</desc><desc class="y centered">262.57548532730135</desc><desc class="x_label" /></g></g></g><g class="series serie-21 color-21"><g class="boxes"><g class="box"><path stroke-width="3" d="M495.105128 266.838623 L505.061538 266.838623" class="reactive tooltip-trigger" /><path stroke-width="3" d="M490.126923 261.597899 L510.039744 261.597899" class="reactive tooltip-trigger" /><path stroke-width="3" d="M495.105128 256.282146 L505.061538 256.282146" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 266.838623 L500.083333 262.887506" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 256.282146 L500.083333 260.252015" class="reactive tooltip-trigger" /><rect x="490.1269230769231" y="260.2520154064823" height="2.635491085184867" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="267.581768727184" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="187.59602087748257" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 49.3190
474 Q1-1.5IQR: 49.6260
475 Q1: 51.2583
476 Median: 51.7910
477 Q3: 52.3470
478 Q3+1.5IQR: 53.9870
479 Max: 82.3620</desc><desc class="x centered">500.08333333333337</desc><desc class="y centered">261.5716380111093</desc><desc class="x_label" /></g></g></g><g class="series serie-22 color-22"><g class="boxes"><g class="box"><path stroke-width="3" d="M517.733333 262.532274 L527.689744 262.532274" class="reactive tooltip-trigger" /><path stroke-width="3" d="M512.755128 256.591987 L532.667949 256.591987" class="reactive tooltip-trigger" /><path stroke-width="3" d="M517.733333 250.501614 L527.689744 250.501614" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 262.532274 L522.711538 258.090369" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 250.501614 L522.711538 255.079074" class="reactive tooltip-trigger" /><rect x="512.7551282051282" y="255.07907373168382" height="3.011295372282575" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="264.50995648742946" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="111.95535240960655" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 50.5880
480 Q1-1.5IQR: 51.4050
481 Q1: 53.2400
482 Median: 53.8590
483 Q3: 54.4840
484 Q3+1.5IQR: 56.3750
485 Max: 113.6100</desc><desc class="x centered">522.7115384615385</desc><desc class="y centered">256.55906339322286</desc><desc class="x_label" /></g></g></g><g class="series serie-23 color-23"><g class="boxes"><g class="box"><path stroke-width="3" d="M540.361538 259.867136 L550.317949 259.867136" class="reactive tooltip-trigger" /><path stroke-width="3" d="M535.383333 252.655995 L555.296154 252.655995" class="reactive tooltip-trigger" /><path stroke-width="3" d="M540.361538 245.154378 L550.317949 245.154378" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 259.867136 L545.339744 254.466649" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 245.154378 L545.339744 250.775155" class="reactive tooltip-trigger" /><rect x="535.3833333333333" y="250.7751549782874" height="3.691493690609036" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="260.31253227395433" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="124.63716746977224" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 52.3220
486 Q1-1.5IQR: 52.5060
487 Q1: 54.7370
488 Median: 55.4850
489 Q3: 56.2620
490 Q3+1.5IQR: 58.5840
491 Max: 108.3710</desc><desc class="x centered">545.3397435897435</desc><desc class="y centered">252.5838625417835</desc><desc class="x_label" /></g></g></g><g class="series serie-24 color-24"><g class="boxes"><g class="box"><path stroke-width="3" d="M562.989744 252.317102 L572.946154 252.317102" class="reactive tooltip-trigger" /><path stroke-width="3" d="M558.011538 246.173478 L577.924359 246.173478" class="reactive tooltip-trigger" /><path stroke-width="3" d="M562.989744 239.988701 L572.946154 239.988701" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 252.317102 L567.967949 247.715434" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 239.988701 L567.967949 244.638787" class="reactive tooltip-trigger" /><rect x="558.0115384615385" y="244.6387868868453" height="3.0766468963672082" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="253.098978031584" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="101.56589550642235" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 55.3020
492 Q1-1.5IQR: 55.6250
493 Q1: 57.5260
494 Median: 58.1630
495 Q3: 58.7970
496 Q3+1.5IQR: 60.7180
497 Max: 117.9020</desc><desc class="x centered">567.9679487179487</desc><desc class="y centered">246.16670041229338</desc><desc class="x_label" /></g></g></g><g class="series serie-25 color-25"><g class="boxes"><g class="box"><path stroke-width="3" d="M585.617949 245.410976 L595.574359 245.410976" class="reactive tooltip-trigger" /><path stroke-width="3" d="M580.639744 239.361755 L600.552564 239.361755" class="reactive tooltip-trigger" /><path stroke-width="3" d="M585.617949 232.528245 L595.574359 232.528245" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 245.410976 L590.596154 240.831085" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 232.528245 L590.596154 237.517214" class="reactive tooltip-trigger" /><rect x="580.6397435897436" y="237.51721440826213" height="3.3138709033464977" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="245.93141907425536" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="176.27218952881162" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 58.2630
498 Q1-1.5IQR: 58.4780
499 Q1: 60.3700
500 Median: 60.9770
501 Q3: 61.7390
502 Q3+1.5IQR: 63.8000
503 Max: 87.0400</desc><desc class="x centered">590.5961538461538</desc><desc class="y centered">239.12985507068953</desc><desc class="x_label" /></g></g></g><g class="series serie-26 color-26"><g class="boxes"><g class="box"><path stroke-width="3" d="M608.246154 85.008606 L618.202564 85.008606" class="reactive tooltip-trigger" /><path stroke-width="3" d="M603.267949 77.925763 L623.180769 77.925763" class="reactive tooltip-trigger" /><path stroke-width="3" d="M608.246154 70.704944 L618.202564 70.704944" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 85.008606 L613.224359 79.700109" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 70.704944 L613.224359 76.107853" class="reactive tooltip-trigger" /><rect x="603.2679487179488" y="76.1078530845532" height="3.5922555387548414" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="86.40290649249584" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="-191.30930655701763" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 124.1660
504 Q1-1.5IQR: 124.7420
505 Q1: 126.9350
506 Median: 127.6680
507 Q3: 128.4190
508 Q3+1.5IQR: 130.6510
509 Max: 238.8920</desc><desc class="x centered">613.224358974359</desc><desc class="y centered">77.88945486835217</desc><desc class="x_label" /></g></g></g><g class="series serie-27 color-27"><g class="boxes"><g class="box"><path stroke-width="3" d="M630.874359 76.773530 L640.830769 76.773530" class="reactive tooltip-trigger" /><path stroke-width="3" d="M625.896154 69.480102 L645.808974 69.480102" class="reactive tooltip-trigger" /><path stroke-width="3" d="M630.874359 61.838087 L640.830769 61.838087" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 76.773530 L635.852564 71.324634" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 61.838087 L635.852564 67.562937" class="reactive tooltip-trigger" /><rect x="625.8961538461539" y="67.5629365640944" height="3.7616974838987858" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="79.11189206876867" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="7.993001315929121" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 127.1780
510 Q1-1.5IQR: 128.1440
511 Q1: 130.3950
512 Median: 131.1570
513 Q3: 131.9490
514 Q3+1.5IQR: 134.3140
515 Max: 156.5580</desc><desc class="x centered">635.8525641025641</desc><desc class="y centered">69.39585791961628</desc><desc class="x_label" /></g></g></g><g class="series serie-28 color-28"><g class="boxes"><g class="box"><path stroke-width="3" d="M653.502564 43.586342 L663.458974 43.586342" class="reactive tooltip-trigger" /><path stroke-width="3" d="M648.524359 36.597903 L668.437179 36.597903" class="reactive tooltip-trigger" /><path stroke-width="3" d="M653.502564 29.515061 L663.458974 29.515061" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 43.586342 L658.480769 38.345013" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 29.515061 L658.480769 34.819932" class="reactive tooltip-trigger" /><rect x="648.524358974359" y="34.81993184556006" height="3.525081111357167" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="45.13071990323431" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="-126.41635273424919" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 141.2160
516 Q1-1.5IQR: 141.8540
517 Q1: 144.0192
518 Median: 144.7410
519 Q3: 145.4755
520 Q3+1.5IQR: 147.6670
521 Max: 212.0840</desc><desc class="x centered">658.4807692307692</desc><desc class="y centered">36.57285020169803</desc><desc class="x_label" /></g></g></g><g class="series serie-29 color-29"><g class="boxes"><g class="box"><path stroke-width="3" d="M676.130769 22.988970 L686.087179 22.988970" class="reactive tooltip-trigger" /><path stroke-width="3" d="M671.152564 16.257129 L691.065385 16.257129" class="reactive tooltip-trigger" /><path stroke-width="3" d="M676.130769 9.251747 L686.087179 9.251747" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 22.988970 L681.108974 17.908624" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 9.251747 L681.108974 14.470078" class="reactive tooltip-trigger" /><rect x="671.1525641025642" y="14.470078402546164" height="3.4385460417684044" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="26.690150732592883" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="-243.99972799019167" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 148.8340
522 Q1-1.5IQR: 150.3630
523 Q1: 152.4617
524 Median: 153.1440
525 Q3: 153.8822
526 Q3+1.5IQR: 156.0380
527 Max: 260.6590</desc><desc class="x centered">681.1089743589744</desc><desc class="y centered">16.175309784142826</desc><desc class="x_label" /></g></g></g></g><g class="titles"><text x="400.0" y="26" class="title plot_title">Speed in Microseconds (us)</text><text x="427.0" y="580.0" class="title">Trial</text><text x="0" y="252.0" class="title" transform="rotate(-90 0.000000 226.000000)">Duration</text></g><g transform="translate(74, 46)" class="plot overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot text-overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot tooltip-overlay"><g transform="translate(0 0)" style="opacity: 0" class="tooltip"><rect rx="0" ry="0" width="0" height="0" class="tooltip-box" /><g class="text" /></g></g></g></svg>
0 <?xml version='1.0' encoding='utf-8'?>
1 <svg xmlns="http://www.w3.org/2000/svg" id="chart-7ffad177-5146-4ca1-823f-60f74aae7bd9" class="pygal-chart" viewBox="0 0 800 600"><!--Generated with pygal 3.0.0 (etree) ©Kozea 2012-2016 on 2022-06-20--><!--http://pygal.org--><!--http://github.com/Kozea/pygal--><defs><style type="text/css">#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9{-webkit-user-select:none;-webkit-font-smoothing:antialiased;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .title{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .legends .legend text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis text{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis text.major{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay text.value{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:16px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay text.label{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:10px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:14px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 text.no_data{font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace;font-size:64px}
2 #chart-7ffad177-5146-4ca1-823f-60f74aae7bd9{background-color:rgba(249,249,249,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 path,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 rect,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 circle{-webkit-transition:150ms;-moz-transition:150ms;transition:150ms}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .graph &gt; .background{fill:rgba(249,249,249,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .plot &gt; .background{fill:rgba(255,255,255,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .graph{fill:rgba(0,0,0,.87)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 text.no_data{fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .title{fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .legends .legend text{fill:rgba(0,0,0,.87)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .legends .legend:hover text{fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .line{stroke:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .guide.line{stroke:rgba(0,0,0,.54)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .major.line{stroke:rgba(0,0,0,.87)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis text.major{fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y .guides:hover .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .line-graph .axis.x .guides:hover .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .stackedline-graph .axis.x .guides:hover .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .xy-graph .axis.x .guides:hover .guide.line{stroke:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .guides:hover text{fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .reactive{fill-opacity:.7;stroke-opacity:.8;stroke-width:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .ci{stroke:rgba(0,0,0,.87)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .reactive.active,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .active .reactive{fill-opacity:.8;stroke-opacity:.9;stroke-width:4}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .ci .reactive.active{stroke-width:1.5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .series text{fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip rect{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,1);-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;transition:opacity 150ms}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip .label{fill:rgba(0,0,0,.87)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip .legend{font-size:.8em;fill:rgba(0,0,0,.54)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip .x_label{font-size:.6em;fill:rgba(0,0,0,1)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip .xlink{font-size:.5em;text-decoration:underline}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip .value{font-size:1.5em}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .bound{font-size:.5em}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .max-value{font-size:.75em;fill:rgba(0,0,0,.54)}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .map-element{fill:rgba(255,255,255,1);stroke:rgba(0,0,0,.54) !important}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .map-element .reactive{fill-opacity:inherit;stroke-opacity:inherit}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-0,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-0 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-1,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-1 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-2,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-2 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-3,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-3 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-4,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-4 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-5,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-5 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-6,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-6 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-7,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-7 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-8,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-8 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-9,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-9 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-10,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-10 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-11,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-11 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-12,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-12 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-13,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-13 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-14,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-14 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-15,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-15 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-16,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-16 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-17,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-17 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-18,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-18 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-19,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-19 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-20,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-20 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-21,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-21 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-22,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-22 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-23,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-23 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-24,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-24 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-25,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-25 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-26,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-26 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-27,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-27 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-28,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-28 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-29,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .color-29 a:visited{stroke:#3F51B5;fill:#3F51B5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-0 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-1 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-2 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-3 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-4 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-5 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-6 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-7 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-8 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-9 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-10 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-11 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-12 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-13 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-14 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-15 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-16 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-17 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-18 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-19 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-20 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-21 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-22 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-23 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-24 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-25 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-26 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-27 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-28 text{fill:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .text-overlay .color-29 text{fill:black}
3 #chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 text.no_data{text-anchor:middle}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .guide.line{fill:none}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .centered{text-anchor:middle}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .title{text-anchor:middle}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .legends .legend text{fill-opacity:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.x text{text-anchor:middle}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.x:not(.web) text[transform]{text-anchor:start}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.x:not(.web) text[transform].backwards{text-anchor:end}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y text{text-anchor:end}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y text[transform].backwards{text-anchor:start}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y2 text{text-anchor:start}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y2 text[transform].backwards{text-anchor:end}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .guide.line{stroke-dasharray:4,4;stroke:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .major.guide.line{stroke-dasharray:6,6;stroke:black}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .horizontal .axis.y .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .horizontal .axis.y2 .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .vertical .axis.x .guide.line{opacity:0}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .horizontal .axis.always_show .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .vertical .axis.always_show .guide.line{opacity:1 !important}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y .guides:hover .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.y2 .guides:hover .guide.line,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis.x .guides:hover .guide.line{opacity:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .axis .guides:hover text{opacity:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .nofill{fill:none}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .subtle-fill{fill-opacity:.2}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .dot{stroke-width:1px;fill-opacity:1;stroke-opacity:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .dot.active{stroke-width:5px}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .dot.negative{fill:transparent}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 text,#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 tspan{stroke:none !important}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .series text.active{opacity:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip rect{fill-opacity:.95;stroke-width:.5}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .tooltip text{fill-opacity:1}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .showable{visibility:hidden}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .showable.shown{visibility:visible}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .gauge-background{fill:rgba(229,229,229,1);stroke:none}#chart-7ffad177-5146-4ca1-823f-60f74aae7bd9 .bg-lines{stroke:rgba(249,249,249,1);stroke-width:2px}
4 .tooltip .value{font-size:1em !important}.axis text{font-size:9px !important}</style><script type="text/javascript">window.pygal = window.pygal || {};window.pygal.config = window.pygal.config || {};window.pygal.config['7ffad177-5146-4ca1-823f-60f74aae7bd9'] = {"allow_interruptions": false, "box_mode": "tukey", "classes": ["pygal-chart"], "css": ["file://style.css", "file://graph.css", "inline:\n .tooltip .value {\n font-size: 1em !important;\n }\n .axis text {\n font-size: 9px !important;\n }\n "], "defs": [], "disable_xml_declaration": false, "dots_size": 2.5, "dynamic_print_values": false, "explicit_size": false, "fill": false, "force_uri_protocol": "https", "formatter": null, "half_pie": false, "height": 600, "include_x_axis": false, "inner_radius": 0, "interpolate": null, "interpolation_parameters": {}, "interpolation_precision": 250, "inverse_y_axis": false, "js": ["file:///home/theel/.pyenv/versions/3.9.13/lib/python3.9/site-packages/pygaljs/static/2.0.x/pygal-tooltips.js"], "legend_at_bottom": false, "legend_at_bottom_columns": null, "legend_box_size": 12, "logarithmic": false, "margin": 20, "margin_bottom": null, "margin_left": null, "margin_right": null, "margin_top": null, "max_scale": 20, "min_scale": 20, "missing_value_fill_truncation": "x", "no_data_text": "No data", "no_prefix": false, "order_min": null, "pretty_print": false, "print_labels": false, "print_values": false, "print_values_position": "center", "print_zeroes": true, "range": [14, 160], "rounded_bars": null, "secondary_range": null, "show_dots": true, "show_legend": false, "show_minor_x_labels": true, "show_minor_y_labels": true, "show_only_major_dots": false, "show_x_guides": false, "show_x_labels": true, "show_y_guides": true, "show_y_labels": true, "spacing": 10, "stack_from_top": false, "strict": false, "stroke": true, "stroke_style": null, "style": {"background": "rgba(249, 249, 249, 1)", "ci_colors": [], "colors": ["#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5", "#3F51B5"], "dot_opacity": "1", "font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "foreground": "rgba(0, 0, 0, .87)", "foreground_strong": "rgba(0, 0, 0, 1)", "foreground_subtle": "rgba(0, 0, 0, .54)", "guide_stroke_color": "black", "guide_stroke_dasharray": "4,4", "label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "label_font_size": 10, "legend_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "legend_font_size": 14, "major_guide_stroke_color": "black", "major_guide_stroke_dasharray": "6,6", "major_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "major_label_font_size": 10, "no_data_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "no_data_font_size": 64, "opacity": ".7", "opacity_hover": ".8", "plot_background": "rgba(255, 255, 255, 1)", "stroke_opacity": ".8", "stroke_opacity_hover": ".9", "stroke_width": "1", "stroke_width_hover": "4", "title_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "title_font_size": 16, "tooltip_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "tooltip_font_size": 14, "transition": "150ms", "value_background": "rgba(229, 229, 229, 1)", "value_colors": [], "value_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_font_size": 16, "value_label_font_family": "Consolas, \"Deja Vu Sans Mono\", \"Bitstream Vera Sans Mono\", \"Courier New\", monospace", "value_label_font_size": 10}, "title": "Speed in Microseconds (us)", "tooltip_border_radius": 0, "tooltip_fancy_mode": true, "truncate_label": 50, "truncate_legend": null, "width": 800, "x_label_rotation": 270, "x_labels": ["simple_tuple_d", "simple_set_d", "simple_list_e", "simple_tuple_e", "simple_set_e", "simple_dict_d", "simple_list_d", "simple_dict_e", "complex_homog_tuple_d", "complex_homog_set_d", "complex_heterog_set_d", "complex_heterog_tuple_d", "complex_homog_list_d", "complex_homog_dict_d", "complex_homog_list_e", "complex_heterog_dict_d", "complex_heterog_list_d", "complex_homog_tuple_e", "complex_homog_set_e", "complex_heterog_set_e", "complex_heterog_list_e", "complex_heterog_tuple_e", "complex_homog_dict_e", "simple_cls_d", "complex_heterog_dict_e", "simple_cls_e", "complex_cls_d", "state_cls_d", "complex_cls_e", "state_cls_e"], "x_labels_major": null, "x_labels_major_count": null, "x_labels_major_every": null, "x_title": "Trial", "xrange": null, "y_label_rotation": 0, "y_labels": null, "y_labels_major": null, "y_labels_major_count": null, "y_labels_major_every": null, "y_title": "Duration", "zero": 14, "legends": ["jsonpickle_benchmarks.py::simple_tuple_d - 15133 rounds", "jsonpickle_benchmarks.py::simple_set_d - 16792 rounds", "jsonpickle_benchmarks.py::simple_list_e - 13251 rounds", "jsonpickle_benchmarks.py::simple_tuple_e - 13300 rounds", "jsonpickle_benchmarks.py::simple_set_e - 17505 rounds", "jsonpickle_benchmarks.py::simple_dict_d - 11427 rounds", "jsonpickle_benchmarks.py::simple_list_d - 1845 rounds", "jsonpickle_benchmarks.py::simple_dict_e - 9720 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_d - 13199 rounds", "jsonpickle_benchmarks.py::complex_homog_set_d - 12972 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_d - 11259 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_d - 9155 rounds", "jsonpickle_benchmarks.py::complex_homog_list_d - 11673 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_d - 9415 rounds", "jsonpickle_benchmarks.py::complex_homog_list_e - 8770 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_d - 8975 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_d - 8358 rounds", "jsonpickle_benchmarks.py::complex_homog_tuple_e - 8736 rounds", "jsonpickle_benchmarks.py::complex_homog_set_e - 10218 rounds", "jsonpickle_benchmarks.py::complex_heterog_set_e - 9623 rounds", "jsonpickle_benchmarks.py::complex_heterog_list_e - 7529 rounds", "jsonpickle_benchmarks.py::complex_heterog_tuple_e - 8611 rounds", "jsonpickle_benchmarks.py::complex_homog_dict_e - 7896 rounds", "jsonpickle_benchmarks.py::simple_cls_d - 6613 rounds", "jsonpickle_benchmarks.py::complex_heterog_dict_e - 7505 rounds", "jsonpickle_benchmarks.py::simple_cls_e - 6559 rounds", "jsonpickle_benchmarks.py::complex_cls_d - 4647 rounds", "jsonpickle_benchmarks.py::state_cls_d - 4523 rounds", "jsonpickle_benchmarks.py::complex_cls_e - 3993 rounds", "jsonpickle_benchmarks.py::state_cls_e - 3931 rounds"]}</script><script type="text/javascript">(function() {
5 var $, get_translation, init, init_svg, matches, padding, r_translation, sibl, svg_ns, tooltip_timeout, xlink_ns;
6
7 svg_ns = 'http://www.w3.org/2000/svg';
8
9 xlink_ns = 'http://www.w3.org/1999/xlink';
10
11 $ = function(sel, ctx) {
12 if (ctx == null) {
13 ctx = null;
14 }
15 ctx = ctx || document;
16 return Array.prototype.slice.call(ctx.querySelectorAll(sel), 0).filter(function(e) {
17 return e !== ctx;
18 });
19 };
20
21 matches = function(el, selector) {
22 return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
23 };
24
25 sibl = function(el, match) {
26 if (match == null) {
27 match = null;
28 }
29 return Array.prototype.filter.call(el.parentElement.children, function(child) {
30 return child !== el &amp;&amp; (!match || matches(child, match));
31 });
32 };
33
34 Array.prototype.one = function() {
35 return this.length &gt; 0 &amp;&amp; this[0] || {};
36 };
37
38 padding = 5;
39
40 tooltip_timeout = null;
41
42 r_translation = /translate\((\d+)[ ,]+(\d+)\)/;
43
44 get_translation = function(el) {
45 return (r_translation.exec(el.getAttribute('transform')) || []).slice(1).map(function(x) {
46 return +x;
47 });
48 };
49
50 init = function(ctx) {
51 var bbox, box, config, el, graph, inner_svg, num, parent, tooltip, tooltip_el, tt, uid, untooltip, xconvert, yconvert, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
52 if ($('svg', ctx).length) {
53 inner_svg = $('svg', ctx).one();
54 parent = inner_svg.parentElement;
55 box = inner_svg.viewBox.baseVal;
56 bbox = parent.getBBox();
57 xconvert = function(x) {
58 return ((x - box.x) / box.width) * bbox.width;
59 };
60 yconvert = function(y) {
61 return ((y - box.y) / box.height) * bbox.height;
62 };
63 } else {
64 xconvert = yconvert = function(x) {
65 return x;
66 };
67 }
68 if (((_ref = window.pygal) != null ? _ref.config : void 0) != null) {
69 if (window.pygal.config.no_prefix != null) {
70 config = window.pygal.config;
71 } else {
72 uid = ctx.id.replace('chart-', '');
73 config = window.pygal.config[uid];
74 }
75 } else {
76 config = window.config;
77 }
78 tooltip_el = null;
79 graph = $('.graph').one();
80 tt = $('.tooltip', ctx).one();
81 _ref1 = $('.reactive', ctx);
82 for (_i = 0, _len = _ref1.length; _i &lt; _len; _i++) {
83 el = _ref1[_i];
84 el.addEventListener('mouseenter', (function(el) {
85 return function() {
86 return el.classList.add('active');
87 };
88 })(el));
89 el.addEventListener('mouseleave', (function(el) {
90 return function() {
91 return el.classList.remove('active');
92 };
93 })(el));
94 }
95 _ref2 = $('.activate-serie', ctx);
96 for (_j = 0, _len1 = _ref2.length; _j &lt; _len1; _j++) {
97 el = _ref2[_j];
98 num = el.id.replace('activate-serie-', '');
99 el.addEventListener('mouseenter', (function(num) {
100 return function() {
101 var re, _k, _len2, _ref3, _results;
102 _ref3 = $('.serie-' + num + ' .reactive', ctx);
103 _results = [];
104 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
105 re = _ref3[_k];
106 _results.push(re.classList.add('active'));
107 }
108 return _results;
109 };
110 })(num));
111 el.addEventListener('mouseleave', (function(num) {
112 return function() {
113 var re, _k, _len2, _ref3, _results;
114 _ref3 = $('.serie-' + num + ' .reactive', ctx);
115 _results = [];
116 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
117 re = _ref3[_k];
118 _results.push(re.classList.remove('active'));
119 }
120 return _results;
121 };
122 })(num));
123 el.addEventListener('click', (function(el, num) {
124 return function() {
125 var ov, re, rect, show, _k, _l, _len2, _len3, _ref3, _ref4, _results;
126 rect = $('rect', el).one();
127 show = rect.style.fill !== '';
128 rect.style.fill = show ? '' : 'transparent';
129 _ref3 = $('.serie-' + num + ' .reactive', ctx);
130 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
131 re = _ref3[_k];
132 re.style.display = show ? '' : 'none';
133 }
134 _ref4 = $('.text-overlay .serie-' + num, ctx);
135 _results = [];
136 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
137 ov = _ref4[_l];
138 _results.push(ov.style.display = show ? '' : 'none');
139 }
140 return _results;
141 };
142 })(el, num));
143 }
144 _ref3 = $('.tooltip-trigger', ctx);
145 for (_k = 0, _len2 = _ref3.length; _k &lt; _len2; _k++) {
146 el = _ref3[_k];
147 el.addEventListener('mouseenter', (function(el) {
148 return function() {
149 return tooltip_el = tooltip(el);
150 };
151 })(el));
152 }
153 tt.addEventListener('mouseenter', function() {
154 return tooltip_el != null ? tooltip_el.classList.add('active') : void 0;
155 });
156 tt.addEventListener('mouseleave', function() {
157 return tooltip_el != null ? tooltip_el.classList.remove('active') : void 0;
158 });
159 ctx.addEventListener('mouseleave', function() {
160 if (tooltip_timeout) {
161 clearTimeout(tooltip_timeout);
162 }
163 return untooltip(0);
164 });
165 graph.addEventListener('mousemove', function(el) {
166 if (tooltip_timeout) {
167 return;
168 }
169 if (!matches(el.target, '.background')) {
170 return;
171 }
172 return untooltip(1000);
173 });
174 tooltip = function(el) {
175 var a, baseline, cls, current_x, current_y, dy, h, i, key, keys, label, legend, name, plot_x, plot_y, rect, serie_index, subval, text, text_group, texts, traversal, value, w, x, x_elt, x_label, xlink, y, y_elt, _l, _len3, _len4, _len5, _m, _n, _ref4, _ref5, _ref6, _ref7, _ref8;
176 clearTimeout(tooltip_timeout);
177 tooltip_timeout = null;
178 tt.style.opacity = 1;
179 tt.style.display = '';
180 text_group = $('g.text', tt).one();
181 rect = $('rect', tt).one();
182 text_group.innerHTML = '';
183 label = sibl(el, '.label').one().textContent;
184 x_label = sibl(el, '.x_label').one().textContent;
185 value = sibl(el, '.value').one().textContent;
186 xlink = sibl(el, '.xlink').one().textContent;
187 serie_index = null;
188 parent = el;
189 traversal = [];
190 while (parent) {
191 traversal.push(parent);
192 if (parent.classList.contains('series')) {
193 break;
194 }
195 parent = parent.parentElement;
196 }
197 if (parent) {
198 _ref4 = parent.classList;
199 for (_l = 0, _len3 = _ref4.length; _l &lt; _len3; _l++) {
200 cls = _ref4[_l];
201 if (cls.indexOf('serie-') === 0) {
202 serie_index = +cls.replace('serie-', '');
203 break;
204 }
205 }
206 }
207 legend = null;
208 if (serie_index !== null) {
209 legend = config.legends[serie_index];
210 }
211 dy = 0;
212 keys = [[label, 'label']];
213 _ref5 = value.split('\n');
214 for (i = _m = 0, _len4 = _ref5.length; _m &lt; _len4; i = ++_m) {
215 subval = _ref5[i];
216 keys.push([subval, 'value-' + i]);
217 }
218 if (config.tooltip_fancy_mode) {
219 keys.push([xlink, 'xlink']);
220 keys.unshift([x_label, 'x_label']);
221 keys.unshift([legend, 'legend']);
222 }
223 texts = {};
224 for (_n = 0, _len5 = keys.length; _n &lt; _len5; _n++) {
225 _ref6 = keys[_n], key = _ref6[0], name = _ref6[1];
226 if (key) {
227 text = document.createElementNS(svg_ns, 'text');
228 text.textContent = key;
229 text.setAttribute('x', padding);
230 text.setAttribute('dy', dy);
231 text.classList.add(name.indexOf('value') === 0 ? 'value' : name);
232 if (name.indexOf('value') === 0 &amp;&amp; config.tooltip_fancy_mode) {
233 text.classList.add('color-' + serie_index);
234 }
235 if (name === 'xlink') {
236 a = document.createElementNS(svg_ns, 'a');
237 a.setAttributeNS(xlink_ns, 'href', key);
238 a.textContent = void 0;
239 a.appendChild(text);
240 text.textContent = 'Link &gt;';
241 text_group.appendChild(a);
242 } else {
243 text_group.appendChild(text);
244 }
245 dy += text.getBBox().height + padding / 2;
246 baseline = padding;
247 if (text.style.dominantBaseline !== void 0) {
248 text.style.dominantBaseline = 'text-before-edge';
249 } else {
250 baseline += text.getBBox().height * .8;
251 }
252 text.setAttribute('y', baseline);
253 texts[name] = text;
254 }
255 }
256 w = text_group.getBBox().width + 2 * padding;
257 h = text_group.getBBox().height + 2 * padding;
258 rect.setAttribute('width', w);
259 rect.setAttribute('height', h);
260 if (texts.value) {
261 texts.value.setAttribute('dx', (w - texts.value.getBBox().width) / 2 - padding);
262 }
263 if (texts.x_label) {
264 texts.x_label.setAttribute('dx', w - texts.x_label.getBBox().width - 2 * padding);
265 }
266 if (texts.xlink) {
267 texts.xlink.setAttribute('dx', w - texts.xlink.getBBox().width - 2 * padding);
268 }
269 x_elt = sibl(el, '.x').one();
270 y_elt = sibl(el, '.y').one();
271 x = parseInt(x_elt.textContent);
272 if (x_elt.classList.contains('centered')) {
273 x -= w / 2;
274 } else if (x_elt.classList.contains('left')) {
275 x -= w;
276 } else if (x_elt.classList.contains('auto')) {
277 x = xconvert(el.getBBox().x + el.getBBox().width / 2) - w / 2;
278 }
279 y = parseInt(y_elt.textContent);
280 if (y_elt.classList.contains('centered')) {
281 y -= h / 2;
282 } else if (y_elt.classList.contains('top')) {
283 y -= h;
284 } else if (y_elt.classList.contains('auto')) {
285 y = yconvert(el.getBBox().y + el.getBBox().height / 2) - h / 2;
286 }
287 _ref7 = get_translation(tt.parentElement), plot_x = _ref7[0], plot_y = _ref7[1];
288 if (x + w + plot_x &gt; config.width) {
289 x = config.width - w - plot_x;
290 }
291 if (y + h + plot_y &gt; config.height) {
292 y = config.height - h - plot_y;
293 }
294 if (x + plot_x &lt; 0) {
295 x = -plot_x;
296 }
297 if (y + plot_y &lt; 0) {
298 y = -plot_y;
299 }
300 _ref8 = get_translation(tt), current_x = _ref8[0], current_y = _ref8[1];
301 if (current_x === x &amp;&amp; current_y === y) {
302 return el;
303 }
304 tt.setAttribute('transform', "translate(" + x + " " + y + ")");
305 return el;
306 };
307 return untooltip = function(ms) {
308 return tooltip_timeout = setTimeout(function() {
309 tt.style.display = 'none';
310 tt.style.opacity = 0;
311 if (tooltip_el != null) {
312 tooltip_el.classList.remove('active');
313 }
314 return tooltip_timeout = null;
315 }, ms);
316 };
317 };
318
319 init_svg = function() {
320 var chart, charts, _i, _len, _results;
321 charts = $('.pygal-chart');
322 if (charts.length) {
323 _results = [];
324 for (_i = 0, _len = charts.length; _i &lt; _len; _i++) {
325 chart = charts[_i];
326 _results.push(init(chart));
327 }
328 return _results;
329 }
330 };
331
332 if (document.readyState !== 'loading') {
333 init_svg();
334 } else {
335 document.addEventListener('DOMContentLoaded', function() {
336 return init_svg();
337 });
338 }
339
340 window.pygal = window.pygal || {};
341
342 window.pygal.init = init;
343
344 window.pygal.init_svg = init_svg;
345
346 }).call(this);
347 </script></defs><title>Speed in Microseconds (us)</title><g class="graph custombox-graph vertical"><rect x="0" y="0" width="800" height="600" class="background" /><g transform="translate(74, 46)" class="plot"><rect x="0" y="0" width="706.0" height="360.0" class="background" /><g class="axis y always_show"><path d="M0.000000 360.000000 h706.000000" class="line" /><g class="guides"><path d="M0.000000 348.335090 h706.000000" class="guide line" /><text x="-5" y="351.8350895679663" class="">16</text><title>16</title></g><g class="guides"><path d="M0.000000 329.367756 h706.000000" class="guide line" /><text x="-5" y="332.8677555321391" class="">24</text><title>24</title></g><g class="guides"><path d="M0.000000 310.400421 h706.000000" class="guide line" /><text x="-5" y="313.9004214963119" class="">32</text><title>32</title></g><g class="guides"><path d="M0.000000 291.433087 h706.000000" class="guide line" /><text x="-5" y="294.93308746048467" class="">40</text><title>40</title></g><g class="guides"><path d="M0.000000 272.465753 h706.000000" class="guide line" /><text x="-5" y="275.9657534246575" class="">48</text><title>48</title></g><g class="guides"><path d="M0.000000 253.498419 h706.000000" class="guide line" /><text x="-5" y="256.9984193888303" class="">56</text><title>56</title></g><g class="guides"><path d="M0.000000 234.531085 h706.000000" class="guide line" /><text x="-5" y="238.03108535300314" class="">64</text><title>64</title></g><g class="guides"><path d="M0.000000 215.563751 h706.000000" class="guide line" /><text x="-5" y="219.06375131717596" class="">72</text><title>72</title></g><g class="guides"><path d="M0.000000 196.596417 h706.000000" class="guide line" /><text x="-5" y="200.09641728134875" class="">80</text><title>80</title></g><g class="guides"><path d="M0.000000 177.629083 h706.000000" class="guide line" /><text x="-5" y="181.12908324552157" class="">88</text><title>88</title></g><g class="guides"><path d="M0.000000 158.661749 h706.000000" class="guide line" /><text x="-5" y="162.16174920969436" class="">96</text><title>96</title></g><g class="guides"><path d="M0.000000 139.694415 h706.000000" class="guide line" /><text x="-5" y="143.1944151738672" class="">104</text><title>104</title></g><g class="guides"><path d="M0.000000 120.727081 h706.000000" class="guide line" /><text x="-5" y="124.22708113804003" class="">112</text><title>112</title></g><g class="guides"><path d="M0.000000 101.759747 h706.000000" class="guide line" /><text x="-5" y="105.25974710221283" class="">120</text><title>120</title></g><g class="guides"><path d="M0.000000 82.792413 h706.000000" class="guide line" /><text x="-5" y="86.29241306638562" class="">128</text><title>128</title></g><g class="guides"><path d="M0.000000 63.825079 h706.000000" class="guide line" /><text x="-5" y="67.32507903055847" class="">136</text><title>136</title></g><g class="guides"><path d="M0.000000 44.857745 h706.000000" class="guide line" /><text x="-5" y="48.35774499473126" class="">144</text><title>144</title></g><g class="guides"><path d="M0.000000 25.890411 h706.000000" class="guide line" /><text x="-5" y="29.390410958904056" class="">152</text><title>152</title></g><g class="guides"><path d="M0.000000 6.923077 h706.000000" class="guide line" /><text x="-5" y="10.423076923076906" class="">160</text><title>160</title></g></g><g class="axis x"><path d="M0.000000 0.000000 v360.000000" class="line" /><g class="guides"><path d="M24.891026 0.000000 v360.000000" class="guide line" /><text x="24.89102564102564" y="375.0" class="backwards" transform="rotate(270 24.891026 375.000000)">simple_tuple_d</text></g><g class="guides"><path d="M47.519231 0.000000 v360.000000" class="guide line" /><text x="47.51923076923077" y="375.0" class="backwards" transform="rotate(270 47.519231 375.000000)">simple_set_d</text></g><g class="guides"><path d="M70.147436 0.000000 v360.000000" class="guide line" /><text x="70.1474358974359" y="375.0" class="backwards" transform="rotate(270 70.147436 375.000000)">simple_list_e</text></g><g class="guides"><path d="M92.775641 0.000000 v360.000000" class="guide line" /><text x="92.77564102564102" y="375.0" class="backwards" transform="rotate(270 92.775641 375.000000)">simple_tuple_e</text></g><g class="guides"><path d="M115.403846 0.000000 v360.000000" class="guide line" /><text x="115.40384615384615" y="375.0" class="backwards" transform="rotate(270 115.403846 375.000000)">simple_set_e</text></g><g class="guides"><path d="M138.032051 0.000000 v360.000000" class="guide line" /><text x="138.03205128205127" y="375.0" class="backwards" transform="rotate(270 138.032051 375.000000)">simple_dict_d</text></g><g class="guides"><path d="M160.660256 0.000000 v360.000000" class="guide line" /><text x="160.6602564102564" y="375.0" class="backwards" transform="rotate(270 160.660256 375.000000)">simple_list_d</text></g><g class="guides"><path d="M183.288462 0.000000 v360.000000" class="guide line" /><text x="183.28846153846155" y="375.0" class="backwards" transform="rotate(270 183.288462 375.000000)">simple_dict_e</text></g><g class="guides"><path d="M205.916667 0.000000 v360.000000" class="guide line" /><text x="205.91666666666666" y="375.0" class="backwards" transform="rotate(270 205.916667 375.000000)">complex_homog_tuple_d</text></g><g class="guides"><path d="M228.544872 0.000000 v360.000000" class="guide line" /><text x="228.5448717948718" y="375.0" class="backwards" transform="rotate(270 228.544872 375.000000)">complex_homog_set_d</text></g><g class="guides"><path d="M251.173077 0.000000 v360.000000" class="guide line" /><text x="251.17307692307688" y="375.0" class="backwards" transform="rotate(270 251.173077 375.000000)">complex_heterog_set_d</text></g><g class="guides"><path d="M273.801282 0.000000 v360.000000" class="guide line" /><text x="273.8012820512821" y="375.0" class="backwards" transform="rotate(270 273.801282 375.000000)">complex_heterog_tuple_d</text></g><g class="guides"><path d="M296.429487 0.000000 v360.000000" class="guide line" /><text x="296.4294871794872" y="375.0" class="backwards" transform="rotate(270 296.429487 375.000000)">complex_homog_list_d</text></g><g class="guides"><path d="M319.057692 0.000000 v360.000000" class="guide line" /><text x="319.05769230769226" y="375.0" class="backwards" transform="rotate(270 319.057692 375.000000)">complex_homog_dict_d</text></g><g class="guides"><path d="M341.685897 0.000000 v360.000000" class="guide line" /><text x="341.6858974358974" y="375.0" class="backwards" transform="rotate(270 341.685897 375.000000)">complex_homog_list_e</text></g><g class="guides"><path d="M364.314103 0.000000 v360.000000" class="guide line" /><text x="364.3141025641026" y="375.0" class="backwards" transform="rotate(270 364.314103 375.000000)">complex_heterog_dict_d</text></g><g class="guides"><path d="M386.942308 0.000000 v360.000000" class="guide line" /><text x="386.9423076923077" y="375.0" class="backwards" transform="rotate(270 386.942308 375.000000)">complex_heterog_list_d</text></g><g class="guides"><path d="M409.570513 0.000000 v360.000000" class="guide line" /><text x="409.5705128205129" y="375.0" class="backwards" transform="rotate(270 409.570513 375.000000)">complex_homog_tuple_e</text></g><g class="guides"><path d="M432.198718 0.000000 v360.000000" class="guide line" /><text x="432.19871794871796" y="375.0" class="backwards" transform="rotate(270 432.198718 375.000000)">complex_homog_set_e</text></g><g class="guides"><path d="M454.826923 0.000000 v360.000000" class="guide line" /><text x="454.8269230769231" y="375.0" class="backwards" transform="rotate(270 454.826923 375.000000)">complex_heterog_set_e</text></g><g class="guides"><path d="M477.455128 0.000000 v360.000000" class="guide line" /><text x="477.4551282051282" y="375.0" class="backwards" transform="rotate(270 477.455128 375.000000)">complex_heterog_list_e</text></g><g class="guides"><path d="M500.083333 0.000000 v360.000000" class="guide line" /><text x="500.08333333333337" y="375.0" class="backwards" transform="rotate(270 500.083333 375.000000)">complex_heterog_tuple_e</text></g><g class="guides"><path d="M522.711538 0.000000 v360.000000" class="guide line" /><text x="522.7115384615385" y="375.0" class="backwards" transform="rotate(270 522.711538 375.000000)">complex_homog_dict_e</text></g><g class="guides"><path d="M545.339744 0.000000 v360.000000" class="guide line" /><text x="545.3397435897435" y="375.0" class="backwards" transform="rotate(270 545.339744 375.000000)">simple_cls_d</text></g><g class="guides"><path d="M567.967949 0.000000 v360.000000" class="guide line" /><text x="567.9679487179487" y="375.0" class="backwards" transform="rotate(270 567.967949 375.000000)">complex_heterog_dict_e</text></g><g class="guides"><path d="M590.596154 0.000000 v360.000000" class="guide line" /><text x="590.5961538461538" y="375.0" class="backwards" transform="rotate(270 590.596154 375.000000)">simple_cls_e</text></g><g class="guides"><path d="M613.224359 0.000000 v360.000000" class="guide line" /><text x="613.224358974359" y="375.0" class="backwards" transform="rotate(270 613.224359 375.000000)">complex_cls_d</text></g><g class="guides"><path d="M635.852564 0.000000 v360.000000" class="guide line" /><text x="635.8525641025641" y="375.0" class="backwards" transform="rotate(270 635.852564 375.000000)">state_cls_d</text></g><g class="guides"><path d="M658.480769 0.000000 v360.000000" class="guide line" /><text x="658.4807692307692" y="375.0" class="backwards" transform="rotate(270 658.480769 375.000000)">complex_cls_e</text></g><g class="guides"><path d="M681.108974 0.000000 v360.000000" class="guide line" /><text x="681.1089743589743" y="375.0" class="backwards" transform="rotate(270 681.108974 375.000000)">state_cls_e</text></g></g><g class="series serie-0 color-0"><g class="boxes"><g class="box"><path stroke-width="3" d="M19.912821 351.855899 L29.869231 351.855899" class="reactive tooltip-trigger" /><path stroke-width="3" d="M14.934615 350.786624 L34.847436 350.786624" class="reactive tooltip-trigger" /><path stroke-width="3" d="M19.912821 349.698364 L29.869231 349.698364" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 351.855899 L24.891026 351.049783" class="reactive tooltip-trigger" /><path stroke-width="2" d="M24.891026 349.698364 L24.891026 350.509224" class="reactive tooltip-trigger" /><rect x="14.934615384615384" y="350.5092242894988" height="0.5405589906146133" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="352.23525068401756" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="24.891025641025642" cy="300.4639122264707" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 14.3550
348 Q1-1.5IQR: 14.5150
349 Q1: 14.8550
350 Median: 14.9660
351 Q3: 15.0830
352 Q3+1.5IQR: 15.4250
353 Max: 36.1910</desc><desc class="x centered">24.891025641025642</desc><desc class="y centered">350.7799790413104</desc><desc class="x_label" /></g></g></g><g class="series serie-1 color-1"><g class="boxes"><g class="box"><path stroke-width="3" d="M42.541026 351.142256 L52.497436 351.142256" class="reactive tooltip-trigger" /><path stroke-width="3" d="M37.562821 350.163063 L57.475641 350.163063" class="reactive tooltip-trigger" /><path stroke-width="3" d="M42.541026 349.160169 L52.497436 349.160169" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 351.142256 L47.519231 350.400157" class="reactive tooltip-trigger" /><path stroke-width="2" d="M47.519231 349.160169 L47.519231 349.904631" class="reactive tooltip-trigger" /><rect x="37.562820512820515" y="349.9046307383007" height="0.4955260648595754" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="351.2489511193418" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="47.519230769230774" cy="325.1380396336886" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 14.7710
354 Q1-1.5IQR: 14.8160
355 Q1: 15.1290
356 Median: 15.2290
357 Q3: 15.3380
358 Q3+1.5IQR: 15.6520
359 Max: 25.7840</desc><desc class="x centered">47.519230769230774</desc><desc class="y centered">350.1540550121594</desc><desc class="x_label" /></g></g></g><g class="series serie-2 color-2"><g class="boxes"><g class="box"><path stroke-width="3" d="M65.169231 349.413857 L75.125641 349.413857" class="reactive tooltip-trigger" /><path stroke-width="3" d="M60.191026 347.955743 L80.103846 347.955743" class="reactive tooltip-trigger" /><path stroke-width="3" d="M65.169231 346.381453 L75.125641 346.381453" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 349.413857 L70.147436 348.323234" class="reactive tooltip-trigger" /><path stroke-width="2" d="M70.147436 346.381453 L70.147436 347.547945" class="reactive tooltip-trigger" /><rect x="60.19102564102564" y="347.54794500027737" height="0.7752891268912094" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="349.60827251266954" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="70.1474358974359" cy="280.3537911975592" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.4630
360 Q1-1.5IQR: 15.5450
361 Q1: 16.0050
362 Median: 16.1600
363 Q3: 16.3320
364 Q3+1.5IQR: 16.8240
365 Max: 44.6730</desc><desc class="x centered">70.1474358974359</desc><desc class="y centered">347.9244464806387</desc><desc class="x_label" /></g></g></g><g class="series serie-3 color-3"><g class="boxes"><g class="box"><path stroke-width="3" d="M87.797436 347.751848 L97.753846 347.751848" class="reactive tooltip-trigger" /><path stroke-width="3" d="M82.819231 346.407536 L102.732051 346.407536" class="reactive tooltip-trigger" /><path stroke-width="3" d="M87.797436 345.008695 L97.753846 345.008695" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 347.751848 L92.775641 346.729978" class="reactive tooltip-trigger" /><path stroke-width="2" d="M92.775641 345.008695 L92.775641 346.042417" class="reactive tooltip-trigger" /><rect x="82.81923076923077" y="346.04241692293994" height="0.687560743850554" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="348.35168914001406" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="92.77564102564102" cy="312.5864032248488" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 15.9930
366 Q1-1.5IQR: 16.2460
367 Q1: 16.6770
368 Median: 16.8130
369 Q3: 16.9670
370 Q3+1.5IQR: 17.4030
371 Max: 31.0780</desc><desc class="x centered">92.77564102564102</desc><desc class="y centered">346.38809487074457</desc><desc class="x_label" /></g></g></g><g class="series serie-4 color-4"><g class="boxes"><g class="box"><path stroke-width="3" d="M110.425641 348.000784 L120.382051 348.000784" class="reactive tooltip-trigger" /><path stroke-width="3" d="M105.447436 346.535562 L125.360256 346.535562" class="reactive tooltip-trigger" /><path stroke-width="3" d="M110.425641 345.013431 L120.382051 345.013431" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 348.000784 L115.403846 346.884087" class="reactive tooltip-trigger" /><path stroke-width="2" d="M115.403846 345.013431 L115.403846 346.136653" class="reactive tooltip-trigger" /><rect x="105.4474358974359" y="346.13665312871234" height="0.747433575516709" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="348.2947791143231" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="115.40384615384615" cy="306.66859721144937" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.0170
372 Q1-1.5IQR: 16.1410
373 Q1: 16.6120
374 Median: 16.7590
375 Q3: 16.9273
376 Q3+1.5IQR: 17.4010
377 Max: 33.5740</desc><desc class="x centered">115.40384615384615</desc><desc class="y centered">346.5141033970133</desc><desc class="x_label" /></g></g></g><g class="series serie-5 color-5"><g class="boxes"><g class="box"><path stroke-width="3" d="M133.053846 346.891203 L143.010256 346.891203" class="reactive tooltip-trigger" /><path stroke-width="3" d="M128.075641 345.558742 L147.988462 345.558742" class="reactive tooltip-trigger" /><path stroke-width="3" d="M133.053846 344.067437 L143.010256 344.067437" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 346.891203 L138.032051 345.869341" class="reactive tooltip-trigger" /><path stroke-width="2" d="M138.032051 344.067437 L138.032051 345.148581" class="reactive tooltip-trigger" /><rect x="128.07564102564103" y="345.1485810556583" height="0.7207596963943956" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="346.8912026137766" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="138.0320512820513" cy="306.1967908450818" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 16.6090
378 Q1-1.5IQR: 16.6090
379 Q1: 17.0400
380 Median: 17.1710
381 Q3: 17.3440
382 Q3+1.5IQR: 17.8000
383 Max: 33.7730</desc><desc class="x centered">138.0320512820513</desc><desc class="y centered">345.5070607403727</desc><desc class="x_label" /></g></g></g><g class="series serie-6 color-6"><g class="boxes"><g class="box"><path stroke-width="3" d="M155.682051 345.615643 L165.638462 345.615643" class="reactive tooltip-trigger" /><path stroke-width="3" d="M150.703846 344.202579 L170.616667 344.202579" class="reactive tooltip-trigger" /><path stroke-width="3" d="M155.682051 342.644885 L165.638462 342.644885" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 345.615643 L160.660256 344.601488" class="reactive tooltip-trigger" /><path stroke-width="2" d="M160.660256 342.644885 L160.660256 343.822643" class="reactive tooltip-trigger" /><rect x="150.70384615384614" y="343.8226434409485" height="0.7788449253287695" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="345.6156434823275" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="160.6602564102564" cy="276.1620115786786" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.1470
384 Q1-1.5IQR: 17.1470
385 Q1: 17.5748
386 Median: 17.7430
387 Q3: 17.9032
388 Q3+1.5IQR: 18.4000
389 Max: 46.4410</desc><desc class="x centered">160.6602564102564</desc><desc class="y centered">344.17744786619835</desc><desc class="x_label" /></g></g></g><g class="series serie-7 color-7"><g class="boxes"><g class="box"><path stroke-width="3" d="M178.310256 344.866437 L188.266667 344.866437" class="reactive tooltip-trigger" /><path stroke-width="3" d="M173.332051 342.924657 L193.244872 342.924657" class="reactive tooltip-trigger" /><path stroke-width="3" d="M178.310256 340.646203 L188.266667 340.646203" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 344.866437 L183.288462 343.372761" class="reactive tooltip-trigger" /><path stroke-width="2" d="M183.288462 340.646203 L183.288462 342.284509" class="reactive tooltip-trigger" /><rect x="173.33205128205125" y="342.2845094035295" height="1.0882511414666851" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="344.8664373984326" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="183.28846153846152" cy="282.70574162122904" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 17.4630
390 Q1-1.5IQR: 17.4630
391 Q1: 18.0930
392 Median: 18.2820
393 Q3: 18.5520
394 Q3+1.5IQR: 19.2430
395 Max: 43.6810</desc><desc class="x centered">183.28846153846152</desc><desc class="y centered">342.8189133480191</desc><desc class="x_label" /></g></g></g><g class="series serie-8 color-8"><g class="boxes"><g class="box"><path stroke-width="3" d="M200.938462 323.468915 L210.894872 323.468915" class="reactive tooltip-trigger" /><path stroke-width="3" d="M195.960256 322.134082 L215.873077 322.134082" class="reactive tooltip-trigger" /><path stroke-width="3" d="M200.938462 320.737622 L210.894872 320.737622" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 323.468915 L205.916667 322.449425" class="reactive tooltip-trigger" /><path stroke-width="2" d="M205.916667 320.737622 L205.916667 321.767190" class="reactive tooltip-trigger" /><rect x="195.9602564102564" y="321.76719015427017" height="0.6822345933709357" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="323.57560153066026" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="205.91666666666666" cy="214.83825026841063" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 26.4430
396 Q1-1.5IQR: 26.4880
397 Q1: 26.9180
398 Median: 27.0510
399 Q3: 27.2057
400 Q3+1.5IQR: 27.6400
401 Max: 72.3060</desc><desc class="x centered">205.91666666666666</desc><desc class="y centered">322.11144664523425</desc><desc class="x_label" /></g></g></g><g class="series serie-9 color-9"><g class="boxes"><g class="box"><path stroke-width="3" d="M223.566667 322.231298 L233.523077 322.231298" class="reactive tooltip-trigger" /><path stroke-width="3" d="M218.588462 320.201798 L238.501282 320.201798" class="reactive tooltip-trigger" /><path stroke-width="3" d="M223.566667 318.153313 L233.523077 318.153313" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 322.231298 L228.544872 320.725762" class="reactive tooltip-trigger" /><path stroke-width="2" d="M228.544872 318.153313 L228.544872 319.696784" class="reactive tooltip-trigger" /><rect x="218.58846153846153" y="319.6967839263551" height="1.0289777712714567" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="322.6485753361797" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="228.5448717948718" cy="252.91518037049912" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 26.8340
402 Q1-1.5IQR: 27.0100
403 Q1: 27.6450
404 Median: 27.8660
405 Q3: 28.0790
406 Q3+1.5IQR: 28.7300
407 Max: 56.2460</desc><desc class="x centered">228.5448717948718</desc><desc class="y centered">320.20179097033554</desc><desc class="x_label" /></g></g></g><g class="series serie-10 color-10"><g class="boxes"><g class="box"><path stroke-width="3" d="M246.194872 320.189938 L256.151282 320.189938" class="reactive tooltip-trigger" /><path stroke-width="3" d="M241.216667 318.599054 L261.129487 318.599054" class="reactive tooltip-trigger" /><path stroke-width="3" d="M246.194872 316.493676 L256.151282 316.493676" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 320.189938 L251.173077 318.990256" class="reactive tooltip-trigger" /><path stroke-width="2" d="M251.173077 316.493676 L251.173077 317.992097" class="reactive tooltip-trigger" /><rect x="241.21666666666664" y="317.9920966351342" height="0.9981594139217123" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="320.18993802136544" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="251.1730769230769" cy="211.01159012475313" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 27.8710
408 Q1-1.5IQR: 27.8710
409 Q1: 28.3770
410 Median: 28.5420
411 Q3: 28.7980
412 Q3+1.5IQR: 29.4300
413 Max: 73.9200</desc><desc class="x centered">251.1730769230769</desc><desc class="y centered">318.4530040156783</desc><desc class="x_label" /></g></g></g><g class="series serie-11 color-11"><g class="boxes"><g class="box"><path stroke-width="3" d="M268.823077 303.294785 L278.779487 303.294785" class="reactive tooltip-trigger" /><path stroke-width="3" d="M263.844872 299.103005 L283.757692 299.103005" class="reactive tooltip-trigger" /><path stroke-width="3" d="M268.823077 294.795051 L278.779487 294.795051" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 303.294785 L273.801282 300.147979" class="reactive tooltip-trigger" /><path stroke-width="2" d="M273.801282 294.795051 L273.801282 298.024233" class="reactive tooltip-trigger" /><rect x="263.84487179487184" y="298.0242334197602" height="2.1237453608147803" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="304.25500144773514" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="273.8012820512821" cy="202.04241309458735" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 34.5920
414 Q1-1.5IQR: 34.9970
415 Q1: 36.3243
416 Median: 36.7650
417 Q3: 37.2200
418 Q3+1.5IQR: 38.5820
419 Max: 77.7030</desc><desc class="x centered">273.8012820512821</desc><desc class="y centered">299.0730106702638</desc><desc class="x_label" /></g></g></g><g class="series serie-12 color-12"><g class="boxes"><g class="box"><path stroke-width="3" d="M291.451282 301.737091 L301.407692 301.737091" class="reactive tooltip-trigger" /><path stroke-width="3" d="M286.473077 299.785831 L306.385897 299.785831" class="reactive tooltip-trigger" /><path stroke-width="3" d="M291.451282 297.727875 L301.407692 297.727875" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 301.737091 L296.429487 300.236298" class="reactive tooltip-trigger" /><path stroke-width="2" d="M296.429487 297.727875 L296.429487 299.233403" class="reactive tooltip-trigger" /><rect x="286.473076923077" y="299.2334032714665" height="1.002894728275237" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="302.1923105908387" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="296.42948717948724" cy="208.82323661791864" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 35.4620
420 Q1-1.5IQR: 35.6540
421 Q1: 36.2870
422 Median: 36.4770
423 Q3: 36.7100
424 Q3+1.5IQR: 37.3450
425 Max: 74.8430</desc><desc class="x centered">296.42948717948724</desc><desc class="y centered">299.744099592947</desc><desc class="x_label" /></g></g></g><g class="series serie-13 color-13"><g class="boxes"><g class="box"><path stroke-width="3" d="M314.079487 301.428873 L324.035897 301.428873" class="reactive tooltip-trigger" /><path stroke-width="3" d="M309.101282 297.836934 L329.014103 297.836934" class="reactive tooltip-trigger" /><path stroke-width="3" d="M314.079487 293.894099 L324.035897 293.894099" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 301.428873 L319.057692 298.635335" class="reactive tooltip-trigger" /><path stroke-width="2" d="M319.057692 293.894099 L319.057692 296.741567" class="reactive tooltip-trigger" /><rect x="309.1012820512821" y="296.7415670041084" height="1.8937677895815455" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="301.4288726878486" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="319.0576923076924" cy="248.52423291239006" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 35.7840
426 Q1-1.5IQR: 35.7840
427 Q1: 36.9623
428 Median: 37.2990
429 Q3: 37.7610
430 Q3+1.5IQR: 38.9620
431 Max: 58.0980</desc><desc class="x centered">319.0576923076924</desc><desc class="y centered">297.70736153633874</desc><desc class="x_label" /></g></g></g><g class="series serie-14 color-14"><g class="boxes"><g class="box"><path stroke-width="3" d="M336.707692 299.117229 L346.664103 299.117229" class="reactive tooltip-trigger" /><path stroke-width="3" d="M331.729487 295.364065 L351.642308 295.364065" class="reactive tooltip-trigger" /><path stroke-width="3" d="M336.707692 291.203112 L346.664103 291.203112" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 299.117229 L341.685897 296.276868" class="reactive tooltip-trigger" /><path stroke-width="2" d="M341.685897 291.203112 L341.685897 294.254475" class="reactive tooltip-trigger" /><rect x="331.7294871794872" y="294.2544746764487" height="2.0223932454948113" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="299.1172285009253" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="341.68589743589746" cy="215.84588893638426" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 36.7590
432 Q1-1.5IQR: 36.7590
433 Q1: 37.9570
434 Median: 38.3420
435 Q3: 38.8100
436 Q3+1.5IQR: 40.0970
437 Max: 71.8810</desc><desc class="x centered">341.68589743589746</desc><desc class="y centered">295.2431496611116</desc><desc class="x_label" /></g></g></g><g class="series serie-15 color-15"><g class="boxes"><g class="box"><path stroke-width="3" d="M359.335897 294.669388 L369.292308 294.669388" class="reactive tooltip-trigger" /><path stroke-width="3" d="M354.357692 290.292681 L374.270513 290.292681" class="reactive tooltip-trigger" /><path stroke-width="3" d="M359.335897 285.757113 L369.292308 285.757113" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 294.669388 L364.314103 291.333510" class="reactive tooltip-trigger" /><path stroke-width="2" d="M364.314103 285.757113 L364.314103 289.107216" class="reactive tooltip-trigger" /><rect x="354.35769230769233" y="289.10721600657826" height="2.2262942427404937" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="295.2692292539699" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="364.3141025641026" cy="163.77819225320627" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 38.3820
438 Q1-1.5IQR: 38.6350
439 Q1: 40.0420
440 Median: 40.4810
441 Q3: 40.9810
442 Q3+1.5IQR: 42.3940
443 Max: 93.8420</desc><desc class="x centered">364.3141025641026</desc><desc class="y centered">290.2319816831707</desc><desc class="x_label" /></g></g></g><g class="series serie-16 color-16"><g class="boxes"><g class="box"><path stroke-width="3" d="M381.964103 293.770817 L391.920513 293.770817" class="reactive tooltip-trigger" /><path stroke-width="3" d="M376.985897 289.275555 L396.898718 289.275555" class="reactive tooltip-trigger" /><path stroke-width="3" d="M381.964103 284.600100 L391.920513 284.600100" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 293.770817 L386.942308 290.347211" class="reactive tooltip-trigger" /><path stroke-width="2" d="M386.942308 284.600100 L386.942308 288.064013" class="reactive tooltip-trigger" /><rect x="376.98589743589747" y="288.0640128852203" height="2.2831977994227373" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="295.2407742411244" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="386.94230769230774" cy="180.62591457687702" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 38.3940
444 Q1-1.5IQR: 39.0140
445 Q1: 40.4580
446 Median: 40.9100
447 Q3: 41.4210
448 Q3+1.5IQR: 42.8820
449 Max: 86.7360</desc><desc class="x centered">386.94230769230774</desc><desc class="y centered">289.21153912195115</desc><desc class="x_label" /></g></g></g><g class="series serie-17 color-17"><g class="boxes"><g class="box"><path stroke-width="3" d="M404.592308 292.443092 L414.548718 292.443092" class="reactive tooltip-trigger" /><path stroke-width="3" d="M399.614103 288.784773 L419.526923 288.784773" class="reactive tooltip-trigger" /><path stroke-width="3" d="M404.592308 285.041097 L414.548718 285.041097" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 292.443092 L409.570513 289.699948" class="reactive tooltip-trigger" /><path stroke-width="2" d="M409.570513 285.041097 L409.570513 287.837593" class="reactive tooltip-trigger" /><rect x="399.6141025641026" y="287.8375932687608" height="1.8623542834332625" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="293.178083384228" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="409.5705128205129" cy="254.56296626137404" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 39.2640
450 Q1-1.5IQR: 39.5740
451 Q1: 40.7310
452 Median: 41.1170
453 Q3: 41.5165
454 Q3+1.5IQR: 42.6960
455 Max: 55.5510</desc><desc class="x centered">409.5705128205129</desc><desc class="y centered">288.7613004305215</desc><desc class="x_label" /></g></g></g><g class="series serie-18 color-18"><g class="boxes"><g class="box"><path stroke-width="3" d="M427.220513 291.245782 L437.176923 291.245782" class="reactive tooltip-trigger" /><path stroke-width="3" d="M422.242308 287.407270 L442.155128 287.407270" class="reactive tooltip-trigger" /><path stroke-width="3" d="M427.220513 283.462064 L437.176923 283.462064" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 291.245782 L432.198718 288.350892" class="reactive tooltip-trigger" /><path stroke-width="2" d="M432.198718 283.462064 L432.198718 286.397260" class="reactive tooltip-trigger" /><rect x="422.24230769230775" y="286.39725986089667" height="1.9536319959028674" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="292.36248802059026" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="432.198717948718" cy="157.77028588691695" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 39.6080
456 Q1-1.5IQR: 40.0790
457 Q1: 41.3000
458 Median: 41.6980
459 Q3: 42.1240
460 Q3+1.5IQR: 43.3620
461 Max: 96.3760</desc><desc class="x centered">432.198717948718</desc><desc class="y centered">287.37265353947305</desc><desc class="x_label" /></g></g></g><g class="series serie-19 color-19"><g class="boxes"><g class="box"><path stroke-width="3" d="M449.848718 279.848786 L459.805128 279.848786" class="reactive tooltip-trigger" /><path stroke-width="3" d="M444.870513 276.076664 L464.783333 276.076664" class="reactive tooltip-trigger" /><path stroke-width="3" d="M449.848718 272.254748 L459.805128 272.254748" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 279.848786 L454.826923 277.008425" class="reactive tooltip-trigger" /><path stroke-width="2" d="M454.826923 272.254748 L454.826923 275.109323" class="reactive tooltip-trigger" /><rect x="444.87051282051283" y="275.10932273426" height="1.8991025654060536" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="280.93703702011453" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="454.8269230769231" cy="162.65200684484222" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 44.4270
462 Q1-1.5IQR: 44.8860
463 Q1: 46.0840
464 Median: 46.4770
465 Q3: 46.8850
466 Q3+1.5IQR: 48.0890
467 Max: 94.3170</desc><desc class="x centered">454.8269230769231</desc><desc class="y centered">276.05958905805574</desc><desc class="x_label" /></g></g></g><g class="series serie-20 color-20"><g class="boxes"><g class="box"><path stroke-width="3" d="M472.476923 266.453108 L482.433333 266.453108" class="reactive tooltip-trigger" /><path stroke-width="3" d="M467.498718 261.590354 L487.411538 261.590354" class="reactive tooltip-trigger" /><path stroke-width="3" d="M472.476923 256.585360 L482.433333 256.585360" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 266.453108 L477.455128 262.781150" class="reactive tooltip-trigger" /><path stroke-width="2" d="M477.455128 256.585360 L477.455128 260.310066" class="reactive tooltip-trigger" /><rect x="467.49871794871797" y="260.31006591739924" height="2.4710836875138398" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="267.58878100643057" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="477.45512820512823" cy="224.9596957499367" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 50.0570
468 Q1-1.5IQR: 50.5360
469 Q1: 52.0848
470 Median: 52.5870
471 Q3: 53.1270
472 Q3+1.5IQR: 54.6980
473 Max: 68.0370</desc><desc class="x centered">477.45512820512823</desc><desc class="y centered">261.54400732840884</desc><desc class="x_label" /></g></g></g><g class="series serie-21 color-21"><g class="boxes"><g class="box"><path stroke-width="3" d="M495.105128 265.051903 L505.061538 265.051903" class="reactive tooltip-trigger" /><path stroke-width="3" d="M490.126923 260.037412 L510.039744 260.037412" class="reactive tooltip-trigger" /><path stroke-width="3" d="M495.105128 254.963648 L505.061538 254.963648" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 265.051903 L500.083333 261.301112" class="reactive tooltip-trigger" /><path stroke-width="2" d="M500.083333 254.963648 L500.083333 258.766597" class="reactive tooltip-trigger" /><rect x="490.1269230769231" y="258.7665971041558" height="2.534514473953834" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="266.05716988609686" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="500.08333333333337" cy="191.31638268720812" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 50.7030
474 Q1-1.5IQR: 51.1270
475 Q1: 52.7090
476 Median: 53.2420
477 Q3: 53.7780
478 Q3+1.5IQR: 55.3820
479 Max: 82.2270</desc><desc class="x centered">500.08333333333337</desc><desc class="y centered">260.02413443995795</desc><desc class="x_label" /></g></g></g><g class="series serie-22 color-22"><g class="boxes"><g class="box"><path stroke-width="3" d="M517.733333 262.296899 L527.689744 262.296899" class="reactive tooltip-trigger" /><path stroke-width="3" d="M512.755128 256.815328 L532.667949 256.815328" class="reactive tooltip-trigger" /><path stroke-width="3" d="M517.733333 251.068235 L527.689744 251.068235" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 262.296899 L522.711538 258.199946" class="reactive tooltip-trigger" /><path stroke-width="2" d="M522.711538 251.068235 L522.711538 255.404636" class="reactive tooltip-trigger" /><rect x="512.7551282051282" y="255.40463604266313" height="2.7953104025368134" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="263.7858319359201" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="522.7115384615385" cy="116.947839498435" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 51.6610
480 Q1-1.5IQR: 52.2890
481 Q1: 54.0170
482 Median: 54.6010
483 Q3: 55.1960
484 Q3+1.5IQR: 57.0250
485 Max: 113.5940</desc><desc class="x centered">522.7115384615385</desc><desc class="y centered">256.7570090457086</desc><desc class="x_label" /></g></g></g><g class="series serie-23 color-23"><g class="boxes"><g class="box"><path stroke-width="3" d="M540.361538 263.219173 L550.317949 263.219173" class="reactive tooltip-trigger" /><path stroke-width="3" d="M535.383333 256.879346 L555.296154 256.879346" class="reactive tooltip-trigger" /><path stroke-width="3" d="M540.361538 250.418600 L550.317949 250.418600" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 263.219173 L545.339744 258.429926" class="reactive tooltip-trigger" /><path stroke-width="2" d="M545.339744 250.418600 L545.339744 255.233930" class="reactive tooltip-trigger" /><rect x="535.3833333333333" y="255.23392968528887" height="3.195996487480585" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="263.3566951508034" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="545.3397435897435" cy="158.08798321584595" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 51.8420
486 Q1-1.5IQR: 51.9000
487 Q1: 53.9200
488 Median: 54.5740
489 Q3: 55.2680
490 Q3+1.5IQR: 57.2990
491 Max: 96.2420</desc><desc class="x centered">545.3397435897435</desc><desc class="y centered">256.8361948871542</desc><desc class="x_label" /></g></g></g><g class="series serie-24 color-24"><g class="boxes"><g class="box"><path stroke-width="3" d="M562.989744 250.359327 L572.946154 250.359327" class="reactive tooltip-trigger" /><path stroke-width="3" d="M558.011538 244.922806 L577.924359 244.922806" class="reactive tooltip-trigger" /><path stroke-width="3" d="M562.989744 239.400947 L572.946154 239.400947" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 250.359327 L567.967949 246.270090" class="reactive tooltip-trigger" /><path stroke-width="2" d="M567.967949 239.400947 L567.967949 243.525753" class="reactive tooltip-trigger" /><rect x="558.0115384615385" y="243.52575281680618" height="2.7443367704776165" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="251.525818438358" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="567.9679487179487" cy="102.89779092180538" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 56.8320
492 Q1-1.5IQR: 57.3240
493 Q1: 59.0487
494 Median: 59.6170
495 Q3: 60.2062
496 Q3+1.5IQR: 61.9460
497 Max: 119.5200</desc><desc class="x centered">567.9679487179487</desc><desc class="y centered">244.8957844884781</desc><desc class="x_label" /></g></g></g><g class="series serie-25 color-25"><g class="boxes"><g class="box"><path stroke-width="3" d="M585.617949 245.027139 L595.574359 245.027139" class="reactive tooltip-trigger" /><path stroke-width="3" d="M580.639744 239.462592 L600.552564 239.462592" class="reactive tooltip-trigger" /><path stroke-width="3" d="M585.617949 233.592208 L595.574359 233.592208" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 245.027139 L590.596154 240.828234" class="reactive tooltip-trigger" /><path stroke-width="2" d="M590.596154 233.592208 L590.596154 237.936316" class="reactive tooltip-trigger" /><rect x="580.6397435897436" y="237.9363158403209" height="2.8919185781584247" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="245.50131690846922" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="590.5961538461538" cy="116.7534242242499" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 59.3730
498 Q1-1.5IQR: 59.5730
499 Q1: 61.3440
500 Median: 61.9200
501 Q3: 62.5637
502 Q3+1.5IQR: 64.3960
503 Max: 113.6760</desc><desc class="x centered">590.5961538461538</desc><desc class="y centered">239.36929786672152</desc><desc class="x_label" /></g></g></g><g class="series serie-26 color-26"><g class="boxes"><g class="box"><path stroke-width="3" d="M608.246154 92.984984 L618.202564 92.984984" class="reactive tooltip-trigger" /><path stroke-width="3" d="M603.267949 86.047688 L623.180769 86.047688" class="reactive tooltip-trigger" /><path stroke-width="3" d="M608.246154 78.707321 L618.202564 78.707321" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 92.984984 L613.224359 87.773121" class="reactive tooltip-trigger" /><path stroke-width="2" d="M613.224359 78.707321 L613.224359 84.224445" class="reactive tooltip-trigger" /><rect x="603.2679487179488" y="84.22444534598424" height="3.5486760590127346" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="94.82244113357626" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="613.224358974359" cy="-187.15305636789526" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 122.9260
504 Q1-1.5IQR: 123.7010
505 Q1: 125.8992
506 Median: 126.6270
507 Q3: 127.3960
508 Q3+1.5IQR: 129.7230
509 Max: 241.8570</desc><desc class="x centered">613.224358974359</desc><desc class="y centered">85.94751195339848</desc><desc class="x_label" /></g></g></g><g class="series serie-27 color-27"><g class="boxes"><g class="box"><path stroke-width="3" d="M630.874359 86.552693 L640.830769 86.552693" class="reactive tooltip-trigger" /><path stroke-width="3" d="M625.896154 79.997103 L645.808974 79.997103" class="reactive tooltip-trigger" /><path stroke-width="3" d="M630.874359 72.789515 L640.830769 72.789515" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 86.552693 L635.852564 81.640145" class="reactive tooltip-trigger" /><path stroke-width="2" d="M635.852564 72.789515 L635.852564 78.134154" class="reactive tooltip-trigger" /><rect x="625.8961538461539" y="78.13415399782366" height="3.505991383408343" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="87.79030956105879" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="635.8525641025641" cy="-203.2492092631668" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 125.8920
510 Q1-1.5IQR: 126.4140
511 Q1: 128.4860
512 Median: 129.1790
513 Q3: 129.9648
514 Q3+1.5IQR: 132.2190
515 Max: 248.6460</desc><desc class="x centered">635.8525641025641</desc><desc class="y centered">79.82272224448394</desc><desc class="x_label" /></g></g></g><g class="series serie-28 color-28"><g class="boxes"><g class="box"><path stroke-width="3" d="M653.502564 41.870388 L663.458974 41.870388" class="reactive tooltip-trigger" /><path stroke-width="3" d="M648.524359 34.769495 L668.437179 34.769495" class="reactive tooltip-trigger" /><path stroke-width="3" d="M653.502564 27.376971 L663.458974 27.376971" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 41.870388 L658.480769 36.499071" class="reactive tooltip-trigger" /><path stroke-width="2" d="M658.480769 27.376971 L658.480769 32.868607" class="reactive tooltip-trigger" /><rect x="648.524358974359" y="32.868607003257466" height="3.630463735749288" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="44.42386944457104" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="658.4807692307692" cy="-222.35168299875966" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 144.1830
516 Q1-1.5IQR: 145.2600
517 Q1: 147.5255
518 Median: 148.2550
519 Q3: 149.0568
520 Q3+1.5IQR: 151.3730
521 Max: 256.7030</desc><desc class="x centered">658.4807692307692</desc><desc class="y centered">34.67690625016377</desc><desc class="x_label" /></g></g></g><g class="series serie-29 color-29"><g class="boxes"><g class="box"><path stroke-width="3" d="M676.130769 21.549265 L686.087179 21.549265" class="reactive tooltip-trigger" /><path stroke-width="3" d="M671.152564 14.519488 L691.065385 14.519488" class="reactive tooltip-trigger" /><path stroke-width="3" d="M676.130769 7.340355 L686.087179 7.340355" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 21.549265 L681.108974 16.247893" class="reactive tooltip-trigger" /><path stroke-width="2" d="M681.108974 7.340355 L681.108974 12.699819" class="reactive tooltip-trigger" /><rect x="671.1525641025642" y="12.699818534630424" height="3.5480744412055287" width="19.912820512820513" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="22.229718455465274" r="3" class="subtle-fill reactive tooltip-trigger" /><circle cx="681.1089743589744" cy="-5475.27897892072" r="3" class="subtle-fill reactive tooltip-trigger" /><desc class="value">Min: 153.5440
522 Q1-1.5IQR: 153.8310
523 Q1: 156.0670
524 Median: 156.7960
525 Q3: 157.5635
526 Q3+1.5IQR: 159.8240
527 Max: 2472.2710</desc><desc class="x centered">681.1089743589744</desc><desc class="y centered">14.471363893089801</desc><desc class="x_label" /></g></g></g></g><g class="titles"><text x="400.0" y="26" class="title plot_title">Speed in Microseconds (us)</text><text x="427.0" y="580.0" class="title">Trial</text><text x="0" y="252.0" class="title" transform="rotate(-90 0.000000 226.000000)">Duration</text></g><g transform="translate(74, 46)" class="plot overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot text-overlay"><g class="series serie-0 color-0" /><g class="series serie-1 color-1" /><g class="series serie-2 color-2" /><g class="series serie-3 color-3" /><g class="series serie-4 color-4" /><g class="series serie-5 color-5" /><g class="series serie-6 color-6" /><g class="series serie-7 color-7" /><g class="series serie-8 color-8" /><g class="series serie-9 color-9" /><g class="series serie-10 color-10" /><g class="series serie-11 color-11" /><g class="series serie-12 color-12" /><g class="series serie-13 color-13" /><g class="series serie-14 color-14" /><g class="series serie-15 color-15" /><g class="series serie-16 color-16" /><g class="series serie-17 color-17" /><g class="series serie-18 color-18" /><g class="series serie-19 color-19" /><g class="series serie-20 color-20" /><g class="series serie-21 color-21" /><g class="series serie-22 color-22" /><g class="series serie-23 color-23" /><g class="series serie-24 color-24" /><g class="series serie-25 color-25" /><g class="series serie-26 color-26" /><g class="series serie-27 color-27" /><g class="series serie-28 color-28" /><g class="series serie-29 color-29" /></g><g transform="translate(74, 46)" class="plot tooltip-overlay"><g transform="translate(0 0)" style="opacity: 0" class="tooltip"><rect rx="0" ry="0" width="0" height="0" class="tooltip-box" /><g class="text" /></g></g></g></svg>
1010
1111 .. warning::
1212
13 jsonpickle can execute arbitrary Python code. Do not load jsonpickles from
14 untrusted / unauthenticated sources.
13 The jsonpickle module **is not secure**. Only unpickle data you trust.
14
15 It is possible to construct malicious pickle data which will **execute
16 arbitrary code during unpickling**. Never unpickle data that could have come
17 from an untrusted source, or that could have been tampered with.
18
19 Consider signing data with an HMAC if you need to ensure that it has not
20 been tampered with.
21
22 Safer deserialization approaches, such as reading the raw JSON
23 directly, may be more appropriate if you are processing untrusted data.
1524
1625 jsonpickle can take almost any Python object and turn the object into JSON.
1726 Additionally, it can reconstitute the object back into Python.
5160 result = jsonpickle.decode(oneway)
5261 assert obj.name == result['name'] == 'Awesome'
5362
63 .. note::
64
65 Please see the note in the :ref:`api-docs` when serializing dictionaries
66 that contain non-string dictionary keys.
67
5468 """
5569 from __future__ import absolute_import, division, unicode_literals
5670
57 from .backend import json
58 from .pickler import encode
59 from .unpickler import decode
60
6171 # Export other names not in __all__
6272 from .backend import JSONBackend # noqa: F401
63 from .version import __version__ # noqa: F401
73 from .backend import json
6474 from .handlers import register # noqa: F401
6575 from .handlers import unregister # noqa: F401
6676 from .pickler import Pickler # noqa: F401
77 from .pickler import encode
6778 from .unpickler import Unpickler # noqa: F401
79 from .unpickler import decode
80 from .version import __version__ # noqa: F401
6881
6982 __all__ = ('encode', 'decode')
7083
00 from __future__ import absolute_import, division, unicode_literals
11
22 from .compat import string_types
3 from .compat import PY3_ORDERED_DICT
43
54
65 class JSONBackend(object):
76 """Manages encoding and decoding using various backends.
87
98 It tries these modules in this order:
10 simplejson, json, demjson
9 simplejson, json, ujson
1110
1211 simplejson is a fast and popular backend and is tried first.
1312 json comes with Python and is tried second.
14 demjson is the most permissive backend and is tried last.
1513
1614 """
17
18 def __init__(self, fallthrough=True):
19 # Whether we should fallthrough to the next backend
20 self._fallthrough = fallthrough
21 # The names of backends that have been successfully imported
22 self._backend_names = []
23
24 # A dictionary mapping backend names to encode/decode functions
25 self._encoders = {}
26 self._decoders = {}
27
28 # Options to pass to specific encoders
29 self._encoder_options = {}
30
31 # Options to pass to specific decoders
32 self._decoder_options = {}
33
34 # The exception class that is thrown when a decoding error occurs
35 self._decoder_exceptions = {}
36
37 # Whether we've loaded any backends successfully
38 self._verified = False
39
40 self.load_backend('simplejson')
41 self.load_backend('json')
42 self.load_backend('demjson', 'encode', 'decode', 'JSONDecodeError')
43 self.load_backend('jsonlib', 'write', 'read', 'ReadError')
44 self.load_backend('yajl')
45 self.load_backend('ujson')
46
47 # Defaults for various encoders
48 sort = not PY3_ORDERED_DICT
49 json_opts = ((), {'sort_keys': sort})
50 self._encoder_options = {
51 'ujson': ((), {'sort_keys': sort, 'escape_forward_slashes': False}),
52 'json': json_opts,
53 'simplejson': json_opts,
54 'django.util.simplejson': json_opts,
55 }
5615
5716 def _verify(self):
5817 """Ensures that we've loaded at least one JSON backend."""
6120 raise AssertionError(
6221 'jsonpickle requires at least one of the '
6322 'following:\n'
64 ' python2.6, simplejson, or demjson'
23 ' python2.6, simplejson'
6524 )
25
26 def encode(self, obj, indent=None, separators=None):
27 """
28 Attempt to encode an object into JSON.
29
30 This tries the loaded backends in order and passes along the last
31 exception if no backend is able to encode the object.
32
33 """
34 self._verify()
35
36 if not self._fallthrough:
37 name = self._backend_names[0]
38 return self.backend_encode(name, obj, indent=indent, separators=separators)
39
40 for idx, name in enumerate(self._backend_names):
41 try:
42 return self.backend_encode(
43 name, obj, indent=indent, separators=separators
44 )
45 except Exception as e:
46 if idx == len(self._backend_names) - 1:
47 raise e
48
49 # def dumps
50 dumps = encode
51
52 def decode(self, string):
53 """
54 Attempt to decode an object from a JSON string.
55
56 This tries the loaded backends in order and passes along the last
57 exception if no backends are able to decode the string.
58
59 """
60 self._verify()
61
62 if not self._fallthrough:
63 name = self._backend_names[0]
64 return self.backend_decode(name, string)
65
66 for idx, name in enumerate(self._backend_names):
67 try:
68 return self.backend_decode(name, string)
69 except self._decoder_exceptions[name] as e:
70 if idx == len(self._backend_names) - 1:
71 raise e
72 else:
73 pass # and try a more forgiving encoder
74
75 # def loads
76 loads = decode
77
78 def __init__(self, fallthrough=True):
79 # Whether we should fallthrough to the next backend
80 self._fallthrough = fallthrough
81 # The names of backends that have been successfully imported
82 self._backend_names = []
83
84 # A dictionary mapping backend names to encode/decode functions
85 self._encoders = {}
86 self._decoders = {}
87
88 # Options to pass to specific encoders
89 self._encoder_options = {}
90
91 # Options to pass to specific decoders
92 self._decoder_options = {}
93
94 # The exception class that is thrown when a decoding error occurs
95 self._decoder_exceptions = {}
96
97 # Whether we've loaded any backends successfully
98 self._verified = False
99
100 self.load_backend('simplejson')
101 self.load_backend('json')
102 self.load_backend('ujson')
103
104 # Defaults for various encoders
105 json_opts = ((), {'sort_keys': False})
106 self._encoder_options = {
107 'ujson': ((), {'sort_keys': False, 'escape_forward_slashes': False}),
108 'json': json_opts,
109 'simplejson': json_opts,
110 'django.util.simplejson': json_opts,
111 }
66112
67113 def enable_fallthrough(self, enable):
68114 """
80126
81127 """
82128 self._fallthrough = enable
129
130 def _store(self, dct, backend, obj, name):
131 try:
132 dct[backend] = getattr(obj, name)
133 except AttributeError:
134 self.remove_backend(backend)
135 return False
136 return True
83137
84138 def load_backend(self, name, dumps='dumps', loads='loads', loads_exc=ValueError):
85139
151205 self._backend_names.remove(name)
152206 self._verified = bool(self._backend_names)
153207
154 def encode(self, obj, indent=None, separators=None):
155 """
156 Attempt to encode an object into JSON.
157
158 This tries the loaded backends in order and passes along the last
159 exception if no backend is able to encode the object.
160
161 """
162 self._verify()
163
164 if not self._fallthrough:
165 name = self._backend_names[0]
166 return self.backend_encode(name, obj, indent=indent, separators=separators)
167
168 for idx, name in enumerate(self._backend_names):
169 try:
170 return self.backend_encode(
171 name, obj, indent=indent, separators=separators
172 )
173 except Exception as e:
174 if idx == len(self._backend_names) - 1:
175 raise e
176
177 # def dumps
178 dumps = encode
179
180208 def backend_encode(self, name, obj, indent=None, separators=None):
181209 optargs, optkwargs = self._encoder_options.get(name, ([], {}))
182210 encoder_kwargs = optkwargs.copy()
187215 encoder_args = (obj,) + tuple(optargs)
188216 return self._encoders[name](*encoder_args, **encoder_kwargs)
189217
190 def decode(self, string):
191 """
192 Attempt to decode an object from a JSON string.
193
194 This tries the loaded backends in order and passes along the last
195 exception if no backends are able to decode the string.
196
197 """
198 self._verify()
199
200 if not self._fallthrough:
201 name = self._backend_names[0]
202 return self.backend_decode(name, string)
203
204 for idx, name in enumerate(self._backend_names):
205 try:
206 return self.backend_decode(name, string)
207 except self._decoder_exceptions[name] as e:
208 if idx == len(self._backend_names) - 1:
209 raise e
210 else:
211 pass # and try a more forgiving encoder, e.g. demjson
212
213 # def loads
214 loads = decode
215
216218 def backend_decode(self, name, string):
217219 optargs, optkwargs = self._decoder_options.get(name, ((), {}))
218220 decoder_kwargs = optkwargs.copy()
230232 set_preferred_backend('simplejson')
231233
232234 If the backend is not one of the built-in jsonpickle backends
233 (json/simplejson, or demjson) then you must load the backend
235 (json/simplejson) then you must load the backend
234236 prior to calling set_preferred_backend.
235237
236238 AssertionError is raised if the backend has not been loaded.
254256 For example::
255257
256258 set_encoder_options('simplejson', sort_keys=True, indent=4)
257 set_encoder_options('demjson', compactly=False)
258259
259260 See the appropriate encoder's documentation for details about
260261 the supported arguments and keyword arguments.
261262
263 WARNING: If you pass sort_keys=True, and the object to encode
264 contains ``__slots__``, and you set ``warn`` to True,
265 a TypeError will be raised!
262266 """
263267 self._encoder_options[name] = (args, kwargs)
264268
273277 For example::
274278
275279 set_decoder_options('simplejson', encoding='utf8', cls=JSONDecoder)
276 set_decoder_options('demjson', strict=True)
277280
278281 See the appropriate decoder's documentation for details about
279282 the supported arguments and keyword arguments.
281284 """
282285 self._decoder_options[name] = (args, kwargs)
283286
284 def _store(self, dct, backend, obj, name):
285 try:
286 dct[backend] = getattr(obj, name)
287 except AttributeError:
288 self.remove_backend(backend)
289 return False
290 return True
291
292287
293288 json = JSONBackend()
00 from __future__ import absolute_import, division, unicode_literals
1
2 import queue # noqa
13 import sys
2 import types
3 import base64
4 from collections.abc import Iterator as abc_iterator # noqa
45
56 PY_MAJOR = sys.version_info[0]
6 PY2 = PY_MAJOR == 2
7 PY3 = PY_MAJOR == 3
8 PY3_ORDERED_DICT = PY3 and sys.version_info[1] >= 6 # Python 3.6+
97
108 class_types = (type,)
119 iterator_types = (type(iter('')),)
1210
13 if PY3:
14 import builtins
15 import queue
16 from base64 import encodebytes, decodebytes
17 from collections.abc import Iterator as abc_iterator
18
19 string_types = (str,)
20 numeric_types = (int, float)
21 ustr = str
22 else:
23 from collections import Iterator as abc_iterator # noqa
24
25 builtins = __import__('__builtin__')
26 class_types += (types.ClassType,)
27 encodebytes = base64.encodestring
28 decodebytes = base64.decodestring
29 string_types = (builtins.basestring,)
30 numeric_types = (int, float, builtins.long)
31 queue = __import__('Queue')
32 ustr = builtins.unicode
11 string_types = (str,)
12 numeric_types = (int, float)
13 ustr = str
3314
3415
3516 def iterator(class_):
36 if PY2 and hasattr(class_, '__next__'):
37 class_.next = class_.__next__
17 # TODO: Replace all instances of this
3818 return class_
0 """
1 Stores custom jsonpickle errors.
2 """
3
4
5 class ClassNotFoundError(BaseException):
6 def __init__(*args, **kwargs):
7 pass
0 import gmpy2 as gmpy
1
2 from ..handlers import BaseHandler, register, unregister
3
4 __all__ = ['register_handlers', 'unregister_handlers']
5
6
7 class GmpyMPZHandler(BaseHandler):
8 def flatten(self, obj, data):
9 data['int'] = int(obj)
10 return data
11
12 def restore(self, data):
13 return gmpy.mpz(data['int'])
14
15
16 def register_handlers():
17 register(gmpy.mpz, GmpyMPZHandler, base=True)
18
19
20 def unregister_handlers():
21 unregister(gmpy.mpz)
00 from __future__ import absolute_import
1
12 import ast
3 import json
24 import sys
5 import warnings
36 import zlib
4 import warnings
5 import json
67
78 import numpy as np
89
10 from .. import compat
11 from ..compat import numeric_types
912 from ..handlers import BaseHandler, register, unregister
10 from ..compat import numeric_types
1113 from ..util import b64decode, b64encode
12 from .. import compat
13
1414
1515 __all__ = ['register_handlers', 'unregister_handlers']
1616
5959 def restore(self, data):
6060 value = self.context.restore(data['value'], reset=False)
6161 return self.restore_dtype(data).type(value)
62
63
64 class UnpickleableNumpyGenericHandler(NumpyGenericHandler):
65 """
66 From issue #381, this is used for simplifying the output of numpy arrays
67 when unpicklable=False (the default is True).
68 """
69
70 def flatten(self, obj, data):
71 if not self.context.unpicklable:
72 return self.context.flatten(obj.tolist(), reset=False)
73 else:
74 return super(NumpyGenericHandler, self).flatten(obj, data)
75
76 def restore(self, data):
77 raise NotImplementedError
6278
6379
6480 class NumpyNDArrayHandler(NumpyBaseHandler):
113129 if size_threshold is None, values are always stored as nested lists
114130 :param compression: a compression module or None
115131 valid values for 'compression' are {zlib, bz2, None}
116 if compresion is None, no compression is applied
132 if compression is None, no compression is applied
117133 """
118134 self.size_threshold = size_threshold
119135 self.compression = compression
135151 data = super(NumpyNDArrayHandlerBinary, self).flatten(obj, data)
136152 else:
137153 # encode as binary
138 if obj.dtype == np.object:
154 if obj.dtype == object:
139155 # There's a bug deep in the bowels of numpy that causes a
140156 # segfault when round-tripping an ndarray of dtype object.
141157 # E.g., the following will result in a segfault:
142158 # import numpy as np
143159 # arr = np.array([str(i) for i in range(3)],
144 # dtype=np.object)
160 # dtype=object)
145161 # dtype = arr.dtype
146162 # shape = arr.shape
147163 # buf = arr.tobytes()
187203 buf = self.compression.decompress(buf)
188204 # See note above about segfault bug for numpy dtype object. Those
189205 # are saved as a list to work around that.
190 if dtype == np.object:
206 if dtype == object:
191207 values = json.loads(buf.decode())
192208 arr = np.array(values, dtype=dtype, order=data.get('order', 'C'))
193209 shape = data.get('shape', None)
231247 def __init__(self, mode='warn', size_threshold=16, compression=zlib):
232248 """
233249 :param mode: {'warn', 'raise', 'ignore'}
234 How to react when encountering array-like objects whos
250 How to react when encountering array-like objects whose
235251 references we cannot safely serialize
236252 :param size_threshold: nonnegative int or None
237253 valid values for 'size_threshold' are all nonnegative
239255 if size_threshold is None, values are always stored as nested lists
240256 :param compression: a compression module or None
241257 valid values for 'compression' are {zlib, bz2, None}
242 if compresion is None, no compression is applied
258 if compression is None, no compression is applied
243259 """
244260 super(NumpyNDArrayHandlerView, self).__init__(size_threshold, compression)
245261 self.mode = mode
00 from __future__ import absolute_import
11
2 import zlib
3 from io import StringIO
4
25 import pandas as pd
3 from io import StringIO
4 import zlib
5
6 from .. import encode, decode
6
7 from .. import decode, encode
78 from ..handlers import BaseHandler, register, unregister
89 from ..util import b64decode, b64encode
910 from .numpy import register_handlers as register_numpy_handlers
2122 dataframes are always stored as csv strings
2223 :param compression: a compression module or None
2324 valid values for 'compression' are {zlib, bz2, None}
24 if compresion is None, no compression is applied
25 if compression is None, no compression is applied
2526 """
2627 self.size_threshold = size_threshold
2728 self.compression = compression
158159 def restore(self, data):
159160 buf, meta = self.pp.restore_pandas(data)
160161 dtype = meta.get('dtype', None)
161 name_bundle = {k: v for k, v in meta.items() if k in {'name', 'names'}}
162 name_bundle = {
163 'name': (tuple if v is not None else lambda x: x)(v)
164 for k, v in meta.items()
165 if k in {'name', 'names'}
166 }
162167 idx = self.index_constructor(decode(buf), dtype=dtype, **name_bundle)
163168 return idx
164169
77
88 """
99 from __future__ import absolute_import, division, unicode_literals
10
1011 import array
1112 import copy
1213 import datetime
1617 import threading
1718 import uuid
1819
19 from . import compat
20 from . import util
20 from . import compat, util
2121
2222
2323 class Registry(object):
9999 """
100100 self.context = context
101101
102 def __call__(self, context):
103 """This permits registering either Handler instances or classes
104
105 :Parameters:
106 - `context`: reference to pickler/unpickler
107 """
108 self.context = context
109 return self
110
111102 def flatten(self, obj, data):
112103 """
113104 Flatten `obj` into a json-friendly form and write result to `data`.
139130 """
140131 registry.register(cls, self)
141132 return cls
133
134 def __call__(self, context):
135 """This permits registering either Handler instances or classes
136
137 :Parameters:
138 - `context`: reference to pickler/unpickler
139 """
140 self.context = context
141 return self
142142
143143
144144 class ArrayHandler(BaseHandler):
44 # This software is licensed as described in the file COPYING, which
55 # you should have received as part of this distribution.
66 from __future__ import absolute_import, division, unicode_literals
7
78 import decimal
9 import inspect
10 import itertools
11 import sys
812 import warnings
9 import sys
10 import types
1113 from itertools import chain, islice
1214
13 from . import compat
14 from . import util
15 from . import tags
16 from . import handlers
15 from . import compat, handlers, tags, util
1716 from .backend import json
18 from .compat import numeric_types, string_types, PY3, PY2
17 from .compat import numeric_types, string_types
1918
2019
2120 def encode(
3534 fail_safe=None,
3635 indent=None,
3736 separators=None,
37 include_properties=False,
3838 ):
3939 """Return a JSON formatted representation of value, a Python object.
4040
41 :param unpicklable: If set to False then the output will not contain the
41 :param unpicklable: If set to ``False`` then the output will not contain the
4242 information necessary to turn the JSON data back into Python objects,
43 but a simpler JSON stream is produced.
43 but a simpler JSON stream is produced. It's recommended to set this
44 parameter to ``False`` when your code does not rely on two objects
45 having the same ``id()`` value, and when it is sufficient for those two
46 objects to be equal by ``==``, such as when serializing sklearn
47 instances. If you experience (de)serialization being incorrect when you
48 use numpy, pandas, or sklearn handlers, this should be set to ``False``.
49 If you want the output to not include the dtype for numpy arrays, add
50 ``jsonpickle.register(numpy.generic,
51 UnpicklableNumpyGenericHandler, base=True)`` before your pickling code.
4452 :param max_depth: If set to a non-negative integer then jsonpickle will
4553 not recurse deeper than 'max_depth' steps into the object. Anything
4654 deeper than 'max_depth' is represented using a Python repr() of the
99107 separators. ``(',', ':')`` is the most compact JSON representation.
100108 This value is passed directly to the active JSON backend library and
101109 not used by jsonpickle directly.
110 :param include_properties:
111 Include the names and values of class properties in the generated json.
112 Properties are unpickled properly regardless of this setting, this is
113 meant to be used if processing the json outside of Python. Defaults to
114 ``False``.
102115
103116 >>> encode('my string') == '"my string"'
104117 True
123136 use_decimal=use_decimal,
124137 use_base85=use_base85,
125138 fail_safe=fail_safe,
139 include_properties=include_properties,
126140 )
127141 return backend.encode(
128142 context.flatten(value, reset=reset), indent=indent, separators=separators
129143 )
144
145
146 def _in_cycle(obj, objs, max_reached, make_refs):
147 """Detect cyclic structures that would lead to infinite recursion"""
148 return (
149 (max_reached or (not make_refs and id(obj) in objs))
150 and not util.is_primitive(obj)
151 and not util.is_enum(obj)
152 )
153
154
155 def _mktyperef(obj):
156 """Return a typeref dictionary
157
158 >>> _mktyperef(AssertionError) == {'py/type': 'builtins.AssertionError'}
159 True
160
161 """
162 return {tags.TYPE: util.importable_name(obj)}
163
164
165 def _wrap_string_slot(string):
166 """Converts __slots__ = 'a' into __slots__ = ('a',)"""
167 if isinstance(string, string_types):
168 return (string,)
169 return string
130170
131171
132172 class Pickler(object):
143183 use_decimal=False,
144184 use_base85=False,
145185 fail_safe=None,
186 include_properties=False,
146187 ):
147188 self.unpicklable = unpicklable
148189 self.make_refs = make_refs
150191 self.keys = keys
151192 self.warn = warn
152193 self.numeric_keys = numeric_keys
153 self.use_base85 = use_base85 and (not PY2)
194 self.use_base85 = use_base85
154195 # The current recursion depth
155196 self._depth = -1
156197 # The maximal recursion depth
175216
176217 # ignore exceptions
177218 self.fail_safe = fail_safe
219 self.include_properties = include_properties
220
221 def _determine_sort_keys(self):
222 for _, options in self.backend._encoder_options.values():
223 if options.get("sort_keys", False):
224 # the user has set one of the backends to sort keys
225 return True
226 return False
227
228 def _sort_attrs(self, obj):
229 if hasattr(obj, "__slots__") and self.warn:
230 # Slots are read-only by default, the only way
231 # to sort keys is to do it in a subclass
232 # and that would require calling the init function
233 # of the parent again. That could cause issues
234 # so we refuse to handle it.
235 raise TypeError(
236 "Objects with __slots__ cannot have their keys reliably sorted by jsonpickle! Please sort the keys in the __slots__ definition instead."
237 )
238 # Somehow some classes don't have slots or dict
239 elif hasattr(obj, "__dict__"):
240 try:
241 obj.__dict__ = dict(sorted(obj.__dict__.items()))
242 except (TypeError, AttributeError):
243 # Can't set attributes of builtin/extension type
244 pass
245 return obj
178246
179247 def reset(self):
180248 self._objs = {}
220288
221289 def _getref(self, obj):
222290 return {tags.ID: self._objs.get(id(obj))}
291
292 def _flatten(self, obj):
293 if self.unpicklable and self.make_refs:
294 result = self._flatten_impl(obj)
295 else:
296 try:
297 result = self._flattened[id(obj)]
298 except KeyError:
299 result = self._flattened[id(obj)] = self._flatten_impl(obj)
300 return result
223301
224302 def flatten(self, obj, reset=True):
225303 """Takes an object and returns a JSON-safe representation of it.
251329 """
252330 if reset:
253331 self.reset()
332 if self._determine_sort_keys():
333 obj = self._sort_attrs(obj)
254334 return self._flatten(obj)
255335
256 def _flatten(self, obj):
257 if self.unpicklable and self.make_refs:
258 result = self._flatten_impl(obj)
259 else:
260 try:
261 result = self._flattened[id(obj)]
262 except KeyError:
263 result = self._flattened[id(obj)] = self._flatten_impl(obj)
264 return result
336 def _flatten_bytestring(self, obj):
337 return {self._bytes_tag: self._bytes_encoder(obj)}
265338
266339 def _flatten_impl(self, obj):
267340 #########################################
268341 # if obj is nonrecursive return immediately
269342 # for performance reasons we don't want to do recursive checks
270 if PY2 and isinstance(obj, types.FileType):
271 return self._flatten_file(obj)
272
273343 if type(obj) is bytes:
274344 return self._flatten_bytestring(obj)
275345
285355
286356 def _max_reached(self):
287357 return self._depth == self._max_depth
358
359 def _pickle_warning(self, obj):
360 if self.warn:
361 msg = 'jsonpickle cannot pickle %r: replaced with None' % obj
362 warnings.warn(msg)
288363
289364 def _flatten_obj(self, obj):
290365 self._seen.append(obj)
317392 def _list_recurse(self, obj):
318393 return [self._flatten(v) for v in obj]
319394
320 def _get_flattener(self, obj):
321 if type(obj) in (list, dict):
322 if self._mkref(obj):
323 return (
324 self._list_recurse if type(obj) is list else self._flatten_dict_obj
325 )
395 def _flatten_function(self, obj):
396 if self.unpicklable:
397 data = {tags.FUNCTION: util.importable_name(obj)}
398 else:
399 data = None
400
401 return data
402
403 def _getstate(self, obj, data):
404 state = self._flatten(obj)
405 if self.unpicklable:
406 data[tags.STATE] = state
407 else:
408 data = state
409 return data
410
411 def _flatten_key_value_pair(self, k, v, data):
412 """Flatten a key/value pair into the passed-in dictionary."""
413 if not util.is_picklable(k, v):
414 return data
415
416 if k is None:
417 k = 'null' # for compatibility with common json encoders
418
419 if self.numeric_keys and isinstance(k, numeric_types):
420 pass
421 elif not isinstance(k, string_types):
422 try:
423 k = repr(k)
424 except Exception:
425 k = compat.ustr(k)
426
427 data[k] = self._flatten(v)
428 return data
429
430 def _flatten_obj_attrs(self, obj, attrs, data):
431 flatten = self._flatten_key_value_pair
432 ok = False
433 for k in attrs:
434 try:
435 if not k.startswith('__'):
436 value = getattr(obj, k)
437 else:
438 value = getattr(obj, f"_{obj.__class__.__name__}{k}")
439 flatten(k, value, data)
440 except AttributeError:
441 # The attribute may have been deleted
442 continue
443 ok = True
444 return ok
445
446 def _flatten_properties(self, obj, data, allslots=None):
447 if allslots is None:
448 # setting a list as a default argument can lead to some weird errors
449 allslots = []
450
451 # convert to set in case there are a lot of slots
452 allslots_set = set(itertools.chain.from_iterable(allslots))
453
454 # i don't like lambdas
455 def valid_property(x):
456 return not x[0].startswith("__") and x[0] not in allslots_set
457
458 properties = [
459 x[0] for x in inspect.getmembers(obj.__class__) if valid_property(x)
460 ]
461
462 properties_dict = {}
463 for p_name in properties:
464 p_val = getattr(obj, p_name)
465 if util.is_not_class(p_val):
466 properties_dict[p_name] = p_val
326467 else:
327 self._push()
328 return self._getref
329
330 # We handle tuples and sets by encoding them in a "(tuple|set)dict"
331 elif type(obj) in (tuple, set):
332 if not self.unpicklable:
333 return self._list_recurse
334 return lambda obj: {
335 tags.TUPLE
336 if type(obj) is tuple
337 else tags.SET: [self._flatten(v) for v in obj]
338 }
339
340 elif util.is_object(obj):
341 return self._ref_obj_instance
342
343 elif util.is_type(obj):
344 return _mktyperef
345
346 elif util.is_module_function(obj):
347 return self._flatten_function
348
349 # instance methods, lambdas, old style classes...
468 properties_dict[p_name] = self._flatten(p_val)
469
470 data[tags.PROPERTY] = properties_dict
471
472 return data
473
474 def _flatten_newstyle_with_slots(self, obj, data):
475 """Return a json-friendly dict for new-style objects with __slots__."""
476 allslots = [
477 _wrap_string_slot(getattr(cls, '__slots__', tuple()))
478 for cls in obj.__class__.mro()
479 ]
480
481 # add properties to the attribute list
482 if self.include_properties:
483 data = self._flatten_properties(obj, data, allslots)
484
485 if not self._flatten_obj_attrs(obj, chain(*allslots), data):
486 attrs = [
487 x for x in dir(obj) if not x.startswith('__') and not x.endswith('__')
488 ]
489 self._flatten_obj_attrs(obj, attrs, data)
490
491 return data
492
493 def _flatten_obj_instance(self, obj):
494 """Recursively flatten an instance and return a json-friendly dict"""
495 data = {}
496 has_class = hasattr(obj, '__class__')
497 has_dict = hasattr(obj, '__dict__')
498 has_slots = not has_dict and hasattr(obj, '__slots__')
499 has_getnewargs = util.has_method(obj, '__getnewargs__')
500 has_getnewargs_ex = util.has_method(obj, '__getnewargs_ex__')
501 has_getinitargs = util.has_method(obj, '__getinitargs__')
502 has_reduce, has_reduce_ex = util.has_reduce(obj)
503
504 # Support objects with __getstate__(); this ensures that
505 # both __setstate__() and __getstate__() are implemented
506 has_own_getstate = hasattr(type(obj), '__getstate__') and type(
507 obj
508 ).__getstate__ is not getattr(object, '__getstate__', None)
509 # not using has_method since __getstate__() is handled separately below
510 # Note: on Python 3.11+, all objects have __getstate__.
511
512 if has_class:
513 cls = obj.__class__
514 else:
515 cls = type(obj)
516
517 # Check for a custom handler
518 class_name = util.importable_name(cls)
519 handler = handlers.get(cls, handlers.get(class_name))
520 if handler is not None:
521 if self.unpicklable:
522 data[tags.OBJECT] = class_name
523 return handler(self).flatten(obj, data)
524
525 reduce_val = None
526
527 if self.include_properties:
528 data = self._flatten_properties(obj, data)
529
530 if self.unpicklable:
531 if has_reduce and not has_reduce_ex:
532 try:
533 reduce_val = obj.__reduce__()
534 except TypeError:
535 # A lot of builtin types have a reduce which
536 # just raises a TypeError
537 # we ignore those
538 pass
539
540 # test for a reduce implementation, and redirect before
541 # doing anything else if that is what reduce requests
542 elif has_reduce_ex:
543 try:
544 # we're implementing protocol 2
545 reduce_val = obj.__reduce_ex__(2)
546 except TypeError:
547 # A lot of builtin types have a reduce which
548 # just raises a TypeError
549 # we ignore those
550 pass
551
552 if reduce_val and isinstance(reduce_val, string_types):
553 try:
554 varpath = iter(reduce_val.split('.'))
555 # curmod will be transformed by the
556 # loop into the value to pickle
557 curmod = sys.modules[next(varpath)]
558 for modname in varpath:
559 curmod = getattr(curmod, modname)
560 # replace obj with value retrieved
561 return self._flatten(curmod)
562 except KeyError:
563 # well, we can't do anything with that, so we ignore it
564 pass
565
566 elif reduce_val:
567 # at this point, reduce_val should be some kind of iterable
568 # pad out to len 5
569 rv_as_list = list(reduce_val)
570 insufficiency = 5 - len(rv_as_list)
571 if insufficiency:
572 rv_as_list += [None] * insufficiency
573
574 if getattr(rv_as_list[0], '__name__', '') == '__newobj__':
575 rv_as_list[0] = tags.NEWOBJ
576
577 f, args, state, listitems, dictitems = rv_as_list
578
579 # check that getstate/setstate is sane
580 if not (
581 state
582 and has_own_getstate
583 and not hasattr(obj, '__setstate__')
584 and not isinstance(obj, dict)
585 ):
586 # turn iterators to iterables for convenient serialization
587 if rv_as_list[3]:
588 rv_as_list[3] = tuple(rv_as_list[3])
589
590 if rv_as_list[4]:
591 rv_as_list[4] = tuple(rv_as_list[4])
592
593 reduce_args = list(map(self._flatten, rv_as_list))
594 last_index = len(reduce_args) - 1
595 while last_index >= 2 and reduce_args[last_index] is None:
596 last_index -= 1
597 data[tags.REDUCE] = reduce_args[: last_index + 1]
598
599 return data
600
601 if has_class and not util.is_module(obj):
602 if self.unpicklable:
603 data[tags.OBJECT] = class_name
604
605 if has_getnewargs_ex:
606 data[tags.NEWARGSEX] = list(map(self._flatten, obj.__getnewargs_ex__()))
607
608 if has_getnewargs and not has_getnewargs_ex:
609 data[tags.NEWARGS] = self._flatten(obj.__getnewargs__())
610
611 if has_getinitargs:
612 data[tags.INITARGS] = self._flatten(obj.__getinitargs__())
613
614 if has_own_getstate:
615 try:
616 state = obj.__getstate__()
617 except TypeError:
618 # Has getstate but it cannot be called, e.g. file descriptors
619 # in Python3
620 self._pickle_warning(obj)
621 return None
622 else:
623 if state:
624 return self._getstate(state, data)
625
626 if util.is_module(obj):
627 if self.unpicklable:
628 data[tags.REPR] = '{name}/{name}'.format(name=obj.__name__)
629 else:
630 data = compat.ustr(obj)
631 return data
632
633 if util.is_dictionary_subclass(obj):
634 self._flatten_dict_obj(obj, data)
635 return data
636
637 if util.is_sequence_subclass(obj):
638 return self._flatten_sequence_obj(obj, data)
639
640 if util.is_iterator(obj):
641 # force list in python 3
642 data[tags.ITERATOR] = list(map(self._flatten, islice(obj, self._max_iter)))
643 return data
644
645 if has_dict:
646 # Support objects that subclasses list and set
647 if util.is_sequence_subclass(obj):
648 return self._flatten_sequence_obj(obj, data)
649
650 # hack for zope persistent objects; this unghostifies the object
651 getattr(obj, '_', None)
652 return self._flatten_dict_obj(obj.__dict__, data)
653
654 if has_slots:
655 return self._flatten_newstyle_with_slots(obj, data)
656
657 # catchall return for data created above without a return
658 # (e.g. __getnewargs__ is not supposed to be the end of the story)
659 if data:
660 return data
661
350662 self._pickle_warning(obj)
351663 return None
352664
371683 self._mkref(obj)
372684 return self._flatten_obj_instance(obj)
373685
374 def _flatten_file(self, obj):
375 """
376 Special case file objects
377 """
378 assert not PY3 and isinstance(obj, types.FileType)
379 return None
380
381 def _flatten_bytestring(self, obj):
382 if PY2:
383 try:
384 return obj.decode('utf-8')
385 except UnicodeDecodeError:
686 def _escape_key(self, k):
687 return tags.JSON_KEY + encode(
688 k,
689 reset=False,
690 keys=True,
691 context=self,
692 backend=self.backend,
693 make_refs=self.make_refs,
694 )
695
696 def _flatten_non_string_key_value_pair(self, k, v, data):
697 """Flatten only non-string key/value pairs"""
698 if not util.is_picklable(k, v):
699 return data
700 if self.keys and not isinstance(k, string_types):
701 k = self._escape_key(k)
702 data[k] = self._flatten(v)
703 return data
704
705 def _flatten_string_key_value_pair(self, k, v, data):
706 """Flatten string key/value pairs only."""
707 if not util.is_picklable(k, v):
708 return data
709 if self.keys:
710 if not isinstance(k, string_types):
711 return data
712 elif k.startswith(tags.JSON_KEY):
713 k = self._escape_key(k)
714 else:
715 if k is None:
716 k = 'null' # for compatibility with common json encoders
717
718 if self.numeric_keys and isinstance(k, numeric_types):
386719 pass
387 return {self._bytes_tag: self._bytes_encoder(obj)}
388
389 def _flatten_obj_instance(self, obj):
390 """Recursively flatten an instance and return a json-friendly dict"""
391 data = {}
392 has_class = hasattr(obj, '__class__')
393 has_dict = hasattr(obj, '__dict__')
394 has_slots = not has_dict and hasattr(obj, '__slots__')
395 has_getnewargs = util.has_method(obj, '__getnewargs__')
396 has_getnewargs_ex = util.has_method(obj, '__getnewargs_ex__')
397 has_getinitargs = util.has_method(obj, '__getinitargs__')
398 has_reduce, has_reduce_ex = util.has_reduce(obj)
399
400 # Support objects with __getstate__(); this ensures that
401 # both __setstate__() and __getstate__() are implemented
402 has_getstate = hasattr(obj, '__getstate__')
403 # not using has_method since __getstate__() is handled separately below
404
405 if has_class:
406 cls = obj.__class__
407 else:
408 cls = type(obj)
409
410 # Check for a custom handler
411 class_name = util.importable_name(cls)
412 handler = handlers.get(cls, handlers.get(class_name))
413 if handler is not None:
414 if self.unpicklable:
415 data[tags.OBJECT] = class_name
416 return handler(self).flatten(obj, data)
417
418 reduce_val = None
419
420 if self.unpicklable:
421 if has_reduce and not has_reduce_ex:
720 elif not isinstance(k, string_types):
422721 try:
423 reduce_val = obj.__reduce__()
424 except TypeError:
425 # A lot of builtin types have a reduce which
426 # just raises a TypeError
427 # we ignore those
428 pass
429
430 # test for a reduce implementation, and redirect before
431 # doing anything else if that is what reduce requests
432 elif has_reduce_ex:
433 try:
434 # we're implementing protocol 2
435 reduce_val = obj.__reduce_ex__(2)
436 except TypeError:
437 # A lot of builtin types have a reduce which
438 # just raises a TypeError
439 # we ignore those
440 pass
441
442 if reduce_val and isinstance(reduce_val, string_types):
443 try:
444 varpath = iter(reduce_val.split('.'))
445 # curmod will be transformed by the
446 # loop into the value to pickle
447 curmod = sys.modules[next(varpath)]
448 for modname in varpath:
449 curmod = getattr(curmod, modname)
450 # replace obj with value retrieved
451 return self._flatten(curmod)
452 except KeyError:
453 # well, we can't do anything with that, so we ignore it
454 pass
455
456 elif reduce_val:
457 # at this point, reduce_val should be some kind of iterable
458 # pad out to len 5
459 rv_as_list = list(reduce_val)
460 insufficiency = 5 - len(rv_as_list)
461 if insufficiency:
462 rv_as_list += [None] * insufficiency
463
464 if getattr(rv_as_list[0], '__name__', '') == '__newobj__':
465 rv_as_list[0] = tags.NEWOBJ
466
467 f, args, state, listitems, dictitems = rv_as_list
468
469 # check that getstate/setstate is sane
470 if not (
471 state
472 and hasattr(obj, '__getstate__')
473 and not hasattr(obj, '__setstate__')
474 and not isinstance(obj, dict)
475 ):
476 # turn iterators to iterables for convenient serialization
477 if rv_as_list[3]:
478 rv_as_list[3] = tuple(rv_as_list[3])
479
480 if rv_as_list[4]:
481 rv_as_list[4] = tuple(rv_as_list[4])
482
483 reduce_args = list(map(self._flatten, rv_as_list))
484 last_index = len(reduce_args) - 1
485 while last_index >= 2 and reduce_args[last_index] is None:
486 last_index -= 1
487 data[tags.REDUCE] = reduce_args[: last_index + 1]
488
489 return data
490
491 if has_class and not util.is_module(obj):
492 if self.unpicklable:
493 data[tags.OBJECT] = class_name
494
495 if has_getnewargs_ex:
496 data[tags.NEWARGSEX] = list(map(self._flatten, obj.__getnewargs_ex__()))
497
498 if has_getnewargs and not has_getnewargs_ex:
499 data[tags.NEWARGS] = self._flatten(obj.__getnewargs__())
500
501 if has_getinitargs:
502 data[tags.INITARGS] = self._flatten(obj.__getinitargs__())
503
504 if has_getstate:
505 try:
506 state = obj.__getstate__()
507 except TypeError:
508 # Has getstate but it cannot be called, e.g. file descriptors
509 # in Python3
510 self._pickle_warning(obj)
511 return None
512 else:
513 return self._getstate(state, data)
514
515 if util.is_module(obj):
516 if self.unpicklable:
517 data[tags.REPR] = '{name}/{name}'.format(name=obj.__name__)
518 else:
519 data = compat.ustr(obj)
520 return data
521
522 if util.is_dictionary_subclass(obj):
523 self._flatten_dict_obj(obj, data)
524 return data
525
526 if util.is_sequence_subclass(obj):
527 return self._flatten_sequence_obj(obj, data)
528
529 if util.is_iterator(obj):
530 # force list in python 3
531 data[tags.ITERATOR] = list(map(self._flatten, islice(obj, self._max_iter)))
532 return data
533
534 if has_dict:
535 # Support objects that subclasses list and set
536 if util.is_sequence_subclass(obj):
537 return self._flatten_sequence_obj(obj, data)
538
539 # hack for zope persistent objects; this unghostifies the object
540 getattr(obj, '_', None)
541 return self._flatten_dict_obj(obj.__dict__, data)
542
543 if has_slots:
544 return self._flatten_newstyle_with_slots(obj, data)
545
546 # catchall return for data created above without a return
547 # (e.g. __getnewargs__ is not supposed to be the end of the story)
548 if data:
549 return data
550
551 self._pickle_warning(obj)
552 return None
553
554 def _flatten_function(self, obj):
555 if self.unpicklable:
556 data = {tags.FUNCTION: util.importable_name(obj)}
557 else:
558 data = None
559
722 k = repr(k)
723 except Exception:
724 k = compat.ustr(k)
725
726 data[k] = self._flatten(v)
560727 return data
561728
562729 def _flatten_dict_obj(self, obj, data=None):
594761 if self._mkref(factory):
595762 # We've never seen this object before so pickle it in-place.
596763 # Create an instance from the factory and assume that the
597 # resulting instance is a suitable examplar.
764 # resulting instance is a suitable exemplar.
598765 value = self._flatten_obj_instance(handlers.CloneFactory(factory()))
599766 else:
600767 # We've seen this object before.
610777
611778 return data
612779
613 def _flatten_obj_attrs(self, obj, attrs, data):
614 flatten = self._flatten_key_value_pair
615 ok = False
616 for k in attrs:
617 try:
618 value = getattr(obj, k)
619 flatten(k, value, data)
620 except AttributeError:
621 # The attribute may have been deleted
622 continue
623 ok = True
624 return ok
625
626 def _flatten_newstyle_with_slots(self, obj, data):
627 """Return a json-friendly dict for new-style objects with __slots__."""
628 allslots = [
629 _wrap_string_slot(getattr(cls, '__slots__', tuple()))
630 for cls in obj.__class__.mro()
631 ]
632
633 if not self._flatten_obj_attrs(obj, chain(*allslots), data):
634 attrs = [
635 x for x in dir(obj) if not x.startswith('__') and not x.endswith('__')
636 ]
637 self._flatten_obj_attrs(obj, attrs, data)
638
639 return data
640
641 def _flatten_key_value_pair(self, k, v, data):
642 """Flatten a key/value pair into the passed-in dictionary."""
643 if not util.is_picklable(k, v):
644 return data
645
646 if k is None:
647 k = 'null' # for compatibility with common json encoders
648
649 if self.numeric_keys and isinstance(k, numeric_types):
650 pass
651 elif not isinstance(k, string_types):
652 try:
653 k = repr(k)
654 except Exception:
655 k = compat.ustr(k)
656
657 data[k] = self._flatten(v)
658 return data
659
660 def _flatten_non_string_key_value_pair(self, k, v, data):
661 """Flatten only non-string key/value pairs"""
662 if not util.is_picklable(k, v):
663 return data
664 if self.keys and not isinstance(k, string_types):
665 k = self._escape_key(k)
666 data[k] = self._flatten(v)
667 return data
668
669 def _flatten_string_key_value_pair(self, k, v, data):
670 """Flatten string key/value pairs only."""
671 if not util.is_picklable(k, v):
672 return data
673 if self.keys:
674 if not isinstance(k, string_types):
675 return data
676 elif k.startswith(tags.JSON_KEY):
677 k = self._escape_key(k)
678 else:
679 if k is None:
680 k = 'null' # for compatibility with common json encoders
681
682 if self.numeric_keys and isinstance(k, numeric_types):
683 pass
684 elif not isinstance(k, string_types):
685 try:
686 k = repr(k)
687 except Exception:
688 k = compat.ustr(k)
689
690 data[k] = self._flatten(v)
691 return data
780 def _get_flattener(self, obj):
781 if type(obj) in (list, dict):
782 if self._mkref(obj):
783 return (
784 self._list_recurse if type(obj) is list else self._flatten_dict_obj
785 )
786 else:
787 self._push()
788 return self._getref
789
790 # We handle tuples and sets by encoding them in a "(tuple|set)dict"
791 elif type(obj) in (tuple, set):
792 if not self.unpicklable:
793 return self._list_recurse
794 return lambda obj: {
795 tags.TUPLE
796 if type(obj) is tuple
797 else tags.SET: [self._flatten(v) for v in obj]
798 }
799
800 elif util.is_object(obj):
801 return self._ref_obj_instance
802
803 elif util.is_type(obj):
804 return _mktyperef
805
806 elif util.is_module_function(obj):
807 return self._flatten_function
808
809 # instance methods, lambdas, old style classes...
810 self._pickle_warning(obj)
811 return None
692812
693813 def _flatten_sequence_obj(self, obj, data):
694814 """Return a json-friendly dict for a sequence subclass."""
700820 else:
701821 return value
702822 return data
703
704 def _escape_key(self, k):
705 return tags.JSON_KEY + encode(
706 k,
707 reset=False,
708 keys=True,
709 context=self,
710 backend=self.backend,
711 make_refs=self.make_refs,
712 )
713
714 def _getstate(self, obj, data):
715 state = self._flatten(obj)
716 if self.unpicklable:
717 data[tags.STATE] = state
718 else:
719 data = state
720 return data
721
722 def _pickle_warning(self, obj):
723 if self.warn:
724 msg = 'jsonpickle cannot pickle %r: replaced with None' % obj
725 warnings.warn(msg)
726
727
728 def _in_cycle(obj, objs, max_reached, make_refs):
729 """Detect cyclic structures that would lead to infinite recursion"""
730 return (
731 (max_reached or (not make_refs and id(obj) in objs))
732 and not util.is_primitive(obj)
733 and not util.is_enum(obj)
734 )
735
736
737 def _mktyperef(obj):
738 """Return a typeref dictionary
739
740 >>> _mktyperef(AssertionError) == {'py/type': 'builtins.AssertionError'}
741 True
742
743 """
744 return {tags.TYPE: util.importable_name(obj)}
745
746
747 def _wrap_string_slot(string):
748 """Converts __slots__ = 'a' into __slots__ = ('a',)"""
749 if isinstance(string, string_types):
750 return (string,)
751 return string
66 that need to be specially handled.
77 """
88 from __future__ import absolute_import, division, unicode_literals
9
109
1110 BYTES = 'py/bytes'
1211 B64 = 'py/b64'
2019 NEWARGSEX = 'py/newargsex'
2120 NEWOBJ = 'py/newobj'
2221 OBJECT = 'py/object'
22 PROPERTY = 'py/property'
2323 REDUCE = 'py/reduce'
2424 REF = 'py/ref'
2525 REPR = 'py/repr'
4040 NEWARGSEX,
4141 NEWOBJ,
4242 OBJECT,
43 PROPERTY,
4344 REDUCE,
4445 REF,
4546 REPR,
44 # This software is licensed as described in the file COPYING, which
55 # you should have received as part of this distribution.
66 from __future__ import absolute_import, division, unicode_literals
7 import quopri
7
8 import dataclasses
89 import sys
9
10 from . import compat
11 from . import util
12 from . import tags
13 from . import handlers
10 import warnings
11
12 from . import compat, errors, handlers, tags, util
13 from .backend import json
1414 from .compat import numeric_types
15 from .backend import json
1615
1716
1817 def decode(
19 string, backend=None, context=None, keys=False, reset=True, safe=False, classes=None
18 string,
19 backend=None,
20 context=None,
21 keys=False,
22 reset=True,
23 safe=False,
24 classes=None,
25 v1_decode=False,
26 on_missing="ignore",
2027 ):
2128 """Convert a JSON string into a Python object.
2229
2633
2734 The keyword argument 'classes' defaults to None.
2835 If set to a single class, or a sequence (list, set, tuple) of classes,
29 then the classes will be made available when constructing objects. This
30 can be used to give jsonpickle access to local classes that are not
31 available through the global module import scope.
36 then the classes will be made available when constructing objects.
37 If set to a dictionary of class names to class objects, the class object
38 will be provided to jsonpickle to deserialize the class name into.
39 This can be used to give jsonpickle access to local classes that are not
40 available through the global module import scope, and the dict method can
41 be used to deserialize encoded objects into a new class.
3242
3343 The keyword argument 'safe' defaults to False.
3444 If set to True, eval() is avoided, but backwards-compatible
3747 The keyword argument 'backend' defaults to None.
3848 If set to an instance of jsonpickle.backend.JSONBackend, jsonpickle
3949 will use that backend for deserialization.
50
51 The keyword argument 'v1_decode' defaults to False.
52 If set to True it enables you to decode objects serialized in jsonpickle v1.
53 Please do not attempt to re-encode the objects in the v1 format! Version 2's
54 format fixes issue #255, and allows dictionary identity to be preserved
55 through an encode/decode cycle.
56
57 The keyword argument 'on_missing' defaults to 'ignore'.
58 If set to 'error', it will raise an error if the class it's decoding is not
59 found. If set to 'warn', it will warn you in said case. If set to a
60 non-awaitable function, it will call said callback function with the class
61 name (a string) as the only parameter. Strings passed to on_missing are
62 lowercased automatically.
63
4064
4165 >>> decode('"my string"') == 'my string'
4266 True
4367 >>> decode('36')
4468 36
4569 """
70
71 if isinstance(on_missing, str):
72 on_missing = on_missing.lower()
73 elif not util.is_function(on_missing):
74 warnings.warn(
75 "Unpickler.on_missing must be a string or a function! It will be ignored!"
76 )
77
4678 backend = backend or json
47 context = context or Unpickler(keys=keys, backend=backend, safe=safe)
79 context = context or Unpickler(
80 keys=keys,
81 backend=backend,
82 safe=safe,
83 v1_decode=v1_decode,
84 on_missing=on_missing,
85 )
4886 data = backend.decode(string)
4987 return context.restore(data, reset=reset, classes=classes)
5088
119157 obj[idx] = proxy.get()
120158
121159
160 def loadclass(module_and_name, classes=None):
161 """Loads the module and returns the class.
162
163 >>> cls = loadclass('datetime.datetime')
164 >>> cls.__name__
165 'datetime'
166
167 >>> loadclass('does.not.exist')
168
169 >>> loadclass('builtins.int')()
170 0
171
172 """
173 # Check if the class exists in a caller-provided scope
174 if classes:
175 try:
176 return classes[module_and_name]
177 except KeyError:
178 # maybe they didn't provide a fully qualified path
179 try:
180 return classes[module_and_name.rsplit('.', 1)[-1]]
181 except KeyError:
182 pass
183 # Otherwise, load classes from globally-accessible imports
184 names = module_and_name.split('.')
185 # First assume that everything up to the last dot is the module name,
186 # then try other splits to handle classes that are defined within
187 # classes
188 for up_to in range(len(names) - 1, 0, -1):
189 module = util.untranslate_module_name('.'.join(names[:up_to]))
190 try:
191 __import__(module)
192 obj = sys.modules[module]
193 for class_name in names[up_to:]:
194 try:
195 obj = getattr(obj, class_name)
196 except AttributeError:
197 continue
198 return obj
199 except (AttributeError, ImportError, ValueError):
200 continue
201 return None
202
203
204 def has_tag(obj, tag):
205 """Helper class that tests to see if the obj is a dictionary
206 and contains a particular key/tag.
207
208 >>> obj = {'test': 1}
209 >>> has_tag(obj, 'test')
210 True
211 >>> has_tag(obj, 'fail')
212 False
213
214 >>> has_tag(42, 'fail')
215 False
216
217 """
218 return type(obj) is dict and tag in obj
219
220
221 def getargs(obj, classes=None):
222 """Return arguments suitable for __new__()"""
223 # Let saved newargs take precedence over everything
224 if has_tag(obj, tags.NEWARGSEX):
225 raise ValueError("__newargs_ex__ returns both args and kwargs")
226
227 if has_tag(obj, tags.NEWARGS):
228 return obj[tags.NEWARGS]
229
230 if has_tag(obj, tags.INITARGS):
231 return obj[tags.INITARGS]
232
233 try:
234 seq_list = obj[tags.SEQ]
235 obj_dict = obj[tags.OBJECT]
236 except KeyError:
237 return []
238 typeref = loadclass(obj_dict, classes=classes)
239 if not typeref:
240 return []
241 if hasattr(typeref, '_fields'):
242 if len(typeref._fields) == len(seq_list):
243 return seq_list
244 return []
245
246
247 class _trivialclassic:
248 """
249 A trivial class that can be instantiated with no args
250 """
251
252
253 def make_blank_classic(cls):
254 """
255 Implement the mandated strategy for dealing with classic classes
256 which cannot be instantiated without __getinitargs__ because they
257 take parameters
258 """
259 instance = _trivialclassic()
260 instance.__class__ = cls
261 return instance
262
263
264 def loadrepr(reprstr):
265 """Returns an instance of the object from the object's repr() string.
266 It involves the dynamic specification of code.
267
268 >>> obj = loadrepr('datetime/datetime.datetime.now()')
269 >>> obj.__class__.__name__
270 'datetime'
271
272 """
273 module, evalstr = reprstr.split('/')
274 mylocals = locals()
275 localname = module
276 if '.' in localname:
277 localname = module.split('.', 1)[0]
278 mylocals[localname] = __import__(module)
279 return eval(evalstr)
280
281
282 def has_tag_dict(obj, tag):
283 """Helper class that tests to see if the obj is a dictionary
284 and contains a particular key/tag.
285
286 >>> obj = {'test': 1}
287 >>> has_tag(obj, 'test')
288 True
289 >>> has_tag(obj, 'fail')
290 False
291
292 >>> has_tag(42, 'fail')
293 False
294
295 """
296 return tag in obj
297
298
122299 class Unpickler(object):
123 def __init__(self, backend=None, keys=False, safe=False):
300 def __init__(
301 self, backend=None, keys=False, safe=False, v1_decode=False, on_missing="ignore"
302 ):
124303 self.backend = backend or json
125304 self.keys = keys
126305 self.safe = safe
306 self.v1_decode = v1_decode
307 self.on_missing = on_missing
127308
128309 self.reset()
129310
142323
143324 # Extra local classes not accessible globally
144325 self._classes = {}
326
327 def _swap_proxies(self):
328 """Replace proxies with their corresponding instances"""
329 for (obj, attr, proxy, method) in self._proxies:
330 method(obj, attr, proxy)
331 self._proxies = []
332
333 def _restore(self, obj):
334 # if obj isn't in these types, neither it nor nothing in it can have a tag
335 # don't change the tuple of types to a set, it won't work with isinstance
336 if not isinstance(obj, (str, list, dict, set, tuple)):
337
338 def restore(x):
339 return x
340
341 else:
342 restore = self._restore_tags(obj)
343 return restore(obj)
145344
146345 def restore(self, obj, reset=True, classes=None):
147346 """Restores a flattened object to its original python state.
173372 if isinstance(classes, (list, tuple, set)):
174373 for cls in classes:
175374 self.register_classes(cls)
375 elif isinstance(classes, dict):
376 for cls in classes.values():
377 self.register_classes(cls)
176378 else:
177379 self._classes[util.importable_name(classes)] = classes
178380
179 def _swap_proxies(self):
180 """Replace proxies with their corresponding instances"""
181 for (obj, attr, proxy, method) in self._proxies:
182 method(obj, attr, proxy)
183 self._proxies = []
184
185 def _restore(self, obj):
186 # if obj isn't in these types, neither it nor nothing in it can have a tag
187 # don't change the tuple of types to a set, it won't work with isinstance
188 if not isinstance(obj, (str, list, dict, set, tuple)):
189
190 def restore(x):
191 return x
192
193 else:
194 restore = self._restore_tags(obj)
195 return restore(obj)
196
197 def _restore_tags(self, obj):
198 try:
199 if not tags.RESERVED <= set(obj) and not type(obj) in (list, dict):
200
201 def restore(x):
202 return x
203
204 return restore
205 except TypeError:
206 pass
207 if has_tag(obj, tags.B64):
208 restore = self._restore_base64
209 elif has_tag(obj, tags.B85):
210 restore = self._restore_base85
211 elif has_tag(obj, tags.ID):
212 restore = self._restore_id
213 elif has_tag(obj, tags.ITERATOR):
214 restore = self._restore_iterator
215 elif has_tag(obj, tags.TYPE):
216 restore = self._restore_type
217 elif has_tag(obj, tags.REDUCE):
218 restore = self._restore_reduce
219 elif has_tag(obj, tags.OBJECT):
220 restore = self._restore_object
221 elif has_tag(obj, tags.FUNCTION):
222 restore = self._restore_function
223 elif has_tag(obj, tags.BYTES): # Backwards compatibility
224 restore = self._restore_quopri
225 elif has_tag(obj, tags.REF): # Backwards compatibility
226 restore = self._restore_ref
227 elif has_tag(obj, tags.REPR): # Backwards compatibility
228 restore = self._restore_repr
229 elif util.is_list(obj):
230 restore = self._restore_list
231 elif has_tag(obj, tags.TUPLE):
232 restore = self._restore_tuple
233 elif has_tag(obj, tags.SET):
234 restore = self._restore_set
235 elif util.is_dictionary(obj):
236 restore = self._restore_dict
237 else:
238
239 def restore(x):
240 return x
241
242 return restore
243
244381 def _restore_base64(self, obj):
245382 return util.b64decode(obj[tags.B64].encode('utf-8'))
246383
247384 def _restore_base85(self, obj):
248385 return util.b85decode(obj[tags.B85].encode('utf-8'))
249386
250 #: For backwards compatibility with bytes data produced by older versions
251 def _restore_quopri(self, obj):
252 return quopri.decodestring(obj[tags.BYTES].encode('utf-8'))
387 def _refname(self):
388 """Calculates the name of the current location in the JSON stack.
389
390 This is called as jsonpickle traverses the object structure to
391 create references to previously-traversed objects. This allows
392 cyclical data structures such as doubly-linked lists.
393 jsonpickle ensures that duplicate python references to the same
394 object results in only a single JSON object definition and
395 special reference tags to represent each reference.
396
397 >>> u = Unpickler()
398 >>> u._namestack = []
399 >>> u._refname() == '/'
400 True
401 >>> u._namestack = ['a']
402 >>> u._refname() == '/a'
403 True
404 >>> u._namestack = ['a', 'b']
405 >>> u._refname() == '/a/b'
406 True
407
408 """
409 return '/' + '/'.join(self._namestack)
410
411 def _mkref(self, obj):
412 obj_id = id(obj)
413 try:
414 self._obj_to_idx[obj_id]
415 except KeyError:
416 self._obj_to_idx[obj_id] = len(self._objs)
417 self._objs.append(obj)
418 # Backwards compatibility: old versions of jsonpickle
419 # produced "py/ref" references.
420 self._namedict[self._refname()] = obj
421 return obj
422
423 def _restore_list(self, obj):
424 parent = []
425 self._mkref(parent)
426 children = [self._restore(v) for v in obj]
427 parent.extend(children)
428 method = _obj_setvalue
429 proxies = [
430 (parent, idx, value, method)
431 for idx, value in enumerate(parent)
432 if isinstance(value, _Proxy)
433 ]
434 self._proxies.extend(proxies)
435 return parent
253436
254437 def _restore_iterator(self, obj):
255438 return iter(self._restore_list(obj[tags.ITERATOR]))
439
440 def _swapref(self, proxy, instance):
441 proxy_id = id(proxy)
442 instance_id = id(instance)
443
444 instance_index = self._obj_to_idx[proxy_id]
445 self._obj_to_idx[instance_id] = instance_index
446 del self._obj_to_idx[proxy_id]
447
448 self._objs[instance_index] = instance
449 self._namedict[self._refname()] = instance
256450
257451 def _restore_reduce(self, obj):
258452 """
324518 except IndexError:
325519 return _IDProxy(self._objs, idx)
326520
327 def _restore_ref(self, obj):
328 return self._namedict.get(obj[tags.REF])
329
330521 def _restore_type(self, obj):
331522 typeref = loadclass(obj[tags.TYPE], classes=self._classes)
332523 if typeref is None:
339530 return None
340531 obj = loadrepr(obj[tags.REPR])
341532 return self._mkref(obj)
342
343 def _restore_object(self, obj):
344 class_name = obj[tags.OBJECT]
345 cls = loadclass(class_name, classes=self._classes)
346 handler = handlers.get(cls, handlers.get(class_name))
347 if handler is not None: # custom handler
348 proxy = _Proxy()
349 self._mkref(proxy)
350 instance = handler(self).restore(obj)
351 proxy.reset(instance)
352 self._swapref(proxy, instance)
353 return instance
354
355 if cls is None:
356 return self._mkref(obj)
357
358 return self._restore_object_instance(obj, cls)
359
360 def _restore_function(self, obj):
361 return loadclass(obj[tags.FUNCTION], classes=self._classes)
362533
363534 def _loadfactory(self, obj):
364535 try:
368539 del obj['default_factory']
369540 return self._restore(default_factory)
370541
371 def _restore_object_instance(self, obj, cls):
372 # This is a placeholder proxy object which allows child objects to
373 # reference the parent object before it has been instantiated.
374 proxy = _Proxy()
375 self._mkref(proxy)
376
377 # An object can install itself as its own factory, so load the factory
378 # after the instance is available for referencing.
379 factory = self._loadfactory(obj)
380
381 if has_tag(obj, tags.NEWARGSEX):
382 args, kwargs = obj[tags.NEWARGSEX]
542 def _process_missing(self, class_name):
543 # most common case comes first
544 if self.on_missing == 'ignore':
545 pass
546 elif self.on_missing == 'warn':
547 warnings.warn("Unpickler._restore_object could not find %s!" % class_name)
548 elif self.on_missing == 'error':
549 raise errors.ClassNotFoundError(
550 "Unpickler.restore_object could not find %s!" % class_name
551 )
552 elif util.is_function(self.on_missing):
553 self.on_missing(class_name)
554
555 def _restore_pickled_key(self, key):
556 """Restore a possibly pickled key"""
557 if _is_json_key(key):
558 key = decode(
559 key[len(tags.JSON_KEY) :],
560 backend=self.backend,
561 context=self,
562 keys=True,
563 reset=False,
564 )
565 return key
566
567 def _restore_key_fn(self):
568 """Return a callable that restores keys
569
570 This function is responsible for restoring non-string keys
571 when we are decoding with `keys=True`.
572
573 """
574 # This function is called before entering a tight loop
575 # where the returned function will be called.
576 # We return a specific function after checking self.keys
577 # instead of doing so in the body of the function to
578 # avoid conditional branching inside a tight loop.
579 if self.keys:
580 restore_key = self._restore_pickled_key
383581 else:
384 args = getargs(obj, classes=self._classes)
385 kwargs = {}
386 if args:
387 args = self._restore(args)
388 if kwargs:
389 kwargs = self._restore(kwargs)
390
391 is_oldstyle = not (isinstance(cls, type) or getattr(cls, '__meta__', None))
392 try:
393 if (not is_oldstyle) and hasattr(cls, '__new__'):
394 # new style classes
395 if factory:
396 instance = cls.__new__(cls, factory, *args, **kwargs)
397 instance.default_factory = factory
398 else:
399 instance = cls.__new__(cls, *args, **kwargs)
400 else:
401 instance = object.__new__(cls)
402 except TypeError: # old-style classes
403 is_oldstyle = True
404
405 if is_oldstyle:
406 try:
407 instance = cls(*args)
408 except TypeError: # fail gracefully
409 try:
410 instance = make_blank_classic(cls)
411 except Exception: # fail gracefully
412 return self._mkref(obj)
413
414 proxy.reset(instance)
415 self._swapref(proxy, instance)
416
417 if isinstance(instance, tuple):
418 return instance
419
420 instance = self._restore_object_instance_variables(obj, instance)
421
422 if _safe_hasattr(instance, 'default_factory') and isinstance(
423 instance.default_factory, _Proxy
424 ):
425 instance.default_factory = instance.default_factory.get()
426
427 return instance
582
583 def restore_key(key):
584 return key
585
586 return restore_key
428587
429588 def _restore_from_dict(self, obj, instance, ignorereserved=True):
430589 restore_key = self._restore_key_fn()
456615 self._namestack.pop()
457616 continue
458617 else:
459 setattr(instance, k, value)
618 if not k.startswith('__'):
619 try:
620 setattr(instance, k, value)
621 except KeyError:
622 # certain numpy objects require us to prepend a _ to the var
623 # this should go in the np handler but I think this could be
624 # useful for other code
625 setattr(instance, f"_{k}", value)
626 except dataclasses.FrozenInstanceError:
627 # issue #240
628 # i think this is the only way to set frozen dataclass attrs
629 object.__setattr__(instance, k, value)
630 else:
631 setattr(instance, f"_{instance.__class__.__name__}{k}", value)
460632
461633 # This instance has an instance variable named `k` that is
462634 # currently a proxy and must be replaced
469641 if deferred:
470642 # SQLAlchemy Immutable mappings must be constructed in one shot
471643 instance = instance.__class__(deferred)
472
473 return instance
474
475 def _restore_object_instance_variables(self, obj, instance):
476 instance = self._restore_from_dict(obj, instance)
477
478 # Handle list and set subclasses
479 if has_tag(obj, tags.SEQ):
480 if hasattr(instance, 'append'):
481 for v in obj[tags.SEQ]:
482 instance.append(self._restore(v))
483 elif hasattr(instance, 'add'):
484 for v in obj[tags.SEQ]:
485 instance.add(self._restore(v))
486
487 if has_tag(obj, tags.STATE):
488 instance = self._restore_state(obj, instance)
489644
490645 return instance
491646
518673 instance = state
519674 return instance
520675
521 def _restore_list(self, obj):
522 parent = []
523 self._mkref(parent)
524 children = [self._restore(v) for v in obj]
525 parent.extend(children)
526 method = _obj_setvalue
527 proxies = [
528 (parent, idx, value, method)
529 for idx, value in enumerate(parent)
530 if isinstance(value, _Proxy)
531 ]
532 self._proxies.extend(proxies)
533 return parent
534
535 def _restore_tuple(self, obj):
536 return tuple([self._restore(v) for v in obj[tags.TUPLE]])
676 def _restore_object_instance_variables(self, obj, instance):
677 instance = self._restore_from_dict(obj, instance)
678
679 # Handle list and set subclasses
680 if has_tag(obj, tags.SEQ):
681 if hasattr(instance, 'append'):
682 for v in obj[tags.SEQ]:
683 instance.append(self._restore(v))
684 elif hasattr(instance, 'add'):
685 for v in obj[tags.SEQ]:
686 instance.add(self._restore(v))
687
688 if has_tag(obj, tags.STATE):
689 instance = self._restore_state(obj, instance)
690
691 return instance
692
693 def _restore_object_instance(self, obj, cls, class_name=""):
694 # This is a placeholder proxy object which allows child objects to
695 # reference the parent object before it has been instantiated.
696 proxy = _Proxy()
697 self._mkref(proxy)
698
699 # An object can install itself as its own factory, so load the factory
700 # after the instance is available for referencing.
701 factory = self._loadfactory(obj)
702
703 if has_tag(obj, tags.NEWARGSEX):
704 args, kwargs = obj[tags.NEWARGSEX]
705 else:
706 args = getargs(obj, classes=self._classes)
707 kwargs = {}
708 if args:
709 args = self._restore(args)
710 if kwargs:
711 kwargs = self._restore(kwargs)
712
713 is_oldstyle = not (isinstance(cls, type) or getattr(cls, '__meta__', None))
714 try:
715 if (not is_oldstyle) and hasattr(cls, '__new__'):
716 # new style classes
717 if factory:
718 instance = cls.__new__(cls, factory, *args, **kwargs)
719 instance.default_factory = factory
720 else:
721 instance = cls.__new__(cls, *args, **kwargs)
722 else:
723 instance = object.__new__(cls)
724 except TypeError: # old-style classes
725 is_oldstyle = True
726
727 if is_oldstyle:
728 try:
729 instance = cls(*args)
730 except TypeError: # fail gracefully
731 try:
732 instance = make_blank_classic(cls)
733 except Exception: # fail gracefully
734 self._process_missing(class_name)
735 return self._mkref(obj)
736
737 proxy.reset(instance)
738 self._swapref(proxy, instance)
739
740 if isinstance(instance, tuple):
741 return instance
742
743 instance = self._restore_object_instance_variables(obj, instance)
744
745 if _safe_hasattr(instance, 'default_factory') and isinstance(
746 instance.default_factory, _Proxy
747 ):
748 instance.default_factory = instance.default_factory.get()
749
750 return instance
751
752 def _restore_object(self, obj):
753 class_name = obj[tags.OBJECT]
754 cls = loadclass(class_name, classes=self._classes)
755 handler = handlers.get(cls, handlers.get(class_name))
756 if handler is not None: # custom handler
757 proxy = _Proxy()
758 self._mkref(proxy)
759 instance = handler(self).restore(obj)
760 proxy.reset(instance)
761 self._swapref(proxy, instance)
762 return instance
763
764 if cls is None:
765 return self._mkref(obj)
766
767 return self._restore_object_instance(obj, cls, class_name)
768
769 def _restore_function(self, obj):
770 return loadclass(obj[tags.FUNCTION], classes=self._classes)
537771
538772 def _restore_set(self, obj):
539773 return {self._restore(v) for v in obj[tags.SET]}
540774
541775 def _restore_dict(self, obj):
542776 data = {}
543 self._mkref(data)
777 if not self.v1_decode:
778 self._mkref(data)
544779
545780 # If we are decoding dicts that can have non-string keys then we
546781 # need to do a two-phase decode where the non-string keys are
585820 self._namestack.pop()
586821 return data
587822
588 def _restore_key_fn(self):
589 """Return a callable that restores keys
590
591 This function is responsible for restoring non-string keys
592 when we are decoding with `keys=True`.
593
594 """
595 # This function is called before entering a tight loop
596 # where the returned function will be called.
597 # We return a specific function after checking self.keys
598 # instead of doing so in the body of the function to
599 # avoid conditional branching inside a tight loop.
600 if self.keys:
601 restore_key = self._restore_pickled_key
823 def _restore_tuple(self, obj):
824 return tuple([self._restore(v) for v in obj[tags.TUPLE]])
825
826 def _restore_tags(self, obj):
827 try:
828 if not tags.RESERVED <= set(obj) and not type(obj) in (list, dict):
829
830 def restore(x):
831 return x
832
833 return restore
834 except TypeError:
835 pass
836 if type(obj) is dict:
837 if tags.TUPLE in obj:
838 restore = self._restore_tuple
839 elif tags.SET in obj:
840 restore = self._restore_set
841 elif tags.B64 in obj:
842 restore = self._restore_base64
843 elif tags.B85 in obj:
844 restore = self._restore_base85
845 elif tags.ID in obj:
846 restore = self._restore_id
847 elif tags.ITERATOR in obj:
848 restore = self._restore_iterator
849 elif tags.OBJECT in obj:
850 restore = self._restore_object
851 elif tags.TYPE in obj:
852 restore = self._restore_type
853 elif tags.REDUCE in obj:
854 restore = self._restore_reduce
855 elif tags.FUNCTION in obj:
856 restore = self._restore_function
857 elif tags.REPR in obj: # Backwards compatibility
858 restore = self._restore_repr
859 else:
860 restore = self._restore_dict
861 elif util.is_list(obj):
862 restore = self._restore_list
602863 else:
603864
604 def restore_key(key):
605 return key
606
607 return restore_key
608
609 def _restore_pickled_key(self, key):
610 """Restore a possibly pickled key"""
611 if _is_json_key(key):
612 key = decode(
613 key[len(tags.JSON_KEY) :],
614 backend=self.backend,
615 context=self,
616 keys=True,
617 reset=False,
618 )
619 return key
620
621 def _refname(self):
622 """Calculates the name of the current location in the JSON stack.
623
624 This is called as jsonpickle traverses the object structure to
625 create references to previously-traversed objects. This allows
626 cyclical data structures such as doubly-linked lists.
627 jsonpickle ensures that duplicate python references to the same
628 object results in only a single JSON object definition and
629 special reference tags to represent each reference.
630
631 >>> u = Unpickler()
632 >>> u._namestack = []
633 >>> u._refname() == '/'
634 True
635 >>> u._namestack = ['a']
636 >>> u._refname() == '/a'
637 True
638 >>> u._namestack = ['a', 'b']
639 >>> u._refname() == '/a/b'
640 True
641
642 """
643 return '/' + '/'.join(self._namestack)
644
645 def _mkref(self, obj):
646 obj_id = id(obj)
647 try:
648 self._obj_to_idx[obj_id]
649 except KeyError:
650 self._obj_to_idx[obj_id] = len(self._objs)
651 self._objs.append(obj)
652 # Backwards compatibility: old versions of jsonpickle
653 # produced "py/ref" references.
654 self._namedict[self._refname()] = obj
655 return obj
656
657 def _swapref(self, proxy, instance):
658 proxy_id = id(proxy)
659 instance_id = id(instance)
660
661 instance_index = self._obj_to_idx[proxy_id]
662 self._obj_to_idx[instance_id] = instance_index
663 del self._obj_to_idx[proxy_id]
664
665 self._objs[instance_index] = instance
666 self._namedict[self._refname()] = instance
667
668
669 def loadclass(module_and_name, classes=None):
670 """Loads the module and returns the class.
671
672 >>> cls = loadclass('datetime.datetime')
673 >>> cls.__name__
674 'datetime'
675
676 >>> loadclass('does.not.exist')
677
678 >>> loadclass('builtins.int')()
679 0
680
681 """
682 # Check if the class exists in a caller-provided scope
683 if classes:
684 try:
685 return classes[module_and_name]
686 except KeyError:
687 pass
688 # Otherwise, load classes from globally-accessible imports
689 names = module_and_name.split('.')
690 # First assume that everything up to the last dot is the module name,
691 # then try other splits to handle classes that are defined within
692 # classes
693 for up_to in range(len(names) - 1, 0, -1):
694 module = util.untranslate_module_name('.'.join(names[:up_to]))
695 try:
696 __import__(module)
697 obj = sys.modules[module]
698 for class_name in names[up_to:]:
699 obj = getattr(obj, class_name)
700 return obj
701 except (AttributeError, ImportError, ValueError):
702 continue
703 return None
704
705
706 def getargs(obj, classes=None):
707 """Return arguments suitable for __new__()"""
708 # Let saved newargs take precedence over everything
709 if has_tag(obj, tags.NEWARGSEX):
710 raise ValueError("__newargs_ex__ returns both args and kwargs")
711
712 if has_tag(obj, tags.NEWARGS):
713 return obj[tags.NEWARGS]
714
715 if has_tag(obj, tags.INITARGS):
716 return obj[tags.INITARGS]
717
718 try:
719 seq_list = obj[tags.SEQ]
720 obj_dict = obj[tags.OBJECT]
721 except KeyError:
722 return []
723 typeref = loadclass(obj_dict, classes=classes)
724 if not typeref:
725 return []
726 if hasattr(typeref, '_fields'):
727 if len(typeref._fields) == len(seq_list):
728 return seq_list
729 return []
730
731
732 class _trivialclassic:
733 """
734 A trivial class that can be instantiated with no args
735 """
736
737
738 def make_blank_classic(cls):
739 """
740 Implement the mandated strategy for dealing with classic classes
741 which cannot be instantiated without __getinitargs__ because they
742 take parameters
743 """
744 instance = _trivialclassic()
745 instance.__class__ = cls
746 return instance
747
748
749 def loadrepr(reprstr):
750 """Returns an instance of the object from the object's repr() string.
751 It involves the dynamic specification of code.
752
753 >>> obj = loadrepr('datetime/datetime.datetime.now()')
754 >>> obj.__class__.__name__
755 'datetime'
756
757 """
758 module, evalstr = reprstr.split('/')
759 mylocals = locals()
760 localname = module
761 if '.' in localname:
762 localname = module.split('.', 1)[0]
763 mylocals[localname] = __import__(module)
764 return eval(evalstr)
765
766
767 def has_tag(obj, tag):
768 """Helper class that tests to see if the obj is a dictionary
769 and contains a particular key/tag.
770
771 >>> obj = {'test': 1}
772 >>> has_tag(obj, 'test')
773 True
774 >>> has_tag(obj, 'fail')
775 False
776
777 >>> has_tag(42, 'fail')
778 False
779
780 """
781 return type(obj) is dict and tag in obj
865 def restore(x):
866 return x
867
868 return restore
88 determining the type of an object.
99 """
1010 from __future__ import absolute_import, division, unicode_literals
11
1112 import base64
1213 import collections
14 import inspect
1315 import io
1416 import operator
1517 import sys
1618 import time
1719 import types
18 import inspect
19
20 from . import tags
21 from . import compat
22 from .compat import (
23 abc_iterator,
24 class_types,
25 iterator_types,
26 numeric_types,
27 PY2,
28 PY3,
29 PY3_ORDERED_DICT,
30 )
31
32 if PY2:
33 import __builtin__
20
21 from . import compat, tags
22 from .compat import abc_iterator, class_types, iterator_types, numeric_types
3423
3524 SEQUENCES = (list, set, tuple)
3625 SEQUENCES_SET = {list, set, tuple}
4433 }
4534 NON_REDUCIBLE_TYPES = (
4635 {
47 int,
48 float,
4936 list,
5037 dict,
5138 set,
5643 | PRIMITIVES
5744 | FUNCTION_TYPES
5845 )
46 NON_CLASS_TYPES = {
47 list,
48 dict,
49 set,
50 tuple,
51 bytes,
52 } | PRIMITIVES
5953
6054
6155 def is_type(obj):
110104 return True
111105
112106 # at this point, the method has to be an instancemthod or a classmethod
113 self_attr = '__self__' if PY3 else 'im_self'
114 if not hasattr(func, self_attr):
115 return False
116 bound_to = getattr(func, self_attr)
107 if not hasattr(func, '__self__'):
108 return False
109 bound_to = getattr(func, '__self__')
117110
118111 # class methods
119112 if isinstance(original, classmethod):
138131 return isinstance(obj, object) and not isinstance(
139132 obj, (type, types.FunctionType, types.BuiltinFunctionType)
140133 )
134
135
136 def is_not_class(obj):
137 """Determines if the object is not a class or a class instance.
138 Used for serializing properties.
139 """
140 return type(obj) in NON_CLASS_TYPES
141141
142142
143143 def is_primitive(obj):
247247 """
248248 return (
249249 hasattr(obj, '__class__')
250 and (issubclass(obj.__class__, SEQUENCES) or is_list_like(obj))
250 and issubclass(obj.__class__, SEQUENCES)
251251 and not is_sequence(obj)
252252 )
253253
355355
356356
357357 def is_iterator(obj):
358 is_file = PY2 and isinstance(obj, __builtin__.file)
359 return (
360 isinstance(obj, abc_iterator) and not isinstance(obj, io.IOBase) and not is_file
361 )
358 return isinstance(obj, abc_iterator) and not isinstance(obj, io.IOBase)
362359
363360
364361 def is_collections(obj):
380377 # defaultdicts may contain functions which we cannot serialise
381378 if is_collections(obj) and not isinstance(obj, collections.defaultdict):
382379 return True
383 # sets are slightly slower in this case
384 if type(obj) in NON_REDUCIBLE_TYPES:
385 return False
386 elif obj is object:
387 return False
388 elif is_list_like(obj):
389 return False
390 elif isinstance(obj, types.ModuleType):
391 return False
392 elif is_dictionary_subclass(obj):
393 return False
394 elif is_reducible_sequence_subclass(obj):
395 return False
396 elif isinstance(getattr(obj, '__slots__', None), iterator_types):
397 return False
398 elif is_type(obj) and obj.__module__ == 'datetime':
399 return False
380 # We turn off the formatting in order to double the speed of the function.
381 # Condensing it into one line seems to save the parser a lot of time.
382 # fmt: off
383 # pylint: disable=line-too-long
384 if type(obj) in NON_REDUCIBLE_TYPES or obj is object or is_dictionary_subclass(obj) or isinstance(obj, types.ModuleType) or is_reducible_sequence_subclass(obj) or is_list_like(obj) or isinstance(getattr(obj, '__slots__', None), iterator_types) or (is_type(obj) and obj.__module__ == 'datetime'): # noqa: E501
385 return False
386 # fmt: on
400387 return True
401388
402389
488475 return lookup.get(module, module)
489476
490477
491 def untranslate_module_name(module):
492 """Rename module names mention in JSON to names that we can import
493
494 This reverses the translation applied by translate_module_name() to
495 a module name available to the current version of Python.
496
497 """
498 module = _0_9_6_compat_untranslate(module)
499 lookup = dict(builtins='__builtin__') if PY2 else {}
500 return lookup.get(module, module)
501
502
503478 def _0_9_6_compat_untranslate(module):
504479 """Provide compatibility for pickles created with jsonpickle 0.9.6 and
505480 earlier, remapping `exceptions` and `__builtin__` to `builtins`.
508483 return lookup.get(module, module)
509484
510485
486 def untranslate_module_name(module):
487 """Rename module names mention in JSON to names that we can import
488
489 This reverses the translation applied by translate_module_name() to
490 a module name available to the current version of Python.
491
492 """
493 return _0_9_6_compat_untranslate(module)
494
495
511496 def importable_name(cls):
512497 """
513498 >>> class Example(object):
529514 # Use the fully-qualified name if available (Python >= 3.3)
530515 name = getattr(cls, '__qualname__', cls.__name__)
531516 module = translate_module_name(cls.__module__)
517 if not module:
518 if hasattr(cls, '__self__'):
519 module = cls.__self__.__class__.__module__
532520 return '{}.{}'.format(module, name)
533521
534522
550538 """
551539 Encode binary data to ascii text in base85. Data must be bytes.
552540 """
553 if PY2:
554 raise NotImplementedError("Python 2 can't encode data in base85.")
555541 return base64.b85encode(data).decode('ascii')
556542
557543
559545 """
560546 Decode payload - must be ascii text.
561547 """
562 if PY2:
563 raise NotImplementedError("Python 2 can't decode base85-encoded data.")
564548 return base64.b85decode(payload)
565549
566550
569553
570554
571555 def items(obj):
572 """Iterate over dicts in a deterministic order
573
574 Python2 does not guarantee dict ordering, so this function
575 papers over the difference in behavior. Python3 does guarantee
576 dict order, without use of OrderedDict, so no sorting is needed there.
577
578 """
579 if PY3_ORDERED_DICT:
580 for k, v in obj.items():
581 yield k, v
582 else:
583 for k, v in sorted(obj.items(), key=itemgetter):
584 yield k, v
556 """
557 TODO: Replace all calls to this with plain dict.items()
558 """
559 for k, v in obj.items():
560 yield k, v
00 Metadata-Version: 2.1
11 Name: jsonpickle
2 Version: 2.0.0
2 Version: 3.0.0
33 Summary: Python library for serializing any arbitrary object graph into JSON
44 Home-page: https://github.com/jsonpickle/jsonpickle
55 Author: David Aguilar
66 Author-email: davvid@gmail.com
77 License: UNKNOWN
8 Description: .. image:: https://img.shields.io/pypi/v/jsonpickle.svg
9 :target: `PyPI link`_
10
11 .. image:: https://img.shields.io/pypi/pyversions/jsonpickle.svg
12 :target: `PyPI link`_
13
14 .. _PyPI link: https://pypi.org/project/jsonpickle
15
16 .. image:: https://dev.azure.com/jaraco/jsonpickle/_apis/build/status/jaraco.jsonpickle?branchName=master
17 :target: https://dev.azure.com/jaraco/jsonpickle/_build/latest?definitionId=1&branchName=master
18
19 .. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest
20 :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest
21
22 .. image:: https://travis-ci.org/jsonpickle/jsonpickle.svg?branch=master
23 :target: https://travis-ci.org/jsonpickle/jsonpickle
24 :alt: travis
25
26 .. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
27 :target: https://github.com/jsonpickle/jsonpickle/blob/master/COPYING
28 :alt: BSD
29
30
31 jsonpickle
32 ==========
33 jsonpickle is a library for the two-way conversion of complex Python objects
34 and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON
35 encoders, such as simplejson, json, and demjson.
36
37 For complete documentation, please visit the
38 `jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_.
39
40 Bug reports and merge requests are encouraged at the
41 `jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_.
42
43 jsonpickle supports Python 2.7 and Python 3.4 or greater.
44
45 **WARNING**:
46 jsonpickle can execute arbitrary Python code. Do not load jsonpickles from untrusted / unauthenticated sources.
47
48 Why jsonpickle?
49 ===============
50 Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena.
51
52 Install
53 =======
54
55 Install from pip for the latest stable release:
56
57 ::
58
59 pip install jsonpickle
60
61 Install from github for the latest changes:
62
63 ::
64
65 pip install git+https://github.com/jsonpickle/jsonpickle.git
66
67 If you have the files checked out for development:
68
69 ::
70
71 git clone https://github.com/jsonpickle/jsonpickle.git
72 cd jsonpickle
73 python setup.py develop
74
75
76 Numpy Support
77 =============
78 jsonpickle includes a built-in numpy extension. If would like to encode
79 sklearn models, numpy arrays, and other numpy-based data then you must
80 enable the numpy extension by registering its handlers::
81
82 >>> import jsonpickle.ext.numpy as jsonpickle_numpy
83 >>> jsonpickle_numpy.register_handlers()
84
85 Pandas Support
86 ==============
87 jsonpickle includes a built-in pandas extension. If would like to encode
88 pandas DataFrame or Series objects then you must enable the pandas extension
89 by registering its handlers::
90
91 >>> import jsonpickle.ext.pandas as jsonpickle_pandas
92 >>> jsonpickle_pandas.register_handlers()
93
94 jsonpickleJS
95 ============
96 `jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_
97 is a javascript implementation of jsonpickle by Michael Scott Cuthbert.
98 jsonpickleJS can be extremely useful for projects that have parallel data
99 structures between Python and Javascript.
100
101 License
102 =======
103 Licensed under the BSD License. See COPYING for details.
104 See jsonpickleJS/LICENSE for details about the jsonpickleJS license.
105
106 Development
107 ===========
108
109 Use `make` to run the unit tests::
110
111 make test
112
113 `pytest` is used to run unit tests internally.
114
115 A `tox` target is provided to run tests using tox.
116 Setting ``multi=1`` tests using all installed and supported Python versions::
117
118 make tox
119 make tox multi=1
120
121 `jsonpickle` itself has no dependencies beyond the Python stdlib.
122 `tox` is required for testing when using the `tox` test runner only.
123
124 The testing requirements are specified in `requirements-dev.txt`.
125 It is recommended to create a virtualenv and run tests from within the
126 virtualenv, or use a tool such as `vx <https://github.com/davvid/vx/>`_
127 to activate the virtualenv without polluting the shell environment::
128
129 python3 -mvenv env3x
130 vx env3x pip install --requirement requirements-dev.txt
131 vx env3x make test
132
133 `jsonpickle` supports multiple Python versions, so using a combination of
134 multiple virtualenvs and `tox` is useful in order to catch compatibility
135 issues when developing.
136
1378 Keywords: json pickle,json,pickle,marshal,serialization,JavaScript Object Notation
1389 Platform: POSIX
13910 Platform: Windows
14112 Classifier: Intended Audience :: Developers
14213 Classifier: License :: OSI Approved :: BSD License
14314 Classifier: Programming Language :: Python
144 Classifier: Programming Language :: Python :: 2
145 Classifier: Programming Language :: Python :: 2.7
14615 Classifier: Programming Language :: Python :: 3
16 Classifier: Programming Language :: Python :: 3.7
17 Classifier: Programming Language :: Python :: 3.8
18 Classifier: Programming Language :: Python :: 3.9
19 Classifier: Programming Language :: Python :: 3.10
14720 Classifier: Programming Language :: JavaScript
14821 Classifier: Operating System :: OS Independent
14922 Classifier: Topic :: Software Development :: Libraries :: Python Modules
150 Requires-Python: >=2.7
23 Requires-Python: >=3.7
15124 Provides-Extra: testing
15225 Provides-Extra: testing.libs
15326 Provides-Extra: docs
27 License-File: LICENSE
28
29 .. image:: https://img.shields.io/pypi/v/jsonpickle.svg
30 :target: `PyPI link`_
31
32 .. image:: https://img.shields.io/pypi/pyversions/jsonpickle.svg
33 :target: `PyPI link`_
34
35 .. _PyPI link: https://pypi.org/project/jsonpickle
36
37 .. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest
38 :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest
39
40 .. image:: https://github.com/jsonpickle/jsonpickle/actions/workflows/test.yml/badge.svg
41 :target: https://github.com/jsonpickle/jsonpickle/actions
42 :alt: Github Actions
43
44 .. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
45 :target: https://github.com/jsonpickle/jsonpickle/blob/main/COPYING
46 :alt: BSD
47
48
49 jsonpickle
50 ==========
51 jsonpickle is a library for the two-way conversion of complex Python objects
52 and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON
53 encoders, such as simplejson, json, and ujson.
54
55 .. warning::
56
57 jsonpickle can execute arbitrary Python code.
58
59 Please see the Security section for more details.
60
61
62 For complete documentation, please visit the
63 `jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_.
64
65 Bug reports and merge requests are encouraged at the
66 `jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_.
67
68 jsonpickle officially supports CPython 2.7 and CPython 3.6 or greater. Version support below CPython 3.7 will be dropped upon release of jsonpickle 3.0.
69
70 Why jsonpickle?
71 ===============
72 Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena.
73
74 Security
75 ========
76
77 jsonpickle should be treated the same as the
78 `Python stdlib pickle module <https://docs.python.org/3/library/pickle.html>`_
79 from a security perspective.
80
81 .. warning::
82
83 The jsonpickle module **is not secure**. Only unpickle data you trust.
84
85 It is possible to construct malicious pickle data which will **execute
86 arbitrary code during unpickling**. Never unpickle data that could have come
87 from an untrusted source, or that could have been tampered with.
88
89 Consider signing data with an HMAC if you need to ensure that it has not
90 been tampered with.
91
92 Safer deserialization approaches, such as reading JSON directly,
93 may be more appropriate if you are processing untrusted data.
94
95
96 Install
97 =======
98
99 Install from pip for the latest stable release:
100
101 ::
102
103 pip install jsonpickle
104
105 Install from github for the latest changes:
106
107 ::
108
109 pip install git+https://github.com/jsonpickle/jsonpickle.git
110
111 If you have the files checked out for development:
112
113 ::
114
115 git clone https://github.com/jsonpickle/jsonpickle.git
116 cd jsonpickle
117 python setup.py develop
118
119
120 Numpy Support
121 =============
122 jsonpickle includes a built-in numpy extension. If would like to encode
123 sklearn models, numpy arrays, and other numpy-based data then you must
124 enable the numpy extension by registering its handlers::
125
126 >>> import jsonpickle.ext.numpy as jsonpickle_numpy
127 >>> jsonpickle_numpy.register_handlers()
128
129 Pandas Support
130 ==============
131 jsonpickle includes a built-in pandas extension. If would like to encode
132 pandas DataFrame or Series objects then you must enable the pandas extension
133 by registering its handlers::
134
135 >>> import jsonpickle.ext.pandas as jsonpickle_pandas
136 >>> jsonpickle_pandas.register_handlers()
137
138 jsonpickleJS
139 ============
140 `jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_
141 is a javascript implementation of jsonpickle by Michael Scott Cuthbert.
142 jsonpickleJS can be extremely useful for projects that have parallel data
143 structures between Python and Javascript.
144
145 License
146 =======
147 Licensed under the BSD License. See COPYING for details.
148 See jsonpickleJS/LICENSE for details about the jsonpickleJS license.
149
150 Development
151 ===========
152
153 Use `make` to run the unit tests::
154
155 make test
156
157 `pytest` is used to run unit tests internally.
158
159 A `tox` target is provided to run tests using tox.
160 Setting ``multi=1`` tests using all installed and supported Python versions::
161
162 make tox
163 make tox multi=1
164
165 `jsonpickle` itself has no dependencies beyond the Python stdlib.
166 `tox` is required for testing when using the `tox` test runner only.
167
168 The testing requirements are specified in `requirements-dev.txt`.
169 It is recommended to create a virtualenv and run tests from within the
170 virtualenv, or use a tool such as `vx <https://github.com/davvid/vx/>`_
171 to activate the virtualenv without polluting the shell environment::
172
173 python3 -mvenv env3x
174 vx env3x pip install --requirement requirements-dev.txt
175 vx env3x make test
176
177 `jsonpickle` supports multiple Python versions, so using a combination of
178 multiple virtualenvs and `tox` is useful in order to catch compatibility
179 issues when developing.
180
181
00 .coveragerc
11 .flake8
22 .gitignore
3 .isort.cfg
34 .pre-commit-config.yaml
45 .readthedocs.yml
5 .travis.yml
6 BENCHMARKS.md
67 CHANGES.rst
78 LICENSE
89 Makefile
1011 appveyor.yml
1112 azure-pipelines.yml
1213 conftest.py
14 jsonpickle_benchmarks.py
1315 pyproject.toml
1416 pytest.ini
1517 requirements-dev.txt
1820 skeleton.md
1921 tox.ini
2022 .github/FUNDING.yml
23 .github/workflows/lint.yml
24 .github/workflows/test.yml
2125 contrib/copy-docs
2226 contrib/pyqt-reduce-handler.py
2327 docs/api.rst
2731 docs/history.rst
2832 docs/index.rst
2933 docs/requirements.txt
34 images/jsonpickle-0.9.6.svg
35 images/jsonpickle-1.5.1.svg
36 images/jsonpickle-1.5.2.svg
37 images/jsonpickle-2.2.0.svg
38 images/jsonpickle-3.0.0-dev.svg
3039 jsonpickle/__init__.py
3140 jsonpickle/backend.py
3241 jsonpickle/compat.py
42 jsonpickle/errors.py
3343 jsonpickle/handlers.py
3444 jsonpickle/pickler.py
3545 jsonpickle/tags.py
4252 jsonpickle.egg-info/requires.txt
4353 jsonpickle.egg-info/top_level.txt
4454 jsonpickle/ext/__init__.py
55 jsonpickle/ext/gmpy.py
4556 jsonpickle/ext/numpy.py
4657 jsonpickle/ext/pandas.py
4758 jsonpickleJS/.gitignore
00
11 [:python_version < "3.8"]
22 importlib_metadata
3
4 [:python_version > "3.10"]
5 setuptools<59
36
47 [docs]
58 sphinx
710 rst.linker>=1.9
811
912 [testing]
10 coverage<5
1113 pytest!=3.7.3,>=3.5
1214 pytest-checkdocs>=1.2.3
13 pytest-flake8
15 pytest-flake8>=1.1.1
1416 pytest-black-multipy
1517 pytest-cov
1618 ecdsa
1719 feedparser
20 gmpy2
1821 numpy
1922 pandas
2023 pymongo
21 sklearn
24 scikit-learn
2225 sqlalchemy
2326
2427 [testing.libs]
25 demjson
2628 simplejson
2729 ujson
28
29 [testing.libs:python_version < "3.8"]
30 yajl
31
32 [testing:python_version == "2.7"]
33 enum34
34 jsonlib
0 """
1 Run "make benchmark" in the directory that this file is in.
2 This will test the version of jsonpickle inside the local directory,
3 NOT the pip installed version.
4 To test the pip installed version, run this outside the jsonpickle directory:
5 py.test --benchmark-only ./jsonpickle_benchmarks.py --benchmark-histogram
6 MAKE SURE you have pytest-benchmark pip installed.
7
8 Names of tests are shortened so they don't take up too much space on the histogram
9 """
10 import itertools
11
12 import jsonpickle
13
14 # DEFINTIIONS:
15 # HOMOGENOUS - Except for sets, each container may only have integers, floats, strings,
16 # and itself inside it
17 # HETEROGENOUS - Except for sets, each container must have at least one of every other
18 # container type being tested
19 # SIMPLE - Each container must have two each of integers, floats, and strings
20 # COMPLEX - Each container must have four each of integers, floats, and strings
21
22 # SETUP
23 ###################################################################################
24
25
26 class SlotPickleMixin(object):
27 def __getstate__(self):
28 all_slots = itertools.chain.from_iterable(
29 getattr(cls, '__slots__', []) for cls in self.__class__.__mro__
30 )
31 return dict(
32 (slot, getattr(self, slot)) for slot in all_slots if hasattr(self, slot)
33 )
34
35 def __setstate__(self, state):
36 for slot, value in dict(state).items():
37 setattr(self, slot, value)
38
39
40 class MyClass(object):
41 __slots__ = ['idk', 'idk2']
42
43 def __init__(self):
44 self.idk = {
45 'a': 0,
46 'b': [0.5783, 1, 2.5789],
47 'c': {0, 1.87559, 2},
48 'd': ['0', '1', '2'],
49 'e': {'0', '1', '2'},
50 'f': {'a': 0, 'b': {'a': 1}},
51 }
52 self.idk2 = [
53 'a',
54 'b',
55 'c',
56 0,
57 0.18752,
58 2,
59 ['a', 'b', 'c', 0.8579, 1, 2.59757],
60 (self.idk, self.idk),
61 ]
62
63
64 class MyClassGetState(SlotPickleMixin):
65 __slots__ = ['idk', 'idk2']
66
67 def __init__(self):
68 self.idk = {
69 'a': 0,
70 'b': [0.5783, 1, 2.5789],
71 'c': {0, 1.87559, 2},
72 'd': ['0', '1', '2'],
73 'e': {'0', '1', '2'},
74 'f': {'a': 0, 'b': {'a': 1}},
75 }
76 self.idk2 = [
77 'a',
78 'b',
79 'c',
80 0,
81 0.18752,
82 2,
83 ['a', 'b', 'c', 0.8579, 1, 2.59757],
84 (self.idk, self.idk),
85 ]
86
87 def __getstate__(self):
88 return SlotPickleMixin.__getstate__(self)
89
90 def __setstate__(self, object_state):
91 SlotPickleMixin.__setstate__(self, object_state)
92
93
94 class MyClassSimple(object):
95 def __init__(self):
96 self.idk = {'a': 0}
97 self.idk2 = ['a', 0]
98
99
100 HOMOGENOUS_COMPLEX_DICT = {
101 'a': 0,
102 'b': 4.2,
103 'c': {6.9: 'd'},
104 -1: {5: 5},
105 6: {8.42: -2.5},
106 }
107 HOMOGENOUS_COMPLEX_LIST = [
108 'a',
109 0,
110 'b',
111 4.2,
112 'c',
113 [6.9, 'd'],
114 -1,
115 [5, 5],
116 6,
117 [8.42, -2.5],
118 ]
119 HOMOGENOUS_COMPLEX_TUPLE = (
120 'a',
121 0,
122 'b',
123 4.2,
124 'c',
125 (6.9, 'd'),
126 -1,
127 (5, 5),
128 6,
129 (8.42, -2.5),
130 )
131 # can't put a set inside a set :(
132 HOMOGENOUS_COMPLEX_SET = {
133 'a',
134 0,
135 'b',
136 4.2,
137 'c',
138 (6.9, 'd'),
139 -1,
140 (5, 5),
141 6,
142 (8.42, -2.5),
143 }
144
145 HETEROGENOUS_COMPLEX_DICT = {
146 'a': (0, '1'),
147 2.53: [3, 1],
148 'c': {4.2, 6.9},
149 'd': {1: 5.432},
150 }
151 HETEROGENOUS_COMPLEX_LIST = [
152 'a',
153 (0, '1'),
154 2.53,
155 [3, 1],
156 'c',
157 {4.2, 6.9},
158 'd',
159 {1: 5.432},
160 ]
161 HETEROGENOUS_COMPLEX_TUPLE = (
162 'a',
163 (0, '1'),
164 2.53,
165 [3, 1],
166 'c',
167 {4.2, 6.9},
168 'd',
169 {1: 5.432},
170 )
171 HETEROGENOUS_COMPLEX_SET = {
172 'a',
173 (0, '1'),
174 2.53,
175 (3, 1),
176 'c',
177 (4.2, 6.9),
178 'd',
179 (1, 5.432),
180 }
181
182 simple_dict_encoded = jsonpickle.encode({'a': 0, 'b': 4.2, 3: 6.9})
183 simple_list_encoded = jsonpickle.encode(['a', 0, 'b', 4.2, 3, 6.9])
184 simple_tuple_encoded = jsonpickle.encode(('a', 0, 'b', 4.2, 3, 6.9))
185 simple_set_encoded = jsonpickle.encode({'a', 0, 'b', 4.2, 3, 6.9})
186
187 homogenous_dict_encoded = jsonpickle.encode(HOMOGENOUS_COMPLEX_DICT)
188 homogenous_list_encoded = jsonpickle.encode(HOMOGENOUS_COMPLEX_LIST)
189 homogenous_tuple_encoded = jsonpickle.encode(HOMOGENOUS_COMPLEX_TUPLE)
190 homogenous_set_encoded = jsonpickle.encode(HOMOGENOUS_COMPLEX_SET)
191
192 heterogenous_dict_encoded = jsonpickle.encode(HETEROGENOUS_COMPLEX_DICT)
193 heterogenous_list_encoded = jsonpickle.encode(HETEROGENOUS_COMPLEX_LIST)
194 heterogenous_tuple_encoded = jsonpickle.encode(HETEROGENOUS_COMPLEX_TUPLE)
195 heterogenous_set_encoded = jsonpickle.encode(HETEROGENOUS_COMPLEX_SET)
196
197 simple_class_encoded = jsonpickle.encode(MyClassSimple())
198 class_encoded = jsonpickle.encode(MyClass())
199 state_class_encoded = jsonpickle.encode(MyClassGetState())
200 ###################################################################################
201
202 # SIMPLE PRIMITIVE ENCODE/DECODE
203
204
205 def simple_dict_encode(benchmark):
206 benchmark(jsonpickle.encode, {'a': 0})
207
208
209 def simple_dict_decode(benchmark):
210 benchmark(jsonpickle.decode, simple_dict_encoded)
211
212
213 def simple_list_encode(benchmark):
214 benchmark(jsonpickle.encode, ['a', 0])
215
216
217 def simple_list_decode(benchmark):
218 benchmark(jsonpickle.decode, simple_list_encoded)
219
220
221 def simple_tuple_encode(benchmark):
222 benchmark(jsonpickle.encode, ('a', 0))
223
224
225 def simple_tuple_decode(benchmark):
226 benchmark(jsonpickle.decode, simple_tuple_encoded)
227
228
229 def simple_set_encode(benchmark):
230 benchmark(jsonpickle.encode, {'a', 0})
231
232
233 def simple_set_decode(benchmark):
234 benchmark(jsonpickle.decode, simple_set_encoded)
235
236
237 # COMPLEX HOMOGENOUS PRIMITIVE ENCODE/DECODE
238 def complex_homogenous_dict_encode(benchmark):
239 benchmark(jsonpickle.encode, HOMOGENOUS_COMPLEX_DICT)
240
241
242 def complex_homogenous_dict_decode(benchmark):
243 benchmark(jsonpickle.decode, homogenous_dict_encoded)
244
245
246 def complex_homogenous_list_encode(benchmark):
247 benchmark(jsonpickle.encode, HOMOGENOUS_COMPLEX_LIST)
248
249
250 def complex_homogenous_list_decode(benchmark):
251 benchmark(jsonpickle.decode, homogenous_list_encoded)
252
253
254 def complex_homogenous_tuple_encode(benchmark):
255 benchmark(jsonpickle.encode, HOMOGENOUS_COMPLEX_TUPLE)
256
257
258 def complex_homogenous_tuple_decode(benchmark):
259 benchmark(jsonpickle.decode, homogenous_tuple_encoded)
260
261
262 def complex_homogenous_set_encode(benchmark):
263 benchmark(jsonpickle.encode, HOMOGENOUS_COMPLEX_SET)
264
265
266 def complex_homogenous_set_decode(benchmark):
267 benchmark(jsonpickle.decode, homogenous_set_encoded)
268
269
270 # COMPLEX HETEROGENOUS PRIMITIVE ENCODE/DECODE
271 def complex_heterogenous_dict_encode(benchmark):
272 benchmark(jsonpickle.encode, HETEROGENOUS_COMPLEX_DICT)
273
274
275 def complex_heterogenous_dict_decode(benchmark):
276 benchmark(jsonpickle.decode, heterogenous_dict_encoded)
277
278
279 def complex_heterogenous_list_encode(benchmark):
280 benchmark(jsonpickle.encode, HETEROGENOUS_COMPLEX_LIST)
281
282
283 def complex_heterogenous_list_decode(benchmark):
284 benchmark(jsonpickle.decode, heterogenous_list_encoded)
285
286
287 def complex_heterogenous_tuple_encode(benchmark):
288 benchmark(jsonpickle.encode, HETEROGENOUS_COMPLEX_TUPLE)
289
290
291 def complex_heterogenous_tuple_decode(benchmark):
292 benchmark(jsonpickle.decode, heterogenous_tuple_encoded)
293
294
295 def complex_heterogenous_set_encode(benchmark):
296 benchmark(jsonpickle.encode, HETEROGENOUS_COMPLEX_SET)
297
298
299 def complex_heterogenous_set_decode(benchmark):
300 benchmark(jsonpickle.decode, heterogenous_set_encoded)
301
302
303 # CUSTOM CLASS ENCODE/DECODE
304 def simple_class_encode(benchmark):
305 benchmark(jsonpickle.encode, MyClassSimple())
306
307
308 def simple_class_decode(benchmark):
309 benchmark(jsonpickle.decode, simple_class_encoded)
310
311
312 def complex_class_encode(benchmark):
313 benchmark(jsonpickle.encode, MyClass())
314
315
316 def complex_class_decode(benchmark):
317 benchmark(jsonpickle.decode, class_encoded)
318
319
320 def state_class_encode(benchmark):
321 benchmark(jsonpickle.encode, MyClassGetState())
322
323
324 def state_class_decode(benchmark):
325 benchmark(jsonpickle.decode, state_class_encoded)
00 [build-system]
1 requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4.1"]
1 # setuptools >= 59 seems to break something with distutils on 3.11
2 requires = ["setuptools>=42,<59", "wheel", "setuptools_scm[toml]>=3.4.1"]
23 build-backend = "setuptools.build_meta"
34
45 [tool.black]
00 [pytest]
11 norecursedirs=dist build .tox .eggs
2 addopts=--doctest-modules --flake8 --black --cov
2 addopts=--doctest-modules --cov
33 doctest_optionflags=ALLOW_UNICODE ELLIPSIS
44 filterwarnings=
55 # https://github.com/pytest-dev/pytest/issues/6928
66 ignore:direct construction of .*Item has been deprecated:DeprecationWarning
7 # flake8 conflicts with black otherwise
8 # we can't make it ignore E501 or else others show up
9 flake8-max-line-length = 2000
10 # add this so we dont have to put test_ before the benchmarks
11 python_functions = test_* simple_* complex_* state_*
00 bson
11 coverage<5
2 demjson
32 ecdsa
4 enum34; python_version < '3.4'
53 feedparser
6 jsonlib; python_version < '3.0'
4 flake8<5
5 gmpy2
76 numpy
87 pandas
98 pymongo
109 pytest
11 pytest-black-multipy
1210 pytest-cov
13 pytest-flake8
11 pytest-flake8>=1.1.1
12 pytest-benchmark
13 pytest-benchmark[histogram]
14 scikit-learn
15 scipy>=1.9.3; python_version>"3.10"
16 scipy; python_version<="3.10"
1417 simplejson
15 sklearn
16 sqlalchemy
18 sqlalchemy>=1.2.19
1719 ujson
18 yajl; sys_platform != 'win32' and python_version < '3.9'
1313 Intended Audience :: Developers
1414 License :: OSI Approved :: BSD License
1515 Programming Language :: Python
16 Programming Language :: Python :: 2
17 Programming Language :: Python :: 2.7
1816 Programming Language :: Python :: 3
17 Programming Language :: Python :: 3.7
18 Programming Language :: Python :: 3.8
19 Programming Language :: Python :: 3.9
20 Programming Language :: Python :: 3.10
1921 Programming Language :: JavaScript
2022 Operating System :: OS Independent
2123 Topic :: Software Development :: Libraries :: Python Modules
3032 serialization
3133 JavaScript Object Notation
3234
35 [tool:pytest]
36 flake8-ignore = E501
37
3338 [options]
3439 packages = find:
3540 include_package_data = true
36 python_requires = >=2.7
41 python_requires = >=3.7
3742 install_requires =
3843 importlib_metadata; python_version<"3.8"
44 setuptools<59; python_version>"3.10"
3945 setup_requires = setuptools_scm[toml] >= 3.4.1
4046
4147 [options.extras_require]
4248 testing =
43 coverage < 5
4449 pytest >= 3.5, !=3.7.3
4550 pytest-checkdocs >= 1.2.3
46 pytest-flake8
51 pytest-flake8 >= 1.1.1
4752 pytest-black-multipy
4853 pytest-cov
4954
5055 ecdsa
51 enum34; python_version=="2.7"
5256 feedparser
53 jsonlib; python_version=="2.7"
57 gmpy2
5458 numpy
5559 pandas
5660 pymongo
57 sklearn
61 scikit-learn
5862 sqlalchemy
5963 testing.libs =
60 demjson
6164 simplejson
6265 ujson
63 yajl; python_version<"3.8"
6466 docs =
6567 sphinx
6668 jaraco.packaging >= 3.2
00 from __future__ import absolute_import, division, unicode_literals
1
12 import decimal
23 import unittest
4 from hashlib import md5
35 from warnings import warn
46
7 from helper import SkippableTest
8
59 import jsonpickle
6 from jsonpickle import compat
7 from jsonpickle.compat import PY2
8 from jsonpickle.compat import PY3
9
10 from helper import SkippableTest
1110
1211
1312 class Thing(object):
1413 def __init__(self, name):
1514 self.name = name
1615 self.child = None
16
17
18 class A(object):
19 def __init__(self):
20 self.id = md5(str(id(self)).encode()).hexdigest()[:5] # unique enough hash
21
22
23 class BSlots(object):
24 __slots__ = ["a2", "a1", "a3"]
25
26 def __init__(self):
27 self.a2 = A() # set attribs not in alphabetical order
28 self.a1 = A()
29 self.a3 = self.a1 # create a reference
1730
1831
1932 SAMPLE_DATA = {'things': [Thing('data')]}
124137 as_json = jsonpickle.dumps(obj)
125138 clone = jsonpickle.loads(as_json)
126139 self.assertTrue(isinstance(clone, decimal.Decimal))
140 # options are persisted unless we disable them
141 jsonpickle.set_encoder_options('simplejson', use_decimal=False)
142 jsonpickle.set_decoder_options('simplejson', use_decimal=False)
143
144 def test_sort_keys(self):
145 jsonpickle.set_encoder_options('simplejson', sort_keys=True)
146 b = BSlots()
147 self.assertRaises(TypeError, jsonpickle.encode, b, keys=True, warn=True)
148 # return encoder options to default
149 jsonpickle.set_encoder_options('simplejson', sort_keys=False)
127150
128151
129152 def has_module(module):
135158 return True
136159
137160
138 class DemjsonTestCase(BackendBase):
139 def setUp(self):
140 self.set_preferred_backend('demjson')
141
142 def test_backend(self):
143 expected_pickled = compat.ustr(
144 '{"things":[{'
145 '"child":null,'
146 '"name":"data",'
147 '"py/object":"backend_test.Thing"}'
148 ']}'
149 )
150 self.assertEncodeDecode(expected_pickled)
151
152 def test_int_dict_keys_with_numeric_keys(self):
153 jsonpickle.set_encoder_options('demjson', strict=False)
154 int_dict = {1000: [1, 2]}
155 pickle = jsonpickle.encode(int_dict, numeric_keys=True)
156 actual = jsonpickle.decode(pickle)
157 self.assertEqual(actual[1000], [1, 2])
158
159
160 class JsonlibTestCase(BackendBase):
161 def setUp(self):
162 if PY2:
163 self.set_preferred_backend('jsonlib')
164
165 def test_backend(self):
166 if PY3:
167 return self.skip('no jsonlib for python3')
168 expected_pickled = (
169 '{"things":[{'
170 r'"py\/object":"backend_test.Thing",'
171 '"name":"data","child":null}'
172 ']}'
173 )
174 self.assertEncodeDecode(expected_pickled)
175
176
177161 class YajlTestCase(BackendBase):
178162 def setUp(self):
179163 self.set_preferred_backend('yajl')
207191 suite.addTest(unittest.makeSuite(JsonTestCase))
208192 suite.addTest(unittest.makeSuite(UJsonTestCase))
209193 suite.addTest(unittest.makeSuite(SimpleJsonTestCase))
210 if has_module('demjson'):
211 suite.addTest(unittest.makeSuite(DemjsonTestCase))
212194 if has_module('yajl'):
213195 suite.addTest(unittest.makeSuite(YajlTestCase))
214 if PY2:
215 if has_module('jsonlib'):
216 suite.addTest(unittest.makeSuite(JsonlibTestCase))
217196 return suite
218197
219198
1010 import os
1111 import sys
1212 import timeit
13
1413
1514 json = """\
1615 import feedparser
44 import pickle
55 import unittest
66
7 from helper import SkippableTest
8
79 import jsonpickle
8
9 from helper import SkippableTest
1010
1111 bson = None
1212
3333 Unit tests for collections
3434 """
3535 from __future__ import absolute_import, division, print_function, unicode_literals
36
37 import sys
3638 from collections import OrderedDict, defaultdict
37 import sys
3839
3940 import pytest
4041
4142 import jsonpickle
42 from jsonpickle.compat import PY2
4343
4444 __status__ = "Stable"
4545 __version__ = "1.0.0"
5555
5656 Tests restorable collections by creating pickled structures featuring
5757 no cycles, self cycles, and mutual cycles, for all supported dictionary and
58 set wrappers. Python bult-in dictionaries and sets are also tested with
58 set wrappers. Python built-in dictionaries and sets are also tested with
5959 expectation of failure via raising exceptions.
6060
6161 """
8585 self.plain_default[key] = (key, value)
8686
8787 def __hash__(self):
88 # return id(self)
89 # the original __hash__() below means the hash can change after being
90 # stored, which JP does not support on Python 2.
91 if PY2:
92 return id(self)
9388 return hash(self.v) if hasattr(self, 'v') else id(self)
9489
9590 def __repr__(self):
110105 self.plain.add(item)
111106
112107 def __hash__(self):
113 if PY2:
114 return id(self)
115108 return hash(self.v) if hasattr(self, 'v') else id(self)
116109
117110 def __repr__(self):
216209 plain_keys = list(c1u.plain.keys())
217210 ordered_keys = list(c1u.plain_ordered.keys())
218211 default_keys = list(c1u.plain_default.keys())
219 if PY2:
220 value = 67
221 else:
222 value = 42
212 value = 42
223213 assert value == c1u.plain[plain_keys[0]][0].v
224214 42 == c1u.plain_ordered[ordered_keys[0]][0].v
225215 42 == c1u.plain_default[default_keys[0]][0].v
226216
227217 # key c2u
228218 # succeeds because c2u does not have a cycle to itself
229 if PY2:
230 key = c1u
231 else:
232 key = c2u
233 assert key == c1u.plain[plain_keys[1]][0]
219 assert c2u == c1u.plain[plain_keys[1]][0]
234220 # succeeds because c2u does not have a cycle to itself
235221 assert c2u == c1u.plain_ordered[ordered_keys[1]][0]
236222 assert 67 == c1u.plain_default[default_keys[1]][0].v
55 # This software is licensed as described in the file COPYING, which
66 # you should have received as part of this distribution.
77
8 import unittest
98 import datetime
109 import time
10 import unittest
1111
1212 import jsonpickle
1313 from jsonpickle import tags
5757 self._dt_write = datetime.datetime.utcnow()
5858 self._value = new_value
5959
60 def erasable(self, td=datetime.timedelta(seconds=1)):
61 dt_now = datetime.datetime.utcnow()
62 td_read = dt_now - self._dt_read
63 td_write = dt_now - self._dt_write
64 return td_read > td and td_write > td
65
6066 def __repr__(self):
6167 dt_now = datetime.datetime.utcnow()
6268 td_read = dt_now - self._dt_read
6773 s += ' dt_write: ' + str(self._dt_write) + ' (%s ago)' % td_write + '\n'
6874 return s
6975
70 def erasable(self, td=datetime.timedelta(seconds=1)):
71 dt_now = datetime.datetime.utcnow()
72 td_read = dt_now - self._dt_read
73 td_write = dt_now - self._dt_write
74 return td_read > td and td_write > td
75
7676
7777 class PersistantVariables(object):
7878 def __init__(self):
00 # -*- coding: utf-8 -*-
11
22 import unittest
3
34 import jsonpickle
45
56
2021 def __init__(self, name):
2122 Node.__init__(self, name)
2223
24 def __repr__(self):
25 return str(self)
26
2327 def __str__(self):
2428 ret_str = 'Document "%s"\n' % self._name
2529 for c in self._children:
2630 ret_str += repr(c)
2731 return ret_str
28
29 def __repr__(self):
30 return str(self)
3132
3233
3334 class Question(Node):
00 """Test serializing ecdsa keys"""
11 from __future__ import absolute_import, division, unicode_literals
2
23 import unittest
4
5 import pytest
6 from helper import SkippableTest
37
48 import jsonpickle
59
6 from helper import SkippableTest
10
11 @pytest.fixture(scope='module', autouse=True)
12 def gmpy_extension():
13 """Initialize the gmpy extension for this test module"""
14 jsonpickle.ext.gmpy.register_handlers()
15 yield # control to the test function.
16 jsonpickle.ext.gmpy.unregister_handlers()
717
818
919 class EcdsaTestCase(SkippableTest):
77
88 import unittest
99
10 from helper import SkippableTest
11
1012 import jsonpickle
11
12 from helper import SkippableTest
1313
1414 RSS_DOC = """<?xml version="1.0" encoding="utf-8"?>
1515 <feed xmlns="http://www.w3.org/2005/Atom"
44 # This software is licensed as described in the file COPYING, which
55 # you should have received as part of this distribution.
66 from __future__ import absolute_import, division, unicode_literals
7
8 import collections
79 import os
810 import unittest
9 import collections
11 import warnings
1012
1113 import pytest
14 from helper import SkippableTest
1215
1316 import jsonpickle
1417 import jsonpickle.backend
1518 import jsonpickle.handlers
1619 from jsonpickle import compat, tags, util
17 from jsonpickle.compat import PY2, PY3
18 from helper import SkippableTest
19
20
21 class Thing(object):
20
21
22 class ListLike:
23 def __init__(self):
24 self.internal_list = []
25
26 def append(self, item):
27 self.internal_list.append(item)
28
29 def __getitem__(self, i):
30 return self.internal_list[i]
31
32
33 class Thing:
2234 def __init__(self, name):
2335 self.name = name
2436 self.child = None
2537
38 def __iter__(self):
39 for attr in [
40 x for x in getattr(self.__class__, "__dict__") if not x.startswith("__")
41 ]:
42 yield attr, getattr(self, attr)
43
2644 def __repr__(self):
2745 return 'Thing("%s")' % self.name
2846
2947
30 class Capture(object):
48 class Capture:
3149 def __init__(self, *args, **kwargs):
3250 self.args = args
3351 self.kwargs = kwargs
3452
3553
36 class ThingWithProps(object):
54 class ThingWithProps:
55 def _get_identity(self):
56 keys = [self.dogs, self.monkies, self.name]
57 return hash('-'.join([str(key) for key in keys]))
58
59 identity = property(_get_identity)
60
61 def _get_dogs(self):
62 return self._critters[0][1]
63
64 dogs = property(_get_dogs)
65
66 def _get_monkies(self):
67 return self._critters[1][1]
68
69 monkies = property(_get_monkies)
70
3771 def __init__(self, name='', dogs='reliable', monkies='tricksy'):
3872 self.name = name
3973 self._critters = (('dogs', dogs), ('monkies', monkies))
4074
41 def _get_identity(self):
42 keys = [self.dogs, self.monkies, self.name]
43 return hash('-'.join([str(key) for key in keys]))
44
45 identity = property(_get_identity)
46
47 def _get_dogs(self):
48 return self._critters[0][1]
49
50 dogs = property(_get_dogs)
51
52 def _get_monkies(self):
53 return self._critters[1][1]
54
55 monkies = property(_get_monkies)
75 def __eq__(self, other):
76 return self.identity == other.identity
5677
5778 def __getstate__(self):
5879 out = dict(
7192 self.name = state_dict.get('nom', '')
7293 ident = state_dict.get('__identity__')
7394 if ident != self.identity:
74 raise ValueError('expanded object does not match originial state!')
75
76 def __eq__(self, other):
77 return self.identity == other.identity
95 raise ValueError('expanded object does not match original state!')
7896
7997
8098 class UserDict(dict):
85103 self.valid = False
86104
87105
88 class Outer(object):
89 class Middle(object):
90 class Inner(object):
106 class Outer:
107 class Middle:
108 class Inner:
91109 pass
110
111
112 class MySlots:
113 __slots__ = ("alpha", "__beta")
114
115 def __init__(self):
116 self.alpha = 1
117 self.__beta = 1
118
119
120 class MyPropertiesSlots:
121 __slots__ = ("alpha", "arr")
122
123 def __init__(self):
124 self.alpha = 1
125 self.arr = [1, 2, 3]
126
127 @property
128 def arr_len(self):
129 return len(self.arr)
130
131 @property
132 def other_object(self):
133 return Thing("Test")
134
135 def __eq__(self, other):
136 return (
137 self.alpha == other.alpha
138 and self.arr == other.arr
139 and self.arr_len == other.arr_len
140 and list(self.other_object) == list(other.other_object)
141 )
142
143
144 class MyPropertiesDict:
145 def __init__(self):
146 self.alpha = 1
147 self.arr = [1, 2, 3]
148
149 @property
150 def arr_len(self):
151 return len(self.arr)
152
153 @property
154 def other_object(self):
155 return Thing("Test")
156
157 def __eq__(self, other):
158 return (
159 self.alpha == other.alpha
160 and self.arr == other.arr
161 and self.arr_len == other.arr_len
162 and list(self.other_object) == list(other.other_object)
163 )
164
165
166 def on_missing_callback(class_name):
167 # not actually a runtime problem but it doesn't matter
168 warnings.warn("The unpickler couldn't find %s" % class_name, RuntimeWarning)
92169
93170
94171 class PicklingTestCase(unittest.TestCase):
101178 self.pickler.reset()
102179 self.unpickler.reset()
103180
104 @unittest.skipIf(not PY2, 'Python 2-specific base85 test')
105 def test_base85_always_false_on_py2(self):
106 self.assertFalse(self.b85_pickler.use_base85)
107
108 @unittest.skipIf(PY2, 'Base85 not supported on Python 2')
109181 def test_base85_override_py3(self):
110182 """Ensure the Python 2 check still lets us set use_base85 on Python 3"""
111183 self.assertTrue(self.b85_pickler.use_base85)
112184
113 @unittest.skipIf(PY2, 'Base85 not supported on Python 2')
114185 def test_bytes_default_base85(self):
115186 data = os.urandom(16)
116187 encoded = util.b85encode(data)
117188 self.assertEqual({tags.B85: encoded}, self.b85_pickler.flatten(data))
118189
119 @unittest.skipIf(PY2, 'Base85 not supported on Python 2')
120190 def test_py3_bytes_base64_default(self):
121191 data = os.urandom(16)
122192 encoded = util.b64encode(data)
123193 self.assertEqual({tags.B64: encoded}, self.pickler.flatten(data))
124194
125 @unittest.skipIf(not PY2, 'Python 2-specific base64 test')
126 def test_py2_default_base64(self):
127 data = os.urandom(16)
128 encoded = util.b64encode(data)
129 self.assertEqual({tags.B64: encoded}, self.pickler.flatten(data))
130
131 @unittest.skipIf(PY2, 'Base85 not supported on Python 2')
132195 def test_decode_base85(self):
133196 pickled = {tags.B85: 'P{Y4;Xv4O{u^=-c'}
134197 expected = u'P\u00ffth\u00f6\u00f1 3!'.encode('utf-8')
135198 self.assertEqual(expected, self.unpickler.restore(pickled))
136199
137 @unittest.skipIf(PY2, 'Base85 not supported on Python 2')
138200 def test_base85_still_handles_base64(self):
139201 pickled = {tags.B64: 'UMO/dGjDtsOxIDMh'}
140202 expected = u'P\u00ffth\u00f6\u00f1 3!'.encode('utf-8')
141203 self.assertEqual(expected, self.unpickler.restore(pickled))
142
143 @unittest.skipIf(not PY2, 'Python 2-specific base85 test')
144 def test_base85_crashes_py2(self):
145 with self.assertRaises(NotImplementedError):
146 self.unpickler.restore({tags.B85: 'P{Y4;Xv4O{u^=-c'})
147204
148205 def test_string(self):
149206 self.assertEqual('a string', self.pickler.flatten('a string'))
433490 no longer supported.
434491 """
435492 ae = jsonpickle.decode('{"py/type": "__builtin__.AssertionError"}')
436 assert ae is AssertionError
493 self.assertTrue(ae is AssertionError)
437494 ae = jsonpickle.decode('{"py/type": "exceptions.AssertionError"}')
438 assert ae is AssertionError
495 self.assertTrue(ae is AssertionError)
439496 cls = jsonpickle.decode('{"py/type": "__builtin__.int"}')
440 assert cls is int
497 self.assertTrue(cls is int)
498
499 def test_unpickler_on_missing(self):
500 class SimpleClass(object):
501 def __init__(self, i):
502 self.i = i
503
504 frozen = jsonpickle.encode(SimpleClass(4))
505 del SimpleClass
506
507 # https://docs.python.org/3/library/warnings.html#testing-warnings
508
509 with warnings.catch_warnings(record=True) as w:
510 warnings.simplefilter("always")
511 jsonpickle.decode(frozen, on_missing='warn')
512 self.assertTrue(issubclass(w[-1].category, UserWarning))
513 self.assertTrue(
514 "Unpickler._restore_object could not find" in str(w[-1].message)
515 )
516
517 jsonpickle.decode(frozen, on_missing=on_missing_callback)
518 self.assertTrue(issubclass(w[-1].category, RuntimeWarning))
519 self.assertTrue("The unpickler couldn't find" in str(w[-1].message))
520
521 self.assertTrue(
522 jsonpickle.decode(frozen, on_missing='ignore')
523 == {
524 'py/object': 'jsonpickle_test.PicklingTestCase.test_unpickler_on_missing.<locals>.SimpleClass',
525 'i': 4,
526 }
527 )
528
529 try:
530 jsonpickle.decode(frozen, on_missing='error')
531 except jsonpickle.errors.ClassNotFoundError:
532 # it's supposed to error
533 self.assertTrue(True)
534 else:
535 self.assertTrue(False)
536
537 def test_private_slot_members(self):
538 obj = jsonpickle.loads(jsonpickle.dumps(MySlots()))
539 alpha = getattr(obj, "alpha", "(missing alpha)")
540 beta = getattr(obj, "_" + obj.__class__.__name__ + "__beta", "(missing beta)")
541 self.assertEqual(alpha, beta)
542
543 def test_include_properties_slots(self):
544 obj = MyPropertiesSlots()
545 dumped = jsonpickle.dumps(obj, include_properties=True)
546 self.assertTrue("py/property" in dumped)
547 self.assertEqual(obj, jsonpickle.loads(dumped))
548
549 def test_include_properties_dict(self):
550 obj = MyPropertiesDict()
551 dumped = jsonpickle.dumps(obj, include_properties=True)
552 self.assertTrue("py/property" in dumped)
553 self.assertEqual(obj, jsonpickle.loads(dumped))
554
555 def test_load_non_fully_qualified_classes(self):
556 # reuse MyPropertiesSlots because it has a nice eq method
557 obj = MyPropertiesSlots()
558 encoded = jsonpickle.encode(obj)
559 # MyPropertiesSlots and MyPropertiesDict have compatible eq methods
560 self.assertEqual(
561 obj,
562 jsonpickle.decode(encoded, classes={"MyPropertiesSlots": MyPropertiesDict}),
563 )
441564
442565
443566 class JSONPickleTestCase(SkippableTest):
494617 self.assertEqual(type(self.obj), type(actual))
495618
496619 def test_unicode_dict_keys(self):
497 if PY2:
498 uni = unichr(0x1234) # noqa
499 else:
500 uni = chr(0x1234)
620 uni = chr(0x1234)
501621 pickle = jsonpickle.encode({uni: uni})
502622 actual = jsonpickle.decode(pickle)
503623 self.assertTrue(uni in actual)
767887 assert decoded.b[0] == 1
768888 assert decoded.a[1][0:3] == '[1,'
769889 assert decoded.a[2][0][0:3] == '[1,'
890
891 def _test_inner_class(self, InnerScope, obj, decoded):
892 self.assertTrue(isinstance(obj, InnerScope))
893 self.assertEqual(decoded.name, obj.name)
770894
771895 def test_can_serialize_inner_classes(self):
772896 class InnerScope(object):
790914 decoded = jsonpickle.decode(encoded, classes={InnerScope})
791915 self._test_inner_class(InnerScope, obj, decoded)
792916
793 def _test_inner_class(self, InnerScope, obj, decoded):
794 self.assertTrue(isinstance(obj, InnerScope))
795 self.assertEqual(decoded.name, obj.name)
796
797917 def test_can_serialize_nested_classes(self):
798 if PY2:
799 return self.skip('Serialization of nested classes requires ' 'Python >= 3')
800
801918 middle = Outer.Middle
802919 inner = Outer.Middle.Inner
803920 encoded_middle = jsonpickle.encode(middle)
812929 self.assertEqual(decoded_inner, inner)
813930
814931 def test_can_serialize_nested_class_objects(self):
815 if PY2:
816 return self.skip('Serialization of nested classes requires ' 'Python >= 3')
817
818932 middle_obj = Outer.Middle()
819933 middle_obj.attribute = 5
820934 inner_obj = Outer.Middle.Inner()
829943 self.assertTrue(isinstance(decoded_inner_obj, Outer.Middle.Inner))
830944 self.assertEqual(decoded_middle_obj.attribute, middle_obj.attribute)
831945 self.assertEqual(decoded_inner_obj.attribute, inner_obj.attribute)
946
947 def test_listlike(self):
948 """
949 https://github.com/jsonpickle/jsonpickle/issues/362
950 """
951 ll = ListLike()
952 ll.internal_list.append(1)
953 roundtrip_ll = jsonpickle.decode(jsonpickle.encode(ll))
954 self.assertEqual(len(ll.internal_list), len(roundtrip_ll.internal_list))
955
956 def test_v1_decode(self):
957 # TODO: Find a simple example that reproduces #364
958 self.assertTrue(True)
832959
833960
834961 class PicklableNamedTuple(object):
9451072
9461073
9471074 class PickleProtocol2ReduceExString(object):
1075 def __reduce_ex__(self, n):
1076 return __name__ + '.slotmagic'
1077
9481078 def __reduce__(self):
9491079 assert False, "Should not be here"
950
951 def __reduce_ex__(self, n):
952 return __name__ + '.slotmagic'
9531080
9541081
9551082 class PickleProtocol2ReduceTuple(object):
9691096
9701097 @compat.iterator
9711098 class ReducibleIterator(object):
1099 def __next__(self):
1100 raise StopIteration()
1101
9721102 def __iter__(self):
9731103 return self
974
975 def __next__(self):
976 raise StopIteration()
9771104
9781105 def __reduce__(self):
9791106 return ReducibleIterator, ()
10321159
10331160
10341161 class PickleProtocol2ReduceTupleSetState(PickleProtocol2ReduceTuple):
1035 def __setstate__(self, state):
1036 self.bar = state['foo']
1037
10381162 def __reduce__(self):
10391163 return (
10401164 type(self), # callable
10441168 iter([]), # dictitems
10451169 )
10461170
1171 def __setstate__(self, state):
1172 self.bar = state['foo']
1173
10471174
10481175 class PickleProtocol2ReduceTupleStateSlots(object):
10491176 __slots__ = ('argval', 'optional', 'foo')
10661193 def __init__(self):
10671194 self.inner = []
10681195
1196 def append(self, item):
1197 self.inner.append(item)
1198
10691199 def __reduce__(self):
10701200 return (
10711201 PickleProtocol2ReduceListitemsAppend, # callable
10751205 iter([]), # dictitems
10761206 )
10771207
1078 def append(self, item):
1079 self.inner.append(item)
1080
10811208
10821209 class PickleProtocol2ReduceListitemsExtend(object):
10831210 def __init__(self):
10841211 self.inner = []
1212
1213 def extend(self, items):
1214 self.inner.exend(items)
10851215
10861216 def __reduce__(self):
10871217 return (
10921222 iter([]), # dictitems
10931223 )
10941224
1095 def extend(self, items):
1096 self.inner.exend(items)
1097
10981225
10991226 class PickleProtocol2ReduceDictitems(object):
11001227 def __init__(self):
11011228 self.inner = {}
1229
1230 def __setitem__(self, k, v):
1231 return self.inner.__setitem__(k, v)
11021232
11031233 def __reduce__(self):
11041234 return (
11091239 iter(zip(['foo', 'bar'], ['foo', 'bar'])), # dictitems
11101240 )
11111241
1112 def __setitem__(self, k, v):
1113 return self.inner.__setitem__(k, v)
1114
11151242
11161243 class PickleProtocol2Classic:
11171244 def __init__(self, foo):
11321259 def test_pickle_newargs_ex(self):
11331260 """
11341261 Ensure we can pickle and unpickle an object whose class needs arguments
1135 to __new__ and get back the same typle
1262 to __new__ and get back the same type
11361263 """
11371264 instance = PicklableNamedTupleEx(**{'a': 'b', 'n': 2})
11381265 encoded = jsonpickle.encode(instance)
11781305
11791306
11801307 class PicklingProtocol2TestCase(SkippableTest):
1181 def test_classic_init_has_args(self):
1182 """
1183 Test unpickling a classic instance whose init takes args,
1184 has no __getinitargs__
1185 Because classic only exists under 2, skipped if PY3
1186 """
1187 if PY3:
1188 return self.skip('No classic classes in PY3')
1189 instance = PickleProtocol2Classic(3)
1190 encoded = jsonpickle.encode(instance)
1191 decoded = jsonpickle.decode(encoded)
1192 self.assertEqual(decoded.foo, 3)
1193
1194 def test_getinitargs(self):
1195 """
1196 Test __getinitargs__ with classic instance
1197
1198 Because classic only exists under 2, skipped if PY3
1199 """
1200 if PY3:
1201 return self.skip('No classic classes in PY3')
1202 instance = PickleProtocol2ClassicInitargs(3)
1203 encoded = jsonpickle.encode(instance)
1204 decoded = jsonpickle.decode(encoded)
1205 self.assertEqual(decoded.bar, 'choo')
1206
12071308 def test_reduce_complex_num(self):
12081309 instance = 5j
12091310 encoded = jsonpickle.encode(instance)
13481449 def test_pickle_newargs(self):
13491450 """
13501451 Ensure we can pickle and unpickle an object whose class needs arguments
1351 to __new__ and get back the same typle
1452 to __new__ and get back the same type
13521453 """
13531454 instance = PicklableNamedTuple(('a', 'b'), (1, 2))
13541455 encoded = jsonpickle.encode(instance)
00 from __future__ import absolute_import, division, unicode_literals
1
12 import datetime
23 import warnings
34
1415 import jsonpickle
1516 import jsonpickle.ext.numpy
1617 from jsonpickle import handlers
17 from jsonpickle.compat import PY2
1818
1919
2020 @pytest.fixture(scope='module', autouse=True)
3131
3232 def test_dtype_roundtrip():
3333 dtypes = [
34 np.int,
35 np.float,
36 np.complex,
34 np.int_,
3735 np.int32,
38 np.str,
39 np.object,
40 np.unicode,
36 np.float_,
37 np.float64,
38 np.complex_,
39 np.complex128,
40 np.str_,
41 np.object_,
42 np.compat.unicode,
4143 np.dtype(np.void),
4244 np.dtype(np.int32),
4345 np.dtype(np.float32),
4446 np.dtype('f4,i4,f2,i1'),
4547 np.dtype(('f4', 'i4'), ('f2', 'i1')),
46 np.dtype('1i4', align=True),
48 np.dtype('i4', align=True),
4749 np.dtype('M8[7D]'),
4850 np.dtype(
4951 {
125127 np.array([0, 1, -1, np.inf, -np.inf, np.nan], dtype='f2'),
126128 ]
127129
128 if not PY2:
129 arrays.extend(
130 [
131 np.rec.array(
132 [('NGC1001', 11), ('NGC1002', 1.0), ('NGC1003', 1.0)],
133 dtype=[('target', 'S20'), ('V_mag', 'f4')],
134 )
135 ]
136 )
130 arrays.extend(
131 [
132 np.rec.array(
133 [('NGC1001', 11), ('NGC1002', 1.0), ('NGC1003', 1.0)],
134 dtype=[('target', 'S20'), ('V_mag', 'f4')],
135 )
136 ]
137 )
137138 for array in arrays:
138139 decoded = roundtrip(array)
139140 assert_equal(decoded, array)
196197 a.strides = 1
197198
198199 # this is kinda fishy; a has overlapping memory, _a does not
199 if PY2:
200 warn_count = 0
201 else:
202 warn_count = 1
200 warn_count = 1
203201 with warnings.catch_warnings(record=True) as w:
204202 _a = roundtrip(a)
205203 assert len(w) == warn_count
250248 b = a[1:, 1:]
251249 assert b.base is a
252250
253 if PY2:
254 warn_count = 0
255 else:
256 warn_count = 1
251 warn_count = 1
257252 with warnings.catch_warnings(record=True) as w:
258253 _a, _b = roundtrip([a, b])
259254 assert len(w) == warn_count
272267 """test behavior with memoryviews which are not ndarrays"""
273268 bstring = 'abcdefgh'.encode('utf-8')
274269 a = np.frombuffer(bstring, dtype=np.byte)
275 if PY2:
276 warn_count = 0
277 else:
278 warn_count = 1
270 warn_count = 1
279271 with warnings.catch_warnings(record=True) as w:
280272 _a = roundtrip(a)
281273 npt.assert_array_equal(a, _a)
289281 is not an ndarray.
290282
291283 """
292 if PY2:
293 warn_count = 0
294 else:
295 warn_count = 1
284 warn_count = 1
296285 a = np.arange(10)
297286 b = np.lib.stride_tricks.as_strided(a, shape=(5,), strides=(a.dtype.itemsize * 2,))
298287 data = [a, b]
336325
337326
338327 def test_zero_dimensional_array():
339 expect = np.array(0.0)
340 actual = roundtrip(expect)
328 expect = np.array(float(0.0), dtype="float64")
329 actual = jsonpickle.decode(jsonpickle.encode(expect))
341330 npt.assert_array_equal(expect, actual)
342331
343332
362351
363352
364353 def test_ndarray_dtype_object():
365 a = np.array(['F' + str(i) for i in range(30)], dtype=np.object)
354 a = np.array(['F' + str(i) for i in range(30)], dtype=object)
366355 buf = jsonpickle.encode(a)
367356 # This is critical for reproducing the numpy segfault issue when
368357 # restoring ndarray of dtype object.
369358 del a
370 expect = np.array(['F' + str(i) for i in range(30)], dtype=np.object)
359 expect = np.array(['F' + str(i) for i in range(30)], dtype=object)
371360 actual = jsonpickle.decode(buf)
372361 npt.assert_array_equal(expect, actual)
373362
382371 assert expect == actual
383372
384373
374 def test_np_poly1d():
375 # issue 391, test poly1d roundtrip
376 obj = np.poly1d([1, 2, 3])
377 assert obj == jsonpickle.decode(jsonpickle.encode(obj))
378
379
385380 if __name__ == '__main__':
386381 pytest.main([__file__])
00 from __future__ import absolute_import, division, unicode_literals
1
12 import array
2 import enum
33 import collections
44 import datetime
55 import decimal
6 import enum
67 import re
78 import threading
9
10 import pytest
811 import pytz
12 from helper import SkippableTest
913
1014 import jsonpickle
11 from jsonpickle import compat
12 from jsonpickle import handlers
13 from jsonpickle import tags
14 from jsonpickle import util
15 from jsonpickle.compat import queue, PY2, PY3_ORDERED_DICT
16
17 import pytest
18
19 from helper import SkippableTest
15 from jsonpickle import compat, handlers, tags, util
16 from jsonpickle.compat import queue
2017
2118
2219 class Thing(object):
107104 pass
108105
109106
107 def func(x):
108 return x
109
110
110111 class ThingWithFunctionRefs(object):
111112 def __init__(self):
112113 self.fn = func
113
114
115 def func(x):
116 return x
117114
118115
119116 class ThingWithQueue(object):
521518 self.assertTrue(decoded == u1)
522519 self.assertTrue(isinstance(decoded, compat.ustr))
523520
524 # bytestrings are wrapped in PY3 but in PY2 we try to decode first
521 # bytestrings are wrapped in py 3
525522 encoded = self.pickler.flatten(b1)
526 if PY2:
527 self.assertEqual(encoded, u1)
528 self.assertTrue(isinstance(encoded, compat.ustr))
529 else:
530 self.assertNotEqual(encoded, u1)
531 encoded_ustr = util.b64encode(b'foo')
532 self.assertEqual({tags.B64: encoded_ustr}, encoded)
533 self.assertTrue(isinstance(encoded[tags.B64], compat.ustr))
523 self.assertNotEqual(encoded, u1)
524 encoded_ustr = util.b64encode(b'foo')
525 self.assertEqual({tags.B64: encoded_ustr}, encoded)
526 self.assertTrue(isinstance(encoded[tags.B64], compat.ustr))
534527 decoded = self.unpickler.restore(encoded)
535528 self.assertTrue(decoded == b1)
536 if PY2:
537 self.assertTrue(isinstance(decoded, compat.ustr))
538 else:
539 self.assertTrue(isinstance(decoded, bytes))
529 self.assertTrue(isinstance(decoded, bytes))
540530
541531 # bytestrings that we can't decode to UTF-8 will always be wrapped
542532 encoded = self.pickler.flatten(b2)
547537 decoded = self.unpickler.restore(encoded)
548538 self.assertEqual(decoded, b2)
549539 self.assertTrue(isinstance(decoded, bytes))
550
551 def test_backcompat_bytes_quoted_printable(self):
552 """Test decoding bytes objects from older jsonpickle versions"""
553
554 b1 = b'foo'
555 b2 = b'foo\xff'
556
557 # older versions of jsonpickle used a quoted-printable encoding
558 expect = b1
559 actual = self.unpickler.restore({tags.BYTES: 'foo'})
560 self.assertEqual(expect, actual)
561
562 expect = b2
563 actual = self.unpickler.restore({tags.BYTES: 'foo=FF'})
564 self.assertEqual(expect, actual)
565540
566541 def test_nested_objects(self):
567542 obj = ThingWithTimedeltaAttribute(99)
604579 typecodes = ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'f', 'd')
605580 for typecode in typecodes:
606581 obj = array.array(typecode, (1, 2, 3))
607 self._test_array_roundtrip(obj)
608
609 def test_array_handler_python2(self):
610 """Python2 allows the "c" byte/char typecode"""
611 if PY2:
612 obj = array.array('c', bytes('abcd'))
613582 self._test_array_roundtrip(obj)
614583
615584 def test_exceptions_with_arguments(self):
693662 decoded = jsonpickle.decode(encoded, keys=True)
694663 assert decoded[0].default_factory() == 0
695664 assert decoded[1] is decoded[2]
696
697
698 def test_defaultdict_subclass_with_self_as_default_factory():
699 """Serialize a defaultdict subclass with self as its default factory"""
700 cls = ThingWithSelfAsDefaultFactory
701 tree = cls()
702 newtree = _test_defaultdict_tree(tree, cls)
703 assert type(newtree['A'].default_factory) == cls
704 assert newtree.default_factory is newtree
705 assert newtree['A'].default_factory is newtree['A']
706 assert newtree['Z'].default_factory is newtree['Z']
707
708
709 def test_defaultdict_subclass_with_class_as_default_factory():
710 """Serialize a defaultdict with a class as its default factory"""
711 cls = ThingWithClassAsDefaultFactory
712 tree = cls()
713 newtree = _test_defaultdict_tree(tree, cls)
714 assert newtree.default_factory is cls
715 assert newtree['A'].default_factory is cls
716 assert newtree['Z'].default_factory is cls
717665
718666
719667 def _test_defaultdict_tree(tree, cls):
740688 return newtree
741689
742690
691 def test_defaultdict_subclass_with_self_as_default_factory():
692 """Serialize a defaultdict subclass with self as its default factory"""
693 cls = ThingWithSelfAsDefaultFactory
694 tree = cls()
695 newtree = _test_defaultdict_tree(tree, cls)
696 assert type(newtree['A'].default_factory) == cls
697 assert newtree.default_factory is newtree
698 assert newtree['A'].default_factory is newtree['A']
699 assert newtree['Z'].default_factory is newtree['Z']
700
701
702 def test_defaultdict_subclass_with_class_as_default_factory():
703 """Serialize a defaultdict with a class as its default factory"""
704 cls = ThingWithClassAsDefaultFactory
705 tree = cls()
706 newtree = _test_defaultdict_tree(tree, cls)
707 assert newtree.default_factory is cls
708 assert newtree['A'].default_factory is cls
709 assert newtree['Z'].default_factory is cls
710
711
743712 def test_posix_stat_result():
744713 """Serialize a posix.stat() result"""
745714 try:
776745
777746 def test_ordered_dict_python3():
778747 """Ensure that we preserve dict order on python3"""
779 if not PY3_ORDERED_DICT:
780 return
781748 # Python3.6+ preserves dict order.
782749 obj = {'z': 'Z', 'x': 'X', 'y': 'Y'}
783750 clone = jsonpickle.decode(jsonpickle.encode(obj))
00 from __future__ import absolute_import, division, unicode_literals
1
12 import datetime
23
34 import pytest
45
56 try:
7 import numpy as np
68 import pandas as pd
7 import numpy as np
8 from pandas.testing import assert_series_equal
9 from pandas.testing import assert_frame_equal
10 from pandas.testing import assert_index_equal
9 from pandas.testing import (
10 assert_frame_equal,
11 assert_index_equal,
12 assert_series_equal,
13 )
1114 except ImportError:
1215 pytest.skip('numpy is not available', allow_module_level=True)
1316
128131
129132
130133 def test_int64_index_roundtrip():
131 idx = pd.Int64Index([-1, 0, 3, 4])
134 idx = pd.Index([-1, 0, 3, 4], dtype=np.int64)
132135 decoded_idx = roundtrip(idx)
133136 assert_index_equal(decoded_idx, idx)
134137
135138
136139 def test_uint64_index_roundtrip():
137 idx = pd.UInt64Index([0, 3, 4])
140 idx = pd.Index([0, 3, 4], dtype=np.uint64)
138141 decoded_idx = roundtrip(idx)
139142 assert_index_equal(decoded_idx, idx)
140143
141144
142145 def test_float64_index_roundtrip():
143 idx = pd.Float64Index([0.1, 3.7, 4.2])
146 idx = pd.Index([0.1, 3.7, 4.2], dtype=np.float64)
144147 decoded_idx = roundtrip(idx)
145148 assert_index_equal(decoded_idx, idx)
146149
11
22 import unittest
33
4 from helper import SkippableTest
5
46 import jsonpickle
5
6 from helper import SkippableTest
77
88 try:
99 import sqlalchemy as sqa
00 # -*- coding: utf-8 -*-
11 """Test miscellaneous objects from the standard library"""
22
3 import unittest
34 import uuid
4 import unittest
55
66 import jsonpickle
77
55 # you should have received as part of this distribution.
66
77 from __future__ import absolute_import, division, unicode_literals
8
9 import doctest
10 import io
11 import time
812 import unittest
9 import doctest
10 import time
11
12 from jsonpickle import compat
13 from jsonpickle import util
13
14 from jsonpickle import compat, util
1415
1516
1617 class Thing(object):
2829
2930
3031 class MethodTestClass(object):
32
33 variable = None
34
3135 @staticmethod
3236 def static_method():
3337 pass
3943 def bound_method(self):
4044 pass
4145
42 variable = None
43
4446
4547 class MethodTestSubclass(MethodTestClass):
4648 pass
5254
5355
5456 class UtilTestCase(unittest.TestCase):
55 @unittest.skipIf(not compat.PY2, 'Python 2-specific Base85 test')
56 def test_b85encode_crashes_on_python2(self):
57 with self.assertRaises(NotImplementedError):
58 util.b85encode(b'')
59
60 @unittest.skipIf(not compat.PY2, 'Python 2-specific Base85 test')
61 def test_b85decode_crashes_on_python2(self):
62 with self.assertRaises(NotImplementedError):
63 util.b85decode(u'RC2?pb0AN3baKO~')
64
6557 def test_is_primitive_int(self):
6658 self.assertTrue(util.is_primitive(0))
6759 self.assertTrue(util.is_primitive(3))
7466 self.assertTrue(util.is_primitive(float(3)))
7567
7668 def test_is_primitive_long(self):
77 self.assertTrue(util.is_primitive(2 ** 64))
69 self.assertTrue(util.is_primitive(2**64))
7870
7971 def test_is_primitive_bool(self):
8072 self.assertTrue(util.is_primitive(True))
234226 old_instance = MethodTestOldStyle()
235227 self.assertTrue(has_method(old_instance, 'bound_method'))
236228 self.assertFalse(has_method(MethodTestOldStyle, 'bound_method'))
229
230 def test_importable_name(self):
231 func_being_tested_obj = util.importable_name
232 io_method_obj = io.BytesIO(b'bytes').readline
233 self.assertEqual(
234 util.importable_name(func_being_tested_obj),
235 'jsonpickle.util.importable_name',
236 )
237 self.assertEqual(util.importable_name(io_method_obj), '_io.BytesIO.readline')
238 self.assertEqual(util.importable_name(dict), 'builtins.dict')
237239
238240
239241 def suite():
55
66 """
77 from __future__ import absolute_import, division, unicode_literals
8
9 import collections
810 import unittest
9 import collections
10
11 from jsonpickle import encode, decode
11
12 from jsonpickle import decode, encode
1213
1314
1415 class World(object):
2122 self.name = name
2223 self.spells = collections.OrderedDict()
2324 world.wizards.append(self)
24
25 def __hash__(self):
26 return hash('Wizard %s' % self.name)
27
28 def __eq__(self, other):
29 for (ka, va), (kb, vb) in zip(self.spells.items(), other.spells.items()):
30 if ka.name != kb.name:
31 print('Wizards differ: %s != %s' % (ka.name, kb.name))
32 return False
33 for sa, sb in zip(va, vb):
34 if sa != sb:
35 print('Spells differ: %s != %s' % (sa.name, sb.name))
36 return False
37 return self.name == other.name
3825
3926 def __cmp__(self, other):
4027 for (ka, va), (kb, vb) in zip(self.spells.items(), other.spells.items()):
4936 return cmp_spell
5037 return cmp(self.name, other.name) # noqa: F821
5138
39 def __eq__(self, other):
40 for (ka, va), (kb, vb) in zip(self.spells.items(), other.spells.items()):
41 if ka.name != kb.name:
42 print('Wizards differ: %s != %s' % (ka.name, kb.name))
43 return False
44 for sa, sb in zip(va, vb):
45 if sa != sb:
46 print('Spells differ: %s != %s' % (sa.name, sb.name))
47 return False
48 return self.name == other.name
49
50 def __hash__(self):
51 return hash('Wizard %s' % self.name)
52
5253
5354 class Spell(object):
5455 def __init__(self, caster, target, name):
6162 spells = caster.spells[target] = []
6263 spells.append(self)
6364
64 def __hash__(self):
65 return hash(
66 'Spell %s by %s on %s' % (self.name, self.caster.name, self.target.name)
67 )
65 def __cmp__(self, other):
66 return (
67 cmp(self.name, other.name) # noqa: F821
68 or cmp(self.caster.name, other.caster.name) # noqa: F821
69 or cmp(self.target.name, other.target.name) # noqa: F821
70 ) # noqa: F821
6871
6972 def __eq__(self, other):
7073 return (
7376 and self.target.name == other.target.name
7477 )
7578
76 def __cmp__(self, other):
77 return (
78 cmp(self.name, other.name) # noqa: F821
79 or cmp(self.caster.name, other.caster.name) # noqa: F821
80 or cmp(self.target.name, other.target.name) # noqa: F821
81 ) # noqa: F821
79 def __hash__(self):
80 return hash(
81 'Spell %s by %s on %s' % (self.name, self.caster.name, self.target.name)
82 )
8283
8384
8485 def hashsum(items):
99
1010
1111 [testenv]
12 passenv =
13 FORCE_COLOR
1214 deps =
13 sa10: sqlalchemy>=1.0,<1.1
14 sa11: sqlalchemy>=1.1,<1.2
1515 sa12: sqlalchemy>=1.2,<1.3
1616 sa13: sqlalchemy>=1.3,<1.4
1717 pip_version = pip