From e2ba502d3e8762b6ad53f5b19ae899a2007f475d Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Thu, 14 Jul 2022 13:33:18 +0900 Subject: [PATCH] Imported Upstream version 4.6.4 --- CHANGES.txt | 13 + LICENSE.txt | 29 + Makefile | 42 +- PKG-INFO | 95 +- README.rst | 11 + benchmark/bench_etree.py | 3 +- benchmark/benchbase.py | 6 +- buildlibxml.py | 19 +- doc/FAQ.txt | 12 +- doc/capi.txt | 7 +- doc/compatibility.txt | 10 +- doc/html/FAQ.html | 48 +- doc/html/api.html | 56 +- doc/html/apidoc/_modules/collections/abc.html | 230 - doc/html/apidoc/_modules/index.html | 148 +- doc/html/apidoc/_modules/lxml.html | 149 +- .../apidoc/_modules/lxml/ElementInclude.html | 148 +- .../apidoc/_modules/lxml/doctestcompare.html | 148 +- doc/html/apidoc/_modules/lxml/html.html | 148 +- .../_modules/lxml/html/_diffcommand.html | 149 +- .../apidoc/_modules/lxml/html/_setmixin.html | 149 +- .../apidoc/_modules/lxml/html/builder.html | 149 +- .../apidoc/_modules/lxml/html/formfill.html | 149 +- .../apidoc/_modules/lxml/isoschematron.html | 148 +- doc/html/apidoc/_static/basic.css | 111 +- doc/html/apidoc/_static/css/theme.css | 4 +- doc/html/apidoc/_static/pygments.css | 10 +- doc/html/apidoc/genindex.html | 210 +- doc/html/apidoc/index.html | 171 +- doc/html/apidoc/lxml.ElementInclude.html | 197 +- doc/html/apidoc/lxml._elementpath.html | 217 +- doc/html/apidoc/lxml.builder.html | 193 +- doc/html/apidoc/lxml.cssselect.html | 169 +- doc/html/apidoc/lxml.doctestcompare.html | 305 +- doc/html/apidoc/lxml.etree.html | 4895 +++++------ doc/html/apidoc/lxml.html | 190 +- doc/html/apidoc/lxml.html.ElementSoup.html | 170 +- doc/html/apidoc/lxml.html._diffcommand.html | 186 +- doc/html/apidoc/lxml.html._setmixin.html | 235 +- doc/html/apidoc/lxml.html.builder.html | 542 +- doc/html/apidoc/lxml.html.clean.html | 362 +- doc/html/apidoc/lxml.html.defs.html | 170 +- doc/html/apidoc/lxml.html.diff.html | 370 +- doc/html/apidoc/lxml.html.formfill.html | 262 +- doc/html/apidoc/lxml.html.html | 655 +- doc/html/apidoc/lxml.html.html5parser.html | 170 +- doc/html/apidoc/lxml.html.soupparser.html | 170 +- doc/html/apidoc/lxml.isoschematron.html | 253 +- doc/html/apidoc/lxml.objectify.html | 409 +- doc/html/apidoc/lxml.sax.html | 252 +- doc/html/apidoc/py-modindex.html | 146 +- doc/html/apidoc/search.html | 153 +- doc/html/build.html | 6 +- doc/html/capi.html | 52 +- ...{changes-4.6.3.html => changes-4.6.4.html} | 856 +- doc/html/compatibility.html | 16 +- doc/html/credits.html | 6 +- doc/html/cssselect.html | 6 +- doc/html/element_classes.html | 60 +- doc/html/elementsoup.html | 10 +- doc/html/extensions.html | 66 +- doc/html/flattr-badge-large.png | Bin 1639 -> 0 bytes doc/html/html5parser.html | 6 +- doc/html/index.html | 27 +- doc/html/installation.html | 6 +- doc/html/intro.html | 6 +- doc/html/lxml-source-howto.html | 6 +- doc/html/lxmlhtml.html | 34 +- doc/html/objectify.html | 236 +- doc/html/parsing.html | 122 +- doc/html/performance.html | 400 +- doc/html/resolvers.html | 20 +- doc/html/sax.html | 18 +- doc/html/sitemap.html | 2 +- doc/html/style.css | 14 +- doc/html/tutorial.html | 246 +- doc/html/validation.html | 34 +- doc/html/xpathxslt.html | 68 +- doc/licenses/ZopePublicLicense.txt | 59 - doc/main.txt | 10 +- doc/mkhtml.py | 23 +- doc/mklatex.py | 17 +- doc/pdf/pubkey.asc | 36 - doc/performance.txt | 394 +- doc/s5/lxml-ep2008.html | 50 +- doc/s5/tagpython.png | Bin 20864 -> 0 bytes doc/update_performance_results.py | 58 + doc/xpathxslt.txt | 11 +- setup.py | 17 +- src/lxml.egg-info/PKG-INFO | 95 +- src/lxml.egg-info/SOURCES.txt | 10 +- src/lxml/__init__.py | 2 +- src/lxml/_elementpath.c | 98 +- src/lxml/builder.c | 44 +- src/lxml/dtd.pxi | 5 + src/lxml/etree.c | 7542 ++++++++-------- src/lxml/etree.h | 2 +- src/lxml/etree_api.h | 2 +- src/lxml/html/clean.c | 198 +- src/lxml/html/diff.c | 76 +- src/lxml/includes/lxml-version.h | 2 +- src/lxml/lxml.etree.h | 2 +- src/lxml/lxml.etree_api.h | 2 +- src/lxml/objectify.c | 7686 +++++++++++------ src/lxml/objectify.pyx | 99 +- src/lxml/sax.c | 42 +- src/lxml/serializer.pxi | 3 +- src/lxml/tests/fuzz_xml_parse.py | 25 + src/lxml/tests/test_dtd.py | 8 + src/lxml/tests/test_etree.py | 5 +- test.py | 4 +- tools/manylinux/build-wheels.sh | 6 +- 112 files changed, 15412 insertions(+), 16787 deletions(-) create mode 100644 LICENSE.txt delete mode 100644 doc/html/apidoc/_modules/collections/abc.html rename doc/html/{changes-4.6.3.html => changes-4.6.4.html} (99%) delete mode 100644 doc/html/flattr-badge-large.png delete mode 100644 doc/licenses/ZopePublicLicense.txt delete mode 100644 doc/pdf/pubkey.asc delete mode 100644 doc/s5/tagpython.png create mode 100644 doc/update_performance_results.py create mode 100644 src/lxml/tests/fuzz_xml_parse.py diff --git a/CHANGES.txt b/CHANGES.txt index 22f4d45..a5fae64 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,19 @@ lxml changelog ============== +4.6.4 (2021-11-01) +================== + +Features added +-------------- + +* GH#317: A new property ``system_url`` was added to DTD entities. + Patch by Thirdegree. + +* GH#314: The ``STATIC_*`` variables in ``setup.py`` can now be passed via env vars. + Patch by Isaac Jurado. + + 4.6.3 (2021-03-21) ================== diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..a76d0ed --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,29 @@ +Copyright (c) 2004 Infrae. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. Neither the name of Infrae nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INFRAE OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile index a8c9de8..555d851 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ PYTHON3?=python3 TESTFLAGS=-p -v TESTOPTS= SETUPFLAGS= -LXMLVERSION:=$(shell sed -ne '/__version__/s|.*__version__\s*=\s*"\([^"]*\)".*|\1|p' src/lxml/__init__.py) +LXMLVERSION:=$(shell $(PYTHON3) -c 'import re; print(re.findall(r"__version__\s*=\s*\"([^\"]+)\"", open("src/lxml/__init__.py").read())[0])' ) PARALLEL?=$(shell $(PYTHON) -c 'import sys; print("-j7" if sys.version_info >= (3, 5) else "")' ) PARALLEL3?=$(shell $(PYTHON3) -c 'import sys; print("-j7" if sys.version_info >= (3, 5) else "")' ) @@ -12,17 +12,21 @@ PY3_WITH_CYTHON?=$(shell $(PYTHON3) -c 'import Cython.Build.Dependencies' >/dev/ CYTHON_WITH_COVERAGE?=$(shell $(PYTHON) -c 'import Cython.Coverage; import sys; assert not hasattr(sys, "pypy_version_info")' >/dev/null 2>/dev/null && echo " --coverage" || true) CYTHON3_WITH_COVERAGE?=$(shell $(PYTHON3) -c 'import Cython.Coverage; import sys; assert not hasattr(sys, "pypy_version_info")' >/dev/null 2>/dev/null && echo " --coverage" || true) +PYTHON_BUILD_VERSION ?= * MANYLINUX_LIBXML2_VERSION=2.9.10 MANYLINUX_LIBXSLT_VERSION=1.1.34 MANYLINUX_CFLAGS=-O3 -g1 -pipe -fPIC -flto MANYLINUX_LDFLAGS=-flto -MANYLINUX_IMAGE_X86_64=quay.io/pypa/manylinux1_x86_64 -MANYLINUX_IMAGE_686=quay.io/pypa/manylinux1_i686 -MANYLINUX_IMAGE_AARCH64=quay.io/pypa/manylinux2014_aarch64 -AARCH64_ENV=-e AR="/opt/rh/devtoolset-9/root/usr/bin/gcc-ar" \ - -e NM="/opt/rh/devtoolset-9/root/usr/bin/gcc-nm" \ - -e RANLIB="/opt/rh/devtoolset-9/root/usr/bin/gcc-ranlib" +MANYLINUX_IMAGES= \ + manylinux1_x86_64 \ + manylinux1_i686 \ + manylinux_2_24_x86_64 \ + manylinux_2_24_i686 \ + manylinux_2_24_aarch64 \ + manylinux_2_24_ppc64le \ + manylinux_2_24_s390x \ + musllinux_1_1_x86_64 .PHONY: all inplace inplace3 rebuild-sdist sdist build require-cython wheel_manylinux wheel @@ -55,19 +59,22 @@ require-cython: qemu-user-static: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -wheel_manylinux: wheel_manylinux64 wheel_manylinux32 wheel_manylinuxaarch64 -wheel_manylinuxaarch64: qemu-user-static +wheel_manylinux: $(addprefix wheel_,$(MANYLINUX_IMAGES)) +$(addprefix wheel_,$(filter-out %_x86_64, $(filter-out %_i686, $(MANYLINUX_IMAGES)))): qemu-user-static -wheel_manylinux32 wheel_manylinux64 wheel_manylinuxaarch64: dist/lxml-$(LXMLVERSION).tar.gz +wheel_%: dist/lxml-$(LXMLVERSION).tar.gz time docker run --rm -t \ -v $(shell pwd):/io \ - $(if $(patsubst %aarch64,,$@),,$(AARCH64_ENV)) \ + -e AR=gcc-ar \ + -e NM=gcc-nm \ + -e RANLIB=gcc-ranlib \ -e CFLAGS="$(MANYLINUX_CFLAGS) $(if $(patsubst %aarch64,,$@),-march=core2,-march=armv8-a -mtune=cortex-a72)" \ -e LDFLAGS="$(MANYLINUX_LDFLAGS)" \ -e LIBXML2_VERSION="$(MANYLINUX_LIBXML2_VERSION)" \ -e LIBXSLT_VERSION="$(MANYLINUX_LIBXSLT_VERSION)" \ - -e WHEELHOUSE=wheelhouse_$(subst wheel_,,$@) \ - $(if $(filter $@,wheel_manylinuxaarch64),$(MANYLINUX_IMAGE_AARCH64),$(if $(patsubst %32,,$@),$(MANYLINUX_IMAGE_X86_64),$(MANYLINUX_IMAGE_686))) \ + -e PYTHON_BUILD_VERSION="$(PYTHON_BUILD_VERSION)" \ + -e WHEELHOUSE=$(subst wheel_,wheelhouse/,$@) \ + quay.io/pypa/$(subst wheel_,,$@) \ bash /io/tools/manylinux/build-wheels.sh /io/$< wheel: @@ -89,6 +96,15 @@ valgrind_test_inplace: inplace valgrind --tool=memcheck --leak-check=full --num-callers=30 --suppressions=valgrind-python.supp \ $(PYTHON) test.py +fuzz: clean + $(MAKE) \ + CC="/usr/bin/clang" \ + CFLAGS="$$CFLAGS -fsanitize=fuzzer-no-link -g2" \ + CXX="/usr/bin/clang++" \ + CXXFLAGS="-fsanitize=fuzzer-no-link" \ + inplace3 + $(PYTHON3) src/lxml/tests/fuzz_xml_parse.py + gdb_test_inplace: inplace @echo "file $(PYTHON)\nrun test.py" > .gdb.command gdb -x .gdb.command -d src -d src/lxml diff --git a/PKG-INFO b/PKG-INFO index 6eceeea..8053216 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: lxml -Version: 4.6.3 +Version: 4.6.4 Summary: Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API. Home-page: https://lxml.de/ Author: lxml dev team @@ -8,48 +8,6 @@ Author-email: lxml-dev@lxml.de Maintainer: lxml dev team Maintainer-email: lxml-dev@lxml.de License: BSD -Description: lxml is a Pythonic, mature binding for the libxml2 and libxslt libraries. It - provides safe and convenient access to these libraries using the ElementTree - API. - - It extends the ElementTree API significantly to offer support for XPath, - RelaxNG, XML Schema, XSLT, C14N and much more. - - To contact the project, go to the `project home page - `_ or see our bug tracker at - https://launchpad.net/lxml - - In case you want to use the current in-development version of lxml, - you can get it from the github repository at - https://github.com/lxml/lxml . Note that this requires Cython to - build the sources, see the build instructions on the project home - page. To the same end, running ``easy_install lxml==dev`` will - install lxml from - https://github.com/lxml/lxml/tarball/master#egg=lxml-dev if you have - an appropriate version of Cython installed. - - - After an official release of a new stable series, bug fixes may become - available at - https://github.com/lxml/lxml/tree/lxml-4.6 . - Running ``easy_install lxml==4.6bugfix`` will install - the unreleased branch state from - https://github.com/lxml/lxml/tarball/lxml-4.6#egg=lxml-4.6bugfix - as soon as a maintenance branch has been established. Note that this - requires Cython to be installed at an appropriate version for the build. - - 4.6.3 (2021-03-21) - ================== - - Bugs fixed - ---------- - - * A vulnerability (CVE-2021-28957) was discovered in the HTML Cleaner by Kevin Chung, - which allowed JavaScript to pass through. The cleaner now removes the HTML5 - ``formaction`` attribute. - - - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers @@ -64,13 +22,62 @@ Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: C Classifier: Operating System :: OS Independent Classifier: Topic :: Text Processing :: Markup :: HTML Classifier: Topic :: Text Processing :: Markup :: XML Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.* +Provides-Extra: source Provides-Extra: cssselect Provides-Extra: html5 Provides-Extra: htmlsoup -Provides-Extra: source +License-File: LICENSE.txt +License-File: LICENSES.txt + +lxml is a Pythonic, mature binding for the libxml2 and libxslt libraries. It +provides safe and convenient access to these libraries using the ElementTree +API. + +It extends the ElementTree API significantly to offer support for XPath, +RelaxNG, XML Schema, XSLT, C14N and much more. + +To contact the project, go to the `project home page +`_ or see our bug tracker at +https://launchpad.net/lxml + +In case you want to use the current in-development version of lxml, +you can get it from the github repository at +https://github.com/lxml/lxml . Note that this requires Cython to +build the sources, see the build instructions on the project home +page. To the same end, running ``easy_install lxml==dev`` will +install lxml from +https://github.com/lxml/lxml/tarball/master#egg=lxml-dev if you have +an appropriate version of Cython installed. + + +After an official release of a new stable series, bug fixes may become +available at +https://github.com/lxml/lxml/tree/lxml-4.6 . +Running ``easy_install lxml==4.6bugfix`` will install +the unreleased branch state from +https://github.com/lxml/lxml/tarball/lxml-4.6#egg=lxml-4.6bugfix +as soon as a maintenance branch has been established. Note that this +requires Cython to be installed at an appropriate version for the build. + +4.6.4 (2021-11-01) +================== + +Features added +-------------- + +* GH#317: A new property ``system_url`` was added to DTD entities. + Patch by Thirdegree. + +* GH#314: The ``STATIC_*`` variables in ``setup.py`` can now be passed via env vars. + Patch by Isaac Jurado. + + + + diff --git a/README.rst b/README.rst index 3ad1ba1..01962c3 100644 --- a/README.rst +++ b/README.rst @@ -50,6 +50,11 @@ for other ways to support the lxml project, as well as commercial consulting, customisations and trainings on lxml and fast Python XML processing. +Note that we are not accepting donations in crypto currencies. +Much of the development and hosting for lxml is done in a carbon-neutral way +or with compensated and very low emissions. +Crypto currencies do not fit into that ambition. + .. |Donate| image:: https://lxml.de/paypal_btn_donateCC_LG.png :width: 160 :height: 47 @@ -69,6 +74,12 @@ Another supporter of the lxml project is Project income report --------------------- +* Total project income in 2020: EUR 6065,86 (506.49 € / month) + + - Tidelift: EUR 4064.77 + - Paypal: EUR 1401.09 + - other: EUR 600.00 + * Total project income in 2019: EUR 717.52 (59.79 € / month) - Tidelift: EUR 360.30 diff --git a/benchmark/bench_etree.py b/benchmark/bench_etree.py index 0f66db8..69ac520 100644 --- a/benchmark/bench_etree.py +++ b/benchmark/bench_etree.py @@ -1,9 +1,10 @@ import copy +from io import BytesIO from itertools import * import benchbase from benchbase import (with_attributes, with_text, onlylib, - serialized, children, nochange, BytesIO) + serialized, children, nochange) TEXT = "some ASCII text" UTEXT = u"some klingon: \F8D2" diff --git a/benchmark/benchbase.py b/benchmark/benchbase.py index e34e610..a9f9ad8 100644 --- a/benchmark/benchbase.py +++ b/benchmark/benchbase.py @@ -1,4 +1,4 @@ -import sys, re, string, time, copy, gc +import sys, re, string, copy, gc from itertools import * import time @@ -474,6 +474,8 @@ def main(benchmark_class): if import_lxml: from lxml import etree _etrees.append(etree) + print("Using lxml %s (with libxml2 %s)" % ( + etree.__version__, '.'.join(map(str, etree.LIBXML_VERSION)))) try: sys.argv.remove('-fel') @@ -521,6 +523,8 @@ def main(benchmark_class): print("No library to test. Exiting.") sys.exit(1) + print("Running benchmarks in Python %s" % (sys.version_info,)) + print("Preparing test suites and trees ...") selected = set( sys.argv[1:] ) benchmark_suites, benchmarks = \ diff --git a/buildlibxml.py b/buildlibxml.py index f45c860..086d911 100644 --- a/buildlibxml.py +++ b/buildlibxml.py @@ -1,4 +1,4 @@ -import os, re, sys, subprocess +import os, re, sys, subprocess, platform import tarfile from distutils import log, version from contextlib import closing @@ -38,7 +38,13 @@ def download_and_extract_windows_binaries(destdir): if release_path in filename ] - arch = "win64" if sys.maxsize > 2**32 else "win32" + if platform.machine() == 'ARM64': + arch = "win-arm64" + elif sys.maxsize > 2**32: + arch = "win64" + else: + arch = "win32" + if sys.version_info < (3, 5): arch = 'vs2008.' + arch @@ -437,6 +443,15 @@ def build_libxml2xslt(download_dir, build_dir, if not has_current_lib("libxml2", libxml2_dir): cmmi(libxml2_configure_cmd, libxml2_dir, multicore, **call_setup) + # Fix up libxslt configure script (needed up to and including 1.1.34) + # https://gitlab.gnome.org/GNOME/libxslt/-/commit/90c34c8bb90e095a8a8fe8b2ce368bd9ff1837cc + with open(os.path.join(libxslt_dir, "configure"), 'rb') as f: + config_script = f.read() + if b' --libs print ' in config_script: + config_script = config_script.replace(b' --libs print ', b' --libs ') + with open(os.path.join(libxslt_dir, "configure"), 'wb') as f: + f.write(config_script) + # build libxslt libxslt_configure_cmd = configure_cmd + [ '--without-python', diff --git a/doc/FAQ.txt b/doc/FAQ.txt index 24ec8c4..48f69a6 100644 --- a/doc/FAQ.txt +++ b/doc/FAQ.txt @@ -117,11 +117,11 @@ wrote a nice article about high-performance aspects when `parsing large files with lxml`_. .. _`lxml.etree Tutorial`: tutorial.html -.. _`tutorial for ElementTree`: https://effbot.org/zone/element.htm +.. _`tutorial for ElementTree`: https://web.archive.org/web/20200720191942/https://effbot.org/zone/element.htm .. _`extended etree API`: api.html .. _`objectify documentation`: objectify.html -.. _`Python XML processing with lxml`: http://www.nmt.edu/tcc/help/pubs/pylxml/ -.. _`element library`: https://effbot.org/zone/element-lib.htm +.. _`Python XML processing with lxml`: https://web.archive.org/web/20190522191656/http://infohost.nmt.edu/tcc/help/pubs/pylxml/web/index.html +.. _`element library`: https://web.archive.org/web/20200703234431/http://www.effbot.org/zone/element-lib.htm .. _`parsing large files with lxml`: http://www.ibm.com/developerworks/xml/library/x-hiperfparse/ @@ -143,7 +143,7 @@ web page`_. The `generated API documentation`_ is a comprehensive API reference for the lxml package. -.. _`ElementTree API`: https://effbot.org/zone/element-index.htm +.. _`ElementTree API`: https://web.archive.org/web/20200703191710/http://www.effbot.org/zone/element-index.htm .. _`the web page`: https://lxml.de/#documentation .. _`generated API documentation`: api/index.html @@ -1239,8 +1239,8 @@ Element. Its children will then inherit this prefix for serialization. How can I specify a default namespace for XPath expressions? ------------------------------------------------------------ -You can't. In XPath, there is no such thing as a default namespace. Just use -an arbitrary prefix and let the namespace dictionary of the XPath evaluators +You can't. In XPath 1.0, there is no such thing as a default namespace. Just +use an arbitrary prefix and let the namespace dictionary of the XPath evaluators map it to your namespace. See also the question above. diff --git a/doc/capi.txt b/doc/capi.txt index 0167a5a..0471d81 100644 --- a/doc/capi.txt +++ b/doc/capi.txt @@ -7,11 +7,10 @@ C extensions to efficiently access public functions and classes of lxml, without going through the Python API. The API is described in the file `etreepublic.pxd`_, which is directly -c-importable by extension modules implemented in Pyrex_ or Cython_. +c-importable by extension modules implemented in Cython_. .. _`etreepublic.pxd`: https://github.com/lxml/lxml/blob/master/src/lxml/includes/etreepublic.pxd -.. _Cython: http://cython.org -.. _Pyrex: http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/ +.. _Cython: https://cython.org .. contents:: .. @@ -45,7 +44,7 @@ Writing external modules in Cython ---------------------------------- This is the easiest way of extending lxml at the C level. A Cython_ -(or Pyrex_) module should start like this:: +module should start like this:: # My Cython extension diff --git a/doc/compatibility.txt b/doc/compatibility.txt index e23d181..654cb7c 100644 --- a/doc/compatibility.txt +++ b/doc/compatibility.txt @@ -146,11 +146,11 @@ ElementTree. Nonetheless, some differences and incompatibilities exist: not. This means that a comment text "text" that ElementTree serializes as "" will become "" in lxml. -* When the string '*' is used as tag filter in the ``Element.getiterator()`` - method, ElementTree returns all elements in the tree, including comments and - processing instructions. lxml.etree only returns real Elements, i.e. tree - nodes that have a string tag name. Without a filter, both libraries iterate - over all nodes. +* When the string ``'*'`` is used as tag filter in the ``Element.iter()`` and + ``.find*()`` methods, ElementTree returns all elements in the tree, including + comments and processing instructions. lxml.etree only returns real Elements, + i.e. tree nodes that have a string tag name. Without a filter, both libraries + iterate over all nodes. Note that currently only lxml.etree supports passing the ``Element`` factory function as filter to select only Elements. Both libraries support passing diff --git a/doc/html/FAQ.html b/doc/html/FAQ.html index b96af6f..6a3cb6b 100644 --- a/doc/html/FAQ.html +++ b/doc/html/FAQ.html @@ -2,7 +2,7 @@ - + lxml FAQ - Frequently Asked Questions @@ -26,7 +26,7 @@ function hide_menu() {
-

lxml FAQ - Frequently Asked Questions

+

lxml FAQ - Frequently Asked Questions

Frequently asked questions on lxml. See also the notes on compatibility to ElementTree.

@@ -108,13 +108,13 @@ function hide_menu() { (just as any good documentation), it provides an overview of the most important concepts in lxml.etree. If you want to help out, improving the tutorial is a very good place to start.

-

There is also a tutorial for ElementTree which works for +

There is also a tutorial for ElementTree which works for lxml.etree. The documentation of the extended etree API also -contains many examples for lxml.etree. Fredrik Lundh's element +contains many examples for lxml.etree. Fredrik Lundh's element library contains a lot of nice recipes that show how to solve common tasks in ElementTree and lxml.etree. To learn using lxml.objectify, read the objectify documentation.

-

John Shipman has written another tutorial called Python XML +

John Shipman has written another tutorial called Python XML processing with lxml that contains lots of examples. Liza Daly wrote a nice article about high-performance aspects when parsing large files with lxml.

@@ -123,8 +123,8 @@ large files with lxml.

Where can I find more documentation about lxml?

There is a lot of documentation on the web and also in the Python standard library documentation, as lxml implements the well-known -ElementTree API and tries to follow its documentation as closely as -possible. The recipes in Fredrik Lundh's element library are +ElementTree API and tries to follow its documentation as closely as +possible. The recipes in Fredrik Lundh's element library are generally worth taking a look at. There are a couple of issues where lxml cannot keep up compatibility. They are described in the compatibility documentation.

@@ -272,7 +272,7 @@ also the section on threading
>>> root = etree.XML("<root><tag>text<child/></tag>tail</root>")
->>> print(etree.tostring(root[0]))
+>>> print(etree.tostring(root[0]))
 <tag>text<child/></tag>tail
 

Here is an example that shows why not serialising the tail would be @@ -280,15 +280,15 @@ even more surprising from an object point of view:

>>> root = etree.Element("test")
 
 >>> root.text = "TEXT"
->>> print(etree.tostring(root))
+>>> print(etree.tostring(root))
 <test>TEXT</test>
 
 >>> root.tail = "TAIL"
->>> print(etree.tostring(root))
+>>> print(etree.tostring(root))
 <test>TEXT</test>TAIL
 
->>> root.tail = None
->>> print(etree.tostring(root))
+>>> root.tail = None
+>>> print(etree.tostring(root))
 <test>TEXT</test>
 

Just imagine a Python list where you append an item and it doesn't @@ -534,12 +534,12 @@ versions of libxml2 and libxslt - and make sure they are used.

import sys
 from lxml import etree
 
-print("%-20s: %s" % ('Python',           sys.version_info))
-print("%-20s: %s" % ('lxml.etree',       etree.LXML_VERSION))
-print("%-20s: %s" % ('libxml used',      etree.LIBXML_VERSION))
-print("%-20s: %s" % ('libxml compiled',  etree.LIBXML_COMPILED_VERSION))
-print("%-20s: %s" % ('libxslt used',     etree.LIBXSLT_VERSION))
-print("%-20s: %s" % ('libxslt compiled', etree.LIBXSLT_COMPILED_VERSION))
+print("%-20s: %s" % ('Python',           sys.version_info))
+print("%-20s: %s" % ('lxml.etree',       etree.LXML_VERSION))
+print("%-20s: %s" % ('libxml used',      etree.LIBXML_VERSION))
+print("%-20s: %s" % ('libxml compiled',  etree.LIBXML_COMPILED_VERSION))
+print("%-20s: %s" % ('libxslt used',     etree.LIBXSLT_VERSION))
+print("%-20s: %s" % ('libxslt compiled', etree.LIBXSLT_COMPILED_VERSION))
 

If you can figure that the problem is not in lxml but in the underlying libxml2 or libxslt, you can ask right on the respective @@ -756,7 +756,7 @@ only added between nodes that do not contain data. This is always the case for trees constructed element-by-element, so no problems should be expected here. For parsed trees, a good way to assure that no conflicting whitespace is left in the tree is the remove_blank_text option:

-
>>> parser = etree.XMLParser(remove_blank_text=True)
+
>>> parser = etree.XMLParser(remove_blank_text=True)
 >>> tree = etree.parse(filename, parser)
 

This will allow the parser to drop blank text nodes when constructing the @@ -782,7 +782,7 @@ use either a DTD to tell the parser which whitespace it can safely ignore, or remove the ignorable whitespace manually after parsing, e.g. by setting all tail text to None:

for element in root.iter():
-    element.tail = None
+    element.tail = None
 

Fredrik Lundh also has a Python-level function for indenting XML by appending whitespace to tags. It can be found on his element library @@ -975,7 +975,7 @@ you can apply the following function:

XPath and Document Traversal

What are the findall() and xpath() methods on Element(Tree)?

-

findall() is part of the original ElementTree API. It supports a +

findall() is part of the original ElementTree API. It supports a simple subset of the XPath language, without predicates, conditions and other advanced features. It is very handy for finding specific tags in a tree. Another important difference is namespace handling, which uses the @@ -1014,8 +1014,8 @@ Element. Its children will then inherit this prefix for serialization.

How can I specify a default namespace for XPath expressions?

-

You can't. In XPath, there is no such thing as a default namespace. Just use -an arbitrary prefix and let the namespace dictionary of the XPath evaluators +

You can't. In XPath 1.0, there is no such thing as a default namespace. Just +use an arbitrary prefix and let the namespace dictionary of the XPath evaluators map it to your namespace. See also the question above.

@@ -1050,7 +1050,7 @@ advance beyond the critical point before touching the tree structure.

diff --git a/doc/html/api.html b/doc/html/api.html index c90579f..89254ec 100644 --- a/doc/html/api.html +++ b/doc/html/api.html @@ -2,7 +2,7 @@ - + APIs specific to lxml.etree
-

APIs specific to lxml.etree

+

APIs specific to lxml.etree

lxml.etree tries to follow established APIs wherever possible. Sometimes, however, the need to expose a feature in an easy way led to the invention of a @@ -93,22 +93,22 @@ model. It knows about parents and siblings of elements:

>>> e = etree.SubElement(d, "e") >>> b.getparent() == root True ->>> print(b.getnext().tag) +>>> print(b.getnext().tag) c ->>> print(c.getprevious().tag) +>>> print(c.getprevious().tag) b

Elements always live within a document context in lxml. This implies that there is also a notion of an absolute document root. You can retrieve an ElementTree for the root node of a document from any of its elements.

>>> tree = d.getroottree()
->>> print(tree.getroot().tag)
+>>> print(tree.getroot().tag)
 root
 

Note that this is different from wrapping an Element in an ElementTree. You can use ElementTrees to create XML trees with an explicit root node:

>>> tree = etree.ElementTree(d)
->>> print(tree.getroot().tag)
+>>> print(tree.getroot().tag)
 d
 >>> etree.tostring(tree)
 b'<d><e/></d>'
@@ -120,11 +120,11 @@ will understand the explicitly chosen root as root node of a document.  They
 will not see any elements outside the ElementTree.  However, ElementTrees do
 not modify their Elements:

>>> element = tree.getroot()
->>> print(element.tag)
+>>> print(element.tag)
 d
->>> print(element.getparent().tag)
+>>> print(element.getparent().tag)
 root
->>> print(element.getroottree().getroot().tag)
+>>> print(element.getroottree().getroot().tag)
 root
 

The rule is that all operations that are applied to Elements use either the @@ -149,11 +149,11 @@ iteration over the children, following/preceding siblings, ancestors and descendants of an element, as defined by the respective XPath axis:

>>> [ child.tag for child in root.iterchildren() ]
 ['a', 'b', 'c', 'd']
->>> [ child.tag for child in root.iterchildren(reversed=True) ]
+>>> [ child.tag for child in root.iterchildren(reversed=True) ]
 ['d', 'c', 'b', 'a']
 >>> [ sibling.tag for sibling in b.itersiblings() ]
 ['c', 'd']
->>> [ sibling.tag for sibling in c.itersiblings(preceding=True) ]
+>>> [ sibling.tag for sibling in c.itersiblings(preceding=True) ]
 ['b', 'a']
 >>> [ ancestor.tag for ancestor in e.iterancestors() ]
 ['d', 'root']
@@ -187,7 +187,7 @@ traverses the tree in document order.  This is implemented by the
 breadth-first traversal, it is almost as simple if you use the
 collections.deque type.

>>> root = etree.XML('<root><a><b/><c/></a><d><e/></d></root>')
->>> print(etree.tostring(root, pretty_print=True, encoding='unicode'))
+>>> print(etree.tostring(root, pretty_print=True, encoding='unicode'))
 <root>
   <a>
     <b/>
@@ -203,7 +203,7 @@ breadth-first traversal, it is almost as simple if you use the
 >>> while queue:
 ...    el = queue.popleft()  # pop next element
 ...    queue.extend(el)      # append its children
-...    print(el.tag)
+...    print(el.tag)
 root
 a
 d
@@ -239,7 +239,7 @@ copy attached to the exception:

to retrieve the log entries or filter them by a specific type, error domain or error level:

>>> log = e.error_log.filter_from_level(etree.ErrorLevels.FATAL)
->>> print(log[0])
+>>> print(log[0])
 <string>:4:8:FATAL:PARSER:ERR_TAG_NAME_MISMATCH: Opening and ending tag mismatch: a line 3 and root
 

This might look a little cryptic at first, but it is the information that @@ -250,11 +250,11 @@ or the filename if available). Here, PARSER is the so-called error domain, see lxml.etree.ErrorDomains for that. You can get it from a log entry like this:

>>> entry = log[0]
->>> print(entry.domain_name)
+>>> print(entry.domain_name)
 PARSER
->>> print(entry.type_name)
+>>> print(entry.type_name)
 ERR_TAG_NAME_MISMATCH
->>> print(entry.filename)
+>>> print(entry.filename)
 <string>
 

There is also a convenience attribute error_log.last_error that returns the @@ -284,7 +284,7 @@ to convert serialised XML to its canonical form directly, without creating a tree in memory. By default, it returns the canonical output, but can be directed to write it to a file instead.

>>> c14n_xml = etree.canonicalize("<root><test z='1' y='2'/></root>")
->>> print(c14n_xml)
+>>> print(c14n_xml)
 <root><test y="2" z="1"></test></root>
 
@@ -296,7 +296,7 @@ printing XML through a keyword argument:

>>> etree.tostring(root) b'<root><test/></root>' ->>> print(etree.tostring(root, pretty_print=True)) +>>> print(etree.tostring(root, pretty_print=True)) <root> <test/> </root> @@ -313,27 +313,27 @@ is required by the standard:

>>> etree.tostring(unicode_root, encoding="utf-8") b'<t\xe3\x84\xa0st>t\xe0\xa8\x8ast</t\xe3\x84\xa0st>' ->>> print(etree.tostring(unicode_root, encoding="iso-8859-1")) +>>> print(etree.tostring(unicode_root, encoding="iso-8859-1")) <?xml version='1.0' encoding='iso-8859-1'?> <t&#12576;st>t&#2570;st</t&#12576;st>

Also see the general remarks on Unicode support.

You can enable or disable the declaration explicitly by passing another keyword argument for the serialisation:

-
>>> print(etree.tostring(root, xml_declaration=True))
+
>>> print(etree.tostring(root, xml_declaration=True))
 <?xml version='1.0' encoding='ASCII'?>
 <root><test/></root>
 
 >>> unicode_root.clear()
 >>> etree.tostring(unicode_root, encoding="UTF-16LE",
-...                              xml_declaration=False)
+...                              xml_declaration=False)
 b'<\x00t\x00 1s\x00t\x00/\x00>\x00'
 

Note that a standard compliant XML parser will not consider the last line well-formed XML if the encoding is not explicitly provided somehow, e.g. in an underlying transport protocol:

>>> notxml = etree.tostring(unicode_root, encoding="UTF-16LE",
-...                                       xml_declaration=False)
+...                                       xml_declaration=False)
 >>> root = etree.XML(notxml)        #doctest: +ELLIPSIS
 Traceback (most recent call last):
   ...
@@ -344,11 +344,11 @@ of the document with a user provided DOCTYPE:

>>> xml = '<!DOCTYPE root>\n<root/>'
 >>> tree = etree.parse(StringIO(xml))
 
->>> print(etree.tostring(tree))
+>>> print(etree.tostring(tree))
 <!DOCTYPE root>
 <root/>
 
->>> print(etree.tostring(tree,
+>>> print(etree.tostring(tree,
 ...     doctype='<!DOCTYPE root SYSTEM "/tmp/test.dtd">'))
 <!DOCTYPE root SYSTEM "/tmp/test.dtd">
 <root/>
@@ -480,7 +480,7 @@ CDATA are rare, this is the best way to deal with this issue.

document is required to adhere to existing XML language definitions. For these special cases, you can instruct the parser to leave CDATA sections in the document:

-
>>> parser = etree.XMLParser(strip_cdata=False)
+
>>> parser = etree.XMLParser(strip_cdata=False)
 >>> root = etree.XML('<root><![CDATA[test]]></root>', parser)
 >>> root.text
 'test'
@@ -519,7 +519,7 @@ xinclude() method on a tree:

>>> tree = etree.parse(data) >>> tree.xinclude() ->>> print(etree.tostring(tree.getroot())) +>>> print(etree.tostring(tree.getroot())) <doc xmlns:xi="http://www.w3.org/2001/XInclude"> <foo/> <a xml:base="doc/test.xml"/> @@ -534,7 +534,7 @@ resolvers, you have to stick to the external Python module.

diff --git a/doc/html/apidoc/_modules/collections/abc.html b/doc/html/apidoc/_modules/collections/abc.html deleted file mode 100644 index 7784193..0000000 --- a/doc/html/apidoc/_modules/collections/abc.html +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - collections.abc — lxml documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - -
- -
- - - - - - - - - - - - - - - - - -
- -
    - -
  • »
  • - -
  • Module code »
  • - -
  • collections.abc
  • - - -
  • - -
  • - -
- - -
-
-
-
- -

Source code for collections.abc

-from _collections_abc import *
-from _collections_abc import __all__
-
- -
- -
-
- - -
- -
-

- - © Copyright 2020, lxml dev team - -

-
- - - - Built with Sphinx using a - - theme - - provided by Read the Docs. - -
- -
-
- -
- -
- - - - - - - - - - - \ No newline at end of file diff --git a/doc/html/apidoc/_modules/index.html b/doc/html/apidoc/_modules/index.html index 8b7ffcc..3911768 100644 --- a/doc/html/apidoc/_modules/index.html +++ b/doc/html/apidoc/_modules/index.html @@ -1,73 +1,35 @@ - - - - - - + + Overview: module code — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml.html b/doc/html/apidoc/_modules/lxml.html index 0640590..5c21151 100644 --- a/doc/html/apidoc/_modules/lxml.html +++ b/doc/html/apidoc/_modules/lxml.html @@ -1,73 +1,35 @@ - - - - - - + + lxml — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/ElementInclude.html b/doc/html/apidoc/_modules/lxml/ElementInclude.html index 1d76824..55d0e0e 100644 --- a/doc/html/apidoc/_modules/lxml/ElementInclude.html +++ b/doc/html/apidoc/_modules/lxml/ElementInclude.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.ElementInclude — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/doctestcompare.html b/doc/html/apidoc/_modules/lxml/doctestcompare.html index 6db6349..e0514c2 100644 --- a/doc/html/apidoc/_modules/lxml/doctestcompare.html +++ b/doc/html/apidoc/_modules/lxml/doctestcompare.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.doctestcompare — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/html.html b/doc/html/apidoc/_modules/lxml/html.html index 966c713..d224ec7 100644 --- a/doc/html/apidoc/_modules/lxml/html.html +++ b/doc/html/apidoc/_modules/lxml/html.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.html — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/html/_diffcommand.html b/doc/html/apidoc/_modules/lxml/html/_diffcommand.html index 5a9d6b0..71b91cb 100644 --- a/doc/html/apidoc/_modules/lxml/html/_diffcommand.html +++ b/doc/html/apidoc/_modules/lxml/html/_diffcommand.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.html._diffcommand — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/html/_setmixin.html b/doc/html/apidoc/_modules/lxml/html/_setmixin.html index 9ddca7c..1176a61 100644 --- a/doc/html/apidoc/_modules/lxml/html/_setmixin.html +++ b/doc/html/apidoc/_modules/lxml/html/_setmixin.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.html._setmixin — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/html/builder.html b/doc/html/apidoc/_modules/lxml/html/builder.html index a04ddce..4e3b757 100644 --- a/doc/html/apidoc/_modules/lxml/html/builder.html +++ b/doc/html/apidoc/_modules/lxml/html/builder.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.html.builder — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/html/formfill.html b/doc/html/apidoc/_modules/lxml/html/formfill.html index a7928ac..e464654 100644 --- a/doc/html/apidoc/_modules/lxml/html/formfill.html +++ b/doc/html/apidoc/_modules/lxml/html/formfill.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.html.formfill — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_modules/lxml/isoschematron.html b/doc/html/apidoc/_modules/lxml/isoschematron.html index 8ebc1b9..ff0d7b7 100644 --- a/doc/html/apidoc/_modules/lxml/isoschematron.html +++ b/doc/html/apidoc/_modules/lxml/isoschematron.html @@ -1,73 +1,35 @@ - - - - - - + + lxml.isoschematron — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/_static/basic.css b/doc/html/apidoc/_static/basic.css index 24bc73e..912859b 100644 --- a/doc/html/apidoc/_static/basic.css +++ b/doc/html/apidoc/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -130,7 +130,7 @@ ul.search li a { font-weight: bold; } -ul.search li div.context { +ul.search li p.context { color: #888; margin: 2px 0 0 30px; text-align: left; @@ -277,25 +277,25 @@ p.rubric { font-weight: bold; } -img.align-left, .figure.align-left, object.align-left { +img.align-left, figure.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } -img.align-right, .figure.align-right, object.align-right { +img.align-right, figure.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } -img.align-center, .figure.align-center, object.align-center { +img.align-center, figure.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } -img.align-default, .figure.align-default { +img.align-default, figure.align-default, .figure.align-default { display: block; margin-left: auto; margin-right: auto; @@ -319,7 +319,8 @@ img.align-default, .figure.align-default { /* -- sidebars -------------------------------------------------------------- */ -div.sidebar { +div.sidebar, +aside.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px; @@ -377,12 +378,14 @@ div.body p.centered { /* -- content of sidebars/topics/admonitions -------------------------------- */ div.sidebar > :last-child, +aside.sidebar > :last-child, div.topic > :last-child, div.admonition > :last-child { margin-bottom: 0; } div.sidebar::after, +aside.sidebar::after, div.topic::after, div.admonition::after, blockquote::after { @@ -455,20 +458,22 @@ td > :last-child { /* -- figures --------------------------------------------------------------- */ -div.figure { +div.figure, figure { margin: 0.5em; padding: 0.5em; } -div.figure p.caption { +div.figure p.caption, figcaption { padding: 0.3em; } -div.figure p.caption span.caption-number { +div.figure p.caption span.caption-number, +figcaption span.caption-number { font-style: italic; } -div.figure p.caption span.caption-text { +div.figure p.caption span.caption-text, +figcaption span.caption-text { } /* -- field list styles ----------------------------------------------------- */ @@ -503,6 +508,63 @@ table.hlist td { vertical-align: top; } +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + /* -- other body styles ----------------------------------------------------- */ @@ -629,14 +691,6 @@ dl.glossary dt { font-size: 1.1em; } -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - .versionmodified { font-style: italic; } @@ -764,8 +818,13 @@ div.code-block-caption code { } table.highlighttable td.linenos, -div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ } div.code-block-caption span.caption-number { @@ -780,16 +839,6 @@ div.literal-block-wrapper { margin: 1em 0; } -code.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -code.descclassname { - background-color: transparent; -} - code.xref, a code { background-color: transparent; font-weight: bold; diff --git a/doc/html/apidoc/_static/css/theme.css b/doc/html/apidoc/_static/css/theme.css index 8cd4f10..0d9ae7e 100644 --- a/doc/html/apidoc/_static/css/theme.css +++ b/doc/html/apidoc/_static/css/theme.css @@ -1,4 +1,4 @@ -html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before,.wy-nav-top a,.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,.wy-nav-top a,.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li span.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li span.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li span.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li span.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li span.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li span.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li span.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p.caption .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.btn .wy-menu-vertical li span.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p.caption .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.nav .wy-menu-vertical li span.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p.caption .btn .headerlink,.rst-content p.caption .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li span.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol li,.rst-content ol.arabic li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content ol.arabic li p:last-child,.rst-content ol.arabic li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.rst-content .wy-breadcrumbs li tt,.wy-breadcrumbs li .rst-content tt,.wy-breadcrumbs li code{padding:5px;border:none;background:none}.rst-content .wy-breadcrumbs li tt.literal,.wy-breadcrumbs li .rst-content tt.literal,.wy-breadcrumbs li code.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover span.toctree-expand,.wy-menu-vertical li.on a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand{display:block;font-size:.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp{user-select:none;pointer-events:none}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink{visibility:hidden;font-size:14px}.rst-content .code-block-caption .headerlink:after,.rst-content .toctree-wrapper>p.caption .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after{content:"\f0c1";font-family:FontAwesome}.rst-content .code-block-caption:hover .headerlink:after,.rst-content .toctree-wrapper>p.caption:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .hlist{width:100%}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl dt span.classifier:before{content:" : "}html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.field-list>dt:after,html.writer-html5 .rst-content dl.footnote>dt:after{content:":"}html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.footnote>dt>span.brackets{margin-right:.5rem}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{font-style:italic}html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.footnote>dd p,html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code,html.writer-html4 .rst-content dl:not(.docutils) tt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.rst-content .wy-breadcrumbs li tt,.wy-breadcrumbs li .rst-content tt,.wy-breadcrumbs li code{padding:5px;border:none;background:none}.rst-content .wy-breadcrumbs li tt.literal,.wy-breadcrumbs li .rst-content tt.literal,.wy-breadcrumbs li code.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.field-list>dt:after,html.writer-html5 .rst-content dl.footnote>dt:after{content:":"}html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.footnote>dt>span.brackets{margin-right:.5rem}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{font-style:italic}html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.footnote>dd p,html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/doc/html/apidoc/_static/pygments.css b/doc/html/apidoc/_static/pygments.css index be9feff..582d5c3 100644 --- a/doc/html/apidoc/_static/pygments.css +++ b/doc/html/apidoc/_static/pygments.css @@ -1,8 +1,8 @@ -pre { line-height: 125%; margin: 0; } -td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } -span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } -td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #f8f8f8; } .highlight .c { color: #408080; font-style: italic } /* Comment */ diff --git a/doc/html/apidoc/genindex.html b/doc/html/apidoc/genindex.html index 3109827..931148d 100644 --- a/doc/html/apidoc/genindex.html +++ b/doc/html/apidoc/genindex.html @@ -1,73 +1,35 @@ - - - - - - + + Index — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/index.html b/doc/html/apidoc/index.html index 46aedd2..d11697a 100644 --- a/doc/html/apidoc/index.html +++ b/doc/html/apidoc/index.html @@ -1,74 +1,37 @@ - - - - - - - lxml API Reference — lxml documentation - - - - - + - - - - - - + + lxml API Reference — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
+
-
-
- -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.ElementInclude.html b/doc/html/apidoc/lxml.ElementInclude.html index 807898b..0f240ba 100644 --- a/doc/html/apidoc/lxml.ElementInclude.html +++ b/doc/html/apidoc/lxml.ElementInclude.html @@ -1,75 +1,38 @@ - - - - - - - lxml.ElementInclude module — lxml documentation - - - - - + - - - - - - + + lxml.ElementInclude module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
-
- - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml._elementpath.html b/doc/html/apidoc/lxml._elementpath.html index 302a6f3..7de80e0 100644 --- a/doc/html/apidoc/lxml._elementpath.html +++ b/doc/html/apidoc/lxml._elementpath.html @@ -1,75 +1,38 @@ - - - - - - - lxml._elementpath module — lxml documentation - - - - - + - - - - - - + + lxml._elementpath module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.builder.html b/doc/html/apidoc/lxml.builder.html index 5892110..e88089c 100644 --- a/doc/html/apidoc/lxml.builder.html +++ b/doc/html/apidoc/lxml.builder.html @@ -1,75 +1,38 @@ - - - - - - - lxml.builder module — lxml documentation - - - - - + - - - - - - + + lxml.builder module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.cssselect.html b/doc/html/apidoc/lxml.cssselect.html index 43d4229..03ba2ae 100644 --- a/doc/html/apidoc/lxml.cssselect.html +++ b/doc/html/apidoc/lxml.cssselect.html @@ -1,75 +1,38 @@ - - - - - - - lxml.cssselect module — lxml documentation - - - - - + - - - - - - + + lxml.cssselect module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.doctestcompare.html b/doc/html/apidoc/lxml.doctestcompare.html index c25a0b9..45dffe1 100644 --- a/doc/html/apidoc/lxml.doctestcompare.html +++ b/doc/html/apidoc/lxml.doctestcompare.html @@ -1,75 +1,38 @@ - - - - - - - lxml.doctestcompare module — lxml documentation - - - - - + - - - - - - + + lxml.doctestcompare module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.etree.html b/doc/html/apidoc/lxml.etree.html index 6307879..c0b6ccf 100644 --- a/doc/html/apidoc/lxml.etree.html +++ b/doc/html/apidoc/lxml.etree.html @@ -1,75 +1,38 @@ - - - - - - - lxml.etree module — lxml documentation - - - - - + - - - - - - + + lxml.etree module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html b/doc/html/apidoc/lxml.html index 0cabb88..f9144de 100644 --- a/doc/html/apidoc/lxml.html +++ b/doc/html/apidoc/lxml.html @@ -1,75 +1,38 @@ - - - - - - - lxml package — lxml documentation - - - - - + - - - - - - + + lxml package — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
-
-

Module contents¶

+ +
+

Module contents

-
-lxml.get_include()[source]¶
+
+lxml.get_include()[source]

Returns a list of header include paths (for lxml itself, libxml2 and libxslt) needed to compile C code against lxml if it was built with statically linked libraries.

-
- + + - - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.ElementSoup.html b/doc/html/apidoc/lxml.html.ElementSoup.html index dbb1d44..7775ab6 100644 --- a/doc/html/apidoc/lxml.html.ElementSoup.html +++ b/doc/html/apidoc/lxml.html.ElementSoup.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.ElementSoup module — lxml documentation - - - - - + - - - - - - + + lxml.html.ElementSoup module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html._diffcommand.html b/doc/html/apidoc/lxml.html._diffcommand.html index d055676..e0c05be 100644 --- a/doc/html/apidoc/lxml.html._diffcommand.html +++ b/doc/html/apidoc/lxml.html._diffcommand.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html._diffcommand module — lxml documentation - - - - - + - - - - - - + + lxml.html._diffcommand module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html._setmixin.html b/doc/html/apidoc/lxml.html._setmixin.html index 460ab1b..8d4a798 100644 --- a/doc/html/apidoc/lxml.html._setmixin.html +++ b/doc/html/apidoc/lxml.html._setmixin.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html._setmixin module — lxml documentation - - - - - + - - - - - - + + lxml.html._setmixin module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.builder.html b/doc/html/apidoc/lxml.html.builder.html index 44c9a8d..0b504dd 100644 --- a/doc/html/apidoc/lxml.html.builder.html +++ b/doc/html/apidoc/lxml.html.builder.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.builder module — lxml documentation - - - - - + - - - - - - + + lxml.html.builder module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.clean.html b/doc/html/apidoc/lxml.html.clean.html index b1fe54b..989e272 100644 --- a/doc/html/apidoc/lxml.html.clean.html +++ b/doc/html/apidoc/lxml.html.clean.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.clean module — lxml documentation - - - - - + - - - - - - + + lxml.html.clean module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.defs.html b/doc/html/apidoc/lxml.html.defs.html index a71c10e..8bb0078 100644 --- a/doc/html/apidoc/lxml.html.defs.html +++ b/doc/html/apidoc/lxml.html.defs.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.defs module — lxml documentation - - - - - + - - - - - - + + lxml.html.defs module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.diff.html b/doc/html/apidoc/lxml.html.diff.html index b4202d0..47da606 100644 --- a/doc/html/apidoc/lxml.html.diff.html +++ b/doc/html/apidoc/lxml.html.diff.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.diff module — lxml documentation - - - - - + - - - - - - + + lxml.html.diff module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.formfill.html b/doc/html/apidoc/lxml.html.formfill.html index 96d1810..01e8a8a 100644 --- a/doc/html/apidoc/lxml.html.formfill.html +++ b/doc/html/apidoc/lxml.html.formfill.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.formfill module — lxml documentation - - - - - + - - - - - - + + lxml.html.formfill module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.html b/doc/html/apidoc/lxml.html.html index 58733c0..e95b568 100644 --- a/doc/html/apidoc/lxml.html.html +++ b/doc/html/apidoc/lxml.html.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html package — lxml documentation - - - - - - - - - - + - + + lxml.html package — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
-
-add(value)[source]¶
+
+add(value)[source]

Add a class.

This has no effect if the class is already present.

-
-discard(value)[source]¶
+
+discard(value)[source]

Remove a class if it is currently present.

If the class is not present, do nothing.

-
-remove(value)[source]¶
+
+remove(value)[source]

Remove a class; it must currently be present.

If the class is not present, raise a KeyError.

-
-toggle(value)[source]¶
+
+toggle(value)[source]

Add a class name if it isn’t there yet, or remove it if it exists.

Returns true if the class was added (and is now enabled) and false if it was removed (and is now disabled).

-
-update(values)[source]¶
+
+update(values)[source]

Add all names from ‘values’.

-
-_abc_impl = <_abc_data object>¶
+
+_abc_impl = <_abc._abc_data object>
-
-class lxml.html.FieldsDict(inputs)[source]¶
+
+class lxml.html.FieldsDict(inputs)[source]

Bases: collections.abc.MutableMapping

-
-keys() → a set-like object providing a view on D’s keys[source]¶
+
+keys() a set-like object providing a view on D's keys[source]
-
-_abc_impl = <_abc_data object>¶
+
+_abc_impl = <_abc._abc_data object>
-
-class lxml.html.FormElement[source]¶
+
+class lxml.html.FormElement[source]

Bases: lxml.html.HtmlElement

Represents a <form> element.

-
-_name()[source]¶
+
+_name()[source]
-
-form_values()[source]¶
+
+form_values()[source]

Return a list of tuples of the field values for the form. This is suitable to be passed to urllib.urlencode().

-
-
-property action¶
+
+
+property action

Get/set the form’s action attribute.

-
-
-property fields¶
+
+
+property fields

Dictionary-like object that represents all the fields in this form. You can set values in this dictionary to effect the form.

-
-
-property inputs¶
+
+
+property inputs

Returns an accessor for all the input elements in the form.

See InputGetter for more information about the object.

-
-
-property method¶
+
+
+property method

Get/set the form’s method. Always returns a capitalized string, and defaults to 'GET'

@@ -380,26 +292,26 @@ string, and defaults to -
-class lxml.html.HTMLParser(**kwargs)[source]¶
+
+class lxml.html.HTMLParser(**kwargs)[source]

Bases: lxml.etree.HTMLParser

An HTML parser that is configured to return lxml.html Element objects.

-
-class lxml.html.HtmlComment[source]¶
+
+class lxml.html.HtmlComment[source]

Bases: lxml.etree.CommentBase, lxml.html.HtmlMixin

-
-class lxml.html.HtmlElement[source]¶
+
+class lxml.html.HtmlElement[source]

Bases: lxml.etree.ElementBase, lxml.html.HtmlMixin

-
-cssselect(expr, translator='html')¶
+
+cssselect(expr, translator='html')

Run the CSS expression on this element and its children, returning a list of the results.

Equivalent to lxml.cssselect.CSSSelect(expr, translator=’html’)(self) @@ -408,8 +320,8 @@ speedup.

-
-set(self, key, value=None)¶
+
+set(self, key, value=None)

Sets an element attribute. If no value is provided, or if the value is None, creates a ‘boolean’ attribute without value, e.g. “<form novalidate></form>” for form.set('novalidate').

@@ -418,8 +330,8 @@ for form.set('noval
-
-class lxml.html.HtmlElementClassLookup(classes=None, mixins=None)[source]¶
+
+class lxml.html.HtmlElementClassLookup(classes=None, mixins=None)[source]

Bases: lxml.etree.CustomElementClassLookup

A lookup scheme for HTML Element classes.

To create a lookup instance with different Element classes, pass a tag @@ -428,30 +340,30 @@ a tag name mapping of Mixin classes in the -

-lookup(self, type, doc, namespace, name)[source]¶
+
+lookup(self, type, doc, namespace, name)[source]
-
-_default_element_classes = {'form': <class 'lxml.html.FormElement'>, 'input': <class 'lxml.html.InputElement'>, 'label': <class 'lxml.html.LabelElement'>, 'select': <class 'lxml.html.SelectElement'>, 'textarea': <class 'lxml.html.TextareaElement'>}¶
+
+_default_element_classes = {'form': <class 'lxml.html.FormElement'>, 'input': <class 'lxml.html.InputElement'>, 'label': <class 'lxml.html.LabelElement'>, 'select': <class 'lxml.html.SelectElement'>, 'textarea': <class 'lxml.html.TextareaElement'>}
-
-class lxml.html.HtmlEntity[source]¶
+
+class lxml.html.HtmlEntity[source]

Bases: lxml.etree.EntityBase, lxml.html.HtmlMixin

-
-class lxml.html.HtmlMixin[source]¶
+
+class lxml.html.HtmlMixin[source]

Bases: object

-
-cssselect(expr, translator='html')[source]¶
+
+cssselect(expr, translator='html')[source]

Run the CSS expression on this element and its children, returning a list of the results.

Equivalent to lxml.cssselect.CSSSelect(expr, translator=’html’)(self) @@ -460,8 +372,8 @@ speedup.

-
-drop_tag()[source]¶
+
+drop_tag()[source]

Remove the tag, but not its children or text. The children and text are merged into the parent.

Example:

@@ -474,28 +386,28 @@ are merged into the parent.

-
-drop_tree()[source]¶
+
+drop_tree()[source]

Removes this element from the tree, including its children and text. The tail text is joined to the previous element or parent.

-
-find_class(class_name)[source]¶
+
+find_class(class_name)[source]

Find any elements with the given class name.

- +

Find any links like <a rel="{rel}">...</a>; returns a list of elements.

-
-get_element_by_id(id, *default)[source]¶
+
+get_element_by_id(id, *default)[source]

Get the first element in a document with the given id. If none is found, return the default argument if provided or raise KeyError otherwise.

@@ -506,8 +418,8 @@ the same.

- +

Yield (element, attribute, link, pos), where attribute may be None (indicating the link is in the text). pos is the position where the link occurs; often 0, but sometimes something else in @@ -523,8 +435,8 @@ links reported later on.

- +

Make all links in the document absolute, given the base_url for the document (the full URL where the document came from), or if no base_url is given, then the .base_url @@ -538,8 +450,8 @@ are ignored. If set to ‘discard’, failing URLs will be removed.

-
-resolve_base_href(handle_failures=None)[source]¶
+
+resolve_base_href(handle_failures=None)[source]

Find any <base href> tag in the document, and apply its values to all links found in the document. Also remove the tag once it has been applied.

@@ -549,8 +461,8 @@ are ignored. If set to ‘discard’, failing URLs will be removed.

- +

Rewrite all the links in the document. For each link link_repl_func(link) will be called, and the return value will replace the old link.

@@ -565,70 +477,70 @@ tag text will be removed completely.

-
-set(self, key, value=None)[source]¶
+
+set(self, key, value=None)[source]

Sets an element attribute. If no value is provided, or if the value is None, creates a ‘boolean’ attribute without value, e.g. “<form novalidate></form>” for form.set('novalidate').

-
-text_content()[source]¶
+
+text_content()[source]

Return the text content of the tag (and the text in any children).

-
-
-property base_url¶
+
+
+property base_url

Returns the base URL, given when the page was parsed.

Use with urlparse.urljoin(el.base_url, href) to get absolute URLs.

-
-
-property body¶
+
+
+property body

Return the <body> element. Can be called from a child element to get the document’s head.

-
-
-property classes¶
+
+
+property classes

A set-like wrapper around the ‘class’ attribute.

-
-
-property forms¶
+
+
+property forms

Return a list of all the forms

-
-
-property head¶
+
+
+property head

Returns the <head> element. Can be called from a child element to get the document’s head.

-
-
-property label¶
+
+
+property label

Get or set any <label> element associated with this element.

-
-class lxml.html.HtmlProcessingInstruction[source]¶
+
+class lxml.html.HtmlProcessingInstruction[source]

Bases: lxml.etree.PIBase, lxml.html.HtmlMixin

-
-class lxml.html.InputElement[source]¶
+
+class lxml.html.InputElement[source]

Bases: lxml.html.InputMixin, lxml.html.HtmlElement

Represents an <input> element.

You can get the type with .type (which is lower-cased and @@ -637,29 +549,29 @@ defaults to 'text'<

Checkboxes and radios have the attribute input.checkable == True (for all others it is false) and a boolean attribute .checked.

-
-
-property checkable¶
+
+
+property checkable

Boolean: can this element be checked?

-
-
-property checked¶
+
+
+property checked

Boolean attribute to get/set the presence of the checked attribute.

You can only use this on checkable input types.

-
-
-property type¶
+
+
+property type

Return the type of this element (using the type attribute).

-
-
-property value¶
+
+
+property value

Get/set the value of this element, using the value attribute.

Also, if this is a checkbox and it has no value, this defaults to 'on'. If it is a checkbox or radio that is not @@ -669,8 +581,8 @@ checked, this returns None.

-
-class lxml.html.InputGetter(form)[source]¶
+
+class lxml.html.InputGetter(form)[source]

Bases: object

An accessor that represents all the input fields in a form.

You can get fields by name from this, with @@ -683,8 +595,8 @@ in this way.

won’t return the same thing as if you get all the names, as checkboxes and radio elements are returned individually.

-
-items()[source]¶
+
+items()[source]

Returns all fields with their names, similar to dict.items().

Returns
@@ -694,8 +606,8 @@ checkboxes and radio elements are returned individually.

-
-keys()[source]¶
+
+keys()[source]

Returns all unique field names, in document order.

Returns
@@ -707,28 +619,28 @@ checkboxes and radio elements are returned individually.

-
-class lxml.html.InputMixin[source]¶
+
+class lxml.html.InputMixin[source]

Bases: object

Mix-in for all input elements (input, select, and textarea)

-
-
-property name¶
+
+
+property name

Get/set the name of the element

-
-class lxml.html.LabelElement[source]¶
+
+class lxml.html.LabelElement[source]

Bases: lxml.html.HtmlElement

Represents a <label> element.

Label elements are linked to other elements with their for attribute. You can access this element with label.for_element.

-
-
-property for_element¶
+
+
+property for_element

Get/set the element this label points to. Return None if it can’t be found.

@@ -736,64 +648,64 @@ can’t be found.

-
-class lxml.html.MultipleSelectOptions(select)[source]¶
+
+class lxml.html.MultipleSelectOptions(select)[source]

Bases: lxml.html._setmixin.SetMixin

Represents all the selected options in a <select multiple> element.

You can add to this set-like option to select an option, or remove to unselect the option.

-
-add(item)[source]¶
+
+add(item)[source]

Add an element.

-
-remove(item)[source]¶
+
+remove(item)[source]

Remove an element. If not a member, raise a KeyError.

-
-_abc_impl = <_abc_data object>¶
+
+_abc_impl = <_abc._abc_data object>
-
-
-property options¶
+
+
+property options

Iterator of all the <option> elements.

-
-class lxml.html.RadioGroup(iterable=(), /)[source]¶
+
+class lxml.html.RadioGroup(iterable=(), /)[source]

Bases: list

This object represents several <input type=radio> elements that have the same name.

You can use this like a list, but also use the property .value to check/uncheck inputs. Also you can use .value_options to get the possible values.

-
-
-property value¶
+
+
+property value

Get/set the value, which checks the radio with that value (and unchecks any other value).

-
-
-property value_options¶
+
+
+property value_options

Returns a list of all the possible values.

-
-class lxml.html.SelectElement[source]¶
+
+class lxml.html.SelectElement[source]

Bases: lxml.html.InputMixin, lxml.html.HtmlElement

<select> element. You can get the name with .name.

.value will be the value of the selected option, unless this @@ -802,23 +714,23 @@ it will be a set-like object. In either case .multiple shows if this is a multi-select.

-
-
-property multiple¶
+
+
+property multiple

Boolean attribute: is there a multiple attribute on this element.

-
-
-property value¶
+
+
+property value

Get/set the value of this select (the selected option).

If this is a multi-select, this is a set-like object that represents all the selected options.

-
-
-property value_options¶
+
+
+property value_options

All the possible values this select can have (the value attribute of all the <option> elements.

@@ -826,22 +738,22 @@ attribute of all the -
-class lxml.html.TextareaElement[source]¶
+
+class lxml.html.TextareaElement[source]

Bases: lxml.html.InputMixin, lxml.html.HtmlElement

<textarea> element. You can get the name with .name and get/set the value with .value

-
-
-property value¶
+
+
+property value

Get/set the value (which is the contents of this element)

-
-class lxml.html.XHTMLParser(**kwargs)[source]¶
+
+class lxml.html.XHTMLParser(**kwargs)[source]

Bases: lxml.etree.XMLParser

An XML parser that is configured to return lxml.html Element objects.

@@ -860,8 +772,8 @@ parser like this:

-
-class lxml.html._MethodFunc(name, copy=False, source_class=<class 'lxml.html.HtmlMixin'>)[source]¶
+
+class lxml.html._MethodFunc(name, copy=False, source_class=<class 'lxml.html.HtmlMixin'>)[source]

Bases: object

An object that represents a method on an element as a function; the function takes either an element or an HTML string. It @@ -871,96 +783,96 @@ of the resulting document.

-
-lxml.html.Element(*args, **kw)[source]¶
+
+lxml.html.Element(*args, **kw)[source]

Create a new HTML Element.

This can also be used for XHTML documents.

-
-lxml.html.__bytes_replace_meta_content_type(repl, string, count=0)¶
+
+lxml.html.__bytes_replace_meta_content_type(repl, string, count=0)

Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl.

-
-lxml.html.__fix_docstring(s)[source]¶
+
+lxml.html.__fix_docstring(s)[source]
-
-lxml.html.__str_replace_meta_content_type(repl, string, count=0)¶
+
+lxml.html.__str_replace_meta_content_type(repl, string, count=0)

Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl.

-
-lxml.html._contains_block_level_tag(el)[source]¶
+
+lxml.html._contains_block_level_tag(el)[source]
-
-lxml.html._element_name(el)[source]¶
+
+lxml.html._element_name(el)[source]
-
-lxml.html._iter_css_imports(string, pos=0, endpos=9223372036854775807)¶
+
+lxml.html._iter_css_imports(string, pos=0, endpos=9223372036854775807)

Return an iterator over all non-overlapping matches for the RE pattern in string.

For each match, the iterator returns a match object.

-
-lxml.html._iter_css_urls(string, pos=0, endpos=9223372036854775807)¶
+
+lxml.html._iter_css_urls(string, pos=0, endpos=9223372036854775807)

Return an iterator over all non-overlapping matches for the RE pattern in string.

For each match, the iterator returns a match object.

-
-lxml.html._looks_like_full_html_bytes(string, pos=0, endpos=9223372036854775807)¶
+
+lxml.html._looks_like_full_html_bytes(string, pos=0, endpos=9223372036854775807)

Matches zero or more characters at the beginning of the string.

-
-lxml.html._looks_like_full_html_unicode(string, pos=0, endpos=9223372036854775807)¶
+
+lxml.html._looks_like_full_html_unicode(string, pos=0, endpos=9223372036854775807)

Matches zero or more characters at the beginning of the string.

-
-lxml.html._nons(tag)[source]¶
+
+lxml.html._nons(tag)[source]
-
-lxml.html._parse_meta_refresh_url(string, pos=0, endpos=9223372036854775807)¶
+
+lxml.html._parse_meta_refresh_url(string, pos=0, endpos=9223372036854775807)

Scan through string looking for a match, and return a corresponding match object instance.

Return None if no position in the string matches.

-
-lxml.html._transform_result(typ, result)[source]¶
+
+lxml.html._transform_result(typ, result)[source]

Convert the result back into the input type.

-
-lxml.html._unquote_match(s, pos)[source]¶
+
+lxml.html._unquote_match(s, pos)[source]
-
-lxml.html.document_fromstring(html, parser=None, ensure_head_body=False, **kw)[source]¶
+
+lxml.html.document_fromstring(html, parser=None, ensure_head_body=False, **kw)[source]
-
-lxml.html.fragment_fromstring(html, create_parent=False, base_url=None, parser=None, **kw)[source]¶
+
+lxml.html.fragment_fromstring(html, create_parent=False, base_url=None, parser=None, **kw)[source]

Parses a single HTML element; it is an error if there is more than one element, or if anything but whitespace precedes or follows the element.

@@ -973,8 +885,8 @@ as result of the parsing.

-
-lxml.html.fragments_fromstring(html, no_leading_text=False, base_url=None, parser=None, **kw)[source]¶
+
+lxml.html.fragments_fromstring(html, no_leading_text=False, base_url=None, parser=None, **kw)[source]

Parses several HTML elements, returning a list of elements.

The first item in the list may be a string. If no_leading_text is true, then it will be an error if there is @@ -984,8 +896,8 @@ leading text, and it will always be a list of only elements.

-
-lxml.html.fromstring(html, base_url=None, parser=None, **kw)[source]¶
+
+lxml.html.fromstring(html, base_url=None, parser=None, **kw)[source]

Parse the html, returning a single element/document.

This tries to minimally parse the chunk of text, without knowing if it is a fragment or a document.

@@ -993,28 +905,28 @@ is a fragment or a document.

-
-lxml.html.html_to_xhtml(html)[source]¶
+
+lxml.html.html_to_xhtml(html)[source]

Convert all tags in an HTML tree to XHTML by moving them to the XHTML namespace.

-
-lxml.html.open_http_urllib(method, url, values)[source]¶
+
+lxml.html.open_http_urllib(method, url, values)[source]
-
-lxml.html.open_in_browser(doc, encoding=None)[source]¶
+
+lxml.html.open_in_browser(doc, encoding=None)[source]

Open the HTML document in a web browser, saving it to a temporary file to open it. Note that this does not delete the file after use. This is mainly meant for debugging.

-
-lxml.html.parse(filename_or_url, parser=None, base_url=None, **kw)[source]¶
+
+lxml.html.parse(filename_or_url, parser=None, base_url=None, **kw)[source]

Parse a filename, URL, or file-like object into an HTML document tree. Note: this returns a tree, not an element. Use parse(...).getroot() to get the document root.

@@ -1023,8 +935,8 @@ is most useful when parsing from a file-like object.

-
-lxml.html.submit_form(form, extra_values=None, open_http=None)[source]¶
+
+lxml.html.submit_form(form, extra_values=None, open_http=None)[source]

Helper function to submit a form. Returns a file-like object, as from urllib.urlopen(). This object also has a .geturl() function, which shows the URL if there were any redirects.

@@ -1048,8 +960,8 @@ form data.

-
-lxml.html.tostring(doc, pretty_print=False, include_meta_content_type=False, encoding=None, method='html', with_tail=True, doctype=None)[source]¶
+
+lxml.html.tostring(doc, pretty_print=False, include_meta_content_type=False, encoding=None, method='html', with_tail=True, doctype=None)[source]

Return an HTML string representation of the document.

Note: if include_meta_content_type is true this will create a <meta http-equiv="Content-Type" ...> tag in the head; @@ -1108,69 +1020,44 @@ when serialising an ElementTree instance.

-
-lxml.html.xhtml_to_html(xhtml)[source]¶
+
+lxml.html.xhtml_to_html(xhtml)[source]

Convert all tags in an XHTML tree to HTML by removing their XHTML namespace.

- - + + - - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.html5parser.html b/doc/html/apidoc/lxml.html.html5parser.html index 53791f9..a5a1264 100644 --- a/doc/html/apidoc/lxml.html.html5parser.html +++ b/doc/html/apidoc/lxml.html.html5parser.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.html5parser module — lxml documentation - - - - - + - - - - - - + + lxml.html.html5parser module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.html.soupparser.html b/doc/html/apidoc/lxml.html.soupparser.html index 3a45aaa..de0f5f2 100644 --- a/doc/html/apidoc/lxml.html.soupparser.html +++ b/doc/html/apidoc/lxml.html.soupparser.html @@ -1,75 +1,38 @@ - - - - - - - lxml.html.soupparser module — lxml documentation - - - - - + - - - - - - + + lxml.html.soupparser module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.isoschematron.html b/doc/html/apidoc/lxml.isoschematron.html index ff2a05b..4526a55 100644 --- a/doc/html/apidoc/lxml.isoschematron.html +++ b/doc/html/apidoc/lxml.isoschematron.html @@ -1,75 +1,38 @@ - - - - - - - lxml.isoschematron package — lxml documentation - - - - - + - - - - - - + + lxml.isoschematron package — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
-
-lxml.isoschematron._stylesheet_param_dict(paramsDict, kwargsDict)[source]¶
+
+lxml.isoschematron._stylesheet_param_dict(paramsDict, kwargsDict)[source]

Return a copy of paramsDict, updated with kwargsDict entries, wrapped as stylesheet arguments. kwargsDict entries with a value of None are ignored.

-
-lxml.isoschematron.stylesheet_params(**kwargs)[source]¶
+
+lxml.isoschematron.stylesheet_params(**kwargs)[source]

Convert keyword args to a dictionary of stylesheet parameters. XSL stylesheet parameters must be XPath expressions, i.e.:

    @@ -382,63 +294,38 @@ If arg is None raise TypeError. Else convert arg to string.

- - + + - - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.objectify.html b/doc/html/apidoc/lxml.objectify.html index 7c95731..a42f7bc 100644 --- a/doc/html/apidoc/lxml.objectify.html +++ b/doc/html/apidoc/lxml.objectify.html @@ -1,75 +1,38 @@ - - - - - - - lxml.objectify module — lxml documentation - - - - - + - - - - - - + + lxml.objectify module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/lxml.sax.html b/doc/html/apidoc/lxml.sax.html index 8fb4163..5e31cce 100644 --- a/doc/html/apidoc/lxml.sax.html +++ b/doc/html/apidoc/lxml.sax.html @@ -1,74 +1,37 @@ - - - - - - - lxml.sax module — lxml documentation - - - - - + - - - - - - + + lxml.sax module — lxml documentation + + - - + - - - - - + - - - +
- -
- - -
- - - - - - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/py-modindex.html b/doc/html/apidoc/py-modindex.html index 75cf09a..a8050a9 100644 --- a/doc/html/apidoc/py-modindex.html +++ b/doc/html/apidoc/py-modindex.html @@ -1,39 +1,20 @@ - - - - - - + + Python Module Index — lxml documentation - - - - - - - - - - - - + + - - + - - - - - + @@ -41,36 +22,17 @@ - - - +
- -
- - -
- - - - - - - - + \ No newline at end of file diff --git a/doc/html/apidoc/search.html b/doc/html/apidoc/search.html index c119ba2..d5cf86a 100644 --- a/doc/html/apidoc/search.html +++ b/doc/html/apidoc/search.html @@ -1,75 +1,38 @@ - - - - - - + + Search — lxml documentation - - - - - - - - - - - - + + - - + - - - - - - + + + - - - +
- -
- - -
- - - - - - - - - - + diff --git a/doc/html/build.html b/doc/html/build.html index 9130ad3..3652aac 100644 --- a/doc/html/build.html +++ b/doc/html/build.html @@ -2,7 +2,7 @@ - + How to build lxml from source
-

How to build lxml from source

+

How to build lxml from source

To build lxml from source, you need libxml2 and libxslt properly installed, including the header files. These are likely shipped in @@ -317,7 +317,7 @@ installed using dpkg -i

diff --git a/doc/html/capi.html b/doc/html/capi.html index 405df7e..95ffc01 100644 --- a/doc/html/capi.html +++ b/doc/html/capi.html @@ -2,7 +2,7 @@ - + The public C-API of lxml.etree
-

The public C-API of lxml.etree

+

The public C-API of lxml.etree

As of version 1.1, lxml.etree provides a public C-API. This allows external C extensions to efficiently access public functions and classes of lxml, without going through the Python API.

The API is described in the file etreepublic.pxd, which is directly -c-importable by extension modules implemented in Pyrex or Cython.

+c-importable by extension modules implemented in Cython.

Contents

    @@ -57,8 +57,8 @@ of the C function adoptExternalDocument().

Writing external modules in Cython

-

This is the easiest way of extending lxml at the C level. A Cython -(or Pyrex) module should start like this:

+

This is the easiest way of extending lxml at the C level. A Cython +module should start like this:

 # My Cython extension
 
@@ -102,29 +102,29 @@ etree.set_element_class_lookup(
 

If you really feel like it, you can also interface with lxml.etree straight from C code. All you have to do is include the header file for the public API, import the lxml.etree module and then call the import function:

-
/* My C extension */
+
/* My C extension */
 
-/* common includes */
-#include "Python.h"
-#include "stdio.h"
-#include "string.h"
-#include "stdarg.h"
-#include "libxml/xmlversion.h"
-#include "libxml/encoding.h"
-#include "libxml/hash.h"
-#include "libxml/tree.h"
-#include "libxml/xmlIO.h"
-#include "libxml/xmlsave.h"
-#include "libxml/globals.h"
-#include "libxml/xmlstring.h"
+/* common includes */
+#include "Python.h"
+#include "stdio.h"
+#include "string.h"
+#include "stdarg.h"
+#include "libxml/xmlversion.h"
+#include "libxml/encoding.h"
+#include "libxml/hash.h"
+#include "libxml/tree.h"
+#include "libxml/xmlIO.h"
+#include "libxml/xmlsave.h"
+#include "libxml/globals.h"
+#include "libxml/xmlstring.h"
 
-/* lxml.etree specific includes */
-#include "lxml-version.h"
-#include "etree_defs.h"
-#include "etree.h"
+/* lxml.etree specific includes */
+#include "lxml-version.h"
+#include "etree_defs.h"
+#include "etree.h"
 
-/* setup code */
-import_lxml__etree()
+/* setup code */
+import_lxml__etree()
 

Note that including etree.h does not automatically include the header files it requires. Note also that the above list of common @@ -133,7 +133,7 @@ includes may not be sufficient.

diff --git a/doc/html/changes-4.6.3.html b/doc/html/changes-4.6.4.html similarity index 99% rename from doc/html/changes-4.6.3.html rename to doc/html/changes-4.6.4.html index 0ce06bb..d694b38 100644 --- a/doc/html/changes-4.6.3.html +++ b/doc/html/changes-4.6.4.html @@ -3,7 +3,7 @@ - + lxml changelog @@ -12,6 +12,18 @@

lxml changelog

+

4.6.4 (2021-11-01)

+
+

Features added

+
    +
  • GH#317: A new property system_url was added to DTD entities. +Patch by Thirdegree.
  • +
  • GH#314: The STATIC_* variables in setup.py can now be passed via env vars. +Patch by Isaac Jurado.
  • +
+
+
+

4.6.3 (2021-03-21)

Bugs fixed

@@ -22,9 +34,9 @@ which allowed JavaScript to pass through. The cleaner now removes the HTML5
-
-

4.6.2 (2020-11-26)

+

4.6.2 (2020-11-26)

+

Bugs fixed

  • A vulnerability (CVE-2020-27783) was discovered in the HTML Cleaner by Yaniv Nizry, @@ -33,9 +45,9 @@ which allowed JavaScript to pass through. The cleaner now removes more sneaky
-
-

4.6.1 (2020-10-18)

+

4.6.1 (2020-10-18)

+

Bugs fixed

  • A vulnerability was discovered in the HTML Cleaner by Yaniv Nizry, which allowed @@ -43,9 +55,9 @@ JavaScript to pass through. The cleaner now removes more sneaky "style&quo
-
+

4.6.0 (2020-10-17)

-
+

Features added

  • GH#310: lxml.html.InputGetter supports __len__() to count the number of input fields. @@ -56,7 +68,7 @@ Patch by Aidan Woolley.
  • Patch by Chris Mayo.
-
+

Bugs fixed

  • LP#1869455: C14N 2.0 serialisation failed for unprefixed attributes @@ -68,9 +80,9 @@ interface.
-
+

4.5.2 (2020-07-09)

-
+

Bugs fixed

  • Cleaner() now validates that only known configuration options can be set.
  • @@ -85,9 +97,9 @@ to "--xml2-config" and "--xslt-config" in 4.5.1 and are now
-
+

4.5.1 (2020-05-19)

-
+

Bugs fixed

  • LP#1570388: Fix failures when serialising documents larger than 2GB in some cases.
  • @@ -99,16 +111,16 @@ Patch by Hugh McMaster.
-
+

4.5.0 (2020-01-29)

-
+

Features added

  • A new function indent() was added to insert tail whitespace for pretty-printing an XML tree.
-
+

Bugs fixed

  • LP#1857794: Tail text of nodes that get removed from a document using item @@ -125,18 +137,18 @@ Set CFLAGS and LDFLAGS explicitly to override it.
-
+

4.4.3 (2020-01-28)

-
+

Bugs fixed

  • LP#1844674: itertext() was missing tail text of comments and PIs since 4.4.0.
-
+

4.4.2 (2019-11-25)

-
+

Bugs fixed

  • LP#1835708: ElementInclude incorrectly rejected repeated non-recursive @@ -145,9 +157,9 @@ Patch by Rainer Hausdorf.
-
+

4.4.1 (2019-08-11)

-
+

Bugs fixed

  • LP#1838252: The order of an OrderedDict was lost in 4.4.0 when passing it as @@ -156,9 +168,9 @@ attrib mapping during element creation.
-
+

4.4.0 (2019-07-27)

-
+

Features added

  • Element.clear() accepts a new keyword argument keep_tail=True to clear @@ -184,7 +196,7 @@ tree when set to false.
  • a c14n2 serialisation method.
-
+

Bugs fixed

  • When writing to file paths that contain the URL escape character '%', the file @@ -213,7 +225,7 @@ of empty tags in lxml.html.defs.
  • It now raises IOError.
-
+

Other changes

  • Support for Python 3.4 was removed.
  • @@ -227,61 +239,61 @@ in a future release.
-
+

4.3.5 (2019-07-27)

  • Rebuilt with Cython 0.29.13 to support Python 3.8.
-
+

4.3.4 (2019-06-10)

  • Rebuilt with Cython 0.29.10 to support Python 3.8.
-
+

4.3.3 (2019-03-26)

-
+

Bugs fixed

  • Fix leak of output buffer and unclosed files in _XSLTResultTree.write_output().
-
+

4.3.2 (2019-02-29)

-
+

Bugs fixed

  • Crash in 4.3.1 when appending a child subtree with certain text nodes.
-
+

Other changes

  • Built with Cython 0.29.6.
-
+

4.3.1 (2019-02-08)

-
+

Bugs fixed

  • LP#1814522: Crash when appending a child subtree that contains unsubstituted entity references.
-
+

Other changes

  • Built with Cython 0.29.5.
-
+

4.3.0 (2019-01-04)

-
+

Features added

  • The module lxml.sax is compiled using Cython in order to speed it up.
  • @@ -292,7 +304,7 @@ is used. Patch by Lennart Regebro. and the corresponding schema to the 2016 version (with optional "properties").
-
+

Other changes

  • GH#270, GH#271: Support for Python 2.6 and 3.3 was removed. @@ -303,9 +315,9 @@ which were released in 2014 and 2012 respectively.
-
+

4.2.6 (2019-01-02)

-
+

Bugs fixed

  • LP#1799755: Fix a DeprecationWarning in Py3.7+.
  • @@ -313,9 +325,9 @@ which were released in 2014 and 2012 respectively.
-
+

4.2.5 (2018-09-09)

-
+

Bugs fixed

  • Javascript URLs that used URL escaping were not removed by the HTML cleaner. @@ -323,16 +335,16 @@ Security problem found by Omar Eissa. (CVE-2018-19787)
-
+

4.2.4 (2018-08-03)

-
+

Features added

  • GH#259: Allow using pkg-config for build configuration. Patch by Patrick Griffis.
-
+

Bugs fixed

  • LP#1773749, GH#268: Crash when moving an element to another document with @@ -341,18 +353,18 @@ Patch by Alexander Weggerle.
-
+

4.2.3 (2018-06-27)

-
+

Bugs fixed

  • Reverted GH#265: lxml links against zlib as a shared library again.
-
+

4.2.2 (2018-06-22)

-
+

Bugs fixed

  • GH#266: Fix sporadic crash during GC when parse-time schema validation is used @@ -363,9 +375,9 @@ Patch by Nehal J Wani.
-
+

4.2.1 (2018-03-21)

-
+

Bugs fixed

  • LP#1755825: iterwalk() failed to return the 'start' event for the initial @@ -375,9 +387,9 @@ element if a tag selector is used.
-
+

4.2.0 (2018-03-13)

-
+

Features added

  • GH#255: SelectElement.value returns more standard-compliant and @@ -390,7 +402,7 @@ first one). If no options are present (not standard-compliant) Patch by stranac.
-
+

Bugs fixed

  • LP#1551797: Some XSLT messages were not captured by the transform error log.
  • @@ -398,19 +410,19 @@ Patch by stranac. validation.
-
+

Other changes

-
+

4.1.1 (2017-11-04)

  • Rebuild with Cython 0.27.3 to improve support for Py3.7.
-
+

4.1.0 (2017-10-13)

-
+

Features added

  • ElementPath supports text predicates for current node, like "[.='text']".
  • @@ -422,7 +434,7 @@ This should have a beneficial impact on the overall performance by providing a tighter compiler integration between lxml and libxml2/libxslt.
-
+

Bugs fixed

  • LP#1722776: Requesting non-Element objects like comments from a document with @@ -430,9 +442,9 @@ a tighter compiler integration between lxml and libxml2/libxslt.
-
+

4.0.0 (2017-09-17)

-
+

Features added

  • The ElementPath implementation is now compiled using Cython, @@ -448,7 +460,7 @@ allow relative resource lookups.
  • output data into a file according to the <xsl:output> configuration.
-
+

Bugs fixed

  • GH#251: HTML comments were handled incorrectly by the soupparser. @@ -481,7 +493,7 @@ to output end tags even after writing failed with an exception.

-
+

Other changes

  • The main module source files were renamed from lxml.*.pyx to plain @@ -492,9 +504,9 @@ be worth validating that third-party code does not notice this change.
-
+

3.8.0 (2017-06-03)

-
+

Features added

  • ElementTree.write() has a new option doctype that writes out a @@ -510,7 +522,7 @@ responsible for the error. Patch by Bob Kline.
  • a default namespace when passing a None prefix.
-
+

Bugs fixed

  • GH#238: Character escapes were not hex-encoded in the xmlfile serialiser. @@ -524,7 +536,7 @@ multi-threaded XSLT processing.
  • LP#1673355, GH#233: fromstring() html5parser failed to parse byte strings.
-
+

Other changes

  • The previously undocumented docstring option in ElementTree.write() @@ -532,9 +544,9 @@ produces a deprecation warning and will eventually be removed.
-
+

3.7.4 (2017-??-??)

-
+

Bugs fixed

  • LP#1551797: revert previous fix for XSLT error logging as it breaks @@ -543,9 +555,9 @@ multi-threaded XSLT processing.
-
+

3.7.3 (2017-02-18)

-
+

Bugs fixed

  • GH#218 was ineffective in Python 3.
  • @@ -554,13 +566,13 @@ Patch by Jakub Wilk.
-
+

3.7.2 (2017-01-08)

  • GH#220: xmlfile allows switching output methods at an element level. Patch by Burak Arslan.
-
+

Bugs fixed

  • Work around installation problems in recent Python 2.7 versions @@ -572,16 +584,16 @@ script/style tags. Patch by Burak Arslan.
-
+

3.7.1 (2016-12-23)

  • No source changes, issued only to solve problems with the binary packages released for 3.7.0.
-
+

3.7.0 (2016-12-10)

-
+

Features added

  • GH#217: XMLSyntaxError now behaves more like its SyntaxError @@ -599,14 +611,14 @@ serialises like <div attrname& marked as disabled in HTML. Patch by Kristian Klemon.
-
+

Bugs fixed

  • GH#206: File name and line number were missing from XSLT error messages. Patch by Marcus Brinkmann.
-
+

Other changes

  • Log entries no longer allow anything but plain string objects as message text @@ -615,27 +627,27 @@ and file name.
-
+

3.6.4 (2016-08-20)

-
+

3.6.3 (2016-08-18)

  • LP#1614603: change linker flags to build multi-linux wheels
-
+

3.6.2 (2016-08-18)

  • LP#1614603: release without source changes to provide cleanly built Linux wheels
-
+

3.6.1 (2016-07-24)

-
+

Features added

  • GH#180: Separate option inline_style for Cleaner that only removes style @@ -643,7 +655,7 @@ attributes instead of all styles. Patch by Christian Pedersen.
  • GH#196: Windows build support for Python 3.5. Contribution by Maximilian Hils.
-
+

Bugs fixed

  • GH#199: Exclude file fields from FormElement.form_values (as browsers do). @@ -656,9 +668,9 @@ Patch by Holger Joukl.
-
+

3.6.0 (2016-03-17)

-
+

Features added

  • GH#187: Now supports (only) version 5.x and later of PyPy. @@ -667,7 +679,7 @@ Patch by Armin Rigo.
  • is installed. Patch by Dirkjan Ochtman.
-
+

Bugs fixed

  • GH#189: Static builds honour FTP proxy configurations when downloading @@ -679,9 +691,9 @@ Patch by Petr Demin.
-
+

3.5.0 (2015-11-13)

-
+

Bugs fixed

  • Unicode string results failed XPath queries in PyPy.
  • @@ -693,7 +705,7 @@ and continued parsing instead.

3.5.0b1 (2015-09-18)

-
+

Features added

  • cleanup_namespaces() accepts a new argument keep_ns_prefixes @@ -725,7 +737,7 @@ Patch by Olli Pottonen.
  • of version 3 if available.
-
+

Bugs fixed

  • Memory errors that occur during tree adaptations (e.g. moving subtrees @@ -752,9 +764,9 @@ with ElementPath to avoid hiding bugs in user code.
-
+

3.4.4 (2015-04-25)

-
+

Bugs fixed

  • An ElementTree compatibility test added in lxml 3.4.3 that failed in @@ -762,9 +774,9 @@ Python 3.4+ was removed again.
-
+

3.4.3 (2015-04-15)

-
+

Bugs fixed

  • Expression cache in ElementPath was ignored. Fix by Changaco.
  • @@ -777,9 +789,9 @@ double quotes. Patch by Olli Pottonen.
-
+

3.4.2 (2015-02-07)

-
+

Bugs fixed

  • LP#1415907: Crash when creating an XMLSchema from a non-root element @@ -791,25 +803,25 @@ with pseudo-attributes.
-
+

3.4.1 (2014-11-20)

-
+

Features added

  • New htmlfile HTML generator to accompany the incremental xmlfile serialisation API. Patch by Burak Arslan.
-
+

Bugs fixed

  • lxml.sax.ElementTreeContentHandler did not initialise its superclass.
-
+

3.4.0 (2014-09-10)

-
+

Features added

  • xmlfile(buffered=False) disables output buffering and flushes the @@ -834,10 +846,10 @@ if it had opened it internally.
  • Allow "bytearray" type for ASCII text input.
-
+

Bugs fixed

-
+

Other changes

  • LP#400588: decoding errors have become hard errors even in recovery mode. @@ -851,9 +863,9 @@ use lxml 3.3.x with older versions.
-
+

3.3.6 (2014-08-28)

-
+

Bugs fixed

  • Prevent tree cycle creation when adding Elements as siblings.
  • @@ -863,9 +875,9 @@ extension functions.
-
+

3.3.5 (2014-04-18)

-
+

Bugs fixed

  • HTML cleaning could fail to strip javascript links that mix control @@ -873,34 +885,34 @@ characters into the link scheme.
-
+

3.3.4 (2014-04-03)

-
+

Features added

  • Source line numbers above 65535 are available on Elements when using libxml2 2.9 or later.
-
+

Bugs fixed

  • lxml.html.fragment_fromstring() failed for bytes input in Py3.
-
+

Other changes

-
+

3.3.3 (2014-03-04)

-
+

Bugs fixed

  • LP#1287118: Crash when using Element subtypes with __slots__.
-
+

Other changes

  • The internal classes _LogEntry and _Attrib can no longer be @@ -908,9 +920,9 @@ subclassed from Python code.
-
+

3.3.2 (2014-02-26)

-
+

Bugs fixed

  • The properties resolvers and version, as well as the methods @@ -931,12 +943,12 @@ provide the same interface as that returned for Elements.
-
+

3.3.1 (2014-02-12)

-
+

Features added

-
+

Bugs fixed

  • LP#1014290: HTML documents parsed with parser.feed() failed to find @@ -948,36 +960,36 @@ header file.
  • LP#1274118: iterparse() failed to parse BOM prefixed files.
-
+

Other changes

-
+

3.3.0 (2014-01-26)

-
+

Features added

-
+

Bugs fixed

  • The heuristic that distinguishes file paths from URLs was tightened to produce less false negatives.
-
+

Other changes

3.3.0beta5 (2014-01-18)

-
+

Features added

  • The PEP 393 unicode parsing support gained a fallback for wchar strings which might still be somewhat common on Windows systems.
-
+

Bugs fixed

  • Several error handling problems were fixed throughout the code base that @@ -990,7 +1002,7 @@ propagate exceptions (its return type is void) parsing the string character by character.
-
+

Other changes

  • Document cleanup code was simplified using the new GC features in @@ -1000,10 +1012,10 @@ Cython 0.20.

3.3.0beta4 (2014-01-12)

-
+

Features added

-
+

Bugs fixed

diff --git a/doc/html/cssselect.html b/doc/html/cssselect.html index dd24b52..584e371 100644 --- a/doc/html/cssselect.html +++ b/doc/html/cssselect.html @@ -2,7 +2,7 @@ - + lxml.cssselect
-

lxml.cssselect

+

lxml.cssselect

lxml supports a number of interesting languages for tree traversal and element selection. The most important is obviously XPath, but there is also @@ -113,7 +113,7 @@ namespace URIs: the CSSSelector class accepts

diff --git a/doc/html/element_classes.html b/doc/html/element_classes.html index 216dde3..a8a36b0 100644 --- a/doc/html/element_classes.html +++ b/doc/html/element_classes.html @@ -2,7 +2,7 @@ - + Using custom Element classes in lxml
-

Using custom Element classes in lxml

+

Using custom Element classes in lxml

lxml has very sophisticated support for custom Element classes. You can provide your own classes for Elements and have lxml use them by @@ -148,14 +148,14 @@ for a parser works as follows:

does not know about your specialised parser and creates a new document that deploys the default parser:

>>> el = etree.Element("root")
->>> print(isinstance(el, honk))
+>>> print(isinstance(el, honk))
 False
 

You should therefore avoid using this factory function in code that uses custom classes. The makeelement() method of parsers provides a simple replacement:

>>> el = parser.makeelement("root")
->>> print(isinstance(el, honk))
+>>> print(isinstance(el, honk))
 True
 

If you use a parser at the module level, you can easily redirect a module @@ -166,21 +166,21 @@ level Element() factory to the parser method b

While the XML() and HTML() factories also depend on the default parser, you can pass them a different parser as second argument:

>>> element = etree.XML("<test/>")
->>> print(isinstance(element, honk))
+>>> print(isinstance(element, honk))
 False
 
 >>> element = etree.XML("<test/>", parser)
->>> print(isinstance(element, honk))
+>>> print(isinstance(element, honk))
 True
 

Whenever you create a document with a parser, it will inherit the lookup scheme and all subsequent element instantiations for this document will use it:

>>> element = etree.fromstring("<test/>", parser)
->>> print(isinstance(element, honk))
+>>> print(isinstance(element, honk))
 True
 >>> el = etree.SubElement(element, "subel")
->>> print(isinstance(el, honk))
+>>> print(isinstance(el, honk))
 True
 

For testing code in the Python interpreter and for small projects, you @@ -207,14 +207,14 @@ also the default lookup (if not configured otherwise).

the constructor. While it accepts classes for element, comment and pi nodes, most use cases will only override the element class:

>>> el = parser.makeelement("myelement")
->>> print(isinstance(el, honk))
+>>> print(isinstance(el, honk))
 False
 
 >>> lookup = etree.ElementDefaultClassLookup(element=honk)
 >>> parser.set_element_class_lookup(lookup)
 
 >>> el = parser.makeelement("myelement")
->>> print(isinstance(el, honk))
+>>> print(isinstance(el, honk))
 True
 >>> el.honking
 False
@@ -228,7 +228,7 @@ the constructor.  While it accepts classes for elem
 ...     '<root honking="true"><!--comment--></root>', parser)
 >>> root.honking
 True
->>> print(root[0].text)
+>>> print(root[0].text)
 comment
 
@@ -254,7 +254,7 @@ desired fallback lookup scheme to the constructor:

... '<root honking="true"><!--comment--></root>', parser) >>> root.honking True ->>> print(root[0].text) +>>> print(root[0].text) comment
@@ -303,7 +303,7 @@ basis. It allows you to implement a custom lookup scheme in a subclass:

... if node_type == 'element': ... return honk # be a bit more selective here ... ... else: -... return None # pass on to (default) fallback +... return None # pass on to (default) fallback >>> parser = etree.XMLParser() >>> parser.set_element_class_lookup(MyLookup()) @@ -312,7 +312,7 @@ basis. It allows you to implement a custom lookup scheme in a subclass:

... '<root honking="true"><!--comment--></root>', parser) >>> root.honking True ->>> print(root[0].text) +>>> print(root[0].text) comment

The .lookup() method must return either None (which triggers the @@ -383,7 +383,7 @@ your Element proxy classes for the elements that they create. The >>> el = hale( "some ", honk(honking = 'true'), bopp, " text" ) ->>> print(etree.tostring(el, encoding='unicode')) +>>> print(etree.tostring(el, encoding='unicode')) <hale>some <honk honking="true"/><bopp/> text</hale> @@ -412,13 +412,13 @@ everything that is not an Element class.

lxml:

>>> xml = '<honk xmlns="http://hui.de/honk" honking="true"/>'
 >>> honk_element = etree.XML(xml, parser)
->>> print(honk_element.honking)
+>>> print(honk_element.honking)
 True
 

The same works when creating elements by hand:

>>> honk_element = parser.makeelement('{http://hui.de/honk}honk',
 ...                                   honking='true')
->>> print(honk_element.honking)
+>>> print(honk_element.honking)
 True
 

Essentially, what this allows you to do, is to give Elements a custom API @@ -433,13 +433,13 @@ implementation:

... '<bla/><!--comment-->' ... '</honk>') >>> honk_element = etree.XML(xml, parser) ->>> print(honk_element.honking) +>>> print(honk_element.honking) True ->>> print(honk_element[0].honking) +>>> print(honk_element[0].honking) Traceback (most recent call last): ... AttributeError: 'lxml.etree._Element' object has no attribute 'honking' ->>> print(honk_element[1].text) +>>> print(honk_element[1].text) comment

You can therefore provide one implementation per element name in each @@ -455,7 +455,7 @@ can just pass None as an element name:

>>> class HonkNSElement(etree.ElementBase):
 ...    def honk(self):
 ...       return "HONK"
->>> namespace[None] = HonkNSElement  # default Element for namespace
+>>> namespace[None] = HonkNSElement  # default Element for namespace
 
 >>> class HonkElement(HonkNSElement):
 ...    @property
@@ -470,24 +470,24 @@ subclasses for elements of this namespace:

... '</honk>') >>> honk_element = etree.fromstring(xml, parser) ->>> print(type(honk_element)) +>>> print(type(honk_element)) <class 'HonkElement'> ->>> print(type(honk_element[0])) +>>> print(type(honk_element[0])) <class 'HonkNSElement'> ->>> print(honk_element.honking) +>>> print(honk_element.honking) True ->>> print(honk_element.honk()) +>>> print(honk_element.honk()) HONK ->>> print(honk_element[0].honk()) +>>> print(honk_element[0].honk()) HONK ->>> print(honk_element[0].honking) +>>> print(honk_element[0].honking) Traceback (most recent call last): ... AttributeError: 'HonkNSElement' object has no attribute 'honking' ->>> print(honk_element[1].text) # uses fallback for non-elements +>>> print(honk_element[1].text) # uses fallback for non-elements comment

Since lxml 4.1, the registration is more conveniently done with @@ -495,7 +495,7 @@ class decorators. The namespace registry object is callable with a name (or None) as argument and can then be used as decorator.

>>> honk_elements = lookup.get_namespace('http://hui.de/honk')
 
->>> @honk_elements(None)
+>>> @honk_elements(None)
 ... class HonkNSElement(etree.ElementBase):
 ...    def honk(self):
 ...       return "HONK"
@@ -525,7 +525,7 @@ and use the blank decorator instead:

diff --git a/doc/html/elementsoup.html b/doc/html/elementsoup.html index e71849f..d874daa 100644 --- a/doc/html/elementsoup.html +++ b/doc/html/elementsoup.html @@ -2,7 +2,7 @@ - + BeautifulSoup Parser
-

BeautifulSoup Parser

+

BeautifulSoup Parser

BeautifulSoup is a Python package for working with real-world and broken HTML, just like lxml.html. As of version 4.x, it can use @@ -74,7 +74,7 @@ Previous versions of lxml 2.0.x only have the Eleme

To see what we have here, you can serialise it:

>>> from lxml.etree import tostring
->>> print(tostring(root, pretty_print=True).strip())
+>>> print(tostring(root, pretty_print=True).strip())
 <html>
   <meta/>
   <head>
@@ -189,7 +189,7 @@ you can simply pass the resulting Unicode string into lxml's parser.

... from BeautifulSoup import UnicodeDammit # BeautifulSoup 3 ... ... def decode_html(html_string): -... converted = UnicodeDammit(html_string, isHTML=True) +... converted = UnicodeDammit(html_string, isHTML=True) ... if not converted.unicode: ... raise UnicodeDecodeError( ... "Failed to detect encoding, tried [%s]", @@ -203,7 +203,7 @@ you can simply pass the resulting Unicode string into lxml's parser.

diff --git a/doc/html/extensions.html b/doc/html/extensions.html index 9f87d67..5d7bb89 100644 --- a/doc/html/extensions.html +++ b/doc/html/extensions.html @@ -2,7 +2,7 @@ - + Python extensions for XPath and XSLT
-

Python extensions for XPath and XSLT

+

Python extensions for XPath and XSLT

This document describes how to use Python extension functions in XPath and XSLT like this:

@@ -77,7 +77,7 @@ the following examples. Any number of arguments is allowed:

is done using the FunctionNamespace class. For simplicity, we choose the empty namespace (None):

>>> from lxml import etree
->>> ns = etree.FunctionNamespace(None)
+>>> ns = etree.FunctionNamespace(None)
 >>> ns['hello'] = hello
 >>> ns['countargs'] = loadsofargs
 
@@ -96,13 +96,13 @@ against:

>>> doc = etree.ElementTree(root)

Done. Now we can have XPath expressions call our new function:

-
>>> print(root.xpath("hello('Dr. Falken')"))
+
>>> print(root.xpath("hello('Dr. Falken')"))
 Hello Dr. Falken
->>> print(root.xpath('hello(local-name(*))'))
+>>> print(root.xpath('hello(local-name(*))'))
 Hello b
->>> print(root.xpath('hello(string(b))'))
+>>> print(root.xpath('hello(string(b))'))
 Hello Haegar
->>> print(root.xpath('countargs(., b, ./*)'))
+>>> print(root.xpath('countargs(., b, ./*)'))
 Got 3 arguments.
 

Note how we call both a Python function (hello()) and an XPath built-in @@ -113,7 +113,7 @@ allows you to do this:

>>> ns['hello'] = hello >>> prefixmap = {'f' : 'http://mydomain.org/myfunctions'} ->>> print(root.xpath('f:hello(local-name(*))', namespaces=prefixmap)) +>>> print(root.xpath('f:hello(local-name(*))', namespaces=prefixmap)) Hello b
@@ -126,7 +126,7 @@ register it with the namespace:

>>> ns.prefix = 'es' >>> ns['hello'] = ola ->>> print(root.xpath('es:hello(local-name(*))')) +>>> print(root.xpath('es:hello(local-name(*))')) Ola b

This is a global assignment, so take care not to assign the same prefix to @@ -145,7 +145,7 @@ was None, but since lxml 2.0 it provides two properties: context_node. The context node is the Element where the current function is called:

>>> def print_tag(context, nodes):
-...     print("%s: %s" % (context.context_node.tag, [ n.tag for n in nodes ]))
+...     print("%s: %s" % (context.context_node.tag, [ n.tag for n in nodes ]))
 
 >>> ns = etree.FunctionNamespace('http://mydomain.org/printtag')
 >>> ns.prefix = "pt"
@@ -159,7 +159,7 @@ is called:

allows functions to keep state:

>>> def print_context(context):
 ...     context.eval_context[context.context_node.tag] = "done"
-...     print(sorted(context.eval_context.items()))
+...     print(sorted(context.eval_context.items()))
 >>> ns["print_context"] = print_context
 
 >>> ignore = root.xpath("//*[pt:print_context()]")
@@ -172,12 +172,12 @@ allows functions to keep state:

Extension functions work for all ways of evaluating XPath expressions and for XSL transformations:

>>> e = etree.XPathEvaluator(doc)
->>> print(e('es:hello(local-name(/a))'))
+>>> print(e('es:hello(local-name(/a))'))
 Ola a
 
 >>> namespaces = {'f' : 'http://mydomain.org/myfunctions'}
 >>> e = etree.XPathEvaluator(doc, namespaces=namespaces)
->>> print(e('f:hello(local-name(/a))'))
+>>> print(e('f:hello(local-name(/a))'))
 Hello a
 
 >>> xslt = etree.XSLT(etree.XML('''
@@ -190,7 +190,7 @@ XSL transformations:

... </template> ... </stylesheet> ... ''')) ->>> print(xslt(doc)) +>>> print(xslt(doc)) Ola Haegar

It is also possible to register namespaces with a single evaluator after its @@ -228,7 +228,7 @@ The value is a dictionary mapping (namespace, name) tuples to functions:

>>> namespaces = {'l' : 'local-ns'} >>> e = etree.XPathEvaluator(doc, namespaces=namespaces, extensions=extensions) ->>> print(e('l:local-hello(string(b))')) +>>> print(e('l:local-hello(string(b))')) Hello Haegar

For larger numbers of extension functions, you can define classes or modules @@ -246,7 +246,7 @@ and use the Extension helper:

>>> extensions = etree.Extension( ext_module, functions, ns='local-ns' ) >>> e = etree.XPathEvaluator(doc, namespaces=namespaces, extensions=extensions) ->>> print(e('l:function1(string(b))')) +>>> print(e('l:function1(string(b))')) 1Haegar

The optional second argument to Extension can either be a @@ -260,17 +260,17 @@ examples will therefore all do the same thing:

>>> functions = ('function1', 'function2', 'function3')
 >>> extensions = etree.Extension( ext_module, functions )
 >>> e = etree.XPathEvaluator(doc, extensions=extensions)
->>> print(e('function1(function2(function3(string(b))))'))
+>>> print(e('function1(function2(function3(string(b))))'))
 123Haegar
 
->>> extensions = etree.Extension( ext_module, functions, ns=None )
+>>> extensions = etree.Extension( ext_module, functions, ns=None )
 >>> e = etree.XPathEvaluator(doc, extensions=extensions)
->>> print(e('function1(function2(function3(string(b))))'))
+>>> print(e('function1(function2(function3(string(b))))'))
 123Haegar
 
 >>> extensions = etree.Extension(ext_module)
 >>> e = etree.XPathEvaluator(doc, extensions=extensions)
->>> print(e('function1(function2(function3(string(b))))'))
+>>> print(e('function1(function2(function3(string(b))))'))
 123Haegar
 
 >>> functions = {
@@ -280,7 +280,7 @@ examples will therefore all do the same thing:

... } >>> extensions = etree.Extension(ext_module, functions) >>> e = etree.XPathEvaluator(doc, extensions=extensions) ->>> print(e('function1(function2(function3(string(b))))')) +>>> print(e('function1(function2(function3(string(b))))')) 123Haegar

For convenience, you can also pass a sequence of extensions:

@@ -288,7 +288,7 @@ examples will therefore all do the same thing:

>>> extensions2 = etree.Extension(ext_module, ns='local-ns') >>> e = etree.XPathEvaluator(doc, extensions=[extensions1, extensions2], ... namespaces=namespaces) ->>> print(e('function1(l:function2(function3(string(b))))')) +>>> print(e('function1(l:function2(function3(string(b))))')) 123Haegar @@ -303,11 +303,11 @@ will also be returned as floats:

>>> def returnsInteger(_): ... return 1 >>> def returnsBool(_): -... return True +... return True >>> def returnFirstNode(_, nodes): ... return nodes[0] ->>> ns = etree.FunctionNamespace(None) +>>> ns = etree.FunctionNamespace(None) >>> ns['float'] = returnsFloat >>> ns['int'] = returnsInteger >>> ns['bool'] = returnsBool @@ -345,13 +345,13 @@ XPath node-sets:

>>> e = etree.XPathEvaluator(doc) >>> r = e("new-node-set()/result") ->>> print([ t.text for t in r ]) +>>> print([ t.text for t in r ]) ['Alpha', 'Beta', 'Gamma', 'Delta'] >>> r = e("new-node-set()") ->>> print([ t.tag for t in r ]) +>>> print([ t.tag for t in r ]) ['results1', 'results2', 'subresult'] ->>> print([ len(t) for t in r ]) +>>> print([ len(t) for t in r ]) [2, 3, 0] >>> r[0][0].text 'Alpha' @@ -370,13 +370,13 @@ Only the elements and their children are passed on, no outlying parents or tail texts will be available in the result. This also means that in the above example, the subresult elements in results2 and results3 are no longer identical within the node-set, they belong to independent trees:

-
>>> print("%s - %s" % (r[1][-1].tag, r[2].tag))
+
>>> print("%s - %s" % (r[1][-1].tag, r[2].tag))
 subresult - subresult
->>> print(r[1][-1] == r[2])
+>>> print(r[1][-1] == r[2])
 False
->>> print(r[1][-1].getparent().tag)
+>>> print(r[1][-1].getparent().tag)
 results2
->>> print(r[2].getparent())
+>>> print(r[2].getparent())
 None
 

This is an implementation detail that you should be aware of, but you should @@ -399,7 +399,7 @@ code like this:

And then you can implement the element in Python like this:

>>> class MyExtElement(etree.XSLTExtension):
 ...     def execute(self, context, self_node, input_node, output_parent):
-...         print("Hello from XSLT!")
+...         print("Hello from XSLT!")
 ...         output_parent.text = "I did it!"
 ...         # just copy own content input to output
 ...         output_parent.extend( list(self_node) )
@@ -530,7 +530,7 @@ will work:

diff --git a/doc/html/flattr-badge-large.png b/doc/html/flattr-badge-large.png deleted file mode 100644 index 1105305850621343d54022dd422415ddf1f659e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1639 zcmV-t2AKJYP)t_els_}nNMyeFqp|I+&`C*Q)S_473%8C!<642`wf;WpUb9?&s{RBQi9P}iuC*<{RE8g)9KOwr* zeUgCwig=9xJ+fpsgS9-;Gw3PWLx`<&`^S!{ai!P)%~2{B1Qpr-r!^>F0@{&yy#W2( zC0DkMEYi#*^tXaBr};wMSH8i-6SXMxJ7ZVpq1U=e`e=&9A_wMMAt2ipXDb{f?~75p zA|USvdKHUJI;hZCBemfO>U%DV*6_>OE;*NwOLjO>U~RG<;Y*>r6K@cphZpYRpwC?o z!HmjW+;yAr@{t;B&ah9i_>7gfE5eLA+6b9#-JYU@g@9QuBE$EHHZ`2D4ou zLi}Pxjq=W2C~mV`5_)puuZU6amNZpmSJINXu*(kc&fJD0NfyjOMRqKoQ0WaKmJ2D~ z!No^Yw%~Z46^*%?Ug=vwRoD~*{~SwX8=#-KXd~32?TjWbP}TOPv-?6zcMARFK9=je zr^e8;yC&C3`0~(C=Q(lE-{pVFJku4!;<-m%m@3`^{fmBFe^7utoei}p^xGpXNUA@G zXqBs^8Q{*OC39H~ff#u{fDfu@O=bCos_V_*;x|*1ZN&aORW{6r45uv~Lr35K5DHMvg0mxq2T$AN?XCf%HQx+~R) z^VKM*x(D--skNdOh2A%O1qpQr5T$gLG}T2-G!7?hrWSGv0-d(o?SLRs9S_cO1(#5$MCu z228G#@a3TgXZ^_S>67v1%v0^D^YPn9LSN_oJS5j!GK=ZvP%{#0e?er`E=hkRA*bj_ zWbFurGyE=C;%M@>h$!+D#*luYEf!N{H2O-^6>6|?!o9|r8%NdBSBc;p7x-jtr#bed zUmt8XxlY2Dhki1{o&zuuY0f;=l8Pr2_XyyfLSNJEWW=ezrxyQ}aacDGz0yU>hD9YT znG49YLwkQU#*JG7&C`CNEfzEA4L*OTE*mG@YmB*ZifgfWH~kt^-2)ng7Tcq-HxGRe zTTHH#@a3TgrtRRimlvVt7>~5T=v@`$HTH;9eg|ED4jTHBXq!2%)*fQIJ#rNZH3xA{ z;UZ}&MSH@Mxu-8j&^b_pxaxgKR2~Bn&C`CN&Bp?C$-0#tiL@<1W_`w(n@eD>HNwlC zkl)Pqc6Lp!_CmfU%;Y)=UmkiuimeEA3k=^;AxdS3(-m7qt>}&f5qE6RH>5*+wI?FV zoh5Df(&Tc5ni!#7P#=Xuv0p>kk-_57OFL2B&9*$2Kap$0#q-d8CF`augW#REjg2D` z`i!x0erHM?P}QCe?<6aP7wiYs1+70yb#ZjdF}Y5{mxu0`WW)VM`tX(tVU@NxS++&g zm#>{;XEnU^=zY)xxpF_kFFQ+`0oI*alp7oW6XUNRv$pnTf$`Hb+{!-Q*&2VuR_$eD zsMI}aTuhZ*dt|A)^tFW7q~nN$J|Q;FkLK7Hvq5xTtiNZlUYM(t311$%Z-Og{mN~7OnDFJH{}FHfoE~`1&dp#s)b~(_xGGPaEp=M)4l8zqPrU7G?ij#FZg>88 zh8-w)A_9Nfu-)kY-GSH8Rmdwn5mw@~qJ6r^5tM77+`XAQ@CuJTxz<qoN$>h<83Fu9Wj&==)>+1|1j>LP2Jy!k6-ecgoiTfu8Yp?`+C)OMG lo{g*iWN$F=Tq6KC_%D-CKj~#=%!>d3002ovPDHLkV1i<{B$EID diff --git a/doc/html/html5parser.html b/doc/html/html5parser.html index f610bdc..d705b6c 100644 --- a/doc/html/html5parser.html +++ b/doc/html/html5parser.html @@ -2,7 +2,7 @@ - + html5lib Parser
-

html5lib Parser

+

html5lib Parser

html5lib is a Python package that implements the HTML5 parsing algorithm which is heavily influenced by current browsers and based on the WHATWG @@ -90,7 +90,7 @@ module. Note that these are the parser classes provided by html5lib.

diff --git a/doc/html/index.html b/doc/html/index.html index 11c0d50..0757387 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -2,7 +2,7 @@ - + lxml - Processing XML and HTML with Python @@ -26,7 +26,7 @@ function hide_menu() {
-

lxml - XML and HTML with Python

+

lxml - XML and HTML with Python

@@ -66,11 +66,15 @@ Thank you for your support.

Support lxml through GitHub Sponsors

via a Tidelift subscription

or via PayPal:

-

Donate to the lxml project

+

Donate to the lxml project

Please contact Stefan Behnel for other ways to support the lxml project, as well as commercial consulting, customisations and trainings on lxml and fast Python XML processing.

+

Note that we are not accepting donations in crypto currencies. +Much of the development and hosting for lxml is done in a carbon-neutral way +or with compensated and very low emissions. +Crypto currencies do not fit into that ambition.

Travis-CI and AppVeyor support the lxml project with their build and CI servers. Jetbrains supports the lxml project by donating free licenses of their @@ -81,7 +85,7 @@ Another supporter of the lxml project is

Documentation

-

The complete lxml documentation is available for download as PDF +

The complete lxml documentation is available for download as PDF documentation. The HTML documentation from this web site is part of the normal source download.

Project income report

    +
  • Total project income in 2020: EUR 6065,86 (506.49 € / month)
      +
    • Tidelift: EUR 4064.77
    • +
    • Paypal: EUR 1401.09
    • +
    • other: EUR 600.00
    • +
    +
  • Total project income in 2019: EUR 717.52 (59.79 € / month)
    • Tidelift: EUR 360.30
    • Paypal: EUR 157.22
    • @@ -260,7 +271,7 @@ donation is non-refundable.

diff --git a/doc/html/installation.html b/doc/html/installation.html index c9f80a1..d1673c0 100644 --- a/doc/html/installation.html +++ b/doc/html/installation.html @@ -2,7 +2,7 @@ - + Installing lxml
-

Installing lxml

+

Installing lxml

Contents

@@ -208,7 +208,7 @@ read the
diff --git a/doc/html/intro.html b/doc/html/intro.html index 790f838..709ae5a 100644 --- a/doc/html/intro.html +++ b/doc/html/intro.html @@ -2,7 +2,7 @@ - + Why lxml?
-

Why lxml?

+

Why lxml?

Contents

@@ -82,7 +82,7 @@ having to learn new things -- XML is complicated enough.

diff --git a/doc/html/lxml-source-howto.html b/doc/html/lxml-source-howto.html index 7345dc0..5407988 100644 --- a/doc/html/lxml-source-howto.html +++ b/doc/html/lxml-source-howto.html @@ -2,7 +2,7 @@ - + How to read the source of lxml @@ -27,7 +27,7 @@ function hide_menu() {
-

How to read the source of lxml

+

How to read the source of lxml

@@ -286,7 +286,7 @@ implemented in pure Python.

diff --git a/doc/html/lxmlhtml.html b/doc/html/lxmlhtml.html index 5c9f700..a38097f 100644 --- a/doc/html/lxmlhtml.html +++ b/doc/html/lxmlhtml.html @@ -2,7 +2,7 @@ - +lxml.html @@ -25,7 +25,7 @@ function hide_menu() {
-

lxml.html

+

lxml.html

@@ -199,13 +199,13 @@ document in a doctest, you can do the following:

... </body></html>... ''') ->>> printlxml.html.tostring(html) +>>> printlxml.html.tostring(html)<html><body onload="" color="white"><p>Hi !</p></body></html> ->>> printlxml.html.tostring(html) +>>> printlxml.html.tostring(html)<html> <body color="white" onload=""> <p>Hi !</p> </body> </html> ->>> printlxml.html.tostring(html) +>>> printlxml.html.tostring(html)<html> <body color="white" onload=""> <p>Hi !</p> @@ -241,7 +241,7 @@ pages and fragments:

... )... ) ->>> printlxml.html.tostring(html) +>>> printlxml.html.tostring(html)<html> <head> <link href="great.css" rel="stylesheet" type="text/css"> @@ -412,7 +412,7 @@ You can, for instance, do:

... name='John Smith',... phone='555-555-3949',... interest=set(['cats','llamas'])) ->>> printtostring(form) +>>> printtostring(form)<html> <body> <form> @@ -493,7 +493,7 @@ content that upsets browsers and tries to run evil code on the client side:

To remove the all suspicious content from this unparsed document, use the clean_html function:

>>> from lxml.html.clean import clean_html
->>> print clean_html(html)
+>>> print clean_html(html)
 <div><style>/* deleted */</style><body>
 
    <a href="">a link</a>
@@ -511,8 +511,8 @@ content that upsets browsers and tries to run evil code on the client side:

which content is removed:

>>> from lxml.html.clean import Cleaner
 
->>> cleaner = Cleaner(page_structure=False, links=False)
->>> print cleaner.clean_html(html)
+>>> cleaner = Cleaner(page_structure=False, links=False)
+>>> print cleaner.clean_html(html)
 <html>
   <head>
     <link rel="alternate" src="evil-rss" type="text/rss">
@@ -531,10 +531,10 @@ which content is removed:

</body> </html> ->>> cleaner = Cleaner(style=True, links=True, add_nofollow=True, -... page_structure=False, safe_attrs_only=False) +>>> cleaner = Cleaner(style=True, links=True, add_nofollow=True, +... page_structure=False, safe_attrs_only=False) ->>> print cleaner.clean_html(html) +>>> print cleaner.clean_html(html) <html> <head> </head> @@ -620,9 +620,9 @@ documents.

>>> doc1 = '''<p>Here is some text.</p>''' >>> doc2 = '''<p>Here is <b>a lot</b> of <i>text</i>.</p>''' >>> doc3 = '''<p>Here is <b>a little</b> <i>text</i>.</p>''' ->>> print htmldiff(doc1, doc2) +>>> print htmldiff(doc1, doc2) <p>Here is <ins><b>a lot</b> of <i>text</i>.</ins> <del>some text.</del> </p> ->>> print html_annotate([(doc1, 'author1'), (doc2, 'author2'), +>>> print html_annotate([(doc1, 'author1'), (doc2, 'author2'), ... (doc3, 'author3')]) <p><span title="author1">Here is</span> <b><span title="author2">a</span> @@ -639,7 +639,7 @@ version. The default version, the output of which you see in the example, looks like:

def default_markup(text, version):
     return '<span title="%s">%s</span>' % (
-        cgi.escape(unicode(version), 1), text)
+        cgi.escape(unicode(version), 1), text)
 
@@ -696,7 +696,7 @@ microformat.

diff --git a/doc/html/objectify.html b/doc/html/objectify.html index f88dc23..14e6412 100644 --- a/doc/html/objectify.html +++ b/doc/html/objectify.html @@ -2,7 +2,7 @@ - + lxml.objectify @@ -25,7 +25,7 @@ function hide_menu() {
-

lxml.objectify

+

lxml.objectify

@@ -100,20 +100,20 @@ behind the usual object attribute access pattern. Asking an element for an attribute will return the sequence of children with corresponding tag names:

>>> root = objectify.Element("root")
 >>> b = objectify.SubElement(root, "b")
->>> print(root.b[0].tag)
+>>> print(root.b[0].tag)
 b
 >>> root.index(root.b[0])
 0
 >>> b = objectify.SubElement(root, "b")
->>> print(root.b[0].tag)
+>>> print(root.b[0].tag)
 b
->>> print(root.b[1].tag)
+>>> print(root.b[1].tag)
 b
 >>> root.index(root.b[1])
 1
 

For convenience, you can omit the index '0' to access the first child:

-
>>> print(root.b.tag)
+
>>> print(root.b.tag)
 b
 >>> root.index(root.b)
 0
@@ -151,11 +151,11 @@ methods for iteration, it supports an optional tag keyword argument:

XML attributes are accessed as in the normal ElementTree API:

>>> c = objectify.SubElement(root, "c", myattr="someval")
->>> print(root.c.get("myattr"))
+>>> print(root.c.get("myattr"))
 someval
 
 >>> root.c.set("c", "oh-oh")
->>> print(root.c.get("c"))
+>>> print(root.c.get("c"))
 oh-oh
 

In addition to the normal ElementTree API for appending elements to trees, @@ -164,9 +164,9 @@ case, the subtree is automatically deep copied and the tag name of its root is updated to match the attribute name:

>>> el = objectify.Element("yet_another_child")
 >>> root.new_child = el
->>> print(root.new_child.tag)
+>>> print(root.new_child.tag)
 new_child
->>> print(el.tag)
+>>> print(el.tag)
 yet_another_child
 
 >>> root.y = [ objectify.Element("y"), objectify.Element("y") ]
@@ -187,22 +187,22 @@ updated to match the attribute name:

>>> subel = objectify.SubElement(el, "sub") >>> root.child = el ->>> print(root.child.sub.tag) +>>> print(root.child.sub.tag) sub >>> root.child[2] = el ->>> print(root.child[2].sub.tag) +>>> print(root.child[2].sub.tag) sub

Note that special care must be taken when changing the tag name of an element:

-
>>> print(root.b.tag)
+
>>> print(root.b.tag)
 b
 >>> root.b.tag = "notB"
 >>> root.b
 Traceback (most recent call last):
   ...
 AttributeError: no such child: b
->>> print(root.notB.tag)
+>>> print(root.notB.tag)
 notB
 
@@ -215,17 +215,17 @@ the module:

>>> fileobject = StringIO('<test/>')
 
 >>> tree = objectify.parse(fileobject)
->>> print(isinstance(tree.getroot(), objectify.ObjectifiedElement))
+>>> print(isinstance(tree.getroot(), objectify.ObjectifiedElement))
 True
 
 >>> root = objectify.fromstring('<test/>')
->>> print(isinstance(root, objectify.ObjectifiedElement))
+>>> print(isinstance(root, objectify.ObjectifiedElement))
 True
 

To build a new tree in memory, objectify replicates the standard factory function Element() from lxml.etree:

>>> obj_el = objectify.Element("new")
->>> print(isinstance(obj_el, objectify.ObjectifiedElement))
+>>> print(isinstance(obj_el, objectify.ObjectifiedElement))
 True
 

After creating such an Element, you can use the usual API of @@ -237,11 +237,11 @@ from their tree. However, all independent elements that you create through the Element() factory of lxml.etree (instead of objectify) will not support the objectify API by themselves:

>>> subel = objectify.SubElement(obj_el, "sub")
->>> print(isinstance(subel, objectify.ObjectifiedElement))
+>>> print(isinstance(subel, objectify.ObjectifiedElement))
 True
 
 >>> independent_el = etree.Element("new")
->>> print(isinstance(independent_el, objectify.ObjectifiedElement))
+>>> print(isinstance(independent_el, objectify.ObjectifiedElement))
 False
 
@@ -252,11 +252,11 @@ will not support the objectify API by themselv >>> root=E.root(... E.a(5),... E.b(6.21), -... E.c(True), +... E.c(True),... E.d("how",tell="me")... ) ->>> print(etree.tostring(root,pretty_print=True)) +>>> print(etree.tostring(root,pretty_print=True))<root xmlns:py="http://codespeak.net/lxml/objectify/pytype"> <a py:pytype="int">5</a> <b py:pytype="float">6.21</b> @@ -274,7 +274,7 @@ will not support the objectify API by themselv ... HOWMANY(5)... ) ->>> print(etree.tostring(root,pretty_print=True)) +>>> print(etree.tostring(root,pretty_print=True))<root xmlns:py="http://codespeak.net/lxml/objectify/pytype"> <title py:pytype="str">The title</title> <how-many py:pytype="int">5</how-many> @@ -284,12 +284,12 @@ will not support the objectify API by themselv creates pytype annotated Elements without a namespace. You can switch off the pytype annotation by passing False to the annotate keyword argument of the constructor. You can also pass a default namespace and an nsmap:

-
>>> myE = objectify.ElementMaker(annotate=False,
-...           namespace="http://my/ns", nsmap={None : "http://my/ns"})
+
>>> myE = objectify.ElementMaker(annotate=False,
+...           namespace="http://my/ns", nsmap={None : "http://my/ns"})
 
 >>> root = myE.root( myE.someint(2) )
 
->>> print(etree.tostring(root, pretty_print=True))
+>>> print(etree.tostring(root, pretty_print=True))
 <root xmlns="http://my/ns">
   <someint>2</someint>
 </root>
@@ -304,7 +304,7 @@ the lookup will use the namespace of the parent:

>>> b = objectify.SubElement(root, "{http://ns/}b") >>> c = objectify.SubElement(root, "{http://other/}c") ->>> print(root.b.tag) +>>> print(root.b.tag) {http://ns/}b

Note that the SubElement() factory of lxml.etree does not @@ -312,10 +312,10 @@ inherit any namespaces when creating a new subelement. Element creation must be explicit about the namespace, and is simplified through the E-factory as described above.

Lookups, however, inherit namespaces implicitly:

-
>>> print(root.b.tag)
+
>>> print(root.b.tag)
 {http://ns/}b
 
->>> print(root.c)
+>>> print(root.c)
 Traceback (most recent call last):
     ...
 AttributeError: no such child: {http://ns/}c
@@ -323,18 +323,18 @@ through the E-factory as described above.

To access an element in a different namespace than its parent, you can use getattr():

>>> c = getattr(root, "{http://other/}c")
->>> print(c.tag)
+>>> print(c.tag)
 {http://other/}c
 

For convenience, there is also a quick way through item access:

>>> c = root["{http://other/}c"]
->>> print(c.tag)
+>>> print(c.tag)
 {http://other/}c
 

The same approach must be used to access children with tag names that are not valid Python identifiers:

>>> el = objectify.SubElement(root, "{http://ns/}tag-name")
->>> print(root["tag-name"].tag)
+>>> print(root["tag-name"].tag)
 {http://ns/}tag-name
 
 >>> new_el = objectify.Element("{http://ns/}new-element")
@@ -343,27 +343,27 @@ valid Python identifiers:

>>> el = objectify.SubElement(new_el, "{http://ns/}child") >>> root["tag-name"] = [ new_el, new_el ] ->>> print(len(root["tag-name"])) +>>> print(len(root["tag-name"])) 2 ->>> print(root["tag-name"].tag) +>>> print(root["tag-name"].tag) {http://ns/}tag-name ->>> print(len(root["tag-name"].child)) +>>> print(len(root["tag-name"].child)) 3 ->>> print(root["tag-name"].child.tag) +>>> print(root["tag-name"].child.tag) {http://ns/}child ->>> print(root["tag-name"][1].child.tag) +>>> print(root["tag-name"][1].child.tag) {http://ns/}child

or for names that have a special meaning in lxml.objectify:

>>> root = objectify.XML("<root><text>TEXT</text></root>")
 
->>> print(root.text.text)
+>>> print(root.text.text)
 Traceback (most recent call last):
   ...
 AttributeError: 'NoneType' object has no attribute 'text'
 
->>> print(root["text"].text)
+>>> print(root["text"].text)
 TEXT
 
@@ -389,7 +389,7 @@ parse the schema from a file-like object (or file or filename):

... </xsd:complexType> ... </xsd:schema> ... ''') ->>> schema = etree.XMLSchema(file=f) +>>> schema = etree.XMLSchema(file=f)

When creating the validating parser, we must make sure it returns objectify trees. This is best done with the makeparser() @@ -400,7 +400,7 @@ function:

>>> xml = "<a><b>test</b></a>"
 >>> a = objectify.fromstring(xml, parser)
 
->>> print(a.b)
+>>> print(a.b)
 test
 

Or an invalid document:

@@ -423,75 +423,75 @@ represented by the ObjectPath class:

>>> d = objectify.SubElement(root, "{http://other/}d") >>> path = objectify.ObjectPath("root.b.c") ->>> print(path) +>>> print(path) root.b.c >>> path.hasattr(root) True ->>> print(path.find(root).tag) +>>> print(path.find(root).tag) {http://ns/}c >>> find = objectify.ObjectPath("root.b.c") ->>> print(find(root).tag) +>>> print(find(root).tag) {http://ns/}c >>> find = objectify.ObjectPath("root.{http://other/}d") ->>> print(find(root).tag) +>>> print(find(root).tag) {http://other/}d ->>> find = objectify.ObjectPath("root.{not}there") ->>> print(find(root).tag) +>>> find = objectify.ObjectPath("root.{not}there") +>>> print(find(root).tag) Traceback (most recent call last): ... AttributeError: no such child: {not}there ->>> find = objectify.ObjectPath("{not}there") ->>> print(find(root).tag) +>>> find = objectify.ObjectPath("{not}there") +>>> print(find(root).tag) Traceback (most recent call last): ... ValueError: root element does not match: need {not}there, got {http://ns/}root >>> find = objectify.ObjectPath("root.b[1]") ->>> print(find(root).tag) +>>> print(find(root).tag) {http://ns/}b >>> find = objectify.ObjectPath("root.{http://ns/}b[1]") ->>> print(find(root).tag) +>>> print(find(root).tag) {http://ns/}b

Apart from strings, ObjectPath also accepts lists of path segments:

>>> find = objectify.ObjectPath(['root', 'b', 'c'])
->>> print(find(root).tag)
+>>> print(find(root).tag)
 {http://ns/}c
 
 >>> find = objectify.ObjectPath(['root', '{http://ns/}b[1]'])
->>> print(find(root).tag)
+>>> print(find(root).tag)
 {http://ns/}b
 

You can also use relative paths starting with a '.' to ignore the actual root element and only inherit its namespace:

>>> find = objectify.ObjectPath(".b[1]")
->>> print(find(root).tag)
+>>> print(find(root).tag)
 {http://ns/}b
 
 >>> find = objectify.ObjectPath(['', 'b[1]'])
->>> print(find(root).tag)
+>>> print(find(root).tag)
 {http://ns/}b
 
 >>> find = objectify.ObjectPath(".unknown[1]")
->>> print(find(root).tag)
+>>> print(find(root).tag)
 Traceback (most recent call last):
   ...
 AttributeError: no such child: {http://ns/}unknown
 
 >>> find = objectify.ObjectPath(".{http://other/}unknown[1]")
->>> print(find(root).tag)
+>>> print(find(root).tag)
 Traceback (most recent call last):
   ...
 AttributeError: no such child: {http://other/}unknown
 

For convenience, a single dot represents the empty ObjectPath (identity):

>>> find = objectify.ObjectPath(".")
->>> print(find(root).tag)
+>>> print(find(root).tag)
 {http://ns/}root
 

ObjectPath objects can be used to manipulate trees:

@@ -508,15 +508,15 @@ element and only inherit its namespace:

>>> path.setattr(root,"my value")# creates children as necessary>>> path.hasattr(root)True ->>> print(path.find(root).text) +>>> print(path.find(root).text)my value ->>> print(root.some.child["{http://other/}unknown"].text) +>>> print(root.some.child["{http://other/}unknown"].text)my value ->>> print(len(path.find(root))) +>>> print(len(path.find(root)))1>>> path.addattr(root,"my new value") ->>> print(len(path.find(root))) +>>> print(len(path.find(root)))2>>> [el.textforelinpath.find(root)]['my value', 'my new value'] @@ -529,7 +529,7 @@ element and only inherit its namespace:

Note, however, that indexing is only supported in this context if the children exist. Indexing of non existing children will not extend or create a list of such children but raise an exception:

-
>>> path = objectify.ObjectPath(".{non}existing[1]")
+
>>> path = objectify.ObjectPath(".{non}existing[1]")
 >>> path.setattr(root, "my value")
 Traceback (most recent call last):
   ...
@@ -549,26 +549,26 @@ operators:

>>> root.a + root.b 16 >>> root.a += root.b ->>> print(root.a) +>>> print(root.a) 16 >>> root.a = 2 ->>> print(root.a + 2) +>>> print(root.a + 2) 4 ->>> print(1 + root.a) +>>> print(1 + root.a) 3 ->>> print(root.c) +>>> print(root.c) True ->>> root.c = False +>>> root.c = False >>> if not root.c: -... print("false!") +... print("false!") false! ->>> print(root.d + " test !") +>>> print(root.d + " test !") hoi test ! >>> root.d = "%s - %s" ->>> print(root.d % (1234, 12345)) +>>> print(root.d % (1234, 12345)) 1234 - 12345

However, data elements continue to provide the objectify API. This means that @@ -576,16 +576,16 @@ sequence operations such as len(), slicing and cannot behave as the Python types. Like all other tree elements, they show the normal slicing behaviour of objectify elements:

>>> root = objectify.fromstring("<root><a>test</a><b>toast</b></root>")
->>> print(root.a + ' me') # behaves like a string, right?
+>>> print(root.a + ' me') # behaves like a string, right?
 test me
 >>> len(root.a) # but there's only one 'a' element!
 1
 >>> [ a.tag for a in root.a ]
 ['a']
->>> print(root.a[0].tag)
+>>> print(root.a[0].tag)
 a
 
->>> print(root.a)
+>>> print(root.a)
 test
 >>> [ str(a) for a in root.a[:1] ]
 ['test']
@@ -618,9 +618,9 @@ to change values, just assign them directly to the attribute:

TypeError: attribute 'pyval' of 'StringElement' objects is not writable >>> root.a = 25 ->>> print(root.a) +>>> print(root.a) 25 ->>> print(root.a.pyval) +>>> print(root.a.pyval) 25

In other words, objectify data elements behave like immutable Python @@ -641,7 +641,7 @@ elements:

... </root> ... """) ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] a = 1 [IntElement] * attr1 = 'foo' @@ -655,24 +655,24 @@ elements:

You can freely switch between different types for the same child:

>>> root = objectify.fromstring("<root><a>5</a></root>")
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = 5 [IntElement]
 
 >>> root.a = 'nice string!'
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = 'nice string!' [StringElement]
       * py:pytype = 'str'
 
->>> root.a = True
->>> print(objectify.dump(root))
+>>> root.a = True
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = True [BoolElement]
       * py:pytype = 'bool'
 
 >>> root.a = [1, 2, 3]
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = 1 [IntElement]
       * py:pytype = 'int'
@@ -682,7 +682,7 @@ elements:

* py:pytype = 'int' >>> root.a = (1, 2, 3) ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] a = 1 [IntElement] * py:pytype = 'int' @@ -710,7 +710,7 @@ objectify elements like this:

... </root> ... """) ->>> print(str(root)) +>>> print(str(root)) root = None [ObjectifiedElement] a = 1 [IntElement] * attr1 = 'foo' @@ -723,7 +723,7 @@ objectify elements like this:

* xsi:nil = 'true'

This behaviour can be switched off in the same way:

-
>>> objectify.enable_recursive_str(False)
+
>>> objectify.enable_recursive_str(False)
 
@@ -759,7 +759,7 @@ classes used in these cases. By default, tree_clas

The "type hint" mechanism deploys an XML attribute defined as lxml.objectify.PYTYPE_ATTRIBUTE. It may contain any of the following string values: int, long, float, str, unicode, NoneType:

-
>>> print(objectify.PYTYPE_ATTRIBUTE)
+
>>> print(objectify.PYTYPE_ATTRIBUTE)
 {http://codespeak.net/lxml/objectify/pytype}pytype
 >>> ns, name = objectify.PYTYPE_ATTRIBUTE[1:].split('}')
 
@@ -771,11 +771,11 @@ string values: int, long, float, str, unicode, NoneType:

... </root> ... """ % ns) ->>> print(root.a + 10) +>>> print(root.a + 10) 510 ->>> print(root.b + 10) +>>> print(root.b + 10) 15 ->>> print(root.c) +>>> print(root.c) None

Note that you can change the name and namespace used for this @@ -784,14 +784,14 @@ function, in case your application ever needs to. There is also a utility function annotate() that recursively generates this attribute for the elements of a tree:

>>> root = objectify.fromstring("<root><a>test</a><b>5</b></root>")
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = 'test' [StringElement]
     b = 5 [IntElement]
 
 >>> objectify.annotate(root)
 
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = 'test' [StringElement]
       * py:pytype = 'str'
@@ -812,7 +812,7 @@ Python types:

... <s xsi:type="xsd:string">5</s> ... </root> ... ''') ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] d = 5.0 [FloatElement] * xsi:type = 'xsd:double' @@ -826,7 +826,7 @@ generates the "xsi:type" attribute for the elements of a tree:

>>> root = objectify.fromstring('''\
 ...    <root><a>test</a><b>5</b><c>true</c></root>
 ...    ''')
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     a = 'test' [StringElement]
     b = 5 [IntElement]
@@ -834,7 +834,7 @@ generates the "xsi:type" attribute for the elements of a tree:

>>> objectify.xsiannotate(root) ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] a = 'test' [StringElement] * xsi:type = 'xsd:string' @@ -856,7 +856,7 @@ and/or 'xsi:type' information:

... <s xsi:type="xsd:string">5</s> ... </root>''') >>> objectify.annotate(root) ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] d = 5.0 [FloatElement] * py:pytype = 'float' @@ -868,7 +868,7 @@ and/or 'xsi:type' information:

* py:pytype = 'str' * xsi:type = 'xsd:string' >>> objectify.deannotate(root) ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] d = 5 [IntElement] i = 5 [IntElement] @@ -887,7 +887,7 @@ arguments 'pytype' (default: True) and 'xsi' (default: True). ... <n xsi:nil="true"/> ... </root>''') >>> objectify.annotate(root) ->>> print(objectify.dump(root)) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] d = 5.0 [FloatElement] * py:pytype = 'float' @@ -901,8 +901,8 @@ arguments 'pytype' (default: True) and 'xsi' (default: True). n = None [NoneElement] * py:pytype = 'NoneType' * xsi:nil = 'true' ->>> objectify.deannotate(root, xsi_nil=True) ->>> print(objectify.dump(root)) +>>> objectify.deannotate(root, xsi_nil=True) +>>> print(objectify.dump(root)) root = None [ObjectifiedElement] d = 5 [IntElement] i = 5 [IntElement] @@ -924,20 +924,20 @@ Python value in one step. You can pass the required Python type name or the XSI type name:

>>> root = objectify.Element("root")
 >>> root.x = objectify.DataElement(5, _pytype="int")
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     x = 5 [IntElement]
       * py:pytype = 'int'
 
 >>> root.x = objectify.DataElement(5, _pytype="str", myattr="someval")
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     x = '5' [StringElement]
       * myattr = 'someval'
       * py:pytype = 'str'
 
 >>> root.x = objectify.DataElement(5, _xsi="integer")
->>> print(objectify.dump(root))
+>>> print(objectify.dump(root))
 root = None [ObjectifiedElement]
     x = 5 [IntElement]
       * py:pytype = 'int'
@@ -948,8 +948,8 @@ tries to correctly prefix the xsi:type attribute value for you:

>>> root = objectify.Element("root")
 >>> root.s = objectify.DataElement(5, _xsi="string")
 
->>> objectify.deannotate(root, xsi=False)
->>> print(etree.tostring(root, pretty_print=True))
+>>> objectify.deannotate(root, xsi=False)
+>>> print(etree.tostring(root, pretty_print=True))
 <root xmlns:py="http://codespeak.net/lxml/objectify/pytype" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <s xsi:type="xsd:string">5</s>
 </root>
@@ -959,12 +959,12 @@ tries to correctly prefix the xsi:type attribute value for you:

>>> namespaces = list(el.nsmap.items()) >>> namespaces.sort() >>> for prefix, namespace in namespaces: -... print("%s - %s" % (prefix, namespace)) +... print("%s - %s" % (prefix, namespace)) py - http://codespeak.net/lxml/objectify/pytype xsd - http://www.w3.org/2001/XMLSchema xsi - http://www.w3.org/2001/XMLSchema-instance ->>> print(el.get("{http://www.w3.org/2001/XMLSchema-instance}type")) +>>> print(el.get("{http://www.w3.org/2001/XMLSchema-instance}type")) xsd:string

While you can set custom namespace prefixes, it is necessary to provide valid @@ -974,12 +974,12 @@ namespace information if you choose to do so:

>>> namespaces = list(el.nsmap.items()) >>> namespaces.sort() >>> for prefix, namespace in namespaces: -... print("%s - %s" % (prefix, namespace)) +... print("%s - %s" % (prefix, namespace)) foo - http://www.w3.org/2001/XMLSchema py - http://codespeak.net/lxml/objectify/pytype xsi - http://www.w3.org/2001/XMLSchema-instance ->>> print(el.get("{http://www.w3.org/2001/XMLSchema-instance}type")) +>>> print(el.get("{http://www.w3.org/2001/XMLSchema-instance}type")) foo:string

Note how lxml chose a default prefix for the XML Schema Instance @@ -990,12 +990,12 @@ namespace. We can override it as in the following example:

>>> namespaces = list(el.nsmap.items()) >>> namespaces.sort() >>> for prefix, namespace in namespaces: -... print("%s - %s" % (prefix, namespace)) +... print("%s - %s" % (prefix, namespace)) foo - http://www.w3.org/2001/XMLSchema myxsi - http://www.w3.org/2001/XMLSchema-instance py - http://codespeak.net/lxml/objectify/pytype ->>> print(el.get("{http://www.w3.org/2001/XMLSchema-instance}type")) +>>> print(el.get("{http://www.w3.org/2001/XMLSchema-instance}type")) foo:string

Care must be taken if different namespace prefixes have been used for the same @@ -1003,15 +1003,15 @@ namespace. Namespace information gets merged to avoid duplicate definitions when adding a new sub-element to a tree, but this mechanism does not adapt the prefixes of attribute values:

>>> root = objectify.fromstring("""<root xmlns:schema="http://www.w3.org/2001/XMLSchema"/>""")
->>> print(etree.tostring(root, pretty_print=True))
+>>> print(etree.tostring(root, pretty_print=True))
 <root xmlns:schema="http://www.w3.org/2001/XMLSchema"/>
 
 >>> s = objectify.DataElement("17", _xsi="string")
->>> print(etree.tostring(s, pretty_print=True))
+>>> print(etree.tostring(s, pretty_print=True))
 <value xmlns:py="http://codespeak.net/lxml/objectify/pytype" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" py:pytype="str" xsi:type="xsd:string">17</value>
 
 >>> root.s = s
->>> print(etree.tostring(root, pretty_print=True))
+>>> print(etree.tostring(root, pretty_print=True))
 <root xmlns:schema="http://www.w3.org/2001/XMLSchema">
   <s xmlns:py="http://codespeak.net/lxml/objectify/pytype" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" py:pytype="str" xsi:type="xsd:string">17</s>
 </root>
@@ -1020,7 +1020,7 @@ prefixes of attribute values:

choose to deviate from the standard prefixes. A convenient way to do this for xsi:type attributes is to use the xsiannotate() utility:

>>> objectify.xsiannotate(root)
->>> print(etree.tostring(root, pretty_print=True))
+>>> print(etree.tostring(root, pretty_print=True))
 <root xmlns:schema="http://www.w3.org/2001/XMLSchema">
   <s xmlns:py="http://codespeak.net/lxml/objectify/pytype" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" py:pytype="str" xsi:type="schema:string">17</s>
 </root>
@@ -1040,7 +1040,7 @@ call should be placed into the element _init()
 

The registration of data classes uses the PyType class:

>>> class ChristmasDate(objectify.ObjectifiedDataElement):
 ...     def call_santa(self):
-...         print("Ho ho ho!")
+...         print("Ho ho ho!")
 
 >>> def checkChristmasDate(date_string):
 ...     if not date_string.startswith('24.12.'):
@@ -1088,7 +1088,7 @@ function defined above:

... <a xsi:type="date">12.24.2000</a> ... </root> ... ''') ->>> print(root.a) +>>> print(root.a) 12.24.2000 >>> root.a.call_santa() Ho ho ho! @@ -1122,10 +1122,10 @@ this alters the document infoset, so if you consider the removed spaces as data in your specific use case, you should go with a normal parser and just set the element class lookup. Most applications, however, will work fine with the following setup:

-
>>> parser = objectify.makeparser(remove_blank_text=True)
+
>>> parser = objectify.makeparser(remove_blank_text=True)
 

What this does internally, is:

-
>>> parser = etree.XMLParser(remove_blank_text=True)
+
>>> parser = etree.XMLParser(remove_blank_text=True)
 
 >>> lookup = objectify.ObjectifyElementClassLookup()
 >>> parser.set_element_class_lookup(lookup)
@@ -1165,7 +1165,7 @@ support any XPath expression.
 
diff --git a/doc/html/parsing.html b/doc/html/parsing.html index b4600bb..8d49b2e 100644 --- a/doc/html/parsing.html +++ b/doc/html/parsing.html @@ -2,7 +2,7 @@ - + Parsing XML and HTML with lxml
-

Parsing XML and HTML with lxml

+

Parsing XML and HTML with lxml

lxml provides a very simple and powerful API for parsing XML and HTML. It supports one-step parsing as well as step-by-step parsing using an @@ -100,7 +100,7 @@ keyword argument:

Parser options

The parsers accept a number of setup options as keyword arguments. The above example is easily extended to clean up namespaces during parsing:

-
>>> parser = etree.XMLParser(ns_clean=True)
+
>>> parser = etree.XMLParser(ns_clean=True)
 >>> tree   = etree.parse(StringIO(xml), parser)
 >>> etree.tostring(tree.getroot())
 b'<a xmlns="test"><b/></a>'
@@ -147,7 +147,7 @@ different IDs if the hash lookup is not used afterwards.
 

Parsers have an error_log property that lists the errors and warnings of the last parser run:

>>> parser = etree.XMLParser()
->>> print(len(parser.error_log))
+>>> print(len(parser.error_log))
 0
 
 >>> tree = etree.XML("<root>\n</b>", parser)  # doctest: +ELLIPSIS
@@ -155,15 +155,15 @@ warnings of the last parser run:

... lxml.etree.XMLSyntaxError: Opening and ending tag mismatch: root line 1 and b, line 2, column 5... ->>> print(len(parser.error_log)) +>>> print(len(parser.error_log)) 1 >>> error = parser.error_log[0] ->>> print(error.message) +>>> print(error.message) Opening and ending tag mismatch: root line 1 and b ->>> print(error.line) +>>> print(error.line) 2 ->>> print(error.column) +>>> print(error.column) 5

Each entry in the log has the following properties:

@@ -201,8 +201,8 @@ this feature.

>>> tree = etree.parse(StringIO(broken_html), parser) >>> result = etree.tostring(tree.getroot(), -... pretty_print=True, method="html") ->>> print(result) +... pretty_print=True, method="html") +>>> print(result) <html> <head> <title>test</title> @@ -215,8 +215,8 @@ this feature.

Lxml has an HTML function, similar to the XML shortcut known from ElementTree:

>>> html = etree.HTML(broken_html)
->>> result = etree.tostring(html, pretty_print=True, method="html")
->>> print(result)
+>>> result = etree.tostring(html, pretty_print=True, method="html")
+>>> print(result)
 <html>
   <head>
     <title>test</title>
@@ -256,21 +256,21 @@ original encoding.  Since lxml 3.5, the doctype references are mutable.

>>> tree = etree.parse(StringIO(xhtml)) >>> docinfo = tree.docinfo ->>> print(docinfo.public_id) +>>> print(docinfo.public_id) -//W3C//DTD XHTML 1.0 Transitional//EN ->>> print(docinfo.system_url) +>>> print(docinfo.system_url) http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd >>> docinfo.doctype == doctype_string True ->>> print(docinfo.xml_version) +>>> print(docinfo.xml_version) 1.0 ->>> print(docinfo.encoding) +>>> print(docinfo.encoding) ascii ->>> docinfo.system_url = None ->>> docinfo.public_id = None ->>> print(etree.tostring(tree)) +>>> docinfo.system_url = None +>>> docinfo.public_id = None +>>> print(etree.tostring(tree)) <!DOCTYPE html> <html><body/></html>
@@ -282,15 +282,15 @@ original encoding. Since lxml 3.5, the doctype references are mutable.

a target object to the parser:

>>> class EchoTarget(object):
 ...     def start(self, tag, attrib):
-...         print("start %s %r" % (tag, dict(attrib)))
+...         print("start %s %r" % (tag, dict(attrib)))
 ...     def end(self, tag):
-...         print("end %s" % tag)
+...         print("end %s" % tag)
 ...     def data(self, data):
-...         print("data %r" % data)
+...         print("data %r" % data)
 ...     def comment(self, text):
-...         print("comment %s" % text)
+...         print("comment %s" % text)
 ...     def close(self):
-...         print("close")
+...         print("close")
 ...         return "closed!"
 
 >>> parser = etree.XMLParser(target = EchoTarget())
@@ -304,7 +304,7 @@ a target object to the parser:

end element close ->>> print(result) +>>> print(result) closed!

It is important for the .close() method to reset the parser target @@ -319,7 +319,7 @@ like:

end element close ->>> print(result) +>>> print(result) closed!

Starting with lxml 2.3, the .close() method will also be called in @@ -350,7 +350,7 @@ that the parser can reuse them afterwards.

lxml.etree.XMLSyntaxError: Opening and ending tag mismatch... >>> for event in parser.target.events: -... print(event) +... print(event) start element {} data u'some' close @@ -366,9 +366,9 @@ object. An example for a parser target that builds a tree is the >>> result = etree.XML("<element>some<!--comment-->text</element>", ... parser) ->>> print(result.tag) +>>> print(result.tag) element ->>> print(result[0].text) +>>> print(result[0].text) comment
@@ -393,9 +393,9 @@ retrieve the root Element of the parse result document, and to unlock the parser:

>>> root = parser.close()
 
->>> print(root.tag)
+>>> print(root.tag)
 root
->>> print(root[0].tag)
+>>> print(root[0].tag)
 a
 

If you do not call close(), the parser will stay locked and @@ -422,7 +422,7 @@ normal error_log and vice versa.

>>> result = parser.close() close ->>> print(result) +>>> print(result) closed!

Again, this prevents the automatic creation of an XML tree and leaves @@ -444,7 +444,7 @@ processed as far as possible in each step.

>>> def print_events(parser): ... for action, element in parser.read_events(): -... print('%s: %s' % (action, element.tag)) +... print('%s: %s' % (action, element.tag)) >>> parser.feed('<root>some text') >>> print_events(parser) @@ -498,11 +498,11 @@ stack and pop the last entry on the 'end-ns' event.

>>> def print_events(events):
 ...     for action, obj in events:
 ...         if action in ('start', 'end'):
-...             print("%s: %s" % (action, obj.tag))
+...             print("%s: %s" % (action, obj.tag))
 ...         elif action == 'start-ns':
-...             print("%s: %s" % (action, obj))
+...             print("%s: %s" % (action, obj))
 ...         else:
-...             print(action)
+...             print(action)
 
 >>> event_types = ("start", "end", "start-ns", "end-ns")
 >>> parser = etree.XMLPullParser(event_types)
@@ -539,15 +539,15 @@ that are no longer needed:

>>> parser.feed('<root><element key="value">text</element>') >>> parser.feed('<element><child /></element>') >>> for action, elem in events: -... print('%s: %d' % (elem.tag, len(elem))) # processing -... elem.clear(keep_tail=True) # delete children +... print('%s: %d' % (elem.tag, len(elem))) # processing +... elem.clear(keep_tail=True) # delete children element: 0 child: 0 element: 1 >>> parser.feed('<empty-element xmlns="http://testns/" /></root>') >>> for action, elem in events: -... print('%s: %d' % (elem.tag, len(elem))) # processing -... elem.clear(keep_tail=True) # delete children +... print('%s: %d' % (elem.tag, len(elem))) # processing +... elem.clear(keep_tail=True) # delete children {http://testns/}empty-element: 0 root: 3 @@ -570,8 +570,8 @@ to save more memory during parsing, you can clean up the preceding siblings of the current element:

>>> for event, element in parser.read_events():
 ...     # ... do something with the element
-...     element.clear(keep_tail=True)   # clean up children
-...     while element.getprevious() is not None:
+...     element.clear(keep_tail=True)   # clean up children
+...     while element.getprevious() is not None:
 ...         del element.getparent()[0]  # clean up preceding siblings
 

The while loop deletes multiple siblings in a row. This is only necessary @@ -594,7 +594,7 @@ specific tag or namespace:

>>> parser.feed('<empty-element xmlns="http://testns/" /></root>') >>> for action, elem in parser.read_events(): -... print("%s: %s" % (action, elem.tag)) +... print("%s: %s" % (action, elem.tag)) end: element end: element @@ -606,7 +606,7 @@ specific tag or namespace:

>>> parser.feed('<empty-element xmlns="http://testns/" /></root>') >>> for action, elem in parser.read_events(): -... print("%s: %s" % (action, elem.tag)) +... print("%s: %s" % (action, elem.tag)) start: {http://testns/}empty-element end: {http://testns/}empty-element
@@ -628,11 +628,11 @@ XML structures.

>>> for action, elem in parser.read_events(): ... if action in ('start', 'end'): -... print("%s: %s" % (action, elem.tag)) +... print("%s: %s" % (action, elem.tag)) ... elif action == 'pi': -... print("%s: -%s=%s-" % (action, elem.target, elem.text)) +... print("%s: -%s=%s-" % (action, elem.target, elem.text)) ... else: # 'comment' -... print("%s: -%s-" % (action, elem.text)) +... print("%s: -%s-" % (action, elem.text)) pi: -some=pi - comment: - a comment - start: root @@ -646,7 +646,7 @@ XML structures.

end: root >>> root = parser.close() ->>> print(root.tag) +>>> print(root.tag) root
@@ -658,13 +658,13 @@ it returns from its .start() and
>>> class Target(object):
 ...     def start(self, tag, attrib):
-...         print('-> start(%s)' % tag)
+...         print('-> start(%s)' % tag)
 ...         return '>>START: %s<<' % tag
 ...     def end(self, tag):
-...         print('-> end(%s)' % tag)
+...         print('-> end(%s)' % tag)
 ...         return '>>END: %s<<' % tag
 ...     def close(self):
-...         print('-> close()')
+...         print('-> close()')
 ...         return "CLOSED!"
 
 >>> event_types = ('start', 'end')
@@ -679,7 +679,7 @@ by the pull parser as the second item of the parse events tuple.

-> end(root) >>> for action, value in parser.read_events(): -... print('%s: %s' % (action, value)) +... print('%s: %s' % (action, value)) start: >>START: root<< start: >>START: child1<< end: >>END: child1<< @@ -687,7 +687,7 @@ by the pull parser as the second item of the parse events tuple.

end: >>END: child2<< end: >>END: root<< ->>> print(parser.close()) +>>> print(parser.close()) -> close() CLOSED!
@@ -711,7 +711,7 @@ filters attributes before they are being added to the tree:

>>> parser.feed('<root><child1 test="123" /><child2 evil="YES" /></root>') >>> for action, element in parser.read_events(): -... print('%s: %s(%r)' % (action, element.tag, element.attrib)) +... print('%s: %s(%r)' % (action, element.tag, element.attrib)) end: child1({'test': '123'}) end: child2({}) end: root({}) @@ -738,7 +738,7 @@ single iterator for them:

>>> context = etree.iterparse(StringIO(xml)) >>> for action, elem in context: -... print("%s: %s" % (action, elem.tag)) +... print("%s: %s" % (action, elem.tag)) end: element end: element end: {http://testns/}empty-element @@ -753,7 +753,7 @@ of the iterator:

>>> events = ("start", "end")
 >>> context = etree.iterparse(StringIO(xml), events=events)
 >>> for action, elem in context:
-...     print("%s: %s" % (action, elem.tag))
+...     print("%s: %s" % (action, elem.tag))
 start: root
 start: element
 end: element
@@ -777,7 +777,7 @@ ElementTrees.  Here is an example for a tree parsed by ...             f, events=("start", "end"), tag="element")
 
 >>> for action, elem in context:
-...     print("%s: %s" % (action, elem.tag))
+...     print("%s: %s" % (action, elem.tag))
 start: element
 end: element
 start: element
@@ -792,7 +792,7 @@ input again:

... root, events=("start", "end"), tag="element") >>> for action, elem in context: -... print("%s: %s" % (action, elem.tag)) +... print("%s: %s" % (action, elem.tag)) start: element end: element start: element @@ -811,7 +811,7 @@ iterator can be instructed to skip over an entire subtree with its >>> context = etree.iterwalk(root, events=("start", "end")) >>> for action, elem in context: -... print("%s: %s" % (action, elem.tag)) +... print("%s: %s" % (action, elem.tag)) ... if action == 'start' and elem.tag == 'a': ... context.skip_subtree() # ignore <b> start: root @@ -854,7 +854,7 @@ number of other byte encodings if asked for:

>>> etree.tostring(root)
 b'<test> &#63697; + &#63698; </test>'
 
->>> etree.tostring(root, encoding='UTF-8', xml_declaration=False)
+>>> etree.tostring(root, encoding='UTF-8', xml_declaration=False)
 b'<test> \xef\xa3\x91 + \xef\xa3\x92 </test>'
 

As an extension, lxml.etree recognises the name 'unicode' as an argument @@ -893,7 +893,7 @@ with UTF-8 is also considerably faster in most cases.

diff --git a/doc/html/performance.html b/doc/html/performance.html index 28f5456..5b66f92 100644 --- a/doc/html/performance.html +++ b/doc/html/performance.html @@ -2,7 +2,7 @@ - + Benchmarks and Speed @@ -27,7 +27,7 @@ function hide_menu() {
-

Benchmarks and Speed

+

Benchmarks and Speed

@@ -109,18 +109,11 @@ benchmarking suite for all ElementTree implementations. New benchmarks are very easy to add as tiny test methods, so if you write a performance test for a specific part of the API yourself, please consider sending it to the lxml mailing list.

-

The timings presented below compare lxml 3.1.1 (with libxml2 2.9.0) to the +

The timings presented below compare lxml 4.6.3 (with libxml2 2.9.10) to the latest released versions of ElementTree (with cElementTree as accelerator -module) in the standard library of CPython 3.3.0. They were run -single-threaded on a 2.9GHz 64bit double core Intel i7 machine under -Ubuntu Linux 12.10 (Quantal). The C libraries were compiled with the -same platform specific optimisation flags. The Python interpreter was -also manually compiled for the platform. Note that many of the following -ElementTree timings are therefore better than what a normal Python -installation with the standard library (c)ElementTree modules would yield. -Note also that CPython 2.7 and 3.2+ come with a newer ElementTree version, -so older Python installations will not perform as good for (c)ElementTree, -and sometimes substantially worse.

+module) in the standard library of CPython 3.8.10. They were run +single-threaded on a 2.3GHz 64bit double core Intel i5 machine under +Ubuntu Linux 20.04 (Focal).

The scripts run a number of simple tests on the different libraries, using different XML tree configurations: different tree sizes (T1-4), with or without attributes (-/A), with or without ASCII string or unicode text @@ -153,50 +146,50 @@ is native to libxml2. While 20 to 40 times faster than (c)ElementTree lxml is still more than 10 times as fast as the much improved ElementTree 1.3 in recent Python versions:

-lxe: tostring_utf16  (S-TR T1)    7.9958 msec/pass
-cET: tostring_utf16  (S-TR T1)   83.1358 msec/pass
+lxe: tostring_utf16  (S-TR T1)    5.9340 msec/pass
+cET: tostring_utf16  (S-TR T1)   38.3270 msec/pass
 
-lxe: tostring_utf16  (UATR T1)    8.3222 msec/pass
-cET: tostring_utf16  (UATR T1)   84.4688 msec/pass
+lxe: tostring_utf16  (UATR T1)    6.2032 msec/pass
+cET: tostring_utf16  (UATR T1)   37.7944 msec/pass
 
-lxe: tostring_utf16  (S-TR T2)    8.2297 msec/pass
-cET: tostring_utf16  (S-TR T2)   87.3415 msec/pass
+lxe: tostring_utf16  (S-TR T2)    6.1841 msec/pass
+cET: tostring_utf16  (S-TR T2)   40.2577 msec/pass
 
-lxe: tostring_utf8   (S-TR T2)    6.5677 msec/pass
-cET: tostring_utf8   (S-TR T2)   76.2064 msec/pass
+lxe: tostring_utf8   (S-TR T2)    4.6697 msec/pass
+cET: tostring_utf8   (S-TR T2)   30.5173 msec/pass
 
-lxe: tostring_utf8   (U-TR T3)    1.1952 msec/pass
-cET: tostring_utf8   (U-TR T3)   22.0058 msec/pass
+lxe: tostring_utf8   (U-TR T3)    1.2085 msec/pass
+cET: tostring_utf8   (U-TR T3)   9.0246 msec/pass
 

The difference is somewhat smaller for plain text serialisation:

-lxe: tostring_text_ascii     (S-TR T1)    2.7738 msec/pass
-cET: tostring_text_ascii     (S-TR T1)    4.7629 msec/pass
+lxe: tostring_text_ascii     (S-TR T1)    2.6727 msec/pass
+cET: tostring_text_ascii     (S-TR T1)    2.9683 msec/pass
 
-lxe: tostring_text_ascii     (S-TR T3)    0.8273 msec/pass
-cET: tostring_text_ascii     (S-TR T3)    1.5273 msec/pass
+lxe: tostring_text_ascii     (S-TR T3)    0.6952 msec/pass
+cET: tostring_text_ascii     (S-TR T3)    1.0073 msec/pass
 
-lxe: tostring_text_utf16     (S-TR T1)    2.7659 msec/pass
-cET: tostring_text_utf16     (S-TR T1)   10.5038 msec/pass
+lxe: tostring_text_utf16     (S-TR T1)    2.7366 msec/pass
+cET: tostring_text_utf16     (S-TR T1)   7.3647 msec/pass
 
-lxe: tostring_text_utf16     (U-TR T1)    2.8017 msec/pass
-cET: tostring_text_utf16     (U-TR T1)   10.5207 msec/pass
+lxe: tostring_text_utf16     (U-TR T1)    3.0322 msec/pass
+cET: tostring_text_utf16     (U-TR T1)   7.5922 msec/pass
 

The tostring() function also supports serialisation to a Python unicode string object, which is currently faster in ElementTree -under CPython 3.3:

+under CPython 3.8:

-lxe: tostring_text_unicode   (S-TR T1)    2.6896 msec/pass
-cET: tostring_text_unicode   (S-TR T1)    1.0056 msec/pass
+lxe: tostring_text_unicode   (S-TR T1)    2.7645 msec/pass
+cET: tostring_text_unicode   (S-TR T1)    1.1806 msec/pass
 
-lxe: tostring_text_unicode   (U-TR T1)    2.7366 msec/pass
-cET: tostring_text_unicode   (U-TR T1)    1.0154 msec/pass
+lxe: tostring_text_unicode   (U-TR T1)    2.9871 msec/pass
+cET: tostring_text_unicode   (U-TR T1)    1.1659 msec/pass
 
-lxe: tostring_text_unicode   (S-TR T3)    0.7997 msec/pass
-cET: tostring_text_unicode   (S-TR T3)    0.3154 msec/pass
+lxe: tostring_text_unicode   (S-TR T3)    0.7446 msec/pass
+cET: tostring_text_unicode   (S-TR T3)    0.4532 msec/pass
 
 lxe: tostring_text_unicode   (U-TR T4)    0.0048 msec/pass
-cET: tostring_text_unicode   (U-TR T4)    0.0160 msec/pass
+cET: tostring_text_unicode   (U-TR T4)    0.0134 msec/pass
 

For parsing, lxml.etree and cElementTree compete for the medal. Depending on the input, either of the two can be faster. The (c)ET @@ -204,80 +197,79 @@ libraries use a very thin layer on top of the expat parser, which is known to be very fast. Here are some timings from the benchmarking suite:

-lxe: parse_bytesIO   (SAXR T1)   13.0246 msec/pass
-cET: parse_bytesIO   (SAXR T1)    8.2929 msec/pass
+lxe: parse_bytesIO   (SAXR T1)   14.2074 msec/pass
+cET: parse_bytesIO   (SAXR T1)    7.9336 msec/pass
 
-lxe: parse_bytesIO   (S-XR T3)    1.3542 msec/pass
-cET: parse_bytesIO   (S-XR T3)    2.4023 msec/pass
+lxe: parse_bytesIO   (S-XR T3)    1.4477 msec/pass
+cET: parse_bytesIO   (S-XR T3)    2.1925 msec/pass
 
-lxe: parse_bytesIO   (UAXR T3)    7.5610 msec/pass
-cET: parse_bytesIO   (UAXR T3)   11.2455 msec/pass
+lxe: parse_bytesIO   (UAXR T3)    8.4128 msec/pass
+cET: parse_bytesIO   (UAXR T3)   12.2926 msec/pass
 

And another couple of timings from a benchmark that Fredrik Lundh used to promote cElementTree, comparing a number of different parsers. First, parsing a 274KB XML file containing Shakespeare's Hamlet:

-xml.etree.ElementTree.parse done in 0.017 seconds
+xml.etree.ElementTree.parse done in 0.006 seconds
 xml.etree.cElementTree.parse done in 0.007 seconds
-xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.007 seconds
-lxml.etree.parse done in 0.003 seconds
-drop_whitespace.parse done in 0.003 seconds
+xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.006 seconds
+lxml.etree.parse done in 0.004 seconds
+drop_whitespace.parse done in 0.004 seconds
 lxml.etree.XMLParser.feed(): 6636 nodes read in 0.004 seconds
-minidom tree read in 0.080 seconds
+minidom tree read in 0.066 seconds
 

And a 3.4MB XML file containing the Old Testament:

-xml.etree.ElementTree.parse done in 0.038 seconds
-xml.etree.cElementTree.parse done in 0.030 seconds
-xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.030 seconds
-lxml.etree.parse done in 0.016 seconds
-drop_whitespace.parse done in 0.015 seconds
-lxml.etree.XMLParser.feed(): 25317 nodes read in 0.022 seconds
-minidom tree read in 0.288 seconds
+xml.etree.ElementTree.parse done in 0.037 seconds
+xml.etree.cElementTree.parse done in 0.036 seconds
+xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.036 seconds
+lxml.etree.parse done in 0.025 seconds
+drop_whitespace.parse done in 0.022 seconds
+lxml.etree.XMLParser.feed(): 25317 nodes read in 0.026 seconds
+minidom tree read in 0.194 seconds
 

Here are the same benchmarks again, but including the memory usage of the process in KB before and after parsing (using os.fork() to make sure we start from a clean state each time). For the 274KB hamlet.xml file:

-Memory usage: 7284
-xml.etree.ElementTree.parse done in 0.017 seconds
-Memory usage: 9432 (+2148)
+Memory usage: 9256
+xml.etree.ElementTree.parse done in 0.006 seconds
+Memory usage: 12764 (+3508)
 xml.etree.cElementTree.parse done in 0.007 seconds
-Memory usage: 9432 (+2152)
-xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.007 seconds
-Memory usage: 9448 (+2164)
-lxml.etree.parse done in 0.003 seconds
-Memory usage: 11032 (+3748)
-drop_whitespace.parse done in 0.003 seconds
-Memory usage: 10224 (+2940)
+Memory usage: 12764 (+3508)
+xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.006 seconds
+Memory usage: 12720 (+3464)
+lxml.etree.parse done in 0.004 seconds
+Memory usage: 15052 (+5796)
+drop_whitespace.parse done in 0.004 seconds
+Memory usage: 14040 (+4784)
 lxml.etree.XMLParser.feed(): 6636 nodes read in 0.004 seconds
-Memory usage: 11804 (+4520)
-minidom tree read in 0.080 seconds
-Memory usage: 12324 (+5040)
+Memory usage: 15812 (+6556)
+minidom tree read in 0.066 seconds
+Memory usage: 15332 (+6076)
 

And for the 3.4MB Old Testament XML file:

-Memory usage: 10420
-xml.etree.ElementTree.parse done in 0.038 seconds
-Memory usage: 20660 (+10240)
-xml.etree.cElementTree.parse done in 0.030 seconds
-Memory usage: 20660 (+10240)
-xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.030 seconds
-Memory usage: 20844 (+10424)
-lxml.etree.parse done in 0.016 seconds
-Memory usage: 27624 (+17204)
-drop_whitespace.parse done in 0.015 seconds
-Memory usage: 24468 (+14052)
-lxml.etree.XMLParser.feed(): 25317 nodes read in 0.022 seconds
-Memory usage: 29844 (+19424)
-minidom tree read in 0.288 seconds
-Memory usage: 28788 (+18368)
+Memory usage: 12456
+xml.etree.ElementTree.parse done in 0.037 seconds
+Memory usage: 23288 (+10832)
+xml.etree.cElementTree.parse done in 0.036 seconds
+Memory usage: 23288 (+10832)
+xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.036 seconds
+Memory usage: 23644 (+11220)
+lxml.etree.parse done in 0.025 seconds
+Memory usage: 31404 (+18948)
+drop_whitespace.parse done in 0.022 seconds
+Memory usage: 28752 (+16296)
+lxml.etree.XMLParser.feed(): 25317 nodes read in 0.026 seconds
+Memory usage: 33924 (+21500)
+minidom tree read in 0.194 seconds
+Memory usage: 31284 (+18828)
 

As can be seen from the sizes, both lxml.etree and cElementTree are -rather memory friendly compared to the pure Python libraries -ElementTree and (especially) minidom. Comparing to older CPython +rather memory friendly and fast. Comparing to older CPython versions, the memory footprint of the minidom library was considerably reduced in CPython 3.3, by about a factor of 4 in this case.

For plain parser performance, lxml.etree and cElementTree tend to stay @@ -285,26 +277,26 @@ rather close to each other, usually within a factor of two, with winners well distributed over both sides. Similar timings can be observed for the iterparse() function:

-lxe: iterparse_bytesIO   (SAXR T1)   17.9198 msec/pass
-cET: iterparse_bytesIO   (SAXR T1)   14.4982 msec/pass
+lxe: iterparse_bytesIO   (SAXR T1)   20.3598 msec/pass
+cET: iterparse_bytesIO   (SAXR T1)   10.8948 msec/pass
 
-lxe: iterparse_bytesIO   (UAXR T3)    8.8522 msec/pass
-cET: iterparse_bytesIO   (UAXR T3)   12.9857 msec/pass
+lxe: iterparse_bytesIO   (UAXR T3)    10.1640 msec/pass
+cET: iterparse_bytesIO   (UAXR T3)   12.9926 msec/pass
 

However, if you benchmark the complete round-trip of a serialise-parse cycle, the numbers will look similar to these:

-lxe: write_utf8_parse_bytesIO   (S-TR T1)   19.8867 msec/pass
-cET: write_utf8_parse_bytesIO   (S-TR T1)   80.7259 msec/pass
+lxe: write_utf8_parse_bytesIO   (S-TR T1)   18.9857 msec/pass
+cET: write_utf8_parse_bytesIO   (S-TR T1)   35.7475 msec/pass
 
-lxe: write_utf8_parse_bytesIO   (UATR T2)   23.7896 msec/pass
-cET: write_utf8_parse_bytesIO   (UATR T2)   98.0766 msec/pass
+lxe: write_utf8_parse_bytesIO   (UATR T2)   22.4853 msec/pass
+cET: write_utf8_parse_bytesIO   (UATR T2)   42.6254 msec/pass
 
-lxe: write_utf8_parse_bytesIO   (S-TR T3)    3.0684 msec/pass
-cET: write_utf8_parse_bytesIO   (S-TR T3)   24.6122 msec/pass
+lxe: write_utf8_parse_bytesIO   (S-TR T3)    3.3801 msec/pass
+cET: write_utf8_parse_bytesIO   (S-TR T3)   11.2493 msec/pass
 
-lxe: write_utf8_parse_bytesIO   (SATR T4)    0.3495 msec/pass
-cET: write_utf8_parse_bytesIO   (SATR T4)    1.9610 msec/pass
+lxe: write_utf8_parse_bytesIO   (SATR T4)    0.4263 msec/pass
+cET: write_utf8_parse_bytesIO   (SATR T4)    1.0326 msec/pass
 

For applications that require a high parser throughput of large files, and that do little to no serialization, both cET and lxml.etree are a @@ -346,14 +338,14 @@ restructuring. This can be seen from the tree setup times of the benchmark (given in seconds):

 lxe:       --     S-     U-     -A     SA     UA
-     T1: 0.0299 0.0343 0.0344 0.0293 0.0345 0.0342
-     T2: 0.0368 0.0423 0.0418 0.0427 0.0474 0.0459
-     T3: 0.0088 0.0084 0.0086 0.0251 0.0258 0.0261
-     T4: 0.0002 0.0002 0.0002 0.0005 0.0006 0.0006
+     T1: 0.0219 0.0254 0.0257 0.0216 0.0259 0.0259
+     T2: 0.0234 0.0279 0.0283 0.0271 0.0318 0.0307
+     T3: 0.0051 0.0050 0.0058 0.0218 0.0233 0.0231
+     T4: 0.0001 0.0001 0.0001 0.0004 0.0004 0.0004
 cET:       --     S-     U-     -A     SA     UA
-     T1: 0.0050 0.0045 0.0093 0.0044 0.0043 0.0043
-     T2: 0.0073 0.0075 0.0074 0.0201 0.0075 0.0074
-     T3: 0.0033 0.0213 0.0032 0.0034 0.0033 0.0035
+     T1: 0.0035 0.0029 0.0078 0.0031 0.0031 0.0029
+     T2: 0.0047 0.0051 0.0053 0.0046 0.0055 0.0048
+     T3: 0.0016 0.0216 0.0027 0.0021 0.0023 0.0026
      T4: 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
 

The timings are somewhat close to each other, although cET can be @@ -370,30 +362,30 @@ the overhead in creating them.

a shallow copy of their list of children, lxml has to create a Python object for each child and collect them in a list:

-lxe: root_list_children        (--TR T1)    0.0038 msec/pass
-cET: root_list_children        (--TR T1)    0.0010 msec/pass
+lxe: root_list_children        (--TR T1)    0.0036 msec/pass
+cET: root_list_children        (--TR T1)    0.0005 msec/pass
 
-lxe: root_list_children        (--TR T2)    0.0455 msec/pass
-cET: root_list_children        (--TR T2)    0.0050 msec/pass
+lxe: root_list_children        (--TR T2)    0.0634 msec/pass
+cET: root_list_children        (--TR T2)    0.0086 msec/pass
 

This handicap is also visible when accessing single children:

-lxe: first_child               (--TR T2)    0.0424 msec/pass
-cET: first_child               (--TR T2)    0.0384 msec/pass
+lxe: first_child               (--TR T2)    0.0601 msec/pass
+cET: first_child               (--TR T2)    0.0548 msec/pass
 
-lxe: last_child                (--TR T1)    0.0477 msec/pass
-cET: last_child                (--TR T1)    0.0467 msec/pass
+lxe: last_child                (--TR T1)    0.0570 msec/pass
+cET: last_child                (--TR T1)    0.0534 msec/pass
 

... unless you also add the time to find a child index in a bigger list. ET and cET use Python lists here, which are based on arrays. The data structure used by libxml2 is a linked tree, and thus, a linked list of children:

-lxe: middle_child              (--TR T1)    0.0710 msec/pass
-cET: middle_child              (--TR T1)    0.0420 msec/pass
+lxe: middle_child              (--TR T1)    0.0892 msec/pass
+cET: middle_child              (--TR T1)    0.0510 msec/pass
 
-lxe: middle_child              (--TR T2)    1.7393 msec/pass
-cET: middle_child              (--TR T2)    0.0396 msec/pass
+lxe: middle_child              (--TR T2)    2.3038 msec/pass
+cET: middle_child              (--TR T2)    0.0508 msec/pass
 
@@ -402,18 +394,18 @@ cET: middle_child (--TR T2) 0.0396 msec/pass in. This results in a major performance difference for creating independent Elements that end up in independently created documents:

-lxe: create_elements           (--TC T2)    1.0045 msec/pass
-cET: create_elements           (--TC T2)    0.0753 msec/pass
+lxe: create_elements           (--TC T2)    0.8032 msec/pass
+cET: create_elements           (--TC T2)    0.0675 msec/pass
 

Therefore, it is always preferable to create Elements for the document they are supposed to end up in, either as SubElements of an Element or using the explicit Element.makeelement() call:

-lxe: makeelement               (--TC T2)    1.0586 msec/pass
-cET: makeelement               (--TC T2)    0.1483 msec/pass
+lxe: makeelement               (--TC T2)    0.8030 msec/pass
+cET: makeelement               (--TC T2)    0.0625 msec/pass
 
-lxe: create_subelements        (--TC T2)    0.8826 msec/pass
-cET: create_subelements        (--TC T2)    0.0827 msec/pass
+lxe: create_subelements        (--TC T2)    0.8621 msec/pass
+cET: create_subelements        (--TC T2)    0.0923 msec/pass
 

So, if the main performance bottleneck of an application is creating large XML trees in memory through calls to Element and SubElement, cET is the best @@ -427,11 +419,11 @@ requires lxml to do recursive adaptations throughout the moved tree structure.The following benchmark appends all root children of the second tree to the root of the first tree:

-lxe: append_from_document      (--TR T1,T2)    1.0812 msec/pass
-cET: append_from_document      (--TR T1,T2)    0.1104 msec/pass
+lxe: append_from_document      (--TR T1,T2)    1.3800 msec/pass
+cET: append_from_document      (--TR T1,T2)    0.0513 msec/pass
 
-lxe: append_from_document      (--TR T3,T4)    0.0155 msec/pass
-cET: append_from_document      (--TR T3,T4)    0.0060 msec/pass
+lxe: append_from_document      (--TR T3,T4)    0.0150 msec/pass
+cET: append_from_document      (--TR T3,T4)    0.0026 msec/pass
 

Although these are fairly small numbers compared to parsing, this easily shows the different performance classes for lxml and (c)ET. Where the latter do not @@ -441,19 +433,19 @@ with the size of the tree that is moved.

This difference is not always as visible, but applies to most parts of the API, like inserting newly created elements:

-lxe: insert_from_document         (--TR T1,T2)    3.9763 msec/pass
-cET: insert_from_document         (--TR T1,T2)    0.1459 msec/pass
+lxe: insert_from_document         (--TR T1,T2)    5.2345 msec/pass
+cET: insert_from_document         (--TR T1,T2)    0.0732 msec/pass
 

or replacing the child slice by a newly created element:

-lxe: replace_children_element   (--TC T1)    0.0749 msec/pass
-cET: replace_children_element   (--TC T1)    0.0081 msec/pass
+lxe: replace_children_element   (--TC T1)    0.0720 msec/pass
+cET: replace_children_element   (--TC T1)    0.0105 msec/pass
 

as opposed to replacing the slice with an existing element from the same document:

-lxe: replace_children           (--TC T1)    0.0052 msec/pass
-cET: replace_children           (--TC T1)    0.0036 msec/pass
+lxe: replace_children           (--TC T1)    0.0060 msec/pass
+cET: replace_children           (--TC T1)    0.0050 msec/pass
 

While these numbers are too small to provide a major performance impact in practice, you should keep this difference in mind when you @@ -465,14 +457,14 @@ thus avoiding the merge overhead when inserting it into that tree.

deepcopy

Deep copying a tree is fast in lxml:

-lxe: deepcopy_all              (--TR T1)    3.1650 msec/pass
-cET: deepcopy_all              (--TR T1)   53.9973 msec/pass
+lxe: deepcopy_all              (--TR T1)    4.1246 msec/pass
+cET: deepcopy_all              (--TR T1)   2.5451 msec/pass
 
-lxe: deepcopy_all              (-ATR T2)    3.7365 msec/pass
-cET: deepcopy_all              (-ATR T2)   61.6267 msec/pass
+lxe: deepcopy_all              (-ATR T2)    4.7867 msec/pass
+cET: deepcopy_all              (-ATR T2)   2.7504 msec/pass
 
-lxe: deepcopy_all              (S-TR T3)    0.7913 msec/pass
-cET: deepcopy_all              (S-TR T3)   13.6220 msec/pass
+lxe: deepcopy_all              (S-TR T3)    1.0097 msec/pass
+cET: deepcopy_all              (S-TR T3)   0.6278 msec/pass
 

So, for example, if you have a database-like scenario where you parse in a large tree and then search and copy independent subtrees from it for further @@ -486,31 +478,31 @@ traversal of the XML tree and especially if few elements are of interest or the target element tag name is known, the .iter() method is a good choice:

-lxe: iter_all             (--TR T1)    1.0529 msec/pass
-cET: iter_all             (--TR T1)    0.2635 msec/pass
+lxe: iter_all             (--TR T1)    1.3661 msec/pass
+cET: iter_all             (--TR T1)    0.2670 msec/pass
 
-lxe: iter_islice          (--TR T2)    0.0110 msec/pass
-cET: iter_islice          (--TR T2)    0.0050 msec/pass
+lxe: iter_islice          (--TR T2)    0.0122 msec/pass
+cET: iter_islice          (--TR T2)    0.0033 msec/pass
 
-lxe: iter_tag             (--TR T2)    0.0079 msec/pass
-cET: iter_tag             (--TR T2)    0.0112 msec/pass
+lxe: iter_tag             (--TR T2)    0.0098 msec/pass
+cET: iter_tag             (--TR T2)    0.0086 msec/pass
 
-lxe: iter_tag_all         (--TR T2)    0.1822 msec/pass
-cET: iter_tag_all         (--TR T2)    0.5343 msec/pass
+lxe: iter_tag_all         (--TR T2)    0.6840 msec/pass
+cET: iter_tag_all         (--TR T2)    0.4323 msec/pass
 

This translates directly into similar timings for Element.findall():

-lxe: findall              (--TR T2)    1.7176 msec/pass
-cET: findall              (--TR T2)    0.9973 msec/pass
+lxe: findall              (--TR T2)    3.9611 msec/pass
+cET: findall              (--TR T2)    0.9227 msec/pass
 
-lxe: findall              (--TR T3)    0.3967 msec/pass
-cET: findall              (--TR T3)    0.2525 msec/pass
+lxe: findall              (--TR T3)    0.3989 msec/pass
+cET: findall              (--TR T3)    0.2670 msec/pass
 
-lxe: findall_tag          (--TR T2)    0.2258 msec/pass
-cET: findall_tag          (--TR T2)    0.5770 msec/pass
+lxe: findall_tag          (--TR T2)    0.7420 msec/pass
+cET: findall_tag          (--TR T2)    0.4942 msec/pass
 
-lxe: findall_tag          (--TR T3)    0.1085 msec/pass
-cET: findall_tag          (--TR T3)    0.1919 msec/pass
+lxe: findall_tag          (--TR T3)    0.1099 msec/pass
+cET: findall_tag          (--TR T3)    0.1748 msec/pass
 

Note that all three libraries currently use the same Python implementation for .findall(), except for their native tree @@ -528,38 +520,38 @@ provides more than one way of accessing it and you should take care which part of the lxml API you use. The most straight forward way is to call the xpath() method on an Element or ElementTree:

-lxe: xpath_method         (--TC T1)    0.3982 msec/pass
-lxe: xpath_method         (--TC T2)    7.8895 msec/pass
-lxe: xpath_method         (--TC T3)    0.0477 msec/pass
-lxe: xpath_method         (--TC T4)    0.3982 msec/pass
+lxe: xpath_method         (--TC T1)    0.2828 msec/pass
+lxe: xpath_method         (--TC T2)    5.4705 msec/pass
+lxe: xpath_method         (--TC T3)    0.0324 msec/pass
+lxe: xpath_method         (--TC T4)    0.2804 msec/pass
 

This is well suited for testing and when the XPath expressions are as diverse as the trees they are called on. However, if you have a single XPath expression that you want to apply to a larger number of different elements, the XPath class is the most efficient way to do it:

-lxe: xpath_class          (--TC T1)    0.0713 msec/pass
-lxe: xpath_class          (--TC T2)    1.1325 msec/pass
-lxe: xpath_class          (--TC T3)    0.0215 msec/pass
-lxe: xpath_class          (--TC T4)    0.0722 msec/pass
+lxe: xpath_class          (--TC T1)    0.0570 msec/pass
+lxe: xpath_class          (--TC T2)    0.6924 msec/pass
+lxe: xpath_class          (--TC T3)    0.0148 msec/pass
+lxe: xpath_class          (--TC T4)    0.0446 msec/pass
 

Note that this still allows you to use variables in the expression, so you can parse it once and then adapt it through variables at call time. In other cases, where you have a fixed Element or ElementTree and want to run different expressions on it, you should consider the XPathEvaluator:

-lxe: xpath_element        (--TR T1)    0.1101 msec/pass
-lxe: xpath_element        (--TR T2)    2.0473 msec/pass
-lxe: xpath_element        (--TR T3)    0.0267 msec/pass
-lxe: xpath_element        (--TR T4)    0.1087 msec/pass
+lxe: xpath_element        (--TR T1)    0.0684 msec/pass
+lxe: xpath_element        (--TR T2)    1.0865 msec/pass
+lxe: xpath_element        (--TR T3)    0.0174 msec/pass
+lxe: xpath_element        (--TR T4)    0.0665 msec/pass
 

While it looks slightly slower, creating an XPath object for each of the expressions generates a much higher overhead here:

-lxe: xpath_class_repeat           (--TC T1   )    0.3884 msec/pass
-lxe: xpath_class_repeat           (--TC T2   )    7.6182 msec/pass
-lxe: xpath_class_repeat           (--TC T3   )    0.0465 msec/pass
-lxe: xpath_class_repeat           (--TC T4   )    0.3877 msec/pass
+lxe: xpath_class_repeat           (--TC T1   )    0.2813 msec/pass
+lxe: xpath_class_repeat           (--TC T2   )    5.4042 msec/pass
+lxe: xpath_class_repeat           (--TC T3   )    0.0339 msec/pass
+lxe: xpath_class_repeat           (--TC T4   )    0.2706 msec/pass
 

Note that tree iteration can be substantially faster than XPath if your code short-circuits after the first couple of elements were @@ -568,25 +560,25 @@ regardless of how much of it will actually be used.

Here is an example where only the first matching element is being searched, a case for which XPath has syntax support as well:

-lxe: find_single                (--TR T2)    0.0184 msec/pass
-cET: find_single                (--TR T2)    0.0052 msec/pass
+lxe: find_single                (--TR T2)    0.0031 msec/pass
+cET: find_single                (--TR T2)    0.0026 msec/pass
 
-lxe: iter_single                (--TR T2)    0.0024 msec/pass
-cET: iter_single                (--TR T2)    0.0007 msec/pass
+lxe: iter_single                (--TR T2)    0.0019 msec/pass
+cET: iter_single                (--TR T2)    0.0002 msec/pass
 
-lxe: xpath_single               (--TR T2)    0.0033 msec/pass
+lxe: xpath_single               (--TR T2)    0.0861 msec/pass
 

When looking for the first two elements out of many, the numbers explode for XPath, as restricting the result subset requires a more complex expression:

-lxe: iterfind_two               (--TR T2)    0.0184 msec/pass
-cET: iterfind_two               (--TR T2)    0.0062 msec/pass
+lxe: iterfind_two               (--TR T2)    0.0050 msec/pass
+cET: iterfind_two               (--TR T2)    0.0036 msec/pass
 
-lxe: iter_two                   (--TR T2)    0.0029 msec/pass
-cET: iter_two                   (--TR T2)    0.0017 msec/pass
+lxe: iter_two                   (--TR T2)    0.0021 msec/pass
+cET: iter_two                   (--TR T2)    0.0014 msec/pass
 
-lxe: xpath_two                  (--TR T2)    0.2768 msec/pass
+lxe: xpath_two                  (--TR T2)    0.0916 msec/pass
 
@@ -718,21 +710,21 @@ instantiated over and over again.

tree. It avoids step-by-step Python element instantiations along the path, which can substantially improve the access time:

-lxe: attribute                  (--TR T1)    4.1828 msec/pass
-lxe: attribute                  (--TR T2)   17.3802 msec/pass
-lxe: attribute                  (--TR T4)    3.8657 msec/pass
+lxe: attribute                  (--TR T1)    2.4018 msec/pass
+lxe: attribute                  (--TR T2)   16.3755 msec/pass
+lxe: attribute                  (--TR T4)    2.3725 msec/pass
 
-lxe: objectpath                 (--TR T1)    0.9289 msec/pass
-lxe: objectpath                 (--TR T2)   13.3109 msec/pass
-lxe: objectpath                 (--TR T4)    0.9289 msec/pass
+lxe: objectpath                 (--TR T1)    1.1816 msec/pass
+lxe: objectpath                 (--TR T2)   14.4675 msec/pass
+lxe: objectpath                 (--TR T4)    1.2276 msec/pass
 
-lxe: attributes_deep            (--TR T1)    6.2900 msec/pass
-lxe: attributes_deep            (--TR T2)   20.4713 msec/pass
-lxe: attributes_deep            (--TR T4)    6.1679 msec/pass
+lxe: attributes_deep            (--TR T1)    3.7086 msec/pass
+lxe: attributes_deep            (--TR T2)   17.5436 msec/pass
+lxe: attributes_deep            (--TR T4)    3.8407 msec/pass
 
-lxe: objectpath_deep            (--TR T1)    1.3049 msec/pass
-lxe: objectpath_deep            (--TR T2)   14.0815 msec/pass
-lxe: objectpath_deep            (--TR T4)    1.3051 msec/pass
+lxe: objectpath_deep            (--TR T1)    1.4980 msec/pass
+lxe: objectpath_deep            (--TR T2)   14.7266 msec/pass
+lxe: objectpath_deep            (--TR T4)    1.4834 msec/pass
 

Note, however, that parsing ObjectPath expressions is not for free either, so this is most effective for frequently accessing the same element.

@@ -754,17 +746,17 @@ expressions to be more selective. By choosing the right trees (or even subtrees and elements) to cache, you can trade memory usage against access speed:

-lxe: attribute_cached           (--TR T1)    3.1357 msec/pass
-lxe: attribute_cached           (--TR T2)   15.8911 msec/pass
-lxe: attribute_cached           (--TR T4)    2.9194 msec/pass
+lxe: attribute_cached           (--TR T1)    1.9207 msec/pass
+lxe: attribute_cached           (--TR T2)   15.6903 msec/pass
+lxe: attribute_cached           (--TR T4)    1.8718 msec/pass
 
-lxe: attributes_deep_cached     (--TR T1)    3.8984 msec/pass
-lxe: attributes_deep_cached     (--TR T2)   16.8300 msec/pass
-lxe: attributes_deep_cached     (--TR T4)    3.6936 msec/pass
+lxe: attributes_deep_cached     (--TR T1)    2.6512 msec/pass
+lxe: attributes_deep_cached     (--TR T2)   16.7937 msec/pass
+lxe: attributes_deep_cached     (--TR T4)    2.5539 msec/pass
 
-lxe: objectpath_deep_cached     (--TR T1)    0.7496 msec/pass
-lxe: objectpath_deep_cached     (--TR T2)   12.3763 msec/pass
-lxe: objectpath_deep_cached     (--TR T4)    0.7427 msec/pass
+lxe: objectpath_deep_cached     (--TR T1)    0.8519 msec/pass
+lxe: objectpath_deep_cached     (--TR T2)   13.9337 msec/pass
+lxe: objectpath_deep_cached     (--TR T4)    0.8645 msec/pass
 

Things to note: you cannot currently use weakref.WeakKeyDictionary objects for this as lxml's element objects do not support weak references (which are @@ -798,7 +790,7 @@ random.

diff --git a/doc/html/resolvers.html b/doc/html/resolvers.html index 5fa07be..64d7b61 100644 --- a/doc/html/resolvers.html +++ b/doc/html/resolvers.html @@ -2,7 +2,7 @@ - + Document loading and URL resolving
-

Document loading and URL resolving

+

Document loading and URL resolving

@@ -83,7 +83,7 @@ registered resolver (or the default resolver) is consulted. Resolving always terminates if resolve() returns the result of any of the above resolve_*() methods.

Resolvers are registered local to a parser:

-
>>> parser = etree.XMLParser(load_dtd=True)
+
>>> parser = etree.XMLParser(load_dtd=True)
 >>> parser.resolvers.add( DTDResolver() )
 

Note that we instantiate a parser that loads the DTD. This is not done by the @@ -93,7 +93,7 @@ document that requires resolving a URL, it will call our custom resolver:

>>> tree = etree.parse(StringIO(xml), parser) Resolving URL 'MissingDTD.dtd' >>> root = tree.getroot() ->>> print(root.text) +>>> print(root.text) [resolved text: MissingDTD.dtd]

The entity in the document was correctly resolved by the generated DTD @@ -116,7 +116,7 @@ resolver that only responds to a specific prefix:

... ''' % prefix ... def resolve(self, url, pubid, context): ... if url.startswith(self.prefix): -... print("Resolved url %s as prefix %s" % (url, self.prefix)) +... print("Resolved url %s as prefix %s" % (url, self.prefix)) ... return self.resolve_string(self.result_xml, context)

We demonstrate this in XSLT and use the following stylesheet as an example:

@@ -189,7 +189,7 @@ needs to resolve the hoi URI in the call to th
>>> honk_parser.resolvers.add( PrefixResolver("hoi") )
 >>> result = transform(honk_doc)
 Resolved url hoi:test as prefix hoi
->>> print(str(result)[:-1])
+>>> print(str(result)[:-1])
 <?xml version="1.0"?>
 <test>hoi-TEST</test>
 
@@ -199,7 +199,7 @@ that this is completely independent of the XML file you transform, as the URI is resolved from within the stylesheet context:

>>> result = transform(normal_doc)
 Resolved url hoi:test as prefix hoi
->>> print(str(result)[:-1])
+>>> print(str(result)[:-1])
 <?xml version="1.0"?>
 <test>hoi-TEST</test>
 
@@ -227,7 +227,7 @@ operations:

>>> result = transform(normal_doc) Resolved url hoi:test as prefix hoi ->>> ac = etree.XSLTAccessControl(read_network=False) +>>> ac = etree.XSLTAccessControl(read_network=False) >>> transform = etree.XSLT(honk_doc, access_control=ac) Resolved url honk:test as prefix honk >>> result = transform(normal_doc) @@ -250,7 +250,7 @@ documents or raises exceptions if access is denied. diff --git a/doc/html/sax.html b/doc/html/sax.html index 4103192..b0c1b82 100644 --- a/doc/html/sax.html +++ b/doc/html/sax.html @@ -2,7 +2,7 @@ - + Sax support
-

Sax support

+

Sax support

In this document we'll describe lxml's SAX support. lxml has support for producing SAX events for an ElementTree or Element. lxml can also turn SAX @@ -48,11 +48,11 @@ do this, we use the special SAX content handler defined by lxml named >>> handler = lxml.sax.ElementTreeContentHandler()

Now let's fire some SAX events at it:

-
>>> handler.startElementNS((None, 'a'), 'a', {})
->>> handler.startElementNS((None, 'b'), 'b', {(None, 'foo'): 'bar'})
+
>>> handler.startElementNS((None, 'a'), 'a', {})
+>>> handler.startElementNS((None, 'b'), 'b', {(None, 'foo'): 'bar'})
 >>> handler.characters('Hello world')
->>> handler.endElementNS((None, 'b'), 'b')
->>> handler.endElementNS((None, 'a'), 'a')
+>>> handler.endElementNS((None, 'b'), 'b')
+>>> handler.endElementNS((None, 'a'), 'a')
 

This constructs an equivalent tree. You can access it through the etree property of the handler:

@@ -77,7 +77,7 @@ content handler.:

... def __init__(self): ... self.a_amount = 0 ... self.b_amount = 0 -... self.text = None +... self.text = None ... ... def startElementNS(self, name, qname, attributes): ... uri, localname = name @@ -117,14 +117,14 @@ DOM implementation cannot generate SAX events from a DOM tree.

PullDOM makes the result available through the document attribute:

>>> dom = handler.document
->>> print(dom.firstChild.localName)
+>>> print(dom.firstChild.localName)
 a
 
diff --git a/doc/html/sitemap.html b/doc/html/sitemap.html index 88cc342..13c1125 100644 --- a/doc/html/sitemap.html +++ b/doc/html/sitemap.html @@ -8,5 +8,5 @@

Sitemap of lxml.de - Processing XML and HTML with Python

-
+
\ No newline at end of file diff --git a/doc/html/style.css b/doc/html/style.css index 4cc454a..7d1b0e6 100644 --- a/doc/html/style.css +++ b/doc/html/style.css @@ -164,7 +164,7 @@ div.banner { border: 2px solid darkred; color: darkgreen; line-height: 1em; - margin: 1ex; + margin: 3ex 1ex 1ex; padding: 3pt; } @@ -321,6 +321,18 @@ html > .pagequote { position: fixed; } +div.admonition { + border: solid 1px; + border-radius: 1ex; + margin: 0.5ex; + padding: 0.5ex 1.5ex 0.5ex 1.5ex; + background: lightyellow; +} + +div.admonition > .admonition-title { + background: yellow; +} + code { color: Black; background-color: #f0f0f0; diff --git a/doc/html/tutorial.html b/doc/html/tutorial.html index 0be5f45..f659e40 100644 --- a/doc/html/tutorial.html +++ b/doc/html/tutorial.html @@ -2,7 +2,7 @@ - + The lxml.etree Tutorial @@ -27,7 +27,7 @@ function hide_menu() {
-

The lxml.etree Tutorial

+

The lxml.etree Tutorial

@@ -76,29 +76,29 @@ functionality that is specific to lxml.etree, of) the following import chain as a fall-back to the original ElementTree:

try:
   from lxml import etree
-  print("running with lxml.etree")
+  print("running with lxml.etree")
 except ImportError:
   try:
     # Python 2.5
-    import xml.etree.cElementTree as etree
-    print("running with cElementTree on Python 2.5+")
+    import xml.etree.cElementTree as etree
+    print("running with cElementTree on Python 2.5+")
   except ImportError:
     try:
       # Python 2.5
-      import xml.etree.ElementTree as etree
-      print("running with ElementTree on Python 2.5+")
+      import xml.etree.ElementTree as etree
+      print("running with ElementTree on Python 2.5+")
     except ImportError:
       try:
         # normal cElementTree install
-        import cElementTree as etree
-        print("running with cElementTree")
+        import cElementTree as etree
+        print("running with cElementTree")
       except ImportError:
         try:
           # normal ElementTree install
-          import elementtree.ElementTree as etree
-          print("running with ElementTree")
+          import elementtree.ElementTree as etree
+          print("running with ElementTree")
         except ImportError:
-          print("Failed to import ElementTree from any known place")
+          print("Failed to import ElementTree from any known place")
 

To aid in writing portable code, this tutorial makes it clear in the examples which part of the presented API is an extension of lxml.etree over the @@ -112,7 +112,7 @@ easily created through the Element factory:

>>> root = etree.Element("root")
 

The XML tag name of elements is accessed through the tag property:

-
>>> print(root.tag)
+
>>> print(root.tag)
 root
 

Elements are organised in an XML tree structure. To create child elements and @@ -126,7 +126,7 @@ to do this: the SubElement factory. It accept >>> child3 = etree.SubElement(root, "child3")

To see that this is really XML, you can serialise the tree you have created:

-
>>> print(etree.tostring(root, pretty_print=True))
+
>>> print(etree.tostring(root, pretty_print=True))
 <root>
   <child1/>
   <child2/>
@@ -139,10 +139,10 @@ to do this: the SubElement factory.  It accept
 elements mimic the behaviour of normal Python lists as closely as
 possible:

>>> child = root[0]
->>> print(child.tag)
+>>> print(child.tag)
 child1
 
->>> print(len(root))
+>>> print(len(root))
 3
 
 >>> root.index(root[1]) # lxml.etree only!
@@ -151,7 +151,7 @@ possible:

>>> children = list(root) >>> for child in root: -... print(child.tag) +... print(child.tag) child1 child2 child3 @@ -160,39 +160,39 @@ possible:

>>> start = root[:1] >>> end = root[-1:] ->>> print(start[0].tag) +>>> print(start[0].tag) child0 ->>> print(end[0].tag) +>>> print(end[0].tag) child3

Prior to ElementTree 1.3 and lxml 2.0, you could also check the truth value of an Element to see if it has children, i.e. if the list of children is empty:

if root:   # this no longer works!
-    print("The root element has children")
+    print("The root element has children")
 

This is no longer supported as people tend to expect that a "something" evaluates to True and expect Elements to be "something", may they have children or not. So, many users find it surprising that any Element would evaluate to False in an if-statement like the above. Instead, use len(element), which is both more explicit and less error prone.

-
>>> print(etree.iselement(root))  # test if it's some kind of Element
+
>>> print(etree.iselement(root))  # test if it's some kind of Element
 True
 >>> if len(root):                 # test if it has children
-...     print("The root element has children")
+...     print("The root element has children")
 The root element has children
 

There is another important case where the behaviour of Elements in lxml (in 2.0 and later) deviates from that of lists and from that of the original ElementTree (prior to version 1.3 or Python 2.7/3.2):

>>> for child in root:
-...     print(child.tag)
+...     print(child.tag)
 child0
 child1
 child2
 child3
 >>> root[0] = root[-1]  # this moves the element in lxml.etree!
 >>> for child in root:
-...     print(child.tag)
+...     print(child.tag)
 child3
 child1
 child2
@@ -227,9 +227,9 @@ from Python's standard library:

>>> element = etree.Element("neu") >>> element.append( deepcopy(root[1]) ) ->>> print(element[0].tag) +>>> print(element[0].tag) child1 ->>> print([ c.tag for c in root ]) +>>> print([ c.tag for c in root ]) ['child3', 'child1', 'child2']

The siblings (or neighbours) of an element are accessed as next and previous @@ -250,13 +250,13 @@ factory:

Attributes are just unordered name-value pairs, so a very convenient way of dealing with them is through the dictionary-like interface of Elements:

-
>>> print(root.get("interesting"))
+
>>> print(root.get("interesting"))
 totally
 
->>> print(root.get("hello"))
+>>> print(root.get("hello"))
 None
 >>> root.set("hello", "Huhu")
->>> print(root.get("hello"))
+>>> print(root.get("hello"))
 Huhu
 
 >>> etree.tostring(root)
@@ -266,7 +266,7 @@ of dealing with them is through the dictionary-like interface of Elements:

['hello', 'interesting'] >>> for name, value in sorted(root.items()): -... print('%s = %r' % (name, value)) +... print('%s = %r' % (name, value)) hello = 'Huhu' interesting = 'totally'
@@ -275,15 +275,15 @@ getting a 'real' dictionary-like object, e.g. for passing it around, you can use the attrib property:

>>> attributes = root.attrib
 
->>> print(attributes["interesting"])
+>>> print(attributes["interesting"])
 totally
->>> print(attributes.get("no-such-attribute"))
+>>> print(attributes.get("no-such-attribute"))
 None
 
 >>> attributes["hello"] = "Guten Tag"
->>> print(attributes["hello"])
+>>> print(attributes["hello"])
 Guten Tag
->>> print(root.get("hello"))
+>>> print(root.get("hello"))
 Guten Tag
 

Note that attrib is a dict-like object backed by the Element itself. @@ -303,7 +303,7 @@ tree, copy it into a dict:

>>> root = etree.Element("root")
 >>> root.text = "TEXT"
 
->>> print(root.text)
+>>> print(root.text)
 TEXT
 
 >>> etree.tostring(root)
@@ -347,7 +347,7 @@ still want the tail text of its children).  For this purpose, the
 tostring() function accepts the keyword argument with_tail:

>>> etree.tostring(br)
 b'<br/>TAIL'
->>> etree.tostring(br, with_tail=False) # lxml.etree only!
+>>> etree.tostring(br, with_tail=False) # lxml.etree only!
 b'<br/>'
 

If you want to read only the text, i.e. without any intermediate @@ -362,14 +362,14 @@ comes to the rescue, this time using the methodUsing XPath to find text

Another way to extract the text content of a tree is XPath, which also allows you to extract the separate text chunks into a list:

-
>>> print(html.xpath("string()")) # lxml.etree only!
+
>>> print(html.xpath("string()")) # lxml.etree only!
 TEXTTAIL
->>> print(html.xpath("//text()")) # lxml.etree only!
+>>> print(html.xpath("//text()")) # lxml.etree only!
 ['TEXT', 'TAIL']
 

If you want to use this more often, you can wrap it in a function:

>>> build_text_list = etree.XPath("//text()") # lxml.etree only!
->>> print(build_text_list(html))
+>>> print(build_text_list(html))
 ['TEXT', 'TAIL']
 

Note that a string result returned by XPath is a special 'smart' @@ -377,32 +377,32 @@ object that knows about its origins. You can ask it where it came from through its getparent() method, just as you would with Elements:

>>> texts = build_text_list(html)
->>> print(texts[0])
+>>> print(texts[0])
 TEXT
 >>> parent = texts[0].getparent()
->>> print(parent.tag)
+>>> print(parent.tag)
 body
 
->>> print(texts[1])
+>>> print(texts[1])
 TAIL
->>> print(texts[1].getparent().tag)
+>>> print(texts[1].getparent().tag)
 br
 

You can also find out if it's normal text content or tail text:

-
>>> print(texts[0].is_text)
+
>>> print(texts[0].is_text)
 True
->>> print(texts[1].is_text)
+>>> print(texts[1].is_text)
 False
->>> print(texts[1].is_tail)
+>>> print(texts[1].is_tail)
 True
 

While this works for the results of the text() function, lxml will not tell you the origin of a string value that was constructed by the XPath functions string() or concat():

>>> stringify = etree.XPath("string()")
->>> print(stringify(html))
+>>> print(stringify(html))
 TEXTTAIL
->>> print(stringify(html).getparent())
+>>> print(stringify(html).getparent())
 None
 
@@ -418,7 +418,7 @@ serialised the tree to XML:

>>> etree.SubElement(root, "child").text = "Child 2" >>> etree.SubElement(root, "another").text = "Child 3" ->>> print(etree.tostring(root, pretty_print=True)) +>>> print(etree.tostring(root, pretty_print=True)) <root> <child>Child 1</child> <child>Child 2</child> @@ -426,7 +426,7 @@ serialised the tree to XML:

</root> >>> for element in root.iter(): -... print("%s - %s" % (element.tag, element.text)) +... print("%s - %s" % (element.tag, element.text)) root - None child - Child 1 child - Child 2 @@ -436,12 +436,12 @@ serialised the tree to XML:

iter() to have it filter for you. Starting with lxml 3.0, you can also pass more than one tag to intercept on multiple tags during iteration.

>>> for element in root.iter("child"):
-...     print("%s - %s" % (element.tag, element.text))
+...     print("%s - %s" % (element.tag, element.text))
 child - Child 1
 child - Child 2
 
 >>> for element in root.iter("another", "child"):
-...     print("%s - %s" % (element.tag, element.text))
+...     print("%s - %s" % (element.tag, element.text))
 child - Child 1
 child - Child 2
 another - Child 3
@@ -454,10 +454,10 @@ make sure only Element objects are returned, you can pass the
 >>> root.append(etree.Comment("some comment"))
 
 >>> for element in root.iter():
-...     if isinstance(element.tag, basestring):  # or 'str' in Python 3
-...         print("%s - %s" % (element.tag, element.text))
+...     if isinstance(element.tag, basestring):  # or 'str' in Python 3
+...         print("%s - %s" % (element.tag, element.text))
 ...     else:
-...         print("SPECIAL: %s - %s" % (element, element.text))
+...         print("SPECIAL: %s - %s" % (element, element.text))
 root - None
 child - Child 1
 child - Child 2
@@ -466,14 +466,14 @@ make sure only Element objects are returned, you can pass the
 SPECIAL: <!--some comment--> - some comment
 
 >>> for element in root.iter(tag=etree.Element):
-...     print("%s - %s" % (element.tag, element.text))
+...     print("%s - %s" % (element.tag, element.text))
 root - None
 child - Child 1
 child - Child 2
 another - Child 3
 
 >>> for element in root.iter(tag=etree.Entity):
-...     print(element.text)
+...     print(element.text)
 &#234;
 

Note that passing a wildcard "*" tag name will also yield all @@ -494,15 +494,15 @@ ASCII:

>>> etree.tostring(root) b'<root><a><b/></a></root>' ->>> print(etree.tostring(root, xml_declaration=True)) +>>> print(etree.tostring(root, xml_declaration=True)) <?xml version='1.0' encoding='ASCII'?> <root><a><b/></a></root> ->>> print(etree.tostring(root, encoding='iso-8859-1')) +>>> print(etree.tostring(root, encoding='iso-8859-1')) <?xml version='1.0' encoding='iso-8859-1'?> <root><a><b/></a></root> ->>> print(etree.tostring(root, pretty_print=True)) +>>> print(etree.tostring(root, pretty_print=True)) <root> <a> <b/> @@ -514,12 +514,12 @@ ASCII:

whitespace indentation to the tree before serialising it, using the indent() function (added in lxml 4.5):

>>> root = etree.XML('<root><a><b/>\n</a></root>')
->>> print(etree.tostring(root))
+>>> print(etree.tostring(root))
 <root><a><b/>
 </a></root>
 
 >>> etree.indent(root)
->>> print(etree.tostring(root))
+>>> print(etree.tostring(root))
 <root>
   <a>
     <b/>
@@ -532,7 +532,7 @@ whitespace indentation to the tree before serialising it, using the
 '\n    '
 
 >>> etree.indent(root, space="    ")
->>> print(etree.tostring(root))
+>>> print(etree.tostring(root))
 <root>
     <a>
         <b/>
@@ -558,7 +558,7 @@ HTML or extract the text content by passing the met
 >>> etree.tostring(root, method='html')
 b'<html><head></head><body><p>Hello<br>World</p></body></html>'
 
->>> print(etree.tostring(root, method='html', pretty_print=True))
+>>> print(etree.tostring(root, method='html', pretty_print=True))
 <html>
 <head></head>
 <body><p>Hello<br>World</p></body>
@@ -603,14 +603,14 @@ general document handling.

... ''') >>> tree = etree.ElementTree(root) ->>> print(tree.docinfo.xml_version) +>>> print(tree.docinfo.xml_version) 1.0 ->>> print(tree.docinfo.doctype) +>>> print(tree.docinfo.doctype) <!DOCTYPE root SYSTEM "test"> >>> tree.docinfo.public_id = '-//W3C//DTD XHTML 1.0 Transitional//EN' >>> tree.docinfo.system_url = 'file://local.dtd' ->>> print(tree.docinfo.doctype) +>>> print(tree.docinfo.doctype) <!DOCTYPE root PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "file://local.dtd">

An ElementTree is also what you get back when you call the @@ -620,7 +620,7 @@ parsing section below).

serialises as a complete document, as opposed to a single Element. This includes top-level processing instructions and comments, as well as a DOCTYPE and other DTD content in the document:

-
>>> print(etree.tostring(tree))  # lxml 1.3.4 and later
+
>>> print(etree.tostring(tree))  # lxml 1.3.4 and later
 <!DOCTYPE root PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "file://local.dtd" [
 <!ENTITY tasty "parsnips">
 ]>
@@ -631,7 +631,7 @@ as a DOCTYPE and other DTD content in the document:

In the original xml.etree.ElementTree implementation and in lxml up to 1.3.3, the output looks the same as when serialising only the root Element:

-
>>> print(etree.tostring(tree.getroot()))
+
>>> print(etree.tostring(tree.getroot()))
 <root>
   <a>parsnips</a>
 </root>
@@ -654,7 +654,7 @@ different parser as second argument.

>>> some_xml_data = "<root>data</root>"
 
 >>> root = etree.fromstring(some_xml_data)
->>> print(root.tag)
+>>> print(root.tag)
 root
 >>> etree.tostring(root)
 b'<root>data</root>'
@@ -665,7 +665,7 @@ different parser as second argument.

The XML() function behaves like the fromstring() function, but is commonly used to write XML literals right into the source:

>>> root = etree.XML("<root>data</root>")
->>> print(root.tag)
+>>> print(root.tag)
 root
 >>> etree.tostring(root)
 b'<root>data</root>'
@@ -696,7 +696,7 @@ doing this all together and use the string parsing functions above.

Note that parse() returns an ElementTree object, not an Element object as the string parser functions:

>>> root = tree.getroot()
->>> print(root.tag)
+>>> print(root.tag)
 root
 >>> etree.tostring(root)
 b'<root>data</root>'
@@ -723,7 +723,7 @@ from while the response is streaming in.

Parser objects

By default, lxml.etree uses a standard parser with a default setup. If you want to configure the parser, you can create a new instance:

-
>>> parser = etree.XMLParser(remove_blank_text=True) # lxml.etree only!
+
>>> parser = etree.XMLParser(remove_blank_text=True) # lxml.etree only!
 

This creates a parser that removes empty text between tags while parsing, which can reduce the size of the tree and avoid dangling tail text if you know @@ -737,8 +737,8 @@ that whitespace-only content is not meaningful for your data. An example:

content at leaf elements tends to be data content (even if blank). You can easily remove it in an additional step by traversing the tree:

>>> for element in root.iter("*"):
-...     if element.text is not None and not element.text.strip():
-...         element.text = None
+...     if element.text is not None and not element.text.strip():
+...         element.text = None
 
 >>> etree.tostring(root)
 b'<root><a/><b/></root>'
@@ -807,7 +807,7 @@ fashion.

>>> some_file_like = BytesIO(b"<root><a>data</a></root>")
 
 >>> for event, element in etree.iterparse(some_file_like):
-...     print("%s, %4s, %s" % (event, element.tag, element.text))
+...     print("%s, %4s, %s" % (event, element.tag, element.text))
 end,    a, data
 end, root, None
 
@@ -817,7 +817,7 @@ element, but you can control this through the event >>> for event, element in etree.iterparse(some_file_like, ... events=("start", "end")): -... print("%5s, %4s, %s" % (event, element.tag, element.text)) +... print("%5s, %4s, %s" % (event, element.tag, element.text)) start, root, None start, a, data end, a, data @@ -838,10 +838,10 @@ have completely read through yet.

>>> for event, element in etree.iterparse(some_file_like): ... if element.tag == 'b': -... print(element.text) +... print(element.text) ... elif element.tag == 'a': -... print("** cleaning up the subtree") -... element.clear(keep_tail=True) +... print("** cleaning up the subtree") +... element.clear(keep_tail=True) data ** cleaning up the subtree None @@ -862,8 +862,8 @@ for data extraction.

... </root>''') >>> for _, element in etree.iterparse(xml_file, tag='a'): -... print('%s -- %s' % (element.findtext('b'), element[1].text)) -... element.clear(keep_tail=True) +... print('%s -- %s' % (element.findtext('b'), element[1].text)) +... element.clear(keep_tail=True) ABC -- abc MORE DATA -- more data XYZ -- xyz @@ -888,13 +888,13 @@ events are generated:

>>> parser = etree.XMLParser(target=parser_target) >>> events = etree.fromstring('<root test="true"/>', parser) ->>> print(parser_target.close_count) +>>> print(parser_target.close_count) 1 >>> for event in events: -... print('event: %s - tag: %s' % (event[0], event[1])) +... print('event: %s - tag: %s' % (event[0], event[1])) ... for attr, value in event[2].items(): -... print(' * %s = %s' % (attr, value)) +... print(' * %s = %s' % (attr, value)) event: start - tag: root * test = true
@@ -902,19 +902,19 @@ events are generated:

should take care that the .close() method really resets the target to a usable state (also in the case of an error!).

>>> events = etree.fromstring('<root test="true"/>', parser)
->>> print(parser_target.close_count)
+>>> print(parser_target.close_count)
 2
 >>> events = etree.fromstring('<root test="true"/>', parser)
->>> print(parser_target.close_count)
+>>> print(parser_target.close_count)
 3
 >>> events = etree.fromstring('<root test="true"/>', parser)
->>> print(parser_target.close_count)
+>>> print(parser_target.close_count)
 4
 
 >>> for event in events:
-...     print('event: %s - tag: %s' % (event[0], event[1]))
+...     print('event: %s - tag: %s' % (event[0], event[1]))
 ...     for attr, value in event[2].items():
-...         print(' * %s = %s' % (attr, value))
+...         print(' * %s = %s' % (attr, value))
 event: start - tag: root
  * test = true
 
@@ -929,7 +929,7 @@ wherever possible and deploys the real namespace (the URI) instead:

>>> body = etree.SubElement(xhtml, "{http://www.w3.org/1999/xhtml}body") >>> body.text = "Hello World" ->>> print(etree.tostring(xhtml, pretty_print=True)) +>>> print(etree.tostring(xhtml, pretty_print=True)) <html:html xmlns:html="http://www.w3.org/1999/xhtml"> <html:body>Hello World</html:body> </html:html> @@ -950,13 +950,13 @@ the Element factory function, e.g. to define the default namespace:

>>> XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"
 >>> XHTML = "{%s}" % XHTML_NAMESPACE
 
->>> NSMAP = {None : XHTML_NAMESPACE} # the default namespace (no prefix)
+>>> NSMAP = {None : XHTML_NAMESPACE} # the default namespace (no prefix)
 
 >>> xhtml = etree.Element(XHTML + "html", nsmap=NSMAP) # lxml only!
 >>> body = etree.SubElement(xhtml, XHTML + "body")
 >>> body.text = "Hello World"
 
->>> print(etree.tostring(xhtml, pretty_print=True))
+>>> print(etree.tostring(xhtml, pretty_print=True))
 <html xmlns="http://www.w3.org/1999/xhtml">
   <body>Hello World</body>
 </html>
@@ -964,29 +964,29 @@ the Element factory function, e.g. to define the default namespace:

You can also use the QName helper class to build or split qualified tag names:

>>> tag = etree.QName('http://www.w3.org/1999/xhtml', 'html')
->>> print(tag.localname)
+>>> print(tag.localname)
 html
->>> print(tag.namespace)
+>>> print(tag.namespace)
 http://www.w3.org/1999/xhtml
->>> print(tag.text)
+>>> print(tag.text)
 {http://www.w3.org/1999/xhtml}html
 
 >>> tag = etree.QName('{http://www.w3.org/1999/xhtml}html')
->>> print(tag.localname)
+>>> print(tag.localname)
 html
->>> print(tag.namespace)
+>>> print(tag.namespace)
 http://www.w3.org/1999/xhtml
 
 >>> root = etree.Element('{http://www.w3.org/1999/xhtml}html')
 >>> tag = etree.QName(root)
->>> print(tag.localname)
+>>> print(tag.localname)
 html
 
 >>> tag = etree.QName(root, 'script')
->>> print(tag.text)
+>>> print(tag.text)
 {http://www.w3.org/1999/xhtml}script
 >>> tag = etree.QName('{http://www.w3.org/1999/xhtml}html', 'script')
->>> print(tag.text)
+>>> print(tag.text)
 {http://www.w3.org/1999/xhtml}script
 

lxml.etree allows you to look up the current namespaces defined for a @@ -1019,12 +1019,12 @@ serialise-parse roundtrip, even if they appear in a namespaced element.

>>> body.set(XHTML + "bgcolor", "#CCFFAA")
 
->>> print(etree.tostring(xhtml, pretty_print=True))
+>>> print(etree.tostring(xhtml, pretty_print=True))
 <html xmlns="http://www.w3.org/1999/xhtml">
   <body xmlns:html="http://www.w3.org/1999/xhtml" html:bgcolor="#CCFFAA">Hello World</body>
 </html>
 
->>> print(body.get("bgcolor"))
+>>> print(body.get("bgcolor"))
 None
 >>> body.get(XHTML + "bgcolor")
 '#CCFFAA'
@@ -1034,18 +1034,18 @@ element.

... "//{%s}body" % XHTML_NAMESPACE) >>> results = find_xhtml_body(xhtml) ->>> print(results[0].tag) +>>> print(results[0].tag) {http://www.w3.org/1999/xhtml}body

For convenience, you can use "*" wildcards in all iterators of lxml.etree, both for tag names and namespaces:

-
>>> for el in xhtml.iter('*'): print(el.tag)   # any element
+
>>> for el in xhtml.iter('*'): print(el.tag)   # any element
 {http://www.w3.org/1999/xhtml}html
 {http://www.w3.org/1999/xhtml}body
->>> for el in xhtml.iter('{http://www.w3.org/1999/xhtml}*'): print(el.tag)
+>>> for el in xhtml.iter('{http://www.w3.org/1999/xhtml}*'): print(el.tag)
 {http://www.w3.org/1999/xhtml}html
 {http://www.w3.org/1999/xhtml}body
->>> for el in xhtml.iter('{*}body'): print(el.tag)
+>>> for el in xhtml.iter('{*}body'): print(el.tag)
 {http://www.w3.org/1999/xhtml}body
 

To look for elements that do not have a namespace, either use the @@ -1054,9 +1054,9 @@ plain tag name or provide the empty namespace explicitly:

['{http://www.w3.org/1999/xhtml}body'] >>> [ el.tag for el in xhtml.iter('body') ] [] ->>> [ el.tag for el in xhtml.iter('{}body') ] +>>> [ el.tag for el in xhtml.iter('{}body') ] [] ->>> [ el.tag for el in xhtml.iter('{}*') ] +>>> [ el.tag for el in xhtml.iter('{}*') ] []
@@ -1085,7 +1085,7 @@ HTML:

... ) ... ) ->>> print(etree.tostring(page, pretty_print=True)) +>>> print(etree.tostring(page, pretty_print=True)) <html> <head> <title>This is a sample document</title> @@ -1125,7 +1125,7 @@ simple vocabulary for an XML language:

... ) ... ) ->>> print(etree.tostring(my_doc, pretty_print=True)) +>>> print(etree.tostring(my_doc, pretty_print=True)) <p:doc xmlns:p="http://my.de/fault/namespace"> <p:title>The dog and the hog</p:title> <p:section> @@ -1170,32 +1170,32 @@ expression
>>> root = etree.XML("<root><a x='123'>aText<b/><c/><b/></a></root>")
 

Find a child of an Element:

-
>>> print(root.find("b"))
+
>>> print(root.find("b"))
 None
->>> print(root.find("a").tag)
+>>> print(root.find("a").tag)
 a
 

Find an Element anywhere in the tree:

-
>>> print(root.find(".//b").tag)
+
>>> print(root.find(".//b").tag)
 b
 >>> [ b.tag for b in root.iterfind(".//b") ]
 ['b', 'b']
 

Find Elements with a certain attribute:

-
>>> print(root.findall(".//a[@x]")[0].tag)
+
>>> print(root.findall(".//a[@x]")[0].tag)
 a
->>> print(root.findall(".//a[@y]"))
+>>> print(root.findall(".//a[@y]"))
 []
 

In lxml 3.4, there is a new helper to generate a structural ElementPath expression for an Element:

>>> tree = etree.ElementTree(root)
 >>> a = root[0]
->>> print(tree.getelementpath(a[0]))
+>>> print(tree.getelementpath(a[0]))
 a/b[1]
->>> print(tree.getelementpath(a[1]))
+>>> print(tree.getelementpath(a[1]))
 a/c
->>> print(tree.getelementpath(a[2]))
+>>> print(tree.getelementpath(a[2]))
 a/b[2]
 >>> tree.find(tree.getelementpath(a[2])) == a[2]
 True
@@ -1207,11 +1207,11 @@ of being self-contained even for documents that use namespaces.

The .iter() method is a special case that only finds specific tags in the tree by their name, not based on a path. That means that the following commands are equivalent in the success case:

-
>>> print(root.find(".//b").tag)
+
>>> print(root.find(".//b").tag)
 b
->>> print(next(root.iterfind(".//b")).tag)
+>>> print(next(root.iterfind(".//b")).tag)
 b
->>> print(next(root.iter("b")).tag)
+>>> print(next(root.iter("b")).tag)
 b
 

Note that the .find() method simply returns None if no match is found, @@ -1220,7 +1220,7 @@ whereas the other two examples would raise a StopIt

diff --git a/doc/html/validation.html b/doc/html/validation.html index a89fb13..3562445 100644 --- a/doc/html/validation.html +++ b/doc/html/validation.html @@ -2,7 +2,7 @@ - + Validation with lxml
-

Validation with lxml

+

Validation with lxml

Apart from the built-in DTD support in parsers, lxml currently supports three schema languages: DTD, Relax NG and XML Schema. All three provide @@ -56,7 +56,7 @@ libxml2 2.6.30.

a DTD or an XML schema. The DTD is retrieved automatically based on the DOCTYPE of the parsed document. All you have to do is use a parser that has DTD validation enabled:

-
>>> parser = etree.XMLParser(dtd_validation=True)
+
>>> parser = etree.XMLParser(dtd_validation=True)
 

Obviously, a request for validation enables the DTD loading feature. There are two other options that enable loading the DTD, but that do @@ -106,15 +106,15 @@ into the constructor to parse a DTD:

Now you can use it to validate documents:

>>> root = etree.XML("<b/>")
->>> print(dtd.validate(root))
+>>> print(dtd.validate(root))
 True
 
 >>> root = etree.XML("<b><a/></b>")
->>> print(dtd.validate(root))
+>>> print(dtd.validate(root))
 False
 

The reason for the validation failure can be found in the error log:

-
>>> print(dtd.error_log.filter_from_errors()[0])
+
>>> print(dtd.error_log.filter_from_errors()[0])
 <string>:1:0:ERROR:VALID:DTD_NOT_EMPTY: Element b was declared EMPTY this one has content
 

As an alternative to parsing from a file, you can use the @@ -127,7 +127,7 @@ in the system catalog:

iterelements provides an iterator over the element declarations:

>>> dtd = etree.DTD(StringIO('<!ELEMENT a EMPTY><!ELEMENT b EMPTY>'))
 >>> for el in dtd.iterelements():
-...     print(el.name)
+...     print(el.name)
 a
 b
 
@@ -236,7 +236,7 @@ method. This is sometimes used in conditional statements:

>>> invalid = StringIO('<a><c></c></a>')
 >>> doc2 = etree.parse(invalid)
 >>> if not relaxng(doc2):
-...     print("invalid!")
+...     print("invalid!")
 invalid!
 

If you prefer getting an exception when validating, you can use the @@ -255,16 +255,16 @@ method. This is sometimes used in conditional statements:

look up the error log of the validation process and check it for relevant messages:

>>> log = relaxng.error_log
->>> print(log.last_error)
+>>> print(log.last_error)
 <string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_ELEMWRONG: Did not expect element c there
 

You can see that the error (ERROR) happened during RelaxNG validation (RELAXNGV). The message then tells you what went wrong. You can also look at the error domain and its type directly:

>>> error = log.last_error
->>> print(error.domain_name)
+>>> print(error.domain_name)
 RELAXNGV
->>> print(error.type_name)
+>>> print(error.type_name)
 RELAXNG_ERR_ELEMWRONG
 

Note that this error log is local to the RelaxNG object. It will only @@ -320,7 +320,7 @@ This is sometimes used in conditional statements:

>>> invalid = StringIO('<a><c></c></a>')
 >>> doc2 = etree.parse(invalid)
 >>> if not xmlschema(doc2):
-...     print("invalid!")
+...     print("invalid!")
 invalid!
 

If you prefer getting an exception when validating, you can use the @@ -338,9 +338,9 @@ This is sometimes used in conditional statements:

Error reporting works as for the RelaxNG class:

>>> log = xmlschema.error_log
 >>> error = log.last_error
->>> print(error.domain_name)
+>>> print(error.domain_name)
 SCHEMASV
->>> print(error.type_name)
+>>> print(error.type_name)
 SCHEMAV_ELEMENT_CONTENT
 

If you were to print this log entry, you would get something like the @@ -405,7 +405,7 @@ This can be useful for conditional statements:

>>> is_valid = isoschematron.Schematron(sct_doc)
 
 >>> if not is_valid(doc):
-...     print("invalid!")
+...     print("invalid!")
 invalid!
 

Built on a pure-xslt implementation, the actual validator is created as an @@ -546,7 +546,7 @@ This is sometimes used in conditional statements:

>>> is_valid = etree.Schematron(sct_doc)
 
 >>> if not is_valid(doc):
-...     print("invalid!")
+...     print("invalid!")
 invalid!
 

Note that libxml2 restricts error reporting to the parsing step (when creating @@ -556,7 +556,7 @@ reporting during validation.

diff --git a/doc/html/xpathxslt.html b/doc/html/xpathxslt.html index 89d3455..9fb005a 100644 --- a/doc/html/xpathxslt.html +++ b/doc/html/xpathxslt.html @@ -2,7 +2,7 @@ - + XPath and XSLT with lxml
-

XPath and XSLT with lxml

+

XPath and XSLT with lxml

lxml supports XPath 1.0, XSLT 1.0 and the EXSLT extensions through libxml2 and libxslt in a standards compliant way.

@@ -69,9 +69,15 @@ frequent evaluation: XPath and xpath() method described here.

-

Note that the .find*() methods are usually faster than the full-blown XPath -support. They also support incremental tree processing through the .iterfind() -method, whereas XPath always collects all results before returning them.

+
+

Note

+

The .find*() methods are usually faster than the full-blown XPath +support. They also support incremental tree processing through the +.iterfind() method, whereas XPath always collects all results before +returning them. They are therefore recommended over XPath for both speed +and memory reasons, whenever there is no need for highly selective XPath +queries.

+

The xpath() method

For ElementTree, the xpath method performs a global XPath query against the @@ -109,13 +115,13 @@ against the element (if relative) or against the root tree (if absolute):

The xpath() method has support for XPath variables:

>>> expr = "//*[local-name() = $name]"
 
->>> print(root.xpath(expr, name = "foo")[0].tag)
+>>> print(root.xpath(expr, name = "foo")[0].tag)
 foo
 
->>> print(root.xpath(expr, name = "bar")[0].tag)
+>>> print(root.xpath(expr, name = "bar")[0].tag)
 bar
 
->>> print(root.xpath("$text", text = "Hello World!"))
+>>> print(root.xpath("$text", text = "Hello World!"))
 Hello World!
 
@@ -194,14 +200,14 @@ relationship using the keyword argument smart_strin >>> find_text = etree.XPath("//text()") >>> text = find_text(root)[0] ->>> print(text) +>>> print(text) TEXT ->>> print(text.getparent().text) +>>> print(text.getparent().text) TEXT ->>> find_text = etree.XPath("//text()", smart_strings=False) +>>> find_text = etree.XPath("//text()", smart_strings=False) >>> text = find_text(root)[0] ->>> print(text) +>>> print(text) TEXT >>> hasattr(text, 'getparent') False @@ -218,7 +224,7 @@ structural, absolute XPath expression to find that element:

>>> d2 = etree.SubElement(c, "d") >>> tree = etree.ElementTree(c) ->>> print(tree.getpath(d2)) +>>> print(tree.getpath(d2)) /c/d[2] >>> tree.xpath(tree.getpath(d2)) == [d2] True @@ -230,7 +236,7 @@ structural, absolute XPath expression to find that element:

>>> root = etree.XML("<root><a><b/></a><b/></root>")
 
 >>> find = etree.XPath("//b")
->>> print(find(root)[0].tag)
+>>> print(find(root)[0].tag)
 b
 

The compilation takes as much time as in the xpath() method, but it is @@ -240,9 +246,9 @@ for repeated evaluation of the same XPath expression.

variables:

>>> count_elements = etree.XPath("count(//*[local-name() = $name])")
 
->>> print(count_elements(root, name = "a"))
+>>> print(count_elements(root, name = "a"))
 1.0
->>> print(count_elements(root, name = "b"))
+>>> print(count_elements(root, name = "b"))
 2.0
 

This supports very efficient evaluation of modified versions of an XPath @@ -251,7 +257,7 @@ expression, as compilation is still only required once.

>>> root = etree.XML("<root xmlns='NS'><a><b/></a><b/></root>")
 
 >>> find = etree.XPath("//n:b", namespaces={'n':'NS'})
->>> print(find(root)[0].tag)
+>>> print(find(root)[0].tag)
 {NS}b
 
@@ -263,7 +269,7 @@ expression, as compilation is still only required once.

... namespaces={'re':regexpNS}) >>> root = etree.XML("<root><a>aB</a><b>aBc</b></root>") ->>> print(find(root)[0].text) +>>> print(find(root)[0].text) aBc

You can disable this with the boolean keyword argument regexp which @@ -278,10 +284,10 @@ XPathEvaluator helper for instantiation:

>>> root = etree.XML("<root><a><b/></a><b/></root>")
 >>> xpatheval = etree.XPathEvaluator(root)
 
->>> print(isinstance(xpatheval, etree.XPathElementEvaluator))
+>>> print(isinstance(xpatheval, etree.XPathElementEvaluator))
 True
 
->>> print(xpatheval("//b")[0].tag)
+>>> print(xpatheval("//b")[0].tag)
 b
 

This class provides efficient support for evaluating different XPath @@ -306,12 +312,12 @@ write:

>>> root = etree.XML("<root xmlns='ns'><a><b/></a><b/></root>")
 
 >>> find = etree.XPath("//p:b", namespaces={'p' : 'ns'})
->>> print(find(root)[0].tag)
+>>> print(find(root)[0].tag)
 {ns}b
 

ETXPath allows you to change this to:

-
>>> find = etree.ETXPath("//{ns}b")
->>> print(find(root)[0].tag)
+
>>> find = etree.ETXPath("//{ns}b")
+>>> print(find(root)[0].tag)
 {ns}b
 
@@ -541,17 +547,17 @@ error log.

>>> bytes(result) b'<?xml version="1.0"?>\n<foo>Text</foo>\n' ->>> print(transform.error_log) +>>> print(transform.error_log) <string>:0:0:ERROR:XSLT:ERR_OK: STARTING <string>:0:0:ERROR:XSLT:ERR_OK: DONE >>> for entry in transform.error_log: -... print('message from line %s, col %s: %s' % ( +... print('message from line %s, col %s: %s' % ( ... entry.line, entry.column, entry.message)) -... print('domain: %s (%d)' % (entry.domain_name, entry.domain)) -... print('type: %s (%d)' % (entry.type_name, entry.type)) -... print('level: %s (%d)' % (entry.level_name, entry.level)) -... print('filename: %s' % entry.filename) +... print('domain: %s (%d)' % (entry.domain_name, entry.domain)) +... print('type: %s (%d)' % (entry.type_name, entry.type)) +... print('level: %s (%d)' % (entry.level_name, entry.level)) +... print('filename: %s' % entry.filename) message from line 0, col 0: STARTING domain: XSLT (22) type: ERR_OK (0) @@ -616,7 +622,7 @@ maintainable.

Profiling

If you want to know how your stylesheet performed, pass the profile_run keyword to the transform:

-
>>> result = transform(doc, a="/a/b/text()", profile_run=True)
+
>>> result = transform(doc, a="/a/b/text()", profile_run=True)
 >>> profile = result.xslt_profile
 

The value of the xslt_profile property is an ElementTree with profiling @@ -635,7 +641,7 @@ If you want to free it from memory, just do:

diff --git a/doc/licenses/ZopePublicLicense.txt b/doc/licenses/ZopePublicLicense.txt deleted file mode 100644 index 44e0648..0000000 --- a/doc/licenses/ZopePublicLicense.txt +++ /dev/null @@ -1,59 +0,0 @@ -Zope Public License (ZPL) Version 2.0 ------------------------------------------------ - -This software is Copyright (c) Zope Corporation (tm) and -Contributors. All rights reserved. - -This license has been certified as open source. It has also -been designated as GPL compatible by the Free Software -Foundation (FSF). - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the -following conditions are met: - -1. Redistributions in source code must retain the above - copyright notice, this list of conditions, and the following - disclaimer. - -2. Redistributions in binary form must reproduce the above - copyright notice, this list of conditions, and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - -3. The name Zope Corporation (tm) must not be used to - endorse or promote products derived from this software - without prior written permission from Zope Corporation. - -4. The right to distribute this software or to use it for - any purpose does not give you the right to use Servicemarks - (sm) or Trademarks (tm) of Zope Corporation. Use of them is - covered in a separate agreement (see - http://www.zope.com/Marks). - -5. If any files are modified, you must cause the modified - files to carry prominent notices stating that you changed - the files and the date of any change. - -Disclaimer - - THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS'' - AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT - NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - - -This software consists of contributions made by Zope -Corporation and many individuals on behalf of Zope -Corporation. Specific attributions are listed in the -accompanying credits file. diff --git a/doc/main.txt b/doc/main.txt index ead457d..75fedd5 100644 --- a/doc/main.txt +++ b/doc/main.txt @@ -159,8 +159,8 @@ Index `_ (PyPI). It has the source that compiles on various platforms. The source distribution is signed with `this key `_. -The latest version is `lxml 4.6.3`_, released 2021-03-21 -(`changes for 4.6.3`_). `Older versions <#old-versions>`_ +The latest version is `lxml 4.6.4`_, released 2021-11-01 +(`changes for 4.6.4`_). `Older versions <#old-versions>`_ are listed below. Please take a look at the @@ -256,7 +256,9 @@ See the websites of lxml .. and the `latest in-development version `_. -.. _`PDF documentation`: lxmldoc-4.6.3.pdf +.. _`PDF documentation`: lxmldoc-4.6.4.pdf + +* `lxml 4.6.4`_, released 2021-11-01 (`changes for 4.6.4`_) * `lxml 4.6.3`_, released 2021-03-21 (`changes for 4.6.3`_) @@ -282,6 +284,7 @@ See the websites of lxml * `older releases `_ +.. _`lxml 4.6.4`: /files/lxml-4.6.4.tgz .. _`lxml 4.6.3`: /files/lxml-4.6.3.tgz .. _`lxml 4.6.2`: /files/lxml-4.6.2.tgz .. _`lxml 4.6.1`: /files/lxml-4.6.1.tgz @@ -294,6 +297,7 @@ See the websites of lxml .. _`lxml 4.4.1`: /files/lxml-4.4.1.tgz .. _`lxml 4.4.0`: /files/lxml-4.4.0.tgz +.. _`changes for 4.6.4`: /changes-4.6.4.html .. _`changes for 4.6.3`: /changes-4.6.3.html .. _`changes for 4.6.2`: /changes-4.6.2.html .. _`changes for 4.6.1`: /changes-4.6.1.html diff --git a/doc/mkhtml.py b/doc/mkhtml.py index c652335..36da5de 100644 --- a/doc/mkhtml.py +++ b/doc/mkhtml.py @@ -194,7 +194,7 @@ def convert_changelog(lxml_path, changelog_file_path, rst2html_script, styleshee out_file.close() -def publish(dirname, lxml_path, release): +def publish(dirname, lxml_path, release, with_donations=True): if not os.path.exists(dirname): os.mkdir(dirname) @@ -245,7 +245,8 @@ def publish(dirname, lxml_path, release): menu = Element("div", {'class': 'sidemenu', 'id': 'sidemenu'}) SubElement(menu, 'div', {'class': 'menutrigger', 'onclick': 'trigger_menu(event)'}).text = "Menu" menu_div = SubElement(menu, 'div', {'class': 'menu'}) - inject_banner(menu_div) + if with_donations: + inject_banner(menu_div) # build HTML pages and parse them back for section, text_files in SITE_STRUCTURE: @@ -266,13 +267,14 @@ def publish(dirname, lxml_path, release): rest2html(script, path, outpath, stylesheet_url) tree = parse(outpath) - page_div = tree.getroot()[1][0] # html->body->div[class=document] - inject_banner(page_div) + if with_donations: + page_div = tree.getroot()[1][0] # html->body->div[class=document] + inject_banner(page_div) - if filename == 'main.txt': - # inject donation buttons - #inject_flatter_button(tree) - inject_donate_buttons(lxml_path, script, tree) + if filename == 'main.txt': + # inject donation buttons + #inject_flatter_button(tree) + inject_donate_buttons(lxml_path, script, tree) trees[filename] = (tree, basename, outpath) build_menu(tree, basename, section_head) @@ -324,4 +326,7 @@ def publish(dirname, lxml_path, release): if __name__ == '__main__': - publish(sys.argv[1], sys.argv[2], sys.argv[3]) + no_donations = '--no-donations' in sys.argv[1:] + if no_donations: + sys.argv.remove('--no-donations') + publish(sys.argv[1], sys.argv[2], sys.argv[3], with_donations=not no_donations) diff --git a/doc/mklatex.py b/doc/mklatex.py index 4151dc8..2bb73b7 100644 --- a/doc/mklatex.py +++ b/doc/mklatex.py @@ -63,6 +63,10 @@ PYGMENTS_IMPORT = r""" \input{_part_pygments.tex} """ +EPYDOC_IMPORT = r""" +\input{_part_epydoc.tex} +""" + def write_chapter(master, title, filename): filename = os.path.join(os.path.dirname(filename), "_part_%s" % os.path.basename(filename)) @@ -175,7 +179,6 @@ def tex_postprocess(src_path, dest_path, want_header=False, process_line=noop): raise Exception("Bueee, no title in %s" % src_path) return title, header - def publish(dirname, lxml_path, release): if not os.path.exists(dirname): os.mkdir(dirname) @@ -250,12 +253,12 @@ def publish(dirname, lxml_path, release): # integrate generated API docs print("Integrating API docs") - apidocsname = 'lxml.tex' - apipath = os.path.join(dirname, "..", "api", "_build", "latex", apidocsname) + apidocsname = 'api.tex' + apipath = os.path.join(dirname, apidocsname) tex_postprocess(apipath, os.path.join(dirname, "_part_%s" % apidocsname), process_line=fix_relative_hyperrefs) - #copy_epydoc_macros(apipath, os.path.join(dirname, '_part_epydoc.tex'), - # set(header)) + copy_epydoc_macros(apipath, os.path.join(dirname, '_part_epydoc.tex'), + set(header)) # convert CHANGES.txt @@ -284,9 +287,9 @@ def publish(dirname, lxml_path, release): for hln in header: if hln.startswith(r"\documentclass"): #hln = hln.replace('article', 'book') - hln = DOCUMENT_CLASS + hln = DOCUMENT_CLASS + EPYDOC_IMPORT elif hln.startswith(r"\begin{document}"): - # pygments support + # pygments and epydoc support master.write(PYGMENTS_IMPORT) elif hln.startswith(r"\title{"): hln = replace_content( diff --git a/doc/pdf/pubkey.asc b/doc/pdf/pubkey.asc deleted file mode 100644 index f72804c..0000000 --- a/doc/pdf/pubkey.asc +++ /dev/null @@ -1,36 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.2 (GNU/Linux) - -mQGiBEQf3JQRBACciSqxoX0q3VurkRENVVtG/pVqtFh/d2CohbVJlLCrO4s7nnPj -CTfZFt6tmykZjsLJl24XpEJt0O/C0jLcaBqvXVgVvRXHz4DjEYYuQF4LPthhI4MA -4T7ExptX4lU5g3BVJ46vPU8uRBbbxarBRas9rYewgnrYKWpZZCa7yMq+9wCgnyyR -Si4E3viLwi77jda135nA6vcD/iqu8zIl9/dFuUcOvxJrhrm+UdY72puZ1TVczSAH -GOqMjrKkfyHlaJh/ZzWENpTZIfOdVhy7Chvva18vH4Wz7jKj5UeIpRrBvjAD28r3 -Y3W5bfsnpPkvDOyU1vqBsw4q+/250GXEX0JqV2Rbf5yLVgEZPdGrswO460dr4UVS -8RS0BACYTmyrz57AugHc5tRkqNw6o7ux2deOT0c3AbUcOWtOocGumCsUf+M1nOrc -VWkeBWTv4HIIiecWYY/KwIemTthQGjxywaZDxOlBT0BOL/+vfYTq/plZULXr+g90 -rSe82+kLl9N5onkBDJKeDIcJDzRoxIRPV1i0Om/5JBI4jmUnv7QnU3RlZmFuIEJl -aG5lbCA8c2NvZGVyQHVzZXJzLmJlcmxpb3MuZGU+iF8EExECACAFAkQiqKYCGwMG -CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRANPVNpCNOgHi+2AJ0a0JH8iP3RqrOL -JefvHz1dSl3MxACYo7Ma6CeIgsGnyaSSdNOmNVXn+IhGBBARAgAGBQJEIqk0AAoJ -ELO5mMzzmgZbmCcAoKZ2En1IlsxBpaPPxgWYrUOWfc6hAKCBWODMMOYptCBkSrjg -m3gsrjHgYbQsU3RlZmFuIEJlaG5lbCA8c2NvZGVyQHVzZXJzLnNvdXJjZWZvcmdl -Lm5ldD6IYAQTEQIAIAUCRB/clAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJ -EA09U2kI06Aen2YAn0hvuDs+Gslq9vPRFFbsFNJI40PmAJ0chjiiEy0xV5C+n6YX -XFuldRDILYhGBBARAgAGBQJEIp4AAAoJELO5mMzzmgZbgKQAn3pWrmFdj8YaEyuR -tEjKVZJDQ6ZVAJ0Y1igwADT40BPra+G/xiLa3YbCrrkCDQREH9ynEAgAiR4/0r0d -doViNECfSLClllu5K0Bo1SEiMtvVNC3sJYgVzBddD8Xn8UAdjyAgmaL5FC2FsNQu -RxxKkNlHNYCq8ZSWtZaL2MQ+SyMUyHv6VXVCGuSW0COpzbx58u+SZpjyESJ1kaZc -73SaIw6kv/dVQHjurwmlo1lg3dLZ3PG08WGCYUMqkkv2K+J7+puzE2Cjo31gTq4s -LYDCV26wjVQ6BqT2EcHQhVEjh0xq5ugc908cr/2FQAKkTifEbF+OVBGWiFMGgri+ -6+G54/BV/RakpvNCFYBiZHn/M9mQaWt7XoTmnEQ1ldq5KNlRhkqnQRF/NK5VpGcQ -29As28aqpZTECwADBgf/WlRvBRI1Q1eIv2falEv7C6sOxqc3kr5z1uUBTRG5v9t6 -ff9k/J4oC6cnQx00GK3ZR8ija6bl8zwu+0m0M3rW49Krb1rsiT7r4ahOZ7p9RRro -oG3NbUJYgMG10D1nxpaioYqa/m+PpILJM0wfYZZEuX0xkZcOB24yb+J7EIcGR09T -mMd5sXtdTU+w/p7Xi2cP61uQ8qixyHBH8E06qgW2JtVFV9rGn7CNUOvkNaUBRnY5 -QxhdkvKJRx7voOLYWZFUBIWgto+6vmTgKmc2Ho6qddzME9UgwUNcknRgm0cf6Cxr -6zPtxZl8a6KemjQcK7kARSmMNCDkqp/Pohe519A5vYhJBBgRAgAJBQJEH9ynAhsM -AAoJEA09U2kI06Aesv4AnjiVQVLzqnNS/64vvMMP1UARY3HtAJ90YxNGhRNIhWYL -UU16oJlGD/9M1Q== -=gWy2 ------END PGP PUBLIC KEY BLOCK----- diff --git a/doc/performance.txt b/doc/performance.txt index 1a0c9ad..c6f2edb 100644 --- a/doc/performance.txt +++ b/doc/performance.txt @@ -88,18 +88,11 @@ very easy to add as tiny test methods, so if you write a performance test for a specific part of the API yourself, please consider sending it to the lxml mailing list. -The timings presented below compare lxml 3.1.1 (with libxml2 2.9.0) to the +The timings presented below compare lxml 4.6.3 (with libxml2 2.9.10) to the latest released versions of ElementTree (with cElementTree as accelerator -module) in the standard library of CPython 3.3.0. They were run -single-threaded on a 2.9GHz 64bit double core Intel i7 machine under -Ubuntu Linux 12.10 (Quantal). The C libraries were compiled with the -same platform specific optimisation flags. The Python interpreter was -also manually compiled for the platform. Note that many of the following -ElementTree timings are therefore better than what a normal Python -installation with the standard library (c)ElementTree modules would yield. -Note also that CPython 2.7 and 3.2+ come with a newer ElementTree version, -so older Python installations will not perform as good for (c)ElementTree, -and sometimes substantially worse. +module) in the standard library of CPython 3.8.10. They were run +single-threaded on a 2.3GHz 64bit double core Intel i5 machine under +Ubuntu Linux 20.04 (Focal). .. _`bench_etree.py`: https://github.com/lxml/lxml/blob/master/benchmark/bench_etree.py .. _`bench_xpath.py`: https://github.com/lxml/lxml/blob/master/benchmark/bench_xpath.py @@ -141,50 +134,50 @@ is native to libxml2. While 20 to 40 times faster than (c)ElementTree lxml is still more than 10 times as fast as the much improved ElementTree 1.3 in recent Python versions:: - lxe: tostring_utf16 (S-TR T1) 7.9958 msec/pass - cET: tostring_utf16 (S-TR T1) 83.1358 msec/pass + lxe: tostring_utf16 (S-TR T1) 5.9340 msec/pass + cET: tostring_utf16 (S-TR T1) 38.3270 msec/pass - lxe: tostring_utf16 (UATR T1) 8.3222 msec/pass - cET: tostring_utf16 (UATR T1) 84.4688 msec/pass + lxe: tostring_utf16 (UATR T1) 6.2032 msec/pass + cET: tostring_utf16 (UATR T1) 37.7944 msec/pass - lxe: tostring_utf16 (S-TR T2) 8.2297 msec/pass - cET: tostring_utf16 (S-TR T2) 87.3415 msec/pass + lxe: tostring_utf16 (S-TR T2) 6.1841 msec/pass + cET: tostring_utf16 (S-TR T2) 40.2577 msec/pass - lxe: tostring_utf8 (S-TR T2) 6.5677 msec/pass - cET: tostring_utf8 (S-TR T2) 76.2064 msec/pass + lxe: tostring_utf8 (S-TR T2) 4.6697 msec/pass + cET: tostring_utf8 (S-TR T2) 30.5173 msec/pass - lxe: tostring_utf8 (U-TR T3) 1.1952 msec/pass - cET: tostring_utf8 (U-TR T3) 22.0058 msec/pass + lxe: tostring_utf8 (U-TR T3) 1.2085 msec/pass + cET: tostring_utf8 (U-TR T3) 9.0246 msec/pass The difference is somewhat smaller for plain text serialisation:: - lxe: tostring_text_ascii (S-TR T1) 2.7738 msec/pass - cET: tostring_text_ascii (S-TR T1) 4.7629 msec/pass + lxe: tostring_text_ascii (S-TR T1) 2.6727 msec/pass + cET: tostring_text_ascii (S-TR T1) 2.9683 msec/pass - lxe: tostring_text_ascii (S-TR T3) 0.8273 msec/pass - cET: tostring_text_ascii (S-TR T3) 1.5273 msec/pass + lxe: tostring_text_ascii (S-TR T3) 0.6952 msec/pass + cET: tostring_text_ascii (S-TR T3) 1.0073 msec/pass - lxe: tostring_text_utf16 (S-TR T1) 2.7659 msec/pass - cET: tostring_text_utf16 (S-TR T1) 10.5038 msec/pass + lxe: tostring_text_utf16 (S-TR T1) 2.7366 msec/pass + cET: tostring_text_utf16 (S-TR T1) 7.3647 msec/pass - lxe: tostring_text_utf16 (U-TR T1) 2.8017 msec/pass - cET: tostring_text_utf16 (U-TR T1) 10.5207 msec/pass + lxe: tostring_text_utf16 (U-TR T1) 3.0322 msec/pass + cET: tostring_text_utf16 (U-TR T1) 7.5922 msec/pass The ``tostring()`` function also supports serialisation to a Python unicode string object, which is currently faster in ElementTree -under CPython 3.3:: +under CPython 3.8:: - lxe: tostring_text_unicode (S-TR T1) 2.6896 msec/pass - cET: tostring_text_unicode (S-TR T1) 1.0056 msec/pass + lxe: tostring_text_unicode (S-TR T1) 2.7645 msec/pass + cET: tostring_text_unicode (S-TR T1) 1.1806 msec/pass - lxe: tostring_text_unicode (U-TR T1) 2.7366 msec/pass - cET: tostring_text_unicode (U-TR T1) 1.0154 msec/pass + lxe: tostring_text_unicode (U-TR T1) 2.9871 msec/pass + cET: tostring_text_unicode (U-TR T1) 1.1659 msec/pass - lxe: tostring_text_unicode (S-TR T3) 0.7997 msec/pass - cET: tostring_text_unicode (S-TR T3) 0.3154 msec/pass + lxe: tostring_text_unicode (S-TR T3) 0.7446 msec/pass + cET: tostring_text_unicode (S-TR T3) 0.4532 msec/pass lxe: tostring_text_unicode (U-TR T4) 0.0048 msec/pass - cET: tostring_text_unicode (U-TR T4) 0.0160 msec/pass + cET: tostring_text_unicode (U-TR T4) 0.0134 msec/pass For parsing, lxml.etree and cElementTree compete for the medal. Depending on the input, either of the two can be faster. The (c)ET @@ -192,37 +185,37 @@ libraries use a very thin layer on top of the expat parser, which is known to be very fast. Here are some timings from the benchmarking suite:: - lxe: parse_bytesIO (SAXR T1) 13.0246 msec/pass - cET: parse_bytesIO (SAXR T1) 8.2929 msec/pass + lxe: parse_bytesIO (SAXR T1) 14.2074 msec/pass + cET: parse_bytesIO (SAXR T1) 7.9336 msec/pass - lxe: parse_bytesIO (S-XR T3) 1.3542 msec/pass - cET: parse_bytesIO (S-XR T3) 2.4023 msec/pass + lxe: parse_bytesIO (S-XR T3) 1.4477 msec/pass + cET: parse_bytesIO (S-XR T3) 2.1925 msec/pass - lxe: parse_bytesIO (UAXR T3) 7.5610 msec/pass - cET: parse_bytesIO (UAXR T3) 11.2455 msec/pass + lxe: parse_bytesIO (UAXR T3) 8.4128 msec/pass + cET: parse_bytesIO (UAXR T3) 12.2926 msec/pass And another couple of timings `from a benchmark`_ that Fredrik Lundh `used to promote cElementTree`_, comparing a number of different parsers. First, parsing a 274KB XML file containing Shakespeare's Hamlet:: - xml.etree.ElementTree.parse done in 0.017 seconds + xml.etree.ElementTree.parse done in 0.006 seconds xml.etree.cElementTree.parse done in 0.007 seconds - xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.007 seconds - lxml.etree.parse done in 0.003 seconds - drop_whitespace.parse done in 0.003 seconds + xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.006 seconds + lxml.etree.parse done in 0.004 seconds + drop_whitespace.parse done in 0.004 seconds lxml.etree.XMLParser.feed(): 6636 nodes read in 0.004 seconds - minidom tree read in 0.080 seconds + minidom tree read in 0.066 seconds And a 3.4MB XML file containing the Old Testament:: - xml.etree.ElementTree.parse done in 0.038 seconds - xml.etree.cElementTree.parse done in 0.030 seconds - xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.030 seconds - lxml.etree.parse done in 0.016 seconds - drop_whitespace.parse done in 0.015 seconds - lxml.etree.XMLParser.feed(): 25317 nodes read in 0.022 seconds - minidom tree read in 0.288 seconds + xml.etree.ElementTree.parse done in 0.037 seconds + xml.etree.cElementTree.parse done in 0.036 seconds + xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.036 seconds + lxml.etree.parse done in 0.025 seconds + drop_whitespace.parse done in 0.022 seconds + lxml.etree.XMLParser.feed(): 25317 nodes read in 0.026 seconds + minidom tree read in 0.194 seconds .. _`from a benchmark`: http://svn.effbot.org/public/elementtree-1.3/benchmark.py .. _`used to promote cElementTree`: http://effbot.org/zone/celementtree.htm#benchmarks @@ -232,43 +225,42 @@ of the process in KB before and after parsing (using os.fork() to make sure we start from a clean state each time). For the 274KB hamlet.xml file:: - Memory usage: 7284 - xml.etree.ElementTree.parse done in 0.017 seconds - Memory usage: 9432 (+2148) + Memory usage: 9256 + xml.etree.ElementTree.parse done in 0.006 seconds + Memory usage: 12764 (+3508) xml.etree.cElementTree.parse done in 0.007 seconds - Memory usage: 9432 (+2152) - xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.007 seconds - Memory usage: 9448 (+2164) - lxml.etree.parse done in 0.003 seconds - Memory usage: 11032 (+3748) - drop_whitespace.parse done in 0.003 seconds - Memory usage: 10224 (+2940) + Memory usage: 12764 (+3508) + xml.etree.cElementTree.XMLParser.feed(): 6636 nodes read in 0.006 seconds + Memory usage: 12720 (+3464) + lxml.etree.parse done in 0.004 seconds + Memory usage: 15052 (+5796) + drop_whitespace.parse done in 0.004 seconds + Memory usage: 14040 (+4784) lxml.etree.XMLParser.feed(): 6636 nodes read in 0.004 seconds - Memory usage: 11804 (+4520) - minidom tree read in 0.080 seconds - Memory usage: 12324 (+5040) + Memory usage: 15812 (+6556) + minidom tree read in 0.066 seconds + Memory usage: 15332 (+6076) And for the 3.4MB Old Testament XML file:: - Memory usage: 10420 - xml.etree.ElementTree.parse done in 0.038 seconds - Memory usage: 20660 (+10240) - xml.etree.cElementTree.parse done in 0.030 seconds - Memory usage: 20660 (+10240) - xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.030 seconds - Memory usage: 20844 (+10424) - lxml.etree.parse done in 0.016 seconds - Memory usage: 27624 (+17204) - drop_whitespace.parse done in 0.015 seconds - Memory usage: 24468 (+14052) - lxml.etree.XMLParser.feed(): 25317 nodes read in 0.022 seconds - Memory usage: 29844 (+19424) - minidom tree read in 0.288 seconds - Memory usage: 28788 (+18368) + Memory usage: 12456 + xml.etree.ElementTree.parse done in 0.037 seconds + Memory usage: 23288 (+10832) + xml.etree.cElementTree.parse done in 0.036 seconds + Memory usage: 23288 (+10832) + xml.etree.cElementTree.XMLParser.feed(): 25317 nodes read in 0.036 seconds + Memory usage: 23644 (+11220) + lxml.etree.parse done in 0.025 seconds + Memory usage: 31404 (+18948) + drop_whitespace.parse done in 0.022 seconds + Memory usage: 28752 (+16296) + lxml.etree.XMLParser.feed(): 25317 nodes read in 0.026 seconds + Memory usage: 33924 (+21500) + minidom tree read in 0.194 seconds + Memory usage: 31284 (+18828) As can be seen from the sizes, both lxml.etree and cElementTree are -rather memory friendly compared to the pure Python libraries -ElementTree and (especially) minidom. Comparing to older CPython +rather memory friendly and fast. Comparing to older CPython versions, the memory footprint of the minidom library was considerably reduced in CPython 3.3, by about a factor of 4 in this case. @@ -277,26 +269,26 @@ rather close to each other, usually within a factor of two, with winners well distributed over both sides. Similar timings can be observed for the ``iterparse()`` function:: - lxe: iterparse_bytesIO (SAXR T1) 17.9198 msec/pass - cET: iterparse_bytesIO (SAXR T1) 14.4982 msec/pass + lxe: iterparse_bytesIO (SAXR T1) 20.3598 msec/pass + cET: iterparse_bytesIO (SAXR T1) 10.8948 msec/pass - lxe: iterparse_bytesIO (UAXR T3) 8.8522 msec/pass - cET: iterparse_bytesIO (UAXR T3) 12.9857 msec/pass + lxe: iterparse_bytesIO (UAXR T3) 10.1640 msec/pass + cET: iterparse_bytesIO (UAXR T3) 12.9926 msec/pass However, if you benchmark the complete round-trip of a serialise-parse cycle, the numbers will look similar to these:: - lxe: write_utf8_parse_bytesIO (S-TR T1) 19.8867 msec/pass - cET: write_utf8_parse_bytesIO (S-TR T1) 80.7259 msec/pass + lxe: write_utf8_parse_bytesIO (S-TR T1) 18.9857 msec/pass + cET: write_utf8_parse_bytesIO (S-TR T1) 35.7475 msec/pass - lxe: write_utf8_parse_bytesIO (UATR T2) 23.7896 msec/pass - cET: write_utf8_parse_bytesIO (UATR T2) 98.0766 msec/pass + lxe: write_utf8_parse_bytesIO (UATR T2) 22.4853 msec/pass + cET: write_utf8_parse_bytesIO (UATR T2) 42.6254 msec/pass - lxe: write_utf8_parse_bytesIO (S-TR T3) 3.0684 msec/pass - cET: write_utf8_parse_bytesIO (S-TR T3) 24.6122 msec/pass + lxe: write_utf8_parse_bytesIO (S-TR T3) 3.3801 msec/pass + cET: write_utf8_parse_bytesIO (S-TR T3) 11.2493 msec/pass - lxe: write_utf8_parse_bytesIO (SATR T4) 0.3495 msec/pass - cET: write_utf8_parse_bytesIO (SATR T4) 1.9610 msec/pass + lxe: write_utf8_parse_bytesIO (SATR T4) 0.4263 msec/pass + cET: write_utf8_parse_bytesIO (SATR T4) 1.0326 msec/pass For applications that require a high parser throughput of large files, and that do little to no serialization, both cET and lxml.etree are a @@ -352,14 +344,14 @@ restructuring. This can be seen from the tree setup times of the benchmark (given in seconds):: lxe: -- S- U- -A SA UA - T1: 0.0299 0.0343 0.0344 0.0293 0.0345 0.0342 - T2: 0.0368 0.0423 0.0418 0.0427 0.0474 0.0459 - T3: 0.0088 0.0084 0.0086 0.0251 0.0258 0.0261 - T4: 0.0002 0.0002 0.0002 0.0005 0.0006 0.0006 + T1: 0.0219 0.0254 0.0257 0.0216 0.0259 0.0259 + T2: 0.0234 0.0279 0.0283 0.0271 0.0318 0.0307 + T3: 0.0051 0.0050 0.0058 0.0218 0.0233 0.0231 + T4: 0.0001 0.0001 0.0001 0.0004 0.0004 0.0004 cET: -- S- U- -A SA UA - T1: 0.0050 0.0045 0.0093 0.0044 0.0043 0.0043 - T2: 0.0073 0.0075 0.0074 0.0201 0.0075 0.0074 - T3: 0.0033 0.0213 0.0032 0.0034 0.0033 0.0035 + T1: 0.0035 0.0029 0.0078 0.0031 0.0031 0.0029 + T2: 0.0047 0.0051 0.0053 0.0046 0.0055 0.0048 + T3: 0.0016 0.0216 0.0027 0.0021 0.0023 0.0026 T4: 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 The timings are somewhat close to each other, although cET can be @@ -379,30 +371,30 @@ The same tree overhead makes operations like collecting children as in a shallow copy of their list of children, lxml has to create a Python object for each child and collect them in a list:: - lxe: root_list_children (--TR T1) 0.0038 msec/pass - cET: root_list_children (--TR T1) 0.0010 msec/pass + lxe: root_list_children (--TR T1) 0.0036 msec/pass + cET: root_list_children (--TR T1) 0.0005 msec/pass - lxe: root_list_children (--TR T2) 0.0455 msec/pass - cET: root_list_children (--TR T2) 0.0050 msec/pass + lxe: root_list_children (--TR T2) 0.0634 msec/pass + cET: root_list_children (--TR T2) 0.0086 msec/pass This handicap is also visible when accessing single children:: - lxe: first_child (--TR T2) 0.0424 msec/pass - cET: first_child (--TR T2) 0.0384 msec/pass + lxe: first_child (--TR T2) 0.0601 msec/pass + cET: first_child (--TR T2) 0.0548 msec/pass - lxe: last_child (--TR T1) 0.0477 msec/pass - cET: last_child (--TR T1) 0.0467 msec/pass + lxe: last_child (--TR T1) 0.0570 msec/pass + cET: last_child (--TR T1) 0.0534 msec/pass ... unless you also add the time to find a child index in a bigger list. ET and cET use Python lists here, which are based on arrays. The data structure used by libxml2 is a linked tree, and thus, a linked list of children:: - lxe: middle_child (--TR T1) 0.0710 msec/pass - cET: middle_child (--TR T1) 0.0420 msec/pass + lxe: middle_child (--TR T1) 0.0892 msec/pass + cET: middle_child (--TR T1) 0.0510 msec/pass - lxe: middle_child (--TR T2) 1.7393 msec/pass - cET: middle_child (--TR T2) 0.0396 msec/pass + lxe: middle_child (--TR T2) 2.3038 msec/pass + cET: middle_child (--TR T2) 0.0508 msec/pass Element creation @@ -412,18 +404,18 @@ As opposed to ET, libxml2 has a notion of documents that each element must be in. This results in a major performance difference for creating independent Elements that end up in independently created documents:: - lxe: create_elements (--TC T2) 1.0045 msec/pass - cET: create_elements (--TC T2) 0.0753 msec/pass + lxe: create_elements (--TC T2) 0.8032 msec/pass + cET: create_elements (--TC T2) 0.0675 msec/pass Therefore, it is always preferable to create Elements for the document they are supposed to end up in, either as SubElements of an Element or using the explicit ``Element.makeelement()`` call:: - lxe: makeelement (--TC T2) 1.0586 msec/pass - cET: makeelement (--TC T2) 0.1483 msec/pass + lxe: makeelement (--TC T2) 0.8030 msec/pass + cET: makeelement (--TC T2) 0.0625 msec/pass - lxe: create_subelements (--TC T2) 0.8826 msec/pass - cET: create_subelements (--TC T2) 0.0827 msec/pass + lxe: create_subelements (--TC T2) 0.8621 msec/pass + cET: create_subelements (--TC T2) 0.0923 msec/pass So, if the main performance bottleneck of an application is creating large XML trees in memory through calls to Element and SubElement, cET is the best @@ -440,11 +432,11 @@ requires lxml to do recursive adaptations throughout the moved tree structure. The following benchmark appends all root children of the second tree to the root of the first tree:: - lxe: append_from_document (--TR T1,T2) 1.0812 msec/pass - cET: append_from_document (--TR T1,T2) 0.1104 msec/pass + lxe: append_from_document (--TR T1,T2) 1.3800 msec/pass + cET: append_from_document (--TR T1,T2) 0.0513 msec/pass - lxe: append_from_document (--TR T3,T4) 0.0155 msec/pass - cET: append_from_document (--TR T3,T4) 0.0060 msec/pass + lxe: append_from_document (--TR T3,T4) 0.0150 msec/pass + cET: append_from_document (--TR T3,T4) 0.0026 msec/pass Although these are fairly small numbers compared to parsing, this easily shows the different performance classes for lxml and (c)ET. Where the latter do not @@ -455,19 +447,19 @@ with the size of the tree that is moved. This difference is not always as visible, but applies to most parts of the API, like inserting newly created elements:: - lxe: insert_from_document (--TR T1,T2) 3.9763 msec/pass - cET: insert_from_document (--TR T1,T2) 0.1459 msec/pass + lxe: insert_from_document (--TR T1,T2) 5.2345 msec/pass + cET: insert_from_document (--TR T1,T2) 0.0732 msec/pass or replacing the child slice by a newly created element:: - lxe: replace_children_element (--TC T1) 0.0749 msec/pass - cET: replace_children_element (--TC T1) 0.0081 msec/pass + lxe: replace_children_element (--TC T1) 0.0720 msec/pass + cET: replace_children_element (--TC T1) 0.0105 msec/pass as opposed to replacing the slice with an existing element from the same document:: - lxe: replace_children (--TC T1) 0.0052 msec/pass - cET: replace_children (--TC T1) 0.0036 msec/pass + lxe: replace_children (--TC T1) 0.0060 msec/pass + cET: replace_children (--TC T1) 0.0050 msec/pass While these numbers are too small to provide a major performance impact in practice, you should keep this difference in mind when you @@ -481,14 +473,14 @@ deepcopy Deep copying a tree is fast in lxml:: - lxe: deepcopy_all (--TR T1) 3.1650 msec/pass - cET: deepcopy_all (--TR T1) 53.9973 msec/pass + lxe: deepcopy_all (--TR T1) 4.1246 msec/pass + cET: deepcopy_all (--TR T1) 2.5451 msec/pass - lxe: deepcopy_all (-ATR T2) 3.7365 msec/pass - cET: deepcopy_all (-ATR T2) 61.6267 msec/pass + lxe: deepcopy_all (-ATR T2) 4.7867 msec/pass + cET: deepcopy_all (-ATR T2) 2.7504 msec/pass - lxe: deepcopy_all (S-TR T3) 0.7913 msec/pass - cET: deepcopy_all (S-TR T3) 13.6220 msec/pass + lxe: deepcopy_all (S-TR T3) 1.0097 msec/pass + cET: deepcopy_all (S-TR T3) 0.6278 msec/pass So, for example, if you have a database-like scenario where you parse in a large tree and then search and copy independent subtrees from it for further @@ -504,31 +496,31 @@ traversal of the XML tree and especially if few elements are of interest or the target element tag name is known, the ``.iter()`` method is a good choice:: - lxe: iter_all (--TR T1) 1.0529 msec/pass - cET: iter_all (--TR T1) 0.2635 msec/pass + lxe: iter_all (--TR T1) 1.3661 msec/pass + cET: iter_all (--TR T1) 0.2670 msec/pass - lxe: iter_islice (--TR T2) 0.0110 msec/pass - cET: iter_islice (--TR T2) 0.0050 msec/pass + lxe: iter_islice (--TR T2) 0.0122 msec/pass + cET: iter_islice (--TR T2) 0.0033 msec/pass - lxe: iter_tag (--TR T2) 0.0079 msec/pass - cET: iter_tag (--TR T2) 0.0112 msec/pass + lxe: iter_tag (--TR T2) 0.0098 msec/pass + cET: iter_tag (--TR T2) 0.0086 msec/pass - lxe: iter_tag_all (--TR T2) 0.1822 msec/pass - cET: iter_tag_all (--TR T2) 0.5343 msec/pass + lxe: iter_tag_all (--TR T2) 0.6840 msec/pass + cET: iter_tag_all (--TR T2) 0.4323 msec/pass This translates directly into similar timings for ``Element.findall()``:: - lxe: findall (--TR T2) 1.7176 msec/pass - cET: findall (--TR T2) 0.9973 msec/pass + lxe: findall (--TR T2) 3.9611 msec/pass + cET: findall (--TR T2) 0.9227 msec/pass - lxe: findall (--TR T3) 0.3967 msec/pass - cET: findall (--TR T3) 0.2525 msec/pass + lxe: findall (--TR T3) 0.3989 msec/pass + cET: findall (--TR T3) 0.2670 msec/pass - lxe: findall_tag (--TR T2) 0.2258 msec/pass - cET: findall_tag (--TR T2) 0.5770 msec/pass + lxe: findall_tag (--TR T2) 0.7420 msec/pass + cET: findall_tag (--TR T2) 0.4942 msec/pass - lxe: findall_tag (--TR T3) 0.1085 msec/pass - cET: findall_tag (--TR T3) 0.1919 msec/pass + lxe: findall_tag (--TR T3) 0.1099 msec/pass + cET: findall_tag (--TR T3) 0.1748 msec/pass Note that all three libraries currently use the same Python implementation for ``.findall()``, except for their native tree @@ -548,38 +540,38 @@ provides more than one way of accessing it and you should take care which part of the lxml API you use. The most straight forward way is to call the ``xpath()`` method on an Element or ElementTree:: - lxe: xpath_method (--TC T1) 0.3982 msec/pass - lxe: xpath_method (--TC T2) 7.8895 msec/pass - lxe: xpath_method (--TC T3) 0.0477 msec/pass - lxe: xpath_method (--TC T4) 0.3982 msec/pass + lxe: xpath_method (--TC T1) 0.2828 msec/pass + lxe: xpath_method (--TC T2) 5.4705 msec/pass + lxe: xpath_method (--TC T3) 0.0324 msec/pass + lxe: xpath_method (--TC T4) 0.2804 msec/pass This is well suited for testing and when the XPath expressions are as diverse as the trees they are called on. However, if you have a single XPath expression that you want to apply to a larger number of different elements, the ``XPath`` class is the most efficient way to do it:: - lxe: xpath_class (--TC T1) 0.0713 msec/pass - lxe: xpath_class (--TC T2) 1.1325 msec/pass - lxe: xpath_class (--TC T3) 0.0215 msec/pass - lxe: xpath_class (--TC T4) 0.0722 msec/pass + lxe: xpath_class (--TC T1) 0.0570 msec/pass + lxe: xpath_class (--TC T2) 0.6924 msec/pass + lxe: xpath_class (--TC T3) 0.0148 msec/pass + lxe: xpath_class (--TC T4) 0.0446 msec/pass Note that this still allows you to use variables in the expression, so you can parse it once and then adapt it through variables at call time. In other cases, where you have a fixed Element or ElementTree and want to run different expressions on it, you should consider the ``XPathEvaluator``:: - lxe: xpath_element (--TR T1) 0.1101 msec/pass - lxe: xpath_element (--TR T2) 2.0473 msec/pass - lxe: xpath_element (--TR T3) 0.0267 msec/pass - lxe: xpath_element (--TR T4) 0.1087 msec/pass + lxe: xpath_element (--TR T1) 0.0684 msec/pass + lxe: xpath_element (--TR T2) 1.0865 msec/pass + lxe: xpath_element (--TR T3) 0.0174 msec/pass + lxe: xpath_element (--TR T4) 0.0665 msec/pass While it looks slightly slower, creating an XPath object for each of the expressions generates a much higher overhead here:: - lxe: xpath_class_repeat (--TC T1 ) 0.3884 msec/pass - lxe: xpath_class_repeat (--TC T2 ) 7.6182 msec/pass - lxe: xpath_class_repeat (--TC T3 ) 0.0465 msec/pass - lxe: xpath_class_repeat (--TC T4 ) 0.3877 msec/pass + lxe: xpath_class_repeat (--TC T1 ) 0.2813 msec/pass + lxe: xpath_class_repeat (--TC T2 ) 5.4042 msec/pass + lxe: xpath_class_repeat (--TC T3 ) 0.0339 msec/pass + lxe: xpath_class_repeat (--TC T4 ) 0.2706 msec/pass Note that tree iteration can be substantially faster than XPath if your code short-circuits after the first couple of elements were @@ -589,25 +581,25 @@ regardless of how much of it will actually be used. Here is an example where only the first matching element is being searched, a case for which XPath has syntax support as well:: - lxe: find_single (--TR T2) 0.0184 msec/pass - cET: find_single (--TR T2) 0.0052 msec/pass + lxe: find_single (--TR T2) 0.0031 msec/pass + cET: find_single (--TR T2) 0.0026 msec/pass - lxe: iter_single (--TR T2) 0.0024 msec/pass - cET: iter_single (--TR T2) 0.0007 msec/pass + lxe: iter_single (--TR T2) 0.0019 msec/pass + cET: iter_single (--TR T2) 0.0002 msec/pass - lxe: xpath_single (--TR T2) 0.0033 msec/pass + lxe: xpath_single (--TR T2) 0.0861 msec/pass When looking for the first two elements out of many, the numbers explode for XPath, as restricting the result subset requires a more complex expression:: - lxe: iterfind_two (--TR T2) 0.0184 msec/pass - cET: iterfind_two (--TR T2) 0.0062 msec/pass + lxe: iterfind_two (--TR T2) 0.0050 msec/pass + cET: iterfind_two (--TR T2) 0.0036 msec/pass - lxe: iter_two (--TR T2) 0.0029 msec/pass - cET: iter_two (--TR T2) 0.0017 msec/pass + lxe: iter_two (--TR T2) 0.0021 msec/pass + cET: iter_two (--TR T2) 0.0014 msec/pass - lxe: xpath_two (--TR T2) 0.2768 msec/pass + lxe: xpath_two (--TR T2) 0.0916 msec/pass A longer example @@ -774,21 +766,21 @@ ObjectPath can be used to speed up the access to elements that are deep in the tree. It avoids step-by-step Python element instantiations along the path, which can substantially improve the access time:: - lxe: attribute (--TR T1) 4.1828 msec/pass - lxe: attribute (--TR T2) 17.3802 msec/pass - lxe: attribute (--TR T4) 3.8657 msec/pass + lxe: attribute (--TR T1) 2.4018 msec/pass + lxe: attribute (--TR T2) 16.3755 msec/pass + lxe: attribute (--TR T4) 2.3725 msec/pass - lxe: objectpath (--TR T1) 0.9289 msec/pass - lxe: objectpath (--TR T2) 13.3109 msec/pass - lxe: objectpath (--TR T4) 0.9289 msec/pass + lxe: objectpath (--TR T1) 1.1816 msec/pass + lxe: objectpath (--TR T2) 14.4675 msec/pass + lxe: objectpath (--TR T4) 1.2276 msec/pass - lxe: attributes_deep (--TR T1) 6.2900 msec/pass - lxe: attributes_deep (--TR T2) 20.4713 msec/pass - lxe: attributes_deep (--TR T4) 6.1679 msec/pass + lxe: attributes_deep (--TR T1) 3.7086 msec/pass + lxe: attributes_deep (--TR T2) 17.5436 msec/pass + lxe: attributes_deep (--TR T4) 3.8407 msec/pass - lxe: objectpath_deep (--TR T1) 1.3049 msec/pass - lxe: objectpath_deep (--TR T2) 14.0815 msec/pass - lxe: objectpath_deep (--TR T4) 1.3051 msec/pass + lxe: objectpath_deep (--TR T1) 1.4980 msec/pass + lxe: objectpath_deep (--TR T2) 14.7266 msec/pass + lxe: objectpath_deep (--TR T4) 1.4834 msec/pass Note, however, that parsing ObjectPath expressions is not for free either, so this is most effective for frequently accessing the same element. @@ -818,17 +810,17 @@ expressions to be more selective. By choosing the right trees (or even subtrees and elements) to cache, you can trade memory usage against access speed:: - lxe: attribute_cached (--TR T1) 3.1357 msec/pass - lxe: attribute_cached (--TR T2) 15.8911 msec/pass - lxe: attribute_cached (--TR T4) 2.9194 msec/pass + lxe: attribute_cached (--TR T1) 1.9207 msec/pass + lxe: attribute_cached (--TR T2) 15.6903 msec/pass + lxe: attribute_cached (--TR T4) 1.8718 msec/pass - lxe: attributes_deep_cached (--TR T1) 3.8984 msec/pass - lxe: attributes_deep_cached (--TR T2) 16.8300 msec/pass - lxe: attributes_deep_cached (--TR T4) 3.6936 msec/pass + lxe: attributes_deep_cached (--TR T1) 2.6512 msec/pass + lxe: attributes_deep_cached (--TR T2) 16.7937 msec/pass + lxe: attributes_deep_cached (--TR T4) 2.5539 msec/pass - lxe: objectpath_deep_cached (--TR T1) 0.7496 msec/pass - lxe: objectpath_deep_cached (--TR T2) 12.3763 msec/pass - lxe: objectpath_deep_cached (--TR T4) 0.7427 msec/pass + lxe: objectpath_deep_cached (--TR T1) 0.8519 msec/pass + lxe: objectpath_deep_cached (--TR T2) 13.9337 msec/pass + lxe: objectpath_deep_cached (--TR T4) 0.8645 msec/pass Things to note: you cannot currently use ``weakref.WeakKeyDictionary`` objects for this as lxml's element objects do not support weak references (which are diff --git a/doc/s5/lxml-ep2008.html b/doc/s5/lxml-ep2008.html index 008bc99..62ffda7 100644 --- a/doc/s5/lxml-ep2008.html +++ b/doc/s5/lxml-ep2008.html @@ -3,7 +3,7 @@ - + Implementing XML languages with lxml