pax_global_header00006660000000000000000000000064147104167110014514gustar00rootroot0000000000000052 comment=fcc60e0fc842d435a07ab2c4fb9e93cd8d50a543 ionelmc-pytest-benchmark-5edf251/000077500000000000000000000000001471041671100170355ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/.bumpversion.cfg000066400000000000000000000013451471041671100221500ustar00rootroot00000000000000[bumpversion] current_version = 5.1.0 commit = True tag = True [bumpversion:file:setup.py] search = version='{current_version}' replace = version='{new_version}' [bumpversion:file (badge):README.rst] search = /v{current_version}.svg replace = /v{new_version}.svg [bumpversion:file (link):README.rst] search = /v{current_version}...main replace = /v{new_version}...main [bumpversion:file:docs/conf.py] search = version = release = '{current_version}' replace = version = release = '{new_version}' [bumpversion:file:src/pytest_benchmark/__init__.py] search = __version__ = '{current_version}' replace = __version__ = '{new_version}' [bumpversion:file:.cookiecutterrc] search = version: {current_version} replace = version: {new_version} ionelmc-pytest-benchmark-5edf251/.cookiecutterrc000066400000000000000000000031431471041671100220640ustar00rootroot00000000000000# Generated by cookiepatcher, a small shim around cookiecutter (pip install cookiepatcher) default_context: c_extension_optional: 'no' c_extension_support: 'no' codacy: 'no' codacy_projectid: '[Get ID from https://app.codacy.com/app/ionelmc/pytest-benchmark/settings]' codeclimate: 'no' codecov: 'yes' command_line_interface: argparse command_line_interface_bin_name: py.test-benchmark coveralls: 'yes' distribution_name: pytest-benchmark email: contact@ionelmc.ro formatter_quote_style: single full_name: Ionel Cristian Mărieș function_name: compute github_actions: 'yes' github_actions_osx: 'yes' github_actions_windows: 'yes' license: BSD 2-Clause License module_name: core package_name: pytest_benchmark pre_commit: 'yes' project_name: pytest-benchmark project_short_description: A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. pypi_badge: 'yes' pypi_disable_upload: 'no' release_date: '2022-10-26' repo_hosting: github.com repo_hosting_domain: github.com repo_main_branch: main repo_name: pytest-benchmark repo_username: ionelmc scrutinizer: 'no' setup_py_uses_setuptools_scm: 'no' sphinx_docs: 'yes' sphinx_docs_hosting: https://pytest-benchmark.readthedocs.io/ sphinx_doctest: 'no' sphinx_theme: furo test_matrix_separate_coverage: 'yes' tests_inside_package: 'no' version: 5.1.0 version_manager: bump2version website: http://blog.ionelmc.ro year_from: '2014' year_to: '2023' ionelmc-pytest-benchmark-5edf251/.coveragerc000066400000000000000000000002651471041671100211610ustar00rootroot00000000000000[paths] source = src [run] branch = true source = src tests parallel = true [report] show_missing = true precision = 2 omit = *migrations* *pep418* *hookspec* ionelmc-pytest-benchmark-5edf251/.editorconfig000066400000000000000000000005411471041671100215120ustar00rootroot00000000000000# see https://editorconfig.org/ root = true [*] # Use Unix-style newlines for most files (except Windows files, see below). end_of_line = lf trim_trailing_whitespace = true indent_style = space insert_final_newline = true indent_size = 4 charset = utf-8 [*.{bat,cmd,ps1}] end_of_line = crlf [*.{yml,yaml}] indent_size = 2 [*.tsv] indent_style = tab ionelmc-pytest-benchmark-5edf251/.github/000077500000000000000000000000001471041671100203755ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/.github/workflows/000077500000000000000000000000001471041671100224325ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/.github/workflows/github-actions.yml000066400000000000000000000435231471041671100261040ustar00rootroot00000000000000name: build on: [push, pull_request, workflow_dispatch] jobs: test: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} timeout-minutes: 30 strategy: fail-fast: false matrix: include: - name: 'check' python: '3.11' toxpython: 'python3.11' tox_env: 'check' os: 'ubuntu-latest' - name: 'docs' python: '3.11' toxpython: 'python3.11' tox_env: 'docs' os: 'ubuntu-latest' - name: 'py39-pytest83-nodist-cover (ubuntu)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-nodist-cover' os: 'ubuntu-latest' - name: 'py39-pytest83-nodist-cover (windows)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-nodist-cover' os: 'windows-latest' - name: 'py39-pytest83-nodist-cover (macos)' python: '3.9' toxpython: 'python3.9' python_arch: 'arm64' tox_env: 'py39-pytest83-nodist-cover' os: 'macos-latest' - name: 'py39-pytest83-nodist-nocov (ubuntu)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-nodist-nocov' os: 'ubuntu-latest' - name: 'py39-pytest83-nodist-nocov (windows)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-nodist-nocov' os: 'windows-latest' - name: 'py39-pytest83-nodist-nocov (macos)' python: '3.9' toxpython: 'python3.9' python_arch: 'arm64' tox_env: 'py39-pytest83-nodist-nocov' os: 'macos-latest' - name: 'py39-pytest83-xdist-cover (ubuntu)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-xdist-cover' os: 'ubuntu-latest' - name: 'py39-pytest83-xdist-cover (windows)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-xdist-cover' os: 'windows-latest' - name: 'py39-pytest83-xdist-cover (macos)' python: '3.9' toxpython: 'python3.9' python_arch: 'arm64' tox_env: 'py39-pytest83-xdist-cover' os: 'macos-latest' - name: 'py39-pytest83-xdist-nocov (ubuntu)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-xdist-nocov' os: 'ubuntu-latest' - name: 'py39-pytest83-xdist-nocov (windows)' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' tox_env: 'py39-pytest83-xdist-nocov' os: 'windows-latest' - name: 'py39-pytest83-xdist-nocov (macos)' python: '3.9' toxpython: 'python3.9' python_arch: 'arm64' tox_env: 'py39-pytest83-xdist-nocov' os: 'macos-latest' - name: 'py310-pytest83-nodist-cover (ubuntu)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-nodist-cover' os: 'ubuntu-latest' - name: 'py310-pytest83-nodist-cover (windows)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-nodist-cover' os: 'windows-latest' - name: 'py310-pytest83-nodist-cover (macos)' python: '3.10' toxpython: 'python3.10' python_arch: 'arm64' tox_env: 'py310-pytest83-nodist-cover' os: 'macos-latest' - name: 'py310-pytest83-nodist-nocov (ubuntu)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-nodist-nocov' os: 'ubuntu-latest' - name: 'py310-pytest83-nodist-nocov (windows)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-nodist-nocov' os: 'windows-latest' - name: 'py310-pytest83-nodist-nocov (macos)' python: '3.10' toxpython: 'python3.10' python_arch: 'arm64' tox_env: 'py310-pytest83-nodist-nocov' os: 'macos-latest' - name: 'py310-pytest83-xdist-cover (ubuntu)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-xdist-cover' os: 'ubuntu-latest' - name: 'py310-pytest83-xdist-cover (windows)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-xdist-cover' os: 'windows-latest' - name: 'py310-pytest83-xdist-cover (macos)' python: '3.10' toxpython: 'python3.10' python_arch: 'arm64' tox_env: 'py310-pytest83-xdist-cover' os: 'macos-latest' - name: 'py310-pytest83-xdist-nocov (ubuntu)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-xdist-nocov' os: 'ubuntu-latest' - name: 'py310-pytest83-xdist-nocov (windows)' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' tox_env: 'py310-pytest83-xdist-nocov' os: 'windows-latest' - name: 'py310-pytest83-xdist-nocov (macos)' python: '3.10' toxpython: 'python3.10' python_arch: 'arm64' tox_env: 'py310-pytest83-xdist-nocov' os: 'macos-latest' - name: 'py311-pytest83-nodist-cover (ubuntu)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-nodist-cover' os: 'ubuntu-latest' - name: 'py311-pytest83-nodist-cover (windows)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-nodist-cover' os: 'windows-latest' - name: 'py311-pytest83-nodist-cover (macos)' python: '3.11' toxpython: 'python3.11' python_arch: 'arm64' tox_env: 'py311-pytest83-nodist-cover' os: 'macos-latest' - name: 'py311-pytest83-nodist-nocov (ubuntu)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-nodist-nocov' os: 'ubuntu-latest' - name: 'py311-pytest83-nodist-nocov (windows)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-nodist-nocov' os: 'windows-latest' - name: 'py311-pytest83-nodist-nocov (macos)' python: '3.11' toxpython: 'python3.11' python_arch: 'arm64' tox_env: 'py311-pytest83-nodist-nocov' os: 'macos-latest' - name: 'py311-pytest83-xdist-cover (ubuntu)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-xdist-cover' os: 'ubuntu-latest' - name: 'py311-pytest83-xdist-cover (windows)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-xdist-cover' os: 'windows-latest' - name: 'py311-pytest83-xdist-cover (macos)' python: '3.11' toxpython: 'python3.11' python_arch: 'arm64' tox_env: 'py311-pytest83-xdist-cover' os: 'macos-latest' - name: 'py311-pytest83-xdist-nocov (ubuntu)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-xdist-nocov' os: 'ubuntu-latest' - name: 'py311-pytest83-xdist-nocov (windows)' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' tox_env: 'py311-pytest83-xdist-nocov' os: 'windows-latest' - name: 'py311-pytest83-xdist-nocov (macos)' python: '3.11' toxpython: 'python3.11' python_arch: 'arm64' tox_env: 'py311-pytest83-xdist-nocov' os: 'macos-latest' - name: 'py312-pytest83-nodist-cover (ubuntu)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-nodist-cover' os: 'ubuntu-latest' - name: 'py312-pytest83-nodist-cover (windows)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-nodist-cover' os: 'windows-latest' - name: 'py312-pytest83-nodist-cover (macos)' python: '3.12' toxpython: 'python3.12' python_arch: 'arm64' tox_env: 'py312-pytest83-nodist-cover' os: 'macos-latest' - name: 'py312-pytest83-nodist-nocov (ubuntu)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-nodist-nocov' os: 'ubuntu-latest' - name: 'py312-pytest83-nodist-nocov (windows)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-nodist-nocov' os: 'windows-latest' - name: 'py312-pytest83-nodist-nocov (macos)' python: '3.12' toxpython: 'python3.12' python_arch: 'arm64' tox_env: 'py312-pytest83-nodist-nocov' os: 'macos-latest' - name: 'py312-pytest83-xdist-cover (ubuntu)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-xdist-cover' os: 'ubuntu-latest' - name: 'py312-pytest83-xdist-cover (windows)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-xdist-cover' os: 'windows-latest' - name: 'py312-pytest83-xdist-cover (macos)' python: '3.12' toxpython: 'python3.12' python_arch: 'arm64' tox_env: 'py312-pytest83-xdist-cover' os: 'macos-latest' - name: 'py312-pytest83-xdist-nocov (ubuntu)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-xdist-nocov' os: 'ubuntu-latest' - name: 'py312-pytest83-xdist-nocov (windows)' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' tox_env: 'py312-pytest83-xdist-nocov' os: 'windows-latest' - name: 'py312-pytest83-xdist-nocov (macos)' python: '3.12' toxpython: 'python3.12' python_arch: 'arm64' tox_env: 'py312-pytest83-xdist-nocov' os: 'macos-latest' - name: 'pypy39-pytest83-nodist-cover (ubuntu)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-nodist-cover' os: 'ubuntu-latest' - name: 'pypy39-pytest83-nodist-cover (windows)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-nodist-cover' os: 'windows-latest' - name: 'pypy39-pytest83-nodist-cover (macos)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'arm64' tox_env: 'pypy39-pytest83-nodist-cover' os: 'macos-latest' - name: 'pypy39-pytest83-nodist-nocov (ubuntu)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-nodist-nocov' os: 'ubuntu-latest' - name: 'pypy39-pytest83-nodist-nocov (windows)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-nodist-nocov' os: 'windows-latest' - name: 'pypy39-pytest83-nodist-nocov (macos)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'arm64' tox_env: 'pypy39-pytest83-nodist-nocov' os: 'macos-latest' - name: 'pypy39-pytest83-xdist-cover (ubuntu)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-xdist-cover' os: 'ubuntu-latest' - name: 'pypy39-pytest83-xdist-cover (windows)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-xdist-cover' os: 'windows-latest' - name: 'pypy39-pytest83-xdist-cover (macos)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'arm64' tox_env: 'pypy39-pytest83-xdist-cover' os: 'macos-latest' - name: 'pypy39-pytest83-xdist-nocov (ubuntu)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-xdist-nocov' os: 'ubuntu-latest' - name: 'pypy39-pytest83-xdist-nocov (windows)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' tox_env: 'pypy39-pytest83-xdist-nocov' os: 'windows-latest' - name: 'pypy39-pytest83-xdist-nocov (macos)' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'arm64' tox_env: 'pypy39-pytest83-xdist-nocov' os: 'macos-latest' - name: 'pypy310-pytest83-nodist-cover (ubuntu)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-nodist-cover' os: 'ubuntu-latest' - name: 'pypy310-pytest83-nodist-cover (windows)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-nodist-cover' os: 'windows-latest' - name: 'pypy310-pytest83-nodist-cover (macos)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'arm64' tox_env: 'pypy310-pytest83-nodist-cover' os: 'macos-latest' - name: 'pypy310-pytest83-nodist-nocov (ubuntu)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-nodist-nocov' os: 'ubuntu-latest' - name: 'pypy310-pytest83-nodist-nocov (windows)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-nodist-nocov' os: 'windows-latest' - name: 'pypy310-pytest83-nodist-nocov (macos)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'arm64' tox_env: 'pypy310-pytest83-nodist-nocov' os: 'macos-latest' - name: 'pypy310-pytest83-xdist-cover (ubuntu)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-xdist-cover' os: 'ubuntu-latest' - name: 'pypy310-pytest83-xdist-cover (windows)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-xdist-cover' os: 'windows-latest' - name: 'pypy310-pytest83-xdist-cover (macos)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'arm64' tox_env: 'pypy310-pytest83-xdist-cover' os: 'macos-latest' - name: 'pypy310-pytest83-xdist-nocov (ubuntu)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-xdist-nocov' os: 'ubuntu-latest' - name: 'pypy310-pytest83-xdist-nocov (windows)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' tox_env: 'pypy310-pytest83-xdist-nocov' os: 'windows-latest' - name: 'pypy310-pytest83-xdist-nocov (macos)' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'arm64' tox_env: 'pypy310-pytest83-xdist-nocov' os: 'macos-latest' steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} architecture: ${{ matrix.python_arch }} - name: install dependencies run: | python -mpip install --progress-bar=off -r ci/requirements.txt virtualenv --version pip --version tox --version pip list --format=freeze - name: test env: TOXPYTHON: '${{ matrix.toxpython }}' run: > tox -e ${{ matrix.tox_env }} -v finish: needs: test if: ${{ always() }} runs-on: ubuntu-latest steps: - uses: coverallsapp/github-action@v2 with: parallel-finished: true - uses: codecov/codecov-action@v3 with: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} ionelmc-pytest-benchmark-5edf251/.gitignore000066400000000000000000000012461471041671100210300ustar00rootroot00000000000000*.py[cod] __pycache__ # Temp files .*.sw[po] *~ *.bak .DS_Store # C extensions *.so # Build and package files *.egg *.egg-info .bootstrap .build .cache .eggs .env .installed.cfg .ve bin build develop-eggs dist eggs lib lib64 parts pip-wheel-metadata/ pyvenv*/ sdist var venv*/ wheelhouse # Installer logs pip-log.txt # Unit test / coverage reports .benchmarks .coverage .coverage.* .pytest .pytest_cache/ .tox coverage.xml htmlcov nosetests.xml # Translations *.mo # Buildout .mr.developer.cfg # IDE project files *.iml *.komodoproject .idea .project .pydevproject .vscode # Complexity output/*.html output/*/index.html # Sphinx docs/_build # Mypy Cache .mypy_cache/ ionelmc-pytest-benchmark-5edf251/.pre-commit-config.yaml000066400000000000000000000012021471041671100233110ustar00rootroot00000000000000# To install the git pre-commit hooks run: # pre-commit install --install-hooks # To update the versions: # pre-commit autoupdate exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' # Note the order is intentional to avoid multiple passes of the hooks repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.7.1 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --show-fixes, --unsafe-fixes] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: debug-statements ionelmc-pytest-benchmark-5edf251/.readthedocs.yml000066400000000000000000000004321471041671100221220ustar00rootroot00000000000000# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 sphinx: configuration: docs/conf.py formats: all build: os: ubuntu-22.04 tools: python: "3" python: install: - requirements: docs/requirements.txt - method: pip path: . ionelmc-pytest-benchmark-5edf251/AUTHORS.rst000066400000000000000000000031251471041671100207150ustar00rootroot00000000000000 Authors ======= * Ionel Cristian Mărieș - https://blog.ionelmc.ro * Marc Abramowitz - http://marc-abramowitz.com * Dave Collins - https://github.com/thedavecollins * Stefan Krastanov - http://blog.krastanov.org * Thomas Waldmann - https://github.com/ThomasWaldmann * Antonio Cuni - http://antocuni.eu * Petr Šebek - https://github.com/Artimi * Swen Kooij - https://github.com/Photonios * "varac" - https://github.com/varac * Andre Bianchi - https://github.com/drebs * Jeremy Dobbins-Bucklad - https://github.com/jad-b * Alexey Popravka - https://github.com/popravich * Ken Crowell - https://github.com/oeuftete * Matthew Feickert - https://github.com/matthewfeickert * Julien Nicoulaud - https://github.com/nicoulaj * Pablo Aguiar - https://github.com/scorphus * Alex Ford - https://github.com/asford * Francesco Ballarin - https://github.com/francesco-ballarin * Lincoln de Sousa - https://github.com/clarete * Jose Eduardo - https://github.com/JoseKilo * Ofek Lev - https://github.com/ofek * Anton Lodder - https://github.com/AnjoMan * Alexander Duryagin - https://github.com/daa * Stanislav Levin - https://github.com/stanislavlevin * Grygorii Iermolenko - https://github.com/gyermolenko * Jonathan Simon Prates - https://github.com/jonathansp * Miroslav Šedivý - https://github.com/eumiro * Dimitris Rozakis - https://github.com/dimrozakis * Friedrich Delgado - https://github.com/TauPan * Sam James - https://github.com/thesamesam * Florian Bruhin - https://github.com/The-Compiler * Johnny Huang - https://github.com/jnhyperion * Tony Kuo - https://github.com/tony92151 * Eugeniy - https://github.com/zcoder ionelmc-pytest-benchmark-5edf251/CHANGELOG.rst000066400000000000000000000443161471041671100210660ustar00rootroot00000000000000 Changelog ========= 5.1.0 (2024-10-30) ------------------ * Fixed broken hooks handling on pytest 8.1 or later (the ``TypeError: import_path() missing 1 required keyword-only argument: 'consider_namespace_packages'`` issue). Unfortunately this sets the minimum supported pytest version to 8.1. 5.0.1 (2024-10-30) ------------------ * Fixed bad fixture check that broke down then `nbmake `_ was enabled. 5.0.0 (2024-10-29) ------------------ * Dropped support for now EOL Python 3.8. Also moved tests suite to only test the latest pytest versions (8.3.x). * Fix generate parametrize tests benchmark csv report errors (issue `#268 `_). Contributed by Johnny Huang in `#269 `_. * Added the ``--benchmark-time-unit`` cli option for overriding the measurement unit used for display. Contributed by Tony Kuo in `#257 `_. * Fixes spelling in some help texts. Contributed by Eugeniy in `#267 `_. * Added new cprofile options: - ``--benchmark-cprofile-loops=LOOPS`` - previously profiling only ran the function once, this allow customization. - ``--benchmark-cprofile-top=COUNT`` - allows showing more rows. - ``--benchmark-cprofile-dump=[FILENAME-PREFIX]`` - allows saving to a file (that you can load in `snakeviz `_, `RunSnakeRun `_ or other tools). * Removed hidden dependency on `py.path `_ (replaced with pathlib). 4.0.0 (2022-10-26) ------------------ * Dropped support for legacy Pythons (2.7, 3.6 or older). * Switched CI to GitHub Actions. * Removed dependency on the ``py`` library (that was not properly specified as a dependency anyway). * Fix skipping test in `test_utils.py` if appropriate VCS not available. Also fix typo. Contributed by Sam James in `#211 `_. * Added support for pytest 7.2.0 by using ``pytest.hookimpl`` and ``pytest.hookspec`` to configure hooks. Contributed by Florian Bruhin in `#224 `_. * Now no save is attempted if ``--benchmark-disable`` is used. Fixes `#205 `_. Contributed by Friedrich Delgado in `#207 `_. 3.4.1 (2021-04-17) ------------------ * Republished with updated changelog. I intended to publish a ``3.3.0`` release but I messed it up because bumpversion doesn't work well with pre-commit apparently... thus ``3.4.0`` was set in by accident. 3.4.0 (2021-04-17) ------------------ * Disable progress indication unless ``--benchmark-verbose`` is used. Contributed by Dimitris Rozakis in `#149 `_. * Added Python 3.9, dropped Python 3.5. Contributed by Miroslav Šedivý in `#189 `_. * Changed the "cpu" data in the json output to include everything that cpuinfo outputs, for better or worse as cpuinfo 6.0 changed some fields. Users should now ensure they are an adequate cpuinfo package installed. **MAY BE BACKWARDS INCOMPATIBLE** * Changed behavior of ``--benchmark-skip`` and ``--benchmark-only`` to apply early in the collection phase. This means skipped tests won't make pytest run fixtures for said tests unnecessarily, but unfortunately this also means the skipping behavior will be applied to any tests that requires a "benchmark" fixture, regardless if it would come from pytest-benchmark or not. **MAY BE BACKWARDS INCOMPATIBLE** * Added ``--benchmark-quiet`` - option to disable reporting and other information output. * Squelched unnecessary warning when ``--benchmark-disable`` and save options are used. Fixes `#199 `_. * ``PerformanceRegression`` exception no longer inherits ``pytest.UsageError`` (apparently a *final* class). 3.2.3 (2020-01-10) ------------------ * Fixed "already-imported" pytest warning. Contributed by Jonathan Simon Prates in `#151 `_. * Fixed breakage that occurs when benchmark is disabled while using cprofile feature (by disabling cprofile too). * Dropped Python 3.4 from the test suite and updated test deps. * Fixed ``pytest_benchmark.utils.clonefunc`` to work on Python 3.8. 3.2.2 (2017-01-12) ------------------ * Added support for pytest items without funcargs. Fixes interoperability with other pytest plugins like pytest-flake8. 3.2.1 (2017-01-10) ------------------ * Updated changelog entries for 3.2.0. I made the release for pytest-cov on the same day and thought I updated the changelogs for both plugins. Alas, I only updated pytest-cov. * Added missing version constraint change. Now pytest >= 3.8 is required (due to pytest 4.1 support). * Fixed couple CI/test issues. * Fixed broken ``pytest_benchmark.__version__``. 3.2.0 (2017-01-07) ------------------ * Added support for simple ``trial`` x-axis histogram label. Contributed by Ken Crowell in `#95 `_). * Added support for Pytest 3.3+, Contributed by Julien Nicoulaud in `#103 `_. * Added support for Pytest 4.0. Contributed by Pablo Aguiar in `#129 `_ and `#130 `_. * Added support for Pytest 4.1. * Various formatting, spelling and documentation fixes. Contributed by Ken Crowell, Ofek Lev, Matthew Feickert, Jose Eduardo, Anton Lodder, Alexander Duryagin and Grygorii Iermolenko in `#97 `_, `#105 `_, `#110 `_, `#111 `_, `#115 `_, `#123 `_, `#131 `_ and `#140 `_. * Fixed broken ``pytest_benchmark_update_machine_info`` hook. Contributed by Alex Ford in `#109 `_. * Fixed bogus xdist warning when using ``--benchmark-disable``. Contributed by Francesco Ballarin in `#113 `_. * Added support for pathlib2. Contributed by Lincoln de Sousa in `#114 `_. * Changed handling so you can use ``--benchmark-skip`` and ``--benchmark-only``, with the later having priority. Contributed by Ofek Lev in `#116 `_. * Fixed various CI/testing issues. Contributed by Stanislav Levin in `#134 `_, `#136 `_ and `#138 `_. 3.1.1 (2017-07-26) ------------------ * Fixed loading data from old json files (missing ``ops`` field, see `#81 `_). * Fixed regression on broken SCM (see `#82 `_). 3.1.0 (2017-07-21) ------------------ * Added "operations per second" (``ops`` field in ``Stats``) metric -- shows the call rate of code being tested. Contributed by Alexey Popravka in `#78 `_. * Added a ``time`` field in ``commit_info``. Contributed by "varac" in `#71 `_. * Added a ``author_time`` field in ``commit_info``. Contributed by "varac" in `#75 `_. * Fixed the leaking of credentials by masking the URL printed when storing data to elasticsearch. * Added a ``--benchmark-netrc`` option to use credentials from a netrc file when storing data to elasticsearch. Both contributed by Andre Bianchi in `#73 `_. * Fixed docs on hooks. Contributed by Andre Bianchi in `#74 `_. * Remove ``git`` and ``hg`` as system dependencies when guessing the project name. 3.1.0a2 (2017-03-27) -------------------- * ``machine_info`` now contains more detailed information about the CPU, in particular the exact model. Contributed by Antonio Cuni in `#61 `_. * Added ``benchmark.extra_info``, which you can use to save arbitrary stuff in the JSON. Contributed by Antonio Cuni in the same PR as above. * Fix support for latest PyGal version (histograms). Contributed by Swen Kooij in `#68 `_. * Added support for getting ``commit_info`` when not running in the root of the repository. Contributed by Vara Canero in `#69 `_. * Added short form for ``--storage``/``--verbose`` options in CLI. * Added an alternate ``pytest-benchmark`` CLI bin (in addition to ``py.test-benchmark``) to match the madness in pytest. * Fix some issues with ``--help`` in CLI. * Improved git remote parsing (for ``commit_info`` in JSON outputs). * Fixed default value for ``--benchmark-columns``. * Fixed comparison mode (loading was done too late). * Remove the project name from the autosave name. This will get the old brief naming from 3.0 back. 3.1.0a1 (2016-10-29) -------------------- * Added ``--benchmark-columns`` command line option. It selects what columns are displayed in the result table. Contributed by Antonio Cuni in `#34 `_. * Added support for grouping by specific test parametrization (``--benchmark-group-by=param:NAME`` where ``NAME`` is your param name). Contributed by Antonio Cuni in `#37 `__. * Added support for ``name`` or ``fullname`` in ``--benchmark-sort``. Contributed by Antonio Cuni in `#37 `_. * Changed signature for ``pytest_benchmark_generate_json`` hook to take 2 new arguments: ``machine_info`` and ``commit_info``. * Changed ``--benchmark-histogram`` to plot groups instead of name-matching runs. * Changed ``--benchmark-histogram`` to plot exactly what you compared against. Now it's ``1:1`` with the compare feature. * Changed ``--benchmark-compare`` to allow globs. You can compare against all the previous runs now. * Changed ``--benchmark-group-by`` to allow multiple values separated by comma. Example: ``--benchmark-group-by=param:foo,param:bar`` * Added a command line tool to compare previous data: ``py.test-benchmark``. It has two commands: * ``list`` - Lists all the available files. * ``compare`` - Displays result tables. Takes options: * ``--sort=COL`` * ``--group-by=LABEL`` * ``--columns=LABELS`` * ``--histogram=[FILENAME-PREFIX]`` * Added ``--benchmark-cprofile`` that profiles last run of benchmarked function. Contributed by Petr Šebek. * Changed ``--benchmark-storage`` so it now allows elasticsearch storage. It allows to store data to elasticsearch instead to json files. Contributed by Petr Šebek in `#58 `_. 3.0.0 (2015-11-08) ------------------ * Improved ``--help`` text for ``--benchmark-histogram``, ``--benchmark-save`` and ``--benchmark-autosave``. * Benchmarks that raised exceptions during test now have special highlighting in result table (red background). * Benchmarks that raised exceptions are not included in the saved data anymore (you can still get the old behavior back by implementing ``pytest_benchmark_generate_json`` in your ``conftest.py``). * The plugin will use pytest's warning system for warnings. There are 2 categories: ``WBENCHMARK-C`` (compare mode issues) and ``WBENCHMARK-U`` (usage issues). * The red warnings are only shown if ``--benchmark-verbose`` is used. They still will be always be shown in the pytest-warnings section. * Using the benchmark fixture more than one time is disallowed (will raise exception). * Not using the benchmark fixture (but requiring it) will issue a warning (``WBENCHMARK-U1``). 3.0.0rc1 (2015-10-25) --------------------- * Changed ``--benchmark-warmup`` to take optional value and automatically activate on PyPy (default value is ``auto``). **MAY BE BACKWARDS INCOMPATIBLE** * Removed the version check in compare mode (previously there was a warning if current version is lower than what's in the file). 3.0.0b3 (2015-10-22) --------------------- * Changed how comparison is displayed in the result table. Now previous runs are shown as normal runs and names get a special suffix indicating the origin. Eg: "test_foobar (NOW)" or "test_foobar (0123)". * Fixed sorting in the result table. Now rows are sorted by the sort column, and then by name. * Show the plugin version in the header section. * Moved the display of default options in the header section. 3.0.0b2 (2015-10-17) --------------------- * Add a ``--benchmark-disable`` option. It's automatically activated when xdist is on * When xdist is on or ``statistics`` can't be imported then ``--benchmark-disable`` is automatically activated (instead of ``--benchmark-skip``). **BACKWARDS INCOMPATIBLE** * Replace the deprecated ``__multicall__`` with the new hookwrapper system. * Improved description for ``--benchmark-max-time``. 3.0.0b1 (2015-10-13) -------------------- * Tests are sorted alphabetically in the results table. * Failing to import ``statistics`` doesn't create hard failures anymore. Benchmarks are automatically skipped if import failure occurs. This would happen on Python 3.2 (or earlier Python 3). 3.0.0a4 (2015-10-08) -------------------- * Changed how failures to get commit info are handled: now they are soft failures. Previously it made the whole test suite fail, just because you didn't have ``git/hg`` installed. 3.0.0a3 (2015-10-02) -------------------- * Added progress indication when computing stats. 3.0.0a2 (2015-09-30) -------------------- * Fixed accidental output capturing caused by capturemanager misuse. 3.0.0a1 (2015-09-13) -------------------- * Added JSON report saving (the ``--benchmark-json`` command line arguments). Based on initial work from Dave Collins in `#8 `_. * Added benchmark data storage(the ``--benchmark-save`` and ``--benchmark-autosave`` command line arguments). * Added comparison to previous runs (the ``--benchmark-compare`` command line argument). * Added performance regression checks (the ``--benchmark-compare-fail`` command line argument). * Added possibility to group by various parts of test name (the ``--benchmark-compare-group-by`` command line argument). * Added historical plotting (the ``--benchmark-histogram`` command line argument). * Added option to fine tune the calibration (the ``--benchmark-calibration-precision`` command line argument and ``calibration_precision`` marker option). * Changed ``benchmark_weave`` to no longer be a context manager. Cleanup is performed automatically. **BACKWARDS INCOMPATIBLE** * Added ``benchmark.weave`` method (alternative to ``benchmark_weave`` fixture). * Added new hooks to allow customization: * ``pytest_benchmark_generate_machine_info(config)`` * ``pytest_benchmark_update_machine_info(config, info)`` * ``pytest_benchmark_generate_commit_info(config)`` * ``pytest_benchmark_update_commit_info(config, info)`` * ``pytest_benchmark_group_stats(config, benchmarks, group_by)`` * ``pytest_benchmark_generate_json(config, benchmarks, include_data)`` * ``pytest_benchmark_update_json(config, benchmarks, output_json)`` * ``pytest_benchmark_compare_machine_info(config, benchmarksession, machine_info, compared_benchmark)`` * Changed the timing code to: * Tracers are automatically disabled when running the test function (like coverage tracers). * Fixed an issue with calibration code getting stuck. * Added ``pedantic mode`` via ``benchmark.pedantic()``. This mode disables calibration and allows a setup function. 2.5.0 (2015-06-20) ------------------ * Improved test suite a bit (not using ``cram`` anymore). * Improved help text on the ``--benchmark-warmup`` option. * Made ``warmup_iterations`` available as a marker argument (eg: ``@pytest.mark.benchmark(warmup_iterations=1234)``). * Fixed ``--benchmark-verbose``'s printouts to work properly with output capturing. * Changed how warmup iterations are computed (now number of total iterations is used, instead of just the rounds). * Fixed a bug where calibration would run forever. * Disabled red/green coloring (it was kinda random) when there's a single test in the results table. 2.4.1 (2015-03-16) ------------------ * Fix regression, plugin was raising ``ValueError: no option named 'dist'`` when xdist wasn't installed. 2.4.0 (2015-03-12) ------------------ * Add a ``benchmark_weave`` experimental fixture. * Fix internal failures when ``xdist`` plugin is active. * Automatically disable benchmarks if ``xdist`` is active. 2.3.0 (2014-12-27) ------------------ * Moved the warmup in the calibration phase. Solves issues with benchmarking on PyPy. Added a ``--benchmark-warmup-iterations`` option to fine-tune that. 2.2.0 (2014-12-26) ------------------ * Make the default rounds smaller (so that variance is more accurate). * Show the defaults in the ``--help`` section. 2.1.0 (2014-12-20) ------------------ * Simplify the calibration code so that the round is smaller. * Add diagnostic output for calibration code (``--benchmark-verbose``). 2.0.0 (2014-12-19) ------------------ * Replace the context-manager based API with a simple callback interface. **BACKWARDS INCOMPATIBLE** * Implement timer calibration for precise measurements. 1.0.0 (2014-12-15) ------------------ * Use a precise default timer for PyPy. ? (?) ----- * README and styling fixes. Contributed by Marc Abramowitz in `#4 `_. * Lots of wild changes. ionelmc-pytest-benchmark-5edf251/CONTRIBUTING.rst000066400000000000000000000045131471041671100215010ustar00rootroot00000000000000============ Contributing ============ Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. Bug reports =========== When `reporting a bug `_ please include: * Your operating system name and version. * Any details about your local setup that might be helpful in troubleshooting. * Detailed steps to reproduce the bug. Documentation improvements ========================== pytest-benchmark could always use more documentation, whether as part of the official pytest-benchmark docs, in docstrings, or even on the web in blog posts, articles, and such. Feature requests and feedback ============================= The best way to send feedback is to file an issue at https://github.com/ionelmc/pytest-benchmark/issues. If you are proposing a feature: * Explain in detail how it would work. * Keep the scope as narrow as possible, to make it easier to implement. * Remember that this is a volunteer-driven project, and that code contributions are welcome :) Development =========== To set up `pytest-benchmark` for local development: 1. Fork `pytest-benchmark `_ (look for the "Fork" button). 2. Clone your fork locally:: git clone git@github.com:YOURGITHUBNAME/pytest-benchmark.git 3. Create a branch for local development:: git checkout -b name-of-your-bugfix-or-feature Now you can make your changes locally. 4. When you're done making changes run all the checks and docs builder with one command:: tox 5. Commit your changes and push your branch to GitHub:: git add . git commit -m "Your detailed description of your changes." git push origin name-of-your-bugfix-or-feature 6. Submit a pull request through the GitHub website. Pull Request Guidelines ----------------------- If you need some code review or feedback while you're developing the code just make the pull request. For merging, you should: 1. Include passing tests (run ``tox``). 2. Update documentation when there's new API, functionality etc. 3. Add a note to ``CHANGELOG.rst`` about the changes. 4. Add yourself to ``AUTHORS.rst``. Tips ---- To run a subset of tests:: tox -e envname -- pytest -k test_myfeature To run all the test environments in *parallel*:: tox -p auto ionelmc-pytest-benchmark-5edf251/LICENSE000066400000000000000000000024621471041671100200460ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2014-2023, Ionel Cristian Mărieș. 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. 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 THE COPYRIGHT HOLDER 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. ionelmc-pytest-benchmark-5edf251/MANIFEST.in000066400000000000000000000006531471041671100205770ustar00rootroot00000000000000graft docs graft src graft ci graft tests include .bumpversion.cfg include .cookiecutterrc include .coveragerc include .editorconfig include .github/workflows/github-actions.yml include .pre-commit-config.yaml include .readthedocs.yml include pytest.ini include tox.ini include AUTHORS.rst include CHANGELOG.rst include CONTRIBUTING.rst include LICENSE include README.rst global-exclude *.py[cod] __pycache__/* *.so *.dylib ionelmc-pytest-benchmark-5edf251/README.rst000066400000000000000000000150671471041671100205350ustar00rootroot00000000000000======== Overview ======== .. start-badges .. list-table:: :stub-columns: 1 * - docs - |docs| |gitter| * - tests - |github-actions| |coveralls| |codecov| * - package - |version| |wheel| |supported-versions| |supported-implementations| |commits-since| .. |docs| image:: https://readthedocs.org/projects/pytest-benchmark/badge/?style=flat :target: https://readthedocs.org/projects/pytest-benchmark/ :alt: Documentation Status .. |github-actions| image:: https://github.com/ionelmc/pytest-benchmark/actions/workflows/github-actions.yml/badge.svg :alt: GitHub Actions Build Status :target: https://github.com/ionelmc/pytest-benchmark/actions .. |gitter| image:: https://badges.gitter.im/ionelmc/pytest-benchmark.svg :alt: Join the chat at https://gitter.im/ionelmc/pytest-benchmark :target: https://gitter.im/ionelmc/pytest-benchmark .. |coveralls| image:: https://coveralls.io/repos/github/ionelmc/pytest-benchmark/badge.svg?branch=main :alt: Coverage Status :target: https://coveralls.io/github/ionelmc/pytest-benchmark?branch=main .. |codecov| image:: https://codecov.io/gh/ionelmc/pytest-benchmark/branch/main/graphs/badge.svg?branch=main :alt: Coverage Status :target: https://app.codecov.io/github/ionelmc/pytest-benchmark .. |version| image:: https://img.shields.io/pypi/v/pytest-benchmark.svg :alt: PyPI Package latest release :target: https://pypi.org/project/pytest-benchmark .. |wheel| image:: https://img.shields.io/pypi/wheel/pytest-benchmark.svg :alt: PyPI Wheel :target: https://pypi.org/project/pytest-benchmark .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/pytest-benchmark.svg :alt: Supported versions :target: https://pypi.org/project/pytest-benchmark .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/pytest-benchmark.svg :alt: Supported implementations :target: https://pypi.org/project/pytest-benchmark .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/pytest-benchmark/v5.1.0.svg :alt: Commits since latest release :target: https://github.com/ionelmc/pytest-benchmark/compare/v5.1.0...main .. end-badges A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. See calibration_ and FAQ_. * Free software: BSD 2-Clause License Installation ============ :: pip install pytest-benchmark Documentation ============= For latest release: `pytest-benchmark.readthedocs.org/en/stable `_. For master branch (may include documentation fixes): `pytest-benchmark.readthedocs.io/en/latest `_. Examples ======== But first, a prologue: This plugin tightly integrates into pytest. To use this effectively you should know a thing or two about pytest first. Take a look at the `introductory material `_ or watch `talks `_. Few notes: * This plugin benchmarks functions and only that. If you want to measure block of code or whole programs you will need to write a wrapper function. * In a test you can only benchmark one function. If you want to benchmark many functions write more tests or use `parametrization `_. * To run the benchmarks you simply use `pytest` to run your "tests". The plugin will automatically do the benchmarking and generate a result table. Run ``pytest --help`` for more details. This plugin provides a `benchmark` fixture. This fixture is a callable object that will benchmark any function passed to it. Example: .. code-block:: python def something(duration=0.000001): """ Function that needs some serious benchmarking. """ time.sleep(duration) # You may return anything you want, like the result of a computation return 123 def test_my_stuff(benchmark): # benchmark something result = benchmark(something) # Extra code, to verify that the run completed correctly. # Sometimes you may want to check the result, fast functions # are no good if they return incorrect results :-) assert result == 123 You can also pass extra arguments: .. code-block:: python def test_my_stuff(benchmark): benchmark(time.sleep, 0.02) Or even keyword arguments: .. code-block:: python def test_my_stuff(benchmark): benchmark(time.sleep, duration=0.02) Another pattern seen in the wild, that is not recommended for micro-benchmarks (very fast code) but may be convenient: .. code-block:: python def test_my_stuff(benchmark): @benchmark def something(): # unnecessary function call time.sleep(0.000001) A better way is to just benchmark the final function: .. code-block:: python def test_my_stuff(benchmark): benchmark(time.sleep, 0.000001) # way more accurate results! If you need to do fine control over how the benchmark is run (like a `setup` function, exact control of `iterations` and `rounds`) there's a special mode - pedantic_: .. code-block:: python def my_special_setup(): ... def test_with_setup(benchmark): benchmark.pedantic(something, setup=my_special_setup, args=(1, 2, 3), kwargs={'foo': 'bar'}, iterations=10, rounds=100) Screenshots ----------- Normal run: .. image:: https://github.com/ionelmc/pytest-benchmark/raw/master/docs/screenshot.png :alt: Screenshot of pytest summary Compare mode (``--benchmark-compare``): .. image:: https://github.com/ionelmc/pytest-benchmark/raw/master/docs/screenshot-compare.png :alt: Screenshot of pytest summary in compare mode Histogram (``--benchmark-histogram``): .. image:: https://cdn.rawgit.com/ionelmc/pytest-benchmark/94860cc8f47aed7ba4f9c7e1380c2195342613f6/docs/sample-tests_test_normal.py_test_xfast_parametrized%5B0%5D.svg :alt: Histogram sample .. Also, it has `nice tooltips `_. Development =========== To run the all tests run:: tox Credits ======= * Timing code and ideas taken from: https://github.com/vstinner/misc/blob/34d3128468e450dad15b6581af96a790f8bd58ce/python/benchmark.py .. _FAQ: http://pytest-benchmark.readthedocs.org/en/latest/faq.html .. _calibration: http://pytest-benchmark.readthedocs.org/en/latest/calibration.html .. _pedantic: http://pytest-benchmark.readthedocs.org/en/latest/pedantic.html ionelmc-pytest-benchmark-5edf251/ci/000077500000000000000000000000001471041671100174305ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/ci/bootstrap.py000077500000000000000000000054631471041671100220320ustar00rootroot00000000000000#!/usr/bin/env python import os import pathlib import subprocess import sys base_path: pathlib.Path = pathlib.Path(__file__).resolve().parent.parent templates_path = base_path / 'ci' / 'templates' def check_call(args): print('+', *args) subprocess.check_call(args) def exec_in_env(): env_path = base_path / '.tox' / 'bootstrap' if sys.platform == 'win32': bin_path = env_path / 'Scripts' else: bin_path = env_path / 'bin' if not env_path.exists(): import subprocess print(f'Making bootstrap env in: {env_path} ...') try: check_call([sys.executable, '-m', 'venv', env_path]) except subprocess.CalledProcessError: try: check_call([sys.executable, '-m', 'virtualenv', env_path]) except subprocess.CalledProcessError: check_call(['virtualenv', env_path]) print('Installing `jinja2` into bootstrap environment...') check_call([bin_path / 'pip', 'install', 'jinja2', 'tox']) python_executable = bin_path / 'python' if not python_executable.exists(): python_executable = python_executable.with_suffix('.exe') print(f'Re-executing with: {python_executable}') print('+ exec', python_executable, __file__, '--no-env') os.execv(python_executable, [python_executable, __file__, '--no-env']) def main(): import jinja2 print(f'Project path: {base_path}') jinja = jinja2.Environment( loader=jinja2.FileSystemLoader(str(templates_path)), trim_blocks=True, lstrip_blocks=True, keep_trailing_newline=True, ) tox_environments = [ line.strip() # 'tox' need not be installed globally, but must be importable # by the Python that is running this script. # This uses sys.executable the same way that the call in # cookiecutter-pylibrary/hooks/post_gen_project.py # invokes this bootstrap.py itself. for line in subprocess.check_output([sys.executable, '-m', 'tox', '--listenvs'], universal_newlines=True).splitlines() ] tox_environments = [line for line in tox_environments if line.startswith('py')] for template in templates_path.rglob('*'): if template.is_file(): template_path = template.relative_to(templates_path).as_posix() destination = base_path / template_path destination.parent.mkdir(parents=True, exist_ok=True) destination.write_text(jinja.get_template(template_path).render(tox_environments=tox_environments)) print(f'Wrote {template_path}') print('DONE.') if __name__ == '__main__': args = sys.argv[1:] if args == ['--no-env']: main() elif not args: exec_in_env() else: print(f'Unexpected arguments: {args}', file=sys.stderr) sys.exit(1) ionelmc-pytest-benchmark-5edf251/ci/requirements.txt000066400000000000000000000000741471041671100227150ustar00rootroot00000000000000virtualenv>=16.6.0 pip>=19.1.1 setuptools>=18.0.1 tox twine ionelmc-pytest-benchmark-5edf251/ci/templates/000077500000000000000000000000001471041671100214265ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/ci/templates/.github/000077500000000000000000000000001471041671100227665ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/ci/templates/.github/workflows/000077500000000000000000000000001471041671100250235ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/ci/templates/.github/workflows/github-actions.yml000066400000000000000000000043631471041671100304740ustar00rootroot00000000000000name: build on: [push, pull_request, workflow_dispatch] jobs: test: name: {{ '${{ matrix.name }}' }} runs-on: {{ '${{ matrix.os }}' }} timeout-minutes: 30 strategy: fail-fast: false matrix: include: - name: 'check' python: '3.11' toxpython: 'python3.11' tox_env: 'check' os: 'ubuntu-latest' - name: 'docs' python: '3.11' toxpython: 'python3.11' tox_env: 'docs' os: 'ubuntu-latest' {% for env in tox_environments %} {% set prefix = env.split('-')[0] -%} {% if prefix.startswith('pypy') %} {% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% set cpython %}pp{{ prefix[4:5] }}{% endset %} {% set toxpython %}pypy{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% else %} {% set python %}{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} {% set cpython %}cp{{ prefix[2:] }}{% endset %} {% set toxpython %}python{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} {% endif %} {% for os, python_arch in [ ['ubuntu', 'x64'], ['windows', 'x64'], ['macos', 'arm64'], ] %} - name: '{{ env }} ({{ os }})' python: '{{ python }}' toxpython: '{{ toxpython }}' python_arch: '{{ python_arch }}' tox_env: '{{ env }}' os: '{{ os }}-latest' {% endfor %} {% endfor %} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: {{ '${{ matrix.python }}' }} architecture: {{ '${{ matrix.python_arch }}' }} - name: install dependencies run: | python -mpip install --progress-bar=off -r ci/requirements.txt virtualenv --version pip --version tox --version pip list --format=freeze - name: test env: TOXPYTHON: '{{ '${{ matrix.toxpython }}' }}' run: > tox -e {{ '${{ matrix.tox_env }}' }} -v finish: needs: test if: {{ '${{ always() }}' }} runs-on: ubuntu-latest steps: - uses: coverallsapp/github-action@v2 with: parallel-finished: true - uses: codecov/codecov-action@v3 with: CODECOV_TOKEN: {% raw %}${{ secrets.CODECOV_TOKEN }}{% endraw %} ionelmc-pytest-benchmark-5edf251/docs/000077500000000000000000000000001471041671100177655ustar00rootroot00000000000000ionelmc-pytest-benchmark-5edf251/docs/authors.rst000066400000000000000000000000341471041671100222010ustar00rootroot00000000000000.. include:: ../AUTHORS.rst ionelmc-pytest-benchmark-5edf251/docs/calibration.rst000066400000000000000000000021541471041671100230100ustar00rootroot00000000000000Calibration =========== ``pytest-benchmark`` will run your function multiple times between measurements. A `round` is that set of runs done between measurements. This is quite similar to the builtin ``timeit`` module but it's more robust. The problem with measuring single runs appears when you have very fast code. To illustrate: .. image:: https://github.com/ionelmc/pytest-benchmark/raw/master/docs/measurement-issues.png :alt: Diagram illustrating issues with measuring very fast code In other words, a `round` is a set of runs that are averaged together, those resulting numbers are then used to compute the result tables. The default settings will try to keep the round small enough (so that you get to see variance), but not too small, because then you have the timer calibration issues illustrated above (your test function is faster than or as fast as the resolution of the timer). By default ``pytest-benchmark`` will try to run your function as many times needed to fit a `10 x TIMER_RESOLUTION` period. You can fine tune this with the ``--benchmark-min-time`` and ``--benchmark-calibration-precision`` options. ionelmc-pytest-benchmark-5edf251/docs/changelog.rst000066400000000000000000000000361471041671100224450ustar00rootroot00000000000000.. include:: ../CHANGELOG.rst ionelmc-pytest-benchmark-5edf251/docs/comparing.rst000066400000000000000000000043741471041671100225060ustar00rootroot00000000000000Comparing past runs =================== Before comparing different runs it's ideal to make your tests as consistent as possible, see :doc:`faq` for more details. `pytest-benchmark` has support for storing stats and data for the previous runs. To store a run just add ``--benchmark-autosave`` or ``--benchmark-save=some-name`` to your pytest arguments. All the files are saved in a path like ``.benchmarks/Linux-CPython-3.4-64bit``. * ``--benchmark-autosave`` saves a file like ``0001_c9cca5de6a4c7eb2_20150815_215724.json`` where: * ``0001`` is an automatically incremented id, much like how django migrations have a number. * ``c9cca5de6a4c7eb2`` is the commit id (if you use Git or Mercurial) * ``20150815_215724`` is the current time You should add ``--benchmark-autosave`` to ``addopts`` in you pytest configuration so you dont have to specify it all the time. * ``--benchmark-save=foobar`` works similarly, but saves a file like ``0001_foobar.json``. It's there in case you want to give specific name to the run. After you have saved your first run you can compare against it with ``--benchmark-compare=0001``. You will get an additional row for each test in the result table, showing the differences. You can also make the suite fail with ``--benchmark-compare-fail=:%`` or ``--benchmark-compare-fail=:``. Examples: * ``--benchmark-compare-fail=min:5%`` will make the suite fail if ``Min`` is 5% slower for any test. * ``--benchmark-compare-fail=mean:0.001`` will make the suite fail if ``Mean`` is 0.001 seconds slower for any test. Comparing outside of pytest --------------------------- There is a convenience CLI for listing/comparing past runs: ``pytest-benchmark`` (:ref:`comparison-cli`). Example:: pytest-benchmark compare 0001 0002 Plotting -------- .. note:: To use plotting you need to ``pip install pygal pygaljs`` or ``pip install pytest-benchmark[histogram]``. You can also get a nice plot with ``--benchmark-histogram``. The result is a modified Tukey box and whisker plot where the outliers (the small bullets) are ``Min`` and ``Max``. Note that if you do not supply a name for the plot it is recommended that ``--benchmark-histogram`` is the last option passed. Example output: .. image:: screenshot-histogram.png ionelmc-pytest-benchmark-5edf251/docs/conf.py000066400000000000000000000017321471041671100212670ustar00rootroot00000000000000extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'sphinx.ext.coverage', 'sphinx.ext.doctest', 'sphinx.ext.extlinks', 'sphinx.ext.ifconfig', 'sphinx.ext.napoleon', 'sphinx.ext.todo', 'sphinx.ext.viewcode', ] source_suffix = '.rst' master_doc = 'index' project = 'pytest-benchmark' year = '2014-2023' author = 'Ionel Cristian Mărieș' copyright = f'{year}, {author}' version = release = '5.1.0' pygments_style = 'trac' templates_path = ['.'] extlinks = { 'issue': ('https://github.com/ionelmc/pytest-benchmark/issues/%s', '#%s'), 'pr': ('https://github.com/ionelmc/pytest-benchmark/pull/%s', 'PR #%s'), } html_theme = 'furo' html_theme_options = { 'githuburl': 'https://github.com/ionelmc/pytest-benchmark/', } html_use_smartypants = True html_last_updated_fmt = '%b %d, %Y' html_split_index = False html_short_title = f'{project}-{version}' napoleon_use_ivar = True napoleon_use_rtype = False napoleon_use_param = False ionelmc-pytest-benchmark-5edf251/docs/contributing.rst000066400000000000000000000000411471041671100232210ustar00rootroot00000000000000.. include:: ../CONTRIBUTING.rst ionelmc-pytest-benchmark-5edf251/docs/faq.rst000066400000000000000000000052171471041671100212730ustar00rootroot00000000000000Frequently Asked Questions ========================== Why is my ``StdDev`` so high? There can be few causes for this: * Bad isolation. You run other services in your machine that eat up your cpu or you run in a VM and that makes machine performance inconsistent. Ideally you'd avoid such setups, stop all services and applications and use bare metal machines. * Bad tests or too much complexity. The function you're testing is doing I/O, using external resources, has side-effects or doing other non-deterministic things. Ideally you'd avoid testing huge chunks of code. One special situation is PyPy: it's GC and JIT can add unpredictable overhead - you'll see it as huge spikes all over the place. You should make sure that you have a good amount of warmup (using ``--benchmark-warmup`` and ``--benchmark-warmup-iterations``) to prime the JIT as much as possible. Unfortunately not much can be done about GC overhead. If you cannot make your tests more predictable and remove overhead you should look at different stats like: IQR and Median. IQR is often better than StdDev. Why is my ``Min`` way lower than ``Q1-1.5IQR``? You may see this issue in the histogram plot. This is another instance of *bad isolation*. For example, Intel CPUs have a feature called `Turbo Boost `_ wich overclocks your CPU depending on how many cores you have at that time and how hot your CPU is. If your CPU is too hot you get no Turbo Boost. If you get Turbo Boost active then the CPU quickly gets hot. You can see how this won't work for sustained workloads. When Turbo Boost kicks in you may see "speed spikes" - and you'd get this strange outlier ``Min``. When you have other programs running on your machine you may also see the "speed spikes" - the other programs idle for a brief moment and that allows your function to run way faster in that brief moment. I can't avoid using VMs or running other programs. What can I do? As a last ditch effort pytest-benchmark allows you to plugin in custom timers (``--benchmark-timer``). You could use something like ``time.process_time`` (Python 3.3+ only) as the timer. Process time `doesn't include sleeping or waiting for I/O `_. The histogram doesn't show ``Max`` time. What gives?! The height of the plot is limited to ``Q3+1.5IQR`` because ``Max`` has the nasty tendency to be way higher and making everything else small and undiscerning. For this reason ``Max`` is *plotted outside*. Most people don't care about ``Max`` at all so this is fine. ionelmc-pytest-benchmark-5edf251/docs/glossary.rst000066400000000000000000000010221471041671100223550ustar00rootroot00000000000000Glossary ======== Iteration A single run of your benchmarked function. Round A set of iterations. The size of a `round` is computed in the calibration phase. Stats are computed with rounds, not with iterations. The duration for a round is an average of all the iterations in that round. See: :doc:`calibration` for an explanation of why it's like this. Mean TODO Median TODO IQR InterQuertile Range. This is a different way to measure variance. StdDev TODO: Standard Deviation Outliers TODO ionelmc-pytest-benchmark-5edf251/docs/hooks.rst000066400000000000000000000002361471041671100216430ustar00rootroot00000000000000Hooks ===== Hooks for customizing various parts of ``pytest-benchmark``. ----- .. automodule:: pytest_benchmark.hookspec :members: :undoc-members: ionelmc-pytest-benchmark-5edf251/docs/index.rst000066400000000000000000000042131471041671100216260ustar00rootroot00000000000000Welcome to pytest-benchmark's documentation! ============================================ This plugin provides a `benchmark` fixture. This fixture is a callable object that will benchmark any function passed to it. Notable features and goals: * Sensible defaults and automatic calibration for microbenchmarks * Good integration with pytest * Comparison and regression tracking * Exhausive statistics * JSON export Examples: .. code-block:: python def something(duration=0.000001): """ Function that needs some serious benchmarking. """ time.sleep(duration) # You may return anything you want, like the result of a computation return 123 def test_my_stuff(benchmark): # benchmark something result = benchmark(something) # Extra code, to verify that the run completed correctly. # Sometimes you may want to check the result, fast functions # are no good if they return incorrect results :-) assert result == 123 def test_my_stuff_different_arg(benchmark): # benchmark something, but add some arguments result = benchmark(something, 0.001) assert result == 123 Screenshots ----------- Normal run: .. image:: https://github.com/ionelmc/pytest-benchmark/raw/master/docs/screenshot.png :alt: Screenshot of py.test summary Compare mode (``--benchmark-compare``): .. image:: https://github.com/ionelmc/pytest-benchmark/raw/master/docs/screenshot-compare.png :alt: Screenshot of py.test summary in compare mode Histogram (``--benchmark-histogram``): .. image:: https://cdn.rawgit.com/ionelmc/pytest-benchmark/94860cc8f47aed7ba4f9c7e1380c2195342613f6/docs/sample-tests_test_normal.py_test_xfast_parametrized%5B0%5D.svg :alt: Histogram sample .. Also, it has `nice tooltips `_. User guide ========== .. toctree:: :maxdepth: 2 installation usage calibration pedantic comparing hooks faq glossary contributing authors changelog Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` ionelmc-pytest-benchmark-5edf251/docs/installation.rst000066400000000000000000000001401471041671100232130ustar00rootroot00000000000000============ Installation ============ At the command line:: pip install pytest-benchmark ionelmc-pytest-benchmark-5edf251/docs/measurement-issues.png000066400000000000000000001404111471041671100243320ustar00rootroot00000000000000PNG  IHDR3 pHYsMMħ IDATxweuʶ$ tH& R ">ObGE)*"b .B-dl;q_=lMXM~k3g93sfs=#""""*h(((((((((((((((((((((((((((((((((((U$ffٿ9&P"P  ft+""#~m2rXEWVb ts~˪,)ZLM> lvѲbՀnw%>̊@]^Q%,0ǁoG; ԁT`g` "p"$jûa7 ܤC2̖&-iEf2{Ew%׳ L%ݔ3uϨM4 iKv{̚I' HEbTyk~B&wB, îꤶu]idx+2j}@ +""#*KVn;\ MVN.wͬ˰*M%M BDR&",_S6ϗfwmf;cjw."" 8RB^`O_;ʬMep tBC8ɪRhx-|mϚ SBX7Bn:4~7`sgcrMbn|u~ 30ؗtb>O~|\k>ưmfg|tq:0 {>9Q_kX>jaoQ`}3+{U}󊈈d9˹PjًREey40?NoaXX1n3ksyџ0ؓ#7#}b.]L\-7}7mځ-)q+UkLj9-ڟvGI1]~CnSP7|:Xw0mSͅulzہ_.g` v`/1+1mGR{PgG2M(JBN4Lv!U6>uNa'ٵ^AjfWGxljfG6s"Bl`E 4`K3P/ @_;>N׸nf=Rƅk6f&jZz`l-y+0{wU\"kJ RӖoK||0?OF؏Tݾafٺ_M=ӿ5Zq`wof^-]DDDFXsm7RK" |.'5;Xm,RW׽)scom.TeG:|^A#1/0>?a"]g߿E*?Ǟ1Gu%x[q:`*kc3#4νI1Ⱬ"gOO1p|̿6Rwo҉{Ĵ/f~A`xosO_?MG\efF|gⳍ䲘c~fwuM7t[oEb %ݲ*h,E%tlT<# e˹Ce`:Ta#M&3]|'ƕ_vyyAA0S+st|FXG:\dQ\+U|,i#⻟efcsL/fTzO<>/B<<{Njx6 070=ƵC4t_V3>w\Wb~ryB|rQQϚe1cݽn-^U-vyqx2F@,,m=?i~m*y_Ej<_NdR[6uf6.rK"y i~?Alc3~T*5<`}R3chWsIj/&5a"k7;+olܽ7<\waZ:p>05Q8ہIDO"znMQY8 f8tfwhΆ[M룒Ejf98,ƴUGmxInigsuLQ; ҉n[Gw-R;jY`_ؑTy>%;0v\˰ (C޲pJv&BWV ?UlJXR;~qrϪlf_#(SwR\R;Y.^Dj xrR{a UJ a:[73lR{IϽ_V} kz&Nm)"Ԥdz{~Cj|7 ʤm~磔?㱗H=?Oj05{ ^ˠa3ùi_&U!"O#]D>tcYDfRU!`F>E:\H\F pU Rm_ si|IM27!"uKͭ&FR3cN`{t?I'͏i1 xzLF!"Rǧҿ*+""2PE3q qaH˯W+[RP΂Iv8?—ځfW˪}+*d֗{fs@jZ$40?nYu^?kR/6{~O ;1.?/O`GX+]Y5t5 t+uY5+-j1P +?L {s#|Ub{Qa|a\vrXsssAʞ{m>?S|,ZC0-j0.Bda^t0VkӍ|Ow|rii1i R|X+Y}U^78^r>6o"^Jࢆi%-75|^\H/.'[^5NLӁEiϦMa=owmi4;\Y^6h)_*>`_.1[ijޏ6٫v0HPȂ 5gޑv=84]-M'ʤFjCK$kH `&Ro֭ӕ | AUkȒ>d}8 HmwEDDWz!5e 2W*w.)I ϟ%]7+wQņkE;4}Yaw"[F7qS^YR]lc ҉@"}yH]EDDWzBM$] hz_x_-j+"" Wgp\>K@Ջ(ʫ mW&""+""""#z^^^^^^Q$UYI@DDDVfV k"pЕDDDdY䜺Ianfǘٹf6Of٢ a"&S>GSTT: # xpuU{xEDDDVvUJL`p]if{ YWF,ˮdj/"""+^16cH@;}`oRw73;W5xe[PW'"""F%#@ԖpR@j;2NZ|m=~P J$an]hc te-~|~AlUUc/Zʍ&H'AZ b;~%*J끭k{IU%g)g%yey[q wi|bCC]{Vd8VuHZOӀq+* zHyj*[Lr+4e0 @+«`6uU-k |`~wVe (Dmd Uj{5Iݙ}J^ܢ)C o3=č2#qJW[uϪx5Υӿ `ƙU{,Ұ;W9?P|[u9N: ofutө;xEDDV~YEjCj྆5xG u#""jߖ|;H^Wi*m """"+{5W{cfGګ+"""ߖjf'3@^^U!B_,ޫ """"RͪWE*b7߶,ޣ """"Rͪ;ԶJUYUB/h`:#Rm,bMdCY^q[>ay/>ٗGP. ̰4<>{/no#UwѥJ;Y+› /tX6-5Rw>m@Sl, Áh,t뱼˫Ƀq=WuBSn'xQŘ'MSn'܁x}>G!/!B_޳Im{4ϸ /{M~tmfWfMr~x䆱=\ =nUhՎA끇/r [lZ-]@t8)Xj,EŘ^tOlԀ I[xށ5bruB x49;[' 010!-!k<  gf'Yݵ=V@{ǛG󁒻Wmg?3kϪ,嚕"D( P)D}7o۬;c s};;XG. 5E/c9PwA|*kdfw<+CfRѤAU/}_YIG7lԋlla9fReT9ފtHtfRZe5EP(OB,oa+&j7gݑx:9lq-jE K쐬E:I1٨Nl18G)HC{(~dּA?>@౗ U}C}9Vsreb?y՞ L3bܪPmzH"vBݜ:>zl9}>6%E^88t8T˹K 6}=ISHM{N# vxȭi"n0O|w V ɪґ;ٔhZ* r|Խo"[eNiqM4  !-Vse?|m R{K;B`6Q`eVERuXvkj#> E: :ߐ466 uY\xͪ#3IO!ye|餡%);w!lA,gz}G6Τ*IJG,rM!S#5#ug1owVQ!yؓtYWwFѝ |?Y6O.WPǐNj&qJE~t"Q+*YQ6?'5E0RWdGN2.{tE<ɿ?'Z IDATl!kx,H]Iy1QZeMn0ųc']n&]vv?&@/~:I٥ gfbRn,*N!W~A,GNbєAGFK]-f^W4|όk,,汥 %bMJK״ 20mqqϑC]HX5n7D^)7j%CYo%?;m|e]6;>Vκ%ۖwe8kߛ^_xǬ[[Nnɲ[7w-9}=~MjJx7zIM.#bynɲdu} #Nη"Rx]߰G!׎D%X]עSW˅lymkV=*ҿngmonxPj dò<:|_َ(F2WN26qfN흤#Ee`FnH=TI7,fmsFpRŶt@ab;IU[PUZÏȗp[![[r oӖ[øsY9,%Rߓ7r tfA̪ؑ~g 'su IzrȪ@o<ߛ{;v9(Ejk[YV3 DU}fx[IЬ_ˤ㿢sX\iM&6fLYBlSQ~~*@eG\œo;T>]t^)Iv& :°P00;2΍まsV#]!6?בN"ޫt@l %BgmuOU"PDWDDd .,X(+K:Y1j`Jm+弭|)b\XU]^kf=NՀG P;nlh`ORݹ& soze8.h;q1B3_UݣI[^SUWw$$V?RŨ,L|磦 2<\R*se@jS%UuB{=a4p(D6 6#r&hONpec(JosC(e-HUÓc2[Ќ#8=0LNw]z x?M'o.ce|,e 8l|j wɚ)%w$uA帱:6~}ms8WEN6A'xgzE,ux5IRb϶;2ji53+NW7k0%M:,"$, aw CH'-i 6`%c<jd[.n~K#H&}1/&u5v+j"&5n_'G:IXnK:C`R;I(+R w90xu1OGj[G% 6s*Idƺ0 R)smuU݅muU]RϏ=gg.F&qp4dx2m>]PѲ`ߣn/O%u_X'UuMj{+p|t5fVWaWWr?*[Ule:~+߅* 3U`2~T,Y"+$Oźt2Wu2Z/B昶X_Tb{]'.5aPE_WVvõW1"+$%cY\֍J=,k$+j9ur~\C6ouDGL:pSFjAU]^ǑקHݿK6 |PUwDL"̌bY>i7U-*G 3w#*"4|KDDo2-6wEiI'LpqmXDd`ng%*j "tR̎{=WYn\\U^YV }yp+f{^#""C(Pލs^Rܫ􊈈3I]5.Z!pf^;!u/""+"+K܍@o]KzD~سN9E'R;ptgH^RW5DDDWDVB=2fMO#unqཇF""" "^̊_JցM) @[0IWDDxEdU|.R$"""cxy͘YVSeo[jr[]\W& D""+2kVڪJjYηpk+􊈈Ȳ0͊-XEXJ[ե `Zpf?Sȝg8zt=z`&W*W߽/{lL=KŊS5l\H FI@VΎ۶/ໟܕ`uRey%|?|NOWԘQXr|aTmnYXqOGB)"c&0f3YLGh/S,,|]ӨaT0Fwg:m\gr[}{nQJggջp Rmg.yU봵9>=byIr ^lЦK8,*bF1Ժ'1_`NM:O?NmƔr7J]BmaKemXlfjۂ4"aL)w݄}L&0]'t1*u m=l^sUm îUb 5l{8O>Mںذڶrk)R*ϣP A 5*dƶW zj=?} EKa%PWV<3 ]|w>GG4?mxFQc,Uc~ԪMu;{i\͹G;`FM:롩·^q==ԛm|羳(<׳ӱ)Cy:=oIjCdzQjzMܮ _琯=Z~'1}WjŅl38۸sI2~{x#/`n`5zLJm'}&/UUߜ+lf?fN{'qETEDDd!Ud,Eu9Ǜ?Cx~< Ɵ㎣X_ͳ/6S)0y~Fo=oңm>ˬe}ag?g$[2ze4/]ll{ȗ|i/r9t1I>OziR?4oiG>sW>Lu&w_t/(;g๻gMo}zv;7okq3OQdqG0yݬSrFݓOme]spwekCa~/X=4yWkQDSOy&pbj'[(hU:<26&k'Td`^bGN[ߧegl]g_H=Àc)8%(-`dgt7w3ޮ34}9Cg]^0̬b{p՗?tV{^ fu6md;:Yx :_ڑb3lZWE_|>{ŕGB5`*cVh$oڇN)/𽵾͏8vQb )ByPPbSaPh_&r la7\.n'm*RJz1m3n+󼳸qMOŨwusŏ6{V[WGnۛof64܍'㩪O^^Ka6N ]%GB7u77} k:Ꮼƙ\VlVZ-6<.PZ ^mf%yX›i[p)/&o%6zҊSƩ4ajjFPi)Z^kYjMKُFqK(S(~i׎o륅D2^~bss~h@OW)p97_MkB'O_e k"""SYqZZišg4CH5~=kwqep{q=tõ۾f}n5:0QYiv' FA^E1w]iX3sw7@g-i`GVws6y^+-N̦i/cThN30%FShtT(P؈NOJ3]Dbp#xSZx"E0*0 餄mLQ_^֠i-قnWYFp+ٜ.yqjztc[M'1m6qTF(ļWʝL= 9|9VgMwì{I}p4χvkp2pW,Ë TA~Ei +xbN6wȏKSUdQWVμJ[;SL]VO-鬔k`[K7Lp9mVxEvǕCAjWYp,Px;?V"" )Wk`6WBYTzZ)N}9.)|Jq iVĽƠaҸdܫ^S0zø1`G1.ˋ fcˁ0fo>W~v^Y%Yvs]q,1H,GͭuNKܽ_pb w@'>3JW^Sa0fX y5 0+N{_24]Wx'/4|Ձܧ^WML^Ľ 3_NL fh/W~Y|ZC}ng>1_zQU)zDs3i0҄*?[7P@{w{?6WfOb= %( fv. LQ`m}.<'M8V4>|$av' VcU0 \/?vav7 a1=A8NR  [^STOX̎׾#"Y C }Ng_8 3ŭ1?o ̓#P["" J8&ԅfL+頫,? իרn&Zzxt]~7AXZ]][x̊3س5HWp}+Ѭ`w Y#xӁkq<O UM.Sq!fHs|My 4yn<,}'s-J1wy̮'5*7kY+3(ʪ|-Mz:HMHR{ pW|0نR :iwqR_mwwM@(b%OƘXcoc%K"v Hkfg?fnC(|=vvf|%'Uyȍ3c( J) J{ak_h{>23ɒiJk~X+g`DnCd0";}˜F~ވl%߇ 1 LЮ> k.\σ5[(JP:PDP{IA8" r p{Xv/ib2l0bz(YF,!Dn%^˜ ^^/T[}Mn0x/.>bzUoi_kc#jٞ$h9CjB&h%Aߴw! p3AyƘ|K]Ხ8D?'h# m>#Y1=;c |Idba/NX7x:8iZo>&c!.-MCO1J ViM)C6 î[H/O2C>44o(f:cJBii {iMJ _NvpKow{6&9/6KW顭KV;V^Rk䗓RJpں`5oe %K%sw0Ze5R5PJ^0ƴN/ KK-gio{hϱm[%nn\-- 奔Rk UJ0.O0̮>Ř,K& U+;ۦ<Ů6~W0\W%h>娔RkUJ`7|LyD$^+RJ)i Zqz .c;M6֖N,1 #o)֨k]bAKCeRJiUkZc/][0X:D ^+0om{ 3Ƙ%'BKi*֤kc|K? lĬ0eH,)HsU"r1zRJ) j>Ɓ&b c˞ˮ3ZBk2$/|tEd00ECRJ) -݁al;}1hkk ZaSN4g>cNARJ) [%;auXq k{;qS/";S=-RxQj8|Id4wI l#["W(lE t,ɶcԈu0ݯ)s!':&GCRJ)>iM >‚gsDZpQq4qMpzHugUtܡ i~P9ܘǻ9AKG =x8k!^7?bw;L:g S6lwu2g޽)N|z>a neIž摏YOS+ryéd!Qb[5qEzl>oRZ2`:k8þҐ.qt'RJ)VDkO,&ʀNWйޝlj?sXbq(Τ1mdJ P_Iu|󛏢CZ yWӥb< #ǨIѷ_׫&,d^1ԥܙG$!UsnS T̴#9o˨oޟO0u^Po:ܕ :5Q0$"iyzoο}rn\k^:>/AzRrǞ G4U7~߲ }:䑳FXN*龤RJiUknhM2F UOR9DXe@ Y.|Wx % KnLs,n;jvWWa f71J,+͎_d{u;6Bħ}4TMe|O9珓{R1 ot`č8a0hӿл<7 6Tzu B(+T;FҭbMG:-׶_@ܩ "Xaazcy{ݳIRJ)"ڤAĢytuA#T}q4Q=Kr̬B5m:gsv!tB@tk|`[9!:`Lsc+NYGӽY4y-87y!!ʨǻDcn C.C,3|z` RMcI8-uq;RJ)>U?=Xx&ɡ)s|x06&oi6}ůLf&xuӶL`<5aXt b$$~w>?n7|.?޻>oM% cpQȁ)x0k|D XؒD439Mxo֑ŭlF u7q qҿO䖱-#i|r~ho@~%'hl=*cRzPJ)4*{t<:禜Ɩ,"vs 4 ʄ пFx?_MA-^vDd..B&xQD9*y/Ig6x O?qa̴T'&1U2Or5|(v]LCҔG'Мc bZ*=>=;; URJ1=FaDcDGb_\`3`1frVr1ƳEnc?01WO2@ƒp&VY3|dWjz0- ]fyA0\m%i"\оh[f{r #i%o8ضsY霐%uLMMw*`zăuA[ci٤v[Le뼂(1D&9 XL<\L aYѮr`1GS_\1߲/!'ƘaRUj^i ۔j"_qx .-2\v Bm;!ԉp!u6lQS0P{ٓ1Czfd#oM8-,/NRJZ.GOpT;7a~A"8Yֹdep7g.7fշeݬ8^68+RJ)WY*́v/߯쫣YƲpVeC)RJ%SJ)RxRJ)RJ)^RJ)4*RJ)W)RJ) J)RJRJ)RJ)^RJ)4*~ތRJ) @RPmrl- ?‰ANID@-tLZK˵xRnNH5ڸ^c'c0 m?>O+W_mExeGKhjSќ#/@AGN1f fc^拈E_^a b]?]"ynzfex~ }[^ك^:VkF jv{"12xMW) cDD&'" yw<|-<+<lvXxIxP!@4Ь%֌@PtD&`d^ ~>s\z\rNVg XZ[>M*ihְ c "ۄ-HKTA<χf<14*WCi 6_𚖊 Bf~w B>D*.A-DƘ4*WC/mw0kc Z(ʮƴ kHSqrxR"=Sቚ lȖM^ ;Z>@w؞曰Z^jKx6;"熯(\vZ CpWd AP`B "3dhfj9o ū4! 8 cn[A(#)qcp pm݁17 bՐqc&B!a=.ôi4*֮>N Cn( a&؛՚| Ƹ͗7'o.AfǠ*W)V01Wgom|/!ݍA޻ϙUJ}; ؃ihggAt nb ^Ԫ>f11 v/c.PF]{S%UJ}"6A N"NOy^E^B޴/?F?+YrΡvU?ƥv¶ٔRxjM(i/[>' %wɛA.ToX,Y-P "#DCRJiU!b *t.uPA_|_0Z鶼o  60aѩKXlhUJ) 1m}̼ ^,7y bxpiú#qt^8s~ئW(^#vBlzR?q}ĞTO)4lf{ld!nήR?Nd%0' {0fNZ5(T1F GlZ *E,:뒶r٫d &G)^$%q ᣃh`!ޒ%j7,JVf9ҒѮ)t$)-RJiU`>_QL>K,T +SC쓖73Zw2mq0t6:y IDATohGHqW]\'}1\&'+8n!ƭO ] ?RJ)2Dըq&0qM_gx;V3{G H^ L$EGm[ѧ4<6O"C}w/]k0s0C8gsr\82N뗿U>Y;~mwt yy/] t\>,9ЏݯgڡqBC3z/?E([<=耡u{tpΝ4t )5>fr7gObf3; gCt9)PVlZRJ Uj5j[[]\2O6F'q)bWW]w:`zm; wxY==c)|R>;vs CG8)luW2ᮡ?ɑgـߋ}g=ɓƀ:1Oĥ2cb :&veȻ3Q=Ӷng5LzSȜ-AuLyֲWIHW&fF} eԙ4uX&T2N95IJ)4**+ù:i? ],^Ok<7"Q&h*ix> ,EʿwM(2EBMY]_g=@}4 zҘM$QlC,s#>ͱ\ЧCwq6N]"JA V#xYR @jd,&|,s˂ ]!!i@Yq>RJRk$#cݢ^y{7KPم(^a=߀E0eRIlņUT`ɿ: ~#D|<aHQ Dp8վEmcTitex 7<FBk =/D)#;|5 f͢($pLxS[XnuP{,>w7jhUJ)R R?E% -=|F>2 Gc_5p;8kh}h#Ho4Ec yZ>ȽJ/_ |xڧP1"'TtɃx nm'R@uy߷z`%C,"'3o{;jk0Qb?=7{}Ȉ[c={,}M)J^V*,Óm| լ.P #&rU0LL4J[ g}<+(`\+ ظG4'ϯ?F|'"Rx C"8y7њ5q_a?O)gSI9ef1`&c, 8wtERoZSJ)W5c3CnX̗]MepĬ)7rSF`̖q9rsf}_$2`s9ئnnم|}n>7J+3^fL VG]|Q%}}53uf@{_ܟ}g})/{_.[ސ!-ros'u#v_|{Mav~u6΃ V^܇=ِg^[{2yovxuæ ?tZ8OwnsD߁/ǹy`1fX] [GkxZͦX6WsDLisHSI}B I/>t d*c <:Cc8J:lұ9>l=iL9$| ǼMce8<@&X'a7;8~=3`R;D|pM&6d1VZip^q4|{rH1 J)4*󰲃&8$}']nz0D.7m6dҰLMT%hct2=(|ײ|&oW)C{iPJ)RxRJ)RJ)^RJ)4*RJ)W)RJ) J)RJRJ)RJ)^RJ)4*RJ)Wy- V/ERxꈻ)'j%ԏ\Nj>8RJ--E~ `gNyR?@oS0S uΈcW)4XyʧpyLt[ドkIjGysie*^]c<1cmSXg :"YZ o=?o=^צ1˕@, \+"xZJJ)WH7 gG$2ɵMGi(lq-p1&RJ1n%k/R-PehMZ(v SAN>czXx@?K}5V,$Rh4*^ڂ؀oY%0&Bp6.b-H-o-]Vc/bA`q&)3.WXûQnҶcj(^S~wدD7"b/kRLoWJ)RxRJ)RJ)^RJ)4*RJ)W)RJ) J)Rj çڗ ,ܮW`#":~X E:RJA®v_P{-m@Hb:Z\CRJ_H|m5 >~Udako!1|{uoEo_GZ[;!cc1 J) ]+ = | ,#ڴA} YLޛ$h԰fmi Z?SǩQƘoJF)^RaWzH#![?mǘ:p-`e|dU!G,=ZssI=&\`_Vm)nЭ{rj:b#xŢNjY򇇸cp?5fa;oV5pvYrVD\îR՘&bN/1`e7@*^b׫%S!n%eO,w V*Z,ZKE)2t 4cRJE˃J)=V/+"xG,iRiZ'xi"6{J=UJ)_y\d5(X9 í1f?m˳0[jchE^Rjy jÝ CE[ r1V|,$8dK{p-x^v_պ˽նFf+"aTa¿Wcl>#c>ĘI큿i1.b}籖)OERJ)(@1L:[!y@}ƥÐi'PzK/͛vC-#X-Z`Y@m/F/ ,߬!j`pZ#$&X:DBR1j.c-(tLAd`" *"IG_f"rup=SIR׌]!R׌fśA Mr+u .N^.G5}ßڡBf888<  +AMVxM k$8/ A-l_`o`[smq[ 0ܩBX"D&!2"#) ۹ȄSM8@3 0#\Wep 0Tpl[ R>I&ُeD1e*I|iQJ x+>t"_3tk,Ƣ_olN%JTI3&lٌa35- ͑4R]kO`SA6<N{ ;0x$ Y0 !n[]):0"wpz coDd Vsā0p&h"0uZP TpYD0DcŃT; }7`?D-Y؄Ӫjz!MΗ'N/+0f&"".~|X9S@p۾ iUJtI%7o }k6CG˶( n۱0i)5 t!dF~$Ħ}!%sSUnj7N9zOf&QPHƂ.cc\)Hqi8] ka׬OЀN<;!{ꄅa';B xI gR4?A+6evG?O 0E/k6&Ԏ ms!1L/< $_+G z87 j{W)=5ɭh~4v!eA<_?s.b%c0O$1NSGcE wQ'I7`%eCr(iOE 2U'AcaBNGt#Lb_Pڐfg:QwI¸9$ٝ 0;8I :ǩ@#GL$5Ma4"itjya Cr{+g"vm9S(Ыᇗao!;lE>)@&s.fff47>ugh\aqʡ:Glc ~ݏٯϠ[_N˙xyl>f: g8wq[eʶcG! أ>ӏc^̿:YKMAGCحk\$!+ץo?kޚD?cu̧|-{ϩoBYJCj WZZޑVЄA!r:t=wf.=_VGZZ?ukl1`1fGi9T2>vxy<P1 Nrt9.]| U%=L,?\P AIē J˰e $,!I/ӝacrSc>UN}KxK/{YN]kJ39*W;ˁcsfrgsyi;$>?<<=~<:]ĕϒM`wpFFlS2yb9\_[[ᄱOϸq䧼H͚(c!Z3QN6d:5OXpsKÍ/3n`O -'[⼃[R_T`0Edw7,⃱AAD{@t|,Ғ_5a0Vl[@[.1JTyMZϧػAl@nN? ε(ޔ sK[^ TexwλO\[!Jp=рȱ?.ybM瀷N4Wyo,~Co,aݸia3.hb!]o=_Ii1Hj6{<TEޝ-{lY?/o` Ftt&wLC>L'dvcox3U&%>%H;ק H eT-m7=xk9:ė9M7CNp$`""ٻ8gfgWZV$70`SL0%;NR!)! j(Cnmll{lm3cflܞ9:N͝;\H͙^$V݉pD 3''<3x2ܯZf2'I҇\ IDAT]Ut600_| Ƥe %Yo_.n p%BK[B٦ l{1a{rf5GkxZ eQ,~u 7M:n48F"aK0 ދ4I$+T{H>[(dl +Q/@aa: iK9vJ˙sԔ{0"C"Bnn#?Yo$6R[XHC~iyN2zj'za_vO?Ch|S_B-1}),Ln3]lU #D mb"/voEAMm6v h;4ior?~ c^!xcyKp^i:k0`X;WVWj7.+JvJeA,<7k)O7}eocp2ögReSPjO8u*'ӐGyױ9-]XHm\ޤbR޹;O_yfpmei"]<668^#U'dV1{^)UDZu߆lw&sL]yB=Faau L0i7UWg?N$ѨɊڡFnʟkb8\ qaZz#xNB8,^Fpj^&Wt°|VLZg2j*Z4e{Rv k*]+7'6z6r7Wtڔ9DKc[dQ6ׇX'c@)%d2G3>8AlߴҼ!f#\T={ dDkN#uDcM3.l䕧.(ʒ1D \x>X/@mSug-^'w{Uk]y Ӛ6sՖMpj[~{|߬U{VTj *V+v$Slñ\$~T~"ؖ󞻐wRsώ \q0$~'2hu|79Pq1ǎdz{GLsxhR'PC)(5!֡UqSC Ve SʘO-jT2ԡJF<ϬcrVu)sN#W(.BC)_W'X{No3:ԋ9u jtS2$F^!ۭsnl]:z@LLjOD49N"xqMk|1Fk![@o:#8JI>h ]wraƘ*Vi(qL~m I)&vY{$x;TҐG1N -"E=HAGQ[v4hgrNuO!twICˠ8NЫ2)z0ٔt"i =V3؈6cP+KZč7aY閹*;l޶9߯lFח`\cO0f6"Ǣ_ZMkJ)T (gam!" F4*R6JiUJ)'FJiUJ)RJRJ)RxRJ)RJ)^RJ)4*RJ) J)RJiUJ)քRJJDZ@R"En{I.Ot"\,|-ԚT²[Hg-XVm3#r}cTh( *XUX6]J)W _D޽ycd>pWힼ;Ore[N<;xvT-[G쮍 9(1RJZ%#"2iɊ/?'<Z:!;C׸Z{8fW*41f zpQ߉ A Z|S[ 4n_M`1;b#\׼~WJ) ;^^&< v9MĘWKP<1FORx Yh3+@_-(|@QD" h[Me1]^U4`KD0EpٰꋧޜRЁ'RJ)^RJ)4*RJ)W)RJ) J)RJiUJ)RJRJ)i?JBA,>H8%"k`FCPJ) J6ڀ9h!7D._+L~BRJR+):&"IH[[!nemCaEC  D0öI<1i@f-iTj1&]zRJR껇]>W[38kg`gyLރNvHc["eƘqI6qPJ) J 1〧=+d)dއ#Y cv`xsaޡ݌1cW)4*V/ HGDSS> EZ>FV6oNG{،b`@kxRJRj5XaN@%}CY#3PYF,/ɧL̈́ӉǻZ˫RxRxz ɤ\)8q Tk8UR3JuvwRT)niw7Kk?ap"nH)^ZAW)4*RJ)W)RJ) J)RJiUJ)RxRJ)RJ)^ZwՏ4۸O 5w.'RxR똘w?~# L7ބ#TųVU&C5+^:w`ָ2fNg؎Y+[ު9#t'[wwݠ,u[rgV9.c2lt;ZODZσn2j9Jӱכ yA>7mQRj;yROdS@>xl斕⻂ NoCؾ 'O6zk€xܖ.)256vs2Y9Uo1kNڗI.ky'סRj5J nS69|v|_c tmFz8ifOe<ŀd#YWpMYƛ!YϢ1:89Ƴm^%!YOW'z*y2Xf_:L#ŢqO[8>vNa7e7Լ T9Yr:cY<00S7bΘ%>~d+>9to~,!•=/'4=h.wHD8j}5sʿR{:,'k2 /mBv7ʺI8`}fS7E(V\8(Ժz"PjpBWNk lF"85 O_ ^dO93&|akh=vΠ.Mu;˹N 7~^3.Gtm;>x`Y2C.bGj:0 f`ǽIEfCWcC8G/taCIv?-_aW[З = m,,fӁ/Ks#8aխOQ :o>{ clFݱ'}ȐJwRJiUJܜ 2 xʻ> fDO)8)\>ot:ktc;MX$[~Dug.ٚcp8!lCJF1'y/tpS=N8%]#ssaEwK#W'tgj8Ńh=x-vt]ǴpQRswf*E;sw}*:{e&86>32eׇ1(NUJu6iPjCD 8>n~vH,Qe|_}{E䛪ݸYr-f<75IA$FDxr\.yuq 8|1Y}˰q(ZX. :Zm `+9<צW4w2;+R1/'o #ǰEqUDrQG0!_;炮$&r_T%Qw[e _RX!Rep0can4bEpelRǝquZ| Oj|0Bm 1}ߊJ>NYM\,9,K"ܾXDhjc'Cb0f̯~+_5( Bo6-l2mv Xo݇nCtN\?EJ)& Jm8yp$)6Nᓮ?a Tنt; ;.+gɬO;R1)؆-qg4ǔpwܳ<0ir6KrX "- ƴ<6dC ]21[煓xq")\@%^6ibڨX8|՞YUK>-Jd꾀Η˥I{M#d~|JHz? J)4*ϵӻLIE.8Cykk({Q n?Tv3ˢqұC#9xx^`~>ƿHrmO`E깰1RNes b;tŸT/ka8&/D0&10 /NOHIϙ{` x\;O>2{?ΗCKitMϟ3n7%_r_S3|CipӽxIkJ)n& Jק!MmMCGfi9K0ombƻ qyW~? 72QE%DFSJa&eo`q0]8blqd2ku3(}Ǽ1H4&3p|x`:oر ψv.y^Huw!YR_'ǡ"z3aA!!v-Lys+*{/b>%5RJ^+1+#1%^|&c+"7p݇rә*]T6I"',b4;8(gc؆F! "kc9H1 DD2|W9&|B)n؜Y,fS-02ӛ,)G'%E -I18un^N=H1mibq*!̦J\z-° L$F 1, >BY Tb FC'xG1CY |eT~I\hoi@kXOGkxxꓭ"1Z>M'ZXYNp`_}RxQ*ʬ|x8Mֵy+"~s "4?NFĒ ètXr#|.!Z| V8>SSqmH`bItGRn u-Kw)m' CRR07enU9(ZKŒP@ekYqC&6s]vc9xQtu'mz CjekRJ RJ)W)RJ) J)RJiUJ)RJRJ)RxRJ)RJ)4j(RJ) J)RJiUJ)RJRJ)RxR+-BX?Y-4*~2~0_ p!n kooRj]"PjI10㽞px&KP!%&J3ëR jg/jzp|4PE^OxEDQ.|ůMPo}{\š1[5>fWL9,5!?뷜wZ)W)c21KE"Cȥ^S^K/AVJ|1X7 kqee i AM\\K1>vm`6UQJRG^Xk_,&7Ԫyu[Xd,}4Lug" X0?PMTIBEāZ&BZ̯ahV< q5/&-Za{fOyI2,#rEf0l+c\,^Ozÿ}E.. [^N4w]x_D c\DN ?RJRj 0d kw.$@kx[ ý-1~2׹k캈 ?9 <1c`v^ԚJYŗYEkE_Ī<7gG`:"yVv#MjNĘـ.`!hvGkxRJD$ |v7Y A)=Ø!bWK^RjcyCKo y'c{v%ܿ}piozRJm(z^=^S;@ha7 \G IDAT:x״y`h RJ I&$`8(ƌâͺFvw+Zm "#كRxRJu^t0Ř-Ql և !v!p-p) a?}zO4(Zj1i˜1+ ۴zMmgØksBb~8Ԇ@kxREZ1U`W4D`V8.(.{~̈B[isl/J>˅6Zu 0r"|j+W)A]+<<^8oe-7 wCfzU ~s+ N:c?vEfӺ/aRxR+"e6EGd5Do"+9<.1>Q!bF5/G!t(SoGޢW.ߐ`1fRweƕR Exz[D;u`lVrYI e;&'"z|Vk06,cf:fųV3 2^4OT,n 1BRxR+J?q*%;sUAmL'cYDVFťr wDI6HKlpX|b1QʽUY&<}Y#"1| JiUJƘ lҏc{'^4 Q*.Ugۜs |M) Jl/:'FJ]gGKGpVŶ ֬A"5DD^ԏzYH&YTX1-~T)C\J:RYBKJՠO(VU(Q- ~"1c-c0*W)#nZ#xzVJRJ)RxRJ)^RJ)4*RJ)W)RJ) J)~8>lHU' Q:RJ@R[v`1q\ 5PVg.)+KZZ/GĪncPGR$77>@ XӠdgih'ǕL)MinU/E՛d'L9p4c+4*zǕ8NOvp7D)_}zWL %j9}JM!eIC0Mp(K  { U'ryK_7d %N\-RZF:x/ZG4Upp4Ua]_'NگChZ "x7NSɡf3y2w}UvЫֺk~cA2 %Jw#؇ |1zL/8M1`p#?pq?!x(1 7@Ǥ6Ud">D~DB}Rҕx"z! ).|}D|x05d/b7KXIiLrNӺI@a Ӳ ӼAp-F vʬP>6_4y[o@.K0R?>YثBz{:=6OOJ`ijr鼷sr;sHM#D~_bN|(YwtygImolL,[ߙ&kqK 8FmsΛ7'sg6Qmǐ~ƙyzG)jf:G>IH5W5f7:.ik ɺ߳ fMɌ8mԉ<}]C'DME*v_i/PvWM򗝦 kPXN{P/[I_^΅[."w@.XJvyۺ[JRJ,HL|ȗE(=\I0o.e^Or̹[tes?b=oaYRz M12JAy틁L="S٣tEmqGXr[^%?gG[H&Ofg8ؗ0!K7 *q :MocI:oW8Z&y?/od.`7[?I$v`5`~u+^\b:MXA̖~ˋvL\ @~z9`GZWǁp_9;\A0~ (=6(^C6p s _ߟ."!x~N"weX%lLǘF9 88赍}( G.!O8U5J)& AD&rg6N;[ Vn_5|ܲ,u~ qb1*8gM7&Oe8S/x<~szw vQ1Ξt%{q_\>օKʳ4TT+e`aϒMtc`!6/KMFIdʑ`lJ˕_?GSG1V{ =9sc*3ǩ3>:'PZ YJyHZ;B@$s>%8d}j?BBQ)<"Fretm_H<9.pna_h#DrO`0F7د|ySٖJ2'Nn)r,G9 3&=^&4r<"#r "!i+ 130<C a@lH_C ^-)4S8D.GOŘ-yrYv7z۸9"L />^ znYn[ӔRDBdw9 cDUJМ{+< z,>z_s, 9N.#%K#2j*P7әpK6 4J #&Nq oK$<0[(k4;7"Qǃ/<$ / QDvfiI|}6~3uDRϥڒtz/Cg+aZ9 >xV:>Ah%iEapʹ\ | ~p9^Q .5 u=) ߇7x,%hr01&`(Aۿ  A;4v"~ Ya8,|TZΛYim{ڊJrzy.|n!"oPۭx5*O)!fQAeVrcN-މ`1s|p~u"U}οOǷB,qƒ4 1&y$WWx.}؃=3z| ]lL CpTD0tm= 2Fdk`,0A$7k0f~؇"o$hG|'hXy2|H4l.q'AQa?1S=NЬ1Ø4Rp5ܗ|X|1"rAh'Whû?NxұMb` 7 cV6iPJH!z)H'/\'[%=*Q!Fҳڄжˌ٤6|ұIk]a/qa':q}⾃h,0Y\; v%=2n+iĵ?"]'O%|F}Ca;g n'vcSaiyo 0u0yd  xn."hK#6@>$|Ao '!RX8p9t]vAy뮴+h<\o8; Awlܸ( Jmx8^h-br '*3n;jIac/?W)(Mx0F\;xV#qp ]VR>Nφ/yk@߲Bhvi.g;haV kaEMN) C/LAMd`װ热3u\rn H63A(!賶-|Rp"7܀7cf!6A|-X0B®v Hi C`fysA"!f[ʥP]h _#maTD#xc}^*1 W)|XU`6};ߡ7ھv8XIJ'2).y+ k77EeH N&6?nOR}j v9_Wxmf[@G:[k̗M ˟L.>xabe^f_= fw J)Uy%n3ah ƅ ԖPkˑZ_ܲ֡pj [<{_~Hg{tC[ʰuYo6cRJ[{j_ l Y[{+y|j$ <`BWZ^O CǼcqk 3x,j.k!:J'YTKÐa/CjѽIWZw}عʫ|Mۺe<ɋ=ZwE&zw'ʪIޟf/{wL̓O7w^ pRT'ôd#vR{?o {/p4;Ny~mе䍀$GN__ޞ_,/ϱu4nYi,lLxk. `탄gUU5=rn/Ƿ\[Nw}ҙ֑2yg w?Ivcb3h%U|%ɕ=q[II^T'o).$wY9GYǷL.3gwi嵰?$rtkA2wS5Lkx7J|'=o 4/%t1I!^\SV^l'.5/^ x@  /^^ /^xPSuiϫy8sq 1%%^pM`ޙǜ9yXa|p=3jwWՐf_$hw`? {c$t{3KѮNr='\>&Ou9XuIˉ}rjd/$R~vU''5Lvw+3ݽx{28'&$;1^}#Þ~YpJYg\U'E'p,t]ݖ2`N׭g4 x@ /.@ /^/^ x@  /^ x x@ //^ x@vsIDAT@ /^^ x@  /^ x@ x@ G *gIENDB`ionelmc-pytest-benchmark-5edf251/docs/pedantic.rst000066400000000000000000000044431471041671100223130ustar00rootroot00000000000000Pedantic mode ============= ``pytest-benchmark`` allows a special mode that doesn't do any automatic calibration. To make it clear it's only for people that know exactly what they need it's called "pedantic". .. sourcecode:: python def test_with_setup(benchmark): benchmark.pedantic(stuff, args=(1, 2, 3), kwargs={'foo': 'bar'}, iterations=10, rounds=100) Reference --------- .. py:function:: benchmark.pedantic(target, args=(), kwargs=None, setup=None, rounds=1, warmup_rounds=0, iterations=1) :type target: callable :param target: Function to benchmark. :type args: list or tuple :param args: Positional arguments to the ``target`` function. :type kwargs: dict :param kwargs: Named arguments to the ``target`` function. :type setup: callable :param setup: A function to call right before calling the ``target`` function. The setup function can also return the arguments for the function (in case you need to create new arguments every time). .. sourcecode:: python def stuff(a, b, c, foo): pass def test_with_setup(benchmark): def setup(): # can optionally return a (args, kwargs) tuple return (1, 2, 3), {'foo': 'bar'} benchmark.pedantic(stuff, setup=setup, rounds=100) # stuff(1, 2, 3, foo='bar') will be benchmarked .. note:: if you use a ``setup`` function then you cannot use the ``args``, ``kwargs`` and ``iterations`` options. :type rounds: int :param rounds: Number of rounds to run. :type iterations: int :param iterations: Number of iterations. In the non-pedantic mode (eg: ``benchmark(stuff, 1, 2, 3, foo='bar')``) the ``iterations`` is automatically chosen depending on what timer you have. In other words, be careful in what you chose for this option. The default value (``1``) is **unsafe** for benchmarking very fast functions that take under 100μs (100 microseconds). :type warmup_rounds: int :param warmup_rounds: Number of warmup rounds. Set to non-zero to enable warmup. Warmup will run with the same number of iterations. Example: if you have ``iteration=5, warmup_rounds=10`` then your function will be called 50 times. ionelmc-pytest-benchmark-5edf251/docs/requirements.txt000066400000000000000000000000211471041671100232420ustar00rootroot00000000000000sphinx>=1.3 furo ionelmc-pytest-benchmark-5edf251/docs/sample.svg000066400000000000000000002515121471041671100217750ustar00rootroot00000000000000 Speed in Nanoseconds (ns)216216224224232232240240248248256256264264272272280280288288296296304304312312000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030NOWMin: 217.3145 Q1-1.5IQR: 217.3145 Q1: 220.1664 Median: 220.1664 Q3: 258.3819 Q3+1.5IQR: 315.9902 Max: 11447.389124.526054590570716323.172467324620130001_b87b9aae14ff14a7887a6bbaa9731b9a8760555d_20150814_190343_uncommitted-changes.jsonMin: 216.9028 Q1-1.5IQR: 216.9028 Q1: 219.2288 Median: 219.8103 Q3: 246.5597 Q3+1.5IQR: 287.8468 Max: 7739.299746.424317617866360.78117468139490002_b87b9aae14ff14a7887a6bbaa9731b9a8760555d_20150814_190348_uncommitted-changes.jsonMin: 215.6286 Q1-1.5IQR: 215.6286 Q1: 217.9660 Median: 218.5504 Q3: 227.9001 Q3+1.5IQR: 243.0935 Max: 10318.615968.32258064516128421.43897524687930003_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030157_uncommitted-changes.jsonMin: 218.0229 Q1-1.5IQR: 218.0229 Q1: 218.7262 Median: 221.5394 Q3: 233.4955 Q3+1.5IQR: 256.0011 Max: 13510.386190.22084367245657399.19516656423330004_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030202_uncommitted-changes.jsonMin: 216.7442 Q1-1.5IQR: 216.7442 Q1: 218.9116 Median: 227.5814 Q3: 227.5814 Q3+1.5IQR: 244.9209 Max: 66598.9789112.11910669975185410.066485443992060005_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030207_uncommitted-changes.jsonMin: 217.6390 Q1-1.5IQR: 217.6390 Q1: 219.8263 Median: 220.3731 Q3: 229.6693 Q3+1.5IQR: 244.9806 Max: 12089.3531134.01736972704714413.000702880487440006_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030213_uncommitted-changes.jsonMin: 217.2258 Q1-1.5IQR: 217.2258 Q1: 219.5806 Median: 219.5806 Q3: 222.5240 Q3+1.5IQR: 227.2335 Max: 30694.1845155.9156327543424436.77631659431210007_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030218_uncommitted-changes.jsonMin: 216.4886 Q1-1.5IQR: 216.4886 Q1: 217.0509 Median: 219.3001 Q3: 219.3001 Q3+1.5IQR: 223.7986 Max: 20802.0210177.81389578163768445.98758129391820008_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030223_uncommitted-changes.jsonMin: 216.2797 Q1-1.5IQR: 216.2797 Q1: 219.1180 Median: 219.1180 Q3: 221.3887 Q3+1.5IQR: 225.9300 Max: 10435.9218199.71215880893297440.666181567443740009_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030228_uncommitted-changes.jsonMin: 218.2705 Q1-1.5IQR: 218.2705 Q1: 219.1100 Median: 221.6285 Q3: 222.4680 Q3+1.5IQR: 228.3446 Max: 21707.0042221.61042183622826433.45757092365950010_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030233_uncommitted-changes.jsonMin: 215.3272 Q1-1.5IQR: 215.3272 Q1: 217.6363 Median: 218.2136 Q3: 220.5228 Q3+1.5IQR: 225.1410 Max: 12184.1708243.50868486352354445.172893255620470011_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030238_uncommitted-changes.jsonMin: 217.2258 Q1-1.5IQR: 217.2258 Q1: 217.2258 Median: 219.5806 Q3: 220.1693 Q3+1.5IQR: 224.8788 Max: 13520.9825265.4069478908188443.151900160030660012_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030243_uncommitted-changes.jsonMin: 216.5051 Q1-1.5IQR: 216.5051 Q1: 217.3816 Median: 220.0113 Q3: 220.8878 Q3+1.5IQR: 227.9001 Max: 16187.0438287.3052109181141439.897696048361750013_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030248_uncommitted-changes.jsonMin: 215.3272 Q1-1.5IQR: 215.3272 Q1: 217.6363 Median: 218.2136 Q3: 220.5228 Q3+1.5IQR: 225.1410 Max: 17053.5672309.20347394540937445.172893255620470014_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030253_uncommitted-changes.jsonMin: 216.2797 Q1-1.5IQR: 218.5504 Q1: 218.5504 Median: 219.1180 Q3: 219.1180 Q3+1.5IQR: 221.3887 Max: 14833.0416331.10173697270466445.27709468193660015_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030259_uncommitted-changes.jsonMin: 217.6363 Q1-1.5IQR: 217.6363 Q1: 219.9455 Median: 220.5228 Q3: 249.3870 Q3+1.5IQR: 294.9925 Max: 18499.0881352.99999999999994349.8285881762790016_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030304_uncommitted-changes.jsonMin: 215.2289 Q1-1.5IQR: 215.2289 Q1: 218.8523 Median: 222.4757 Q3: 236.9692 Q3+1.5IQR: 264.5069 Max: 22644.6923374.89826302729523389.94613730802370017_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030310_uncommitted-changes.jsonMin: 217.6363 Q1-1.5IQR: 219.9455 Q1: 219.9455 Median: 220.5228 Q3: 220.5228 Q3+1.5IQR: 222.2546 Max: 19833.1930396.7965260545905439.44181480822830018_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030315_uncommitted-changes.jsonMin: 215.3272 Q1-1.5IQR: 215.3272 Q1: 217.6363 Median: 218.2136 Q3: 220.5228 Q3+1.5IQR: 225.1410 Max: 22278.5710418.6947890818858445.172893255620470019_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030320_uncommitted-changes.jsonMin: 215.0442 Q1-1.5IQR: 219.7191 Q1: 219.7191 Median: 219.7191 Q3: 219.7191 Q3+1.5IQR: 223.4590 Max: 11502.0602440.5930521091811440.214131262101430020_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030325_uncommitted-changes.jsonMin: 218.5504 Q1-1.5IQR: 221.3887 Q1: 221.3887 Median: 221.3887 Q3: 221.9563 Q3+1.5IQR: 223.6593 Max: 12379.0332462.4913151364764433.49365005601080021_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030330_uncommitted-changes.jsonMin: 217.6363 Q1-1.5IQR: 217.6363 Q1: 218.2136 Median: 220.5228 Q3: 220.5228 Q3+1.5IQR: 225.1410 Max: 19387.5292484.38957816377166440.48382907139060022_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030335_uncommitted-changes.jsonMin: 216.2797 Q1-1.5IQR: 218.5504 Q1: 218.5504 Median: 219.1180 Q3: 219.1180 Q3+1.5IQR: 221.3887 Max: 10045.3695506.28784119106695445.27709468193660023_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030340_uncommitted-changes.jsonMin: 216.4199 Q1-1.5IQR: 216.4199 Q1: 217.0144 Median: 219.3927 Q3: 219.3927 Q3+1.5IQR: 224.1491 Max: 13516.7281528.1861042183623445.59905370239990024_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030346_uncommitted-changes.jsonMin: 216.4886 Q1-1.5IQR: 216.4886 Q1: 217.0509 Median: 219.3001 Q3: 226.0478 Q3+1.5IQR: 240.1055 Max: 12556.8993550.0843672456575425.18047337160040025_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030351_uncommitted-changes.jsonMin: 230.3049 Q1-1.5IQR: 230.3049 Q1: 230.3049 Median: 232.8014 Q3: 243.4116 Q3+1.5IQR: 264.0080 Max: 11630.7074571.9826302729529351.32068713426260026_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030356_uncommitted-changes.jsonMin: 216.9028 Q1-1.5IQR: 216.9028 Q1: 219.2288 Median: 219.8103 Q3: 245.9782 Q3+1.5IQR: 287.2653 Max: 23576.1084593.8808933002481361.83081343916560027_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030402_uncommitted-changes.jsonMin: 215.0330 Q1-1.5IQR: 215.0330 Q1: 217.8849 Median: 220.1664 Q3: 236.7074 Q3+1.5IQR: 265.2264 Max: 12268.2900615.7791563275434392.66709082056330028_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030408_uncommitted-changes.jsonMin: 215.3272 Q1-1.5IQR: 215.3272 Q1: 217.6363 Median: 218.2136 Q3: 234.9549 Q3+1.5IQR: 261.5100 Max: 15590.7278637.6774193548387399.32426567648360029_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030413_uncommitted-changes.jsonMin: 217.9511 Q1-1.5IQR: 217.9511 Q1: 217.9511 Median: 220.1638 Q3: 236.7591 Q3+1.5IQR: 266.6305 Max: 13290.0380659.575682382134388.66235639447590030_5b78858eb718649a31fb93d8dc96ca2cee41a4cd_20150815_030419_uncommitted-changes.jsonMin: 217.9511 Q1-1.5IQR: 217.9511 Q1: 217.9511 Median: 220.1638 Q3: 236.7591 Q3+1.5IQR: 266.6305 Max: 13290.0380681.4739454094292388.6623563944759Speed in Nanoseconds (ns)TrialDuration ionelmc-pytest-benchmark-5edf251/docs/screenshot-compare.png000066400000000000000000003424421471041671100243050ustar00rootroot00000000000000PNG  IHDRti. IDATx_#I/魞uStץnOt/dرT\ȹd,KzPe?leP҃gWpoK N>a= #4{9Ӊ]KedU{۷jwG)eD*RUYP """""""""""""""""7:>~y||X1DDtY?ys%""KC@DDt.+ochvSsn介vWH1)| 'ώ_rW* ۃ-8 DDDhl6FnFn˶B_ ˆk{,Z?e@g$=]fc~fcIFլ퍎Mw0}A*l Ӑ/#ElΥjwCo vϓ$TKn]R\̢ 6kDDDtyfnFnF3_}'x݊uo[[[w%˰EĻ+gfSY?!(ʈ!7r#7r#7rL癣̉qTlYqzwp\6Oc/VgVlKbw< ^sz̲ , F麮g#1 :1Q= %93jQZa^gt}6ۼ^wWKg.<'rIӝHWo9KnOg̜zq{8:1rdV/ْT.[JP_8-]o9gr}fqzVWjg.kSUu<(FtЩwM{EsF5x+㧋OhmsãJ#s0Q˃l i0.Hg6-mLe;[ZNtVA.w hY͗ 1ê[UmwT\Qu[aN' r0OB MR?LaEQjA#7/Ot0M@zBՂmWMykb%5UCR5;֌ҁiٟ;fv uF }`{n(vb}kW:\( f/q3˹VzzPQ5;Tt=a9 ç`hgjE'-BA8eAV{ﺮۮ=Z(S&?sDIo9akhizk'i!y*͖Jmu\YbMYۨХ7*.g<㈈hqGOjѴْ'1M̖Ƭt:F%VU7{27hDوhYKxuX.vqk 7z턅CU-j$ rFJm\c.*GI+(nCC0#r쁨r@vY~jQJ6B5OHt#y9yl:Fqm'!Gh3BD3YFq1^0z^L|?yxtQ\д~jNCš`3u*3YTO(Vmmg/rڕ%uRu;kV;(yPst+Its"luGvQufi]#R!+G8Z̫Ji'+pV@sm@תukUShFЭV58"""+/g֢ ě if$J`̟dLyz,/RyNSQ|V#6u:͔5Ǡy.4E= '&8|QTR0MXzH&\AU3 9#}8pډtJˎ|pLm~7jfa}39YpFo 7z5WE5ԢpV,FkY|ADDDt ]ĵ_}ojQbsj搈E7Fd"""CpGmo6PS%6fo.#ȞLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDt\՗- Blsg/A@dvyr/JϣMXYOk!Fgvº=.s}qsq̜' әf\n9Q0tsM;RbJA1mVϩV}{[=<<4R9Enm[Nr(wSyjA]PZ|)ET=:?l.vQ4DFYl0ς8WsF2D檩cGLFmu6'$+)*FmrJ}Kz(&\dqKPNQ쟙wܳ0QYzIUkt0eMvaYQd9kz5E#oRboVm#-mL2'O[xG++R) OtF9"/?ծ!┒{5S['Q#Q_R~[H,>\~ٝ\Dm4:PܓqCo'Q:0M4c@x P5,eq;2tbY`7]Π8˨`laT5߅+GsGpՉlsfVcAnjfq-8L cmƶğuR߬"*L=-]rYy]Ņ'PZqV8ԭsB7TzrJvChFaK8 'iEl 4oT/X=YlKzF? ~'yBPoq<'(Tq8QK8˖^Vh:~z^\g{4:pi 9v%f&#/X$r6moM,Vo 4> _[NuWVU͆VoeqЏO!f`oOόşiUKAo9Qr,CͅE09#sLb݃- C=r}: 675} {^xƭPx]tp" rV[ZP6Yev/ ^:)5$o5UGқdg܊w. ͇G—N5K%KWy2/Y)D^zok]G͡^#p*ƞKRjjgȼΞCߝl'u溙.'qvS~y癵F \nvN;ZgWpF&Gz`k%=&zVeX Ӡa}VHz[$ uhAAōrjۘs8v-QUkN1sG3}+G}ҧ׭{Ѷ8aGi‹{0&\dqc*hΒ.G6;3:lYgXvaI\e*i5DxcK{@t:GSgbẍ3GDאU I_s=nE^|ZNakB~< a[hH,9"Dx8 կK=$6>~%wڏOF"" yܲҽ.?uJj}3uf,-`c@%MK$W1<[{XwjD/DJ"""""چSzrlNl亲aI1׌'њ'q:O(yI;y3*!"""":ߚu{kة6\pVϭV5Cz_jƤo̔r(9QaLzQG4m$&RpnܯsWfϢGrq2K9U@ `bZx[m 6FY=:ZJ3R62>(rڥDaU$6qkfNZMa{3$/[ig@"/ k$u^.NOS:wEPǔs8៳:bSY.-?,Q..kz&nhe".&bx#K1g"*sݞ!J MWPt22_MW3ddnRo9ѶdHhY}mH錄AYv83W.QT m4&ϕ9 mscKR}M,;rٚVE) H8B.l m jA3u|z %(I`1wYMŁFzq暼Ѥ]x6P ]4#XْE)UT)vm8厧it+F-ضUk$+x앞8 Х M$k:3s3;mhƆ.EL [-gW<+*&۽3ib""""1E^62Zhuے5zեnjRCQjh]#"ͥ ,RMF^8]/=WT~01 <[o/nM~|z&~vC~ϙ7xm~dcXvF+JgtyJ\u#osVGQ.#jffufg0ojF!`d(ת*@dHTtQrqbz4h,M2>2g\gQ- ut60XrmSBpDDDDD';fiڀswZznDծu̮nQFzuxN*u2=A@r{6uXU?Pk_ƺw|z554˺ZUm:طz2moIWvpH"&I)Z]?[iF#|7sSzqj˙7k3k*ܖѤhfF0-|e:Վh;&Nd2iy4UYFxzru`UwV-D~CL-et GDDDD4zoU3 DՋ;ܫx`! #ea )YHL=Z=UզGBՎ9_vil> \1_gƲI&:OyS FF/w """"""y-20s=<~$߾vI^DDDDDDDWz̼1>lƳ{_񃭭W?Q[[w8D&""""""(s6-NM&\s鍂Cu.h"IR?lY0IH'oLl/ DDDDDDtӅgp7:׳ʘ7ςIE^;]?{x|rٸU8W(RX'O__>ke҉¸_Ir^`woy||ՎZOnMpwkOg_'i_8G_}vS7 IDATEgKLmxzY{t;wߺNFDDDDDtAg~ Ϟlvp7#V,<*gʑy뭭&j\ roF#"""""0f;7F<?_|lץwFB}䋢v\xn+(t:z/>?Emot6ygy9j{ug6V)q]'CDDDDDD{/.*zg{5¯2ZH+zՑioA T ~PxD"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""":۳Nqw8-r?azq]uW(j^3&]FM_DDDDDD66o6`dlrF0t]O{*eDo9;xl9E[Q+RV)*DRTM+Lahad3znu(/HziABDDDDDDg"Yo9_T/]RO]VG7u$F[;on\gE"(r抡RDf%I("""""":]ٺ^)hknCC#mW6NTYn2~?FBQalx݌y=/an4Ybt< rVX>Ƶ\XQ+f7xU;s!,.*XFq1e6? CQjhc/%""""":y`.7&fÝtne)u#O0<ܗ{:jm-4zIߦmՌdFZW{҄Ǽ(αxlۮMVvSvڮ&x5ttwqJfL8p+~ Nm/aFt0R4: ˩ncQFX˹v.JDDDDDtEd슒'"""""":sN57[?o.g%O_}ɯ2]j-n'EFDDK:i%Yg'jKrE_78S(O"9|+*Ds8+~INeAאdOQ6\!= ERv^-]{e%opcX^E! Ļ'+.;fFT0Vnd\j#a<υDžtEWbsDVNEg!VܹWJB;ؚ ',w={K 7XǹJ\zE4lBa6;k; J* uaWS UvX͞Gs6g-**n\p>ֱc>p1z9wFvz0&aG/Qoa )s}Q:iؙ ~&*ѣ,J@͘Ěc:c0OP)랣9֮OgX!V7Y$tNN5Y,]/껫.(lKAs P.cRXVtv)nRBtaf9p\LѩiPh,L_cF  `vQ5a)ЙCw>[{:x!,H Y[)c9OIgHg$,0#YU3(xSRp %< iIw'W^j{z/Va&sE1(8wMۆi6!Wܗ5:S-4=OXY'?(&ꄻo҂yCH-g EOW0;wu}٧uGȝɔ@vꘃbTpN"tI5 aXma5`=&'jlysM 8]F$QjoaVIVUv\myϵb0bmh (@1enOQfq(p\m h'k8qY""tbD.̃C35O]9#asZ3qZ"#qs/.!NF|AtNit,qk$+fQE?TͅfF+}͋@ER֗(0v>j#vsv k.:v M(4ûN ']~PS 'Sf^ӈfC8!R7zDq4“+ׅٝiKj.ՌQ &&ܪYJI35536J+bNF}^oAWW:Oisut20{5.]qּ 3l:r D\O,ž,=M\#g.,zz!5:}n0R]h~hՔmJ-Q"{.[aÝZFkU3YhK_3Gh ^XVy0[fVLwKeݻ9ssֿpި>HG5R8h4s#uJW}>^Km)Q-I"[ѡW0*:̯<<~r]AxLYKkۛxTΦ 4^RTFZEZ#vubcą#nu>x_\/S}Я=W<]vNPx";am`L`*ҭ熅fLp_3#q@D 3Z|c'ퟲ R1F`vϮ|һ_“K^jXV¬AM/>(g:W^φexOϯyYrU( =KlbW vOd?zpcf@2Gk(FF29|QR>'0d=.Ԣ" )L)R1_NQJ(7~(0#asd=A|̼:r|zS &]OXz݅_*wϑDPdϣe^ҕr ֻ~opcttAtZ)ݩet NxL}}.^%ܻwy~;z=hAs"/5-NEtOsXx^$l &"""""""""""""""""""""""""""""n{|DDDEDDkvx||wo=$;shzwS#H.knTfr?ݫ!q:1j{?J ? KlY3BK\\9;Wd!?&M^wVsi T#{Fi%m}Ng""s0f7mtK^*҅xS6:t9ͷ_G[[W_5@ ?c>^9w>w~6;~.}}Wu^|]&qFF\|ow+Y)J> c|w)랣9֭VPB'DėO~Fd ץsW8{?KUw^z~.v@z <7 U7Fw;LJ-yu vc{o\ 苻oߘ챿uSp|l}~G7T PS(w{R)k{iܿ{|Ϭ0٬:wߞ+$xcn듒j%G.c{Éo3o|r7wc7xӿ?窡3]~}hYCa7_| 7ͽzF_.u$ ,ϩtg@mGsar>J/yw:~/+H/jFx"(KJ"C}=~Fo.C!,Er ʹG$T{pT-{s|{ڳox}WW?):^?tcܼ̽};or>z{ l~*:Q-Y`OxwQJ"~/Q\eOCWџl֫.{j@\^ †)QX=7j#u|g7V݈_pq7E߻oo<עcџl'>=~wJŋ0EA~M7u7w'sN.qKV)gQm+~tm|[DJI3(R‹}1zȿ'CLCĝ6OsI9s_v} /]=uWxIW uۙ&%s O}I&%)> @TN ZV;ʎˉO'VEqSܚDDt\o> |w9{޷/?`:`>t@{]K|ng>{{Ϸv s;\ǓĹRPNvYsK?Ζ ]飷3x7~x^zrBpb_~YS߹10?=<_|1zp7_wo~׵gS[oG@ѿo~?D{xg1ȵ߼)e}){?ۺ7'"qeWsv<~(O9ޏտM7?}7ndJI355%QJg$j ]'ܿlm/=*YQ9eG[G.<WO"s&52ʹ`_н:uO&v< O/DKwos}%=׽X|^ŧaѣgsߏԞħ7hF{92x o￿N:}psNc+\s|m9} ^.}rCy/;o _߫9 x;;ݍK1 s.H^$C9|GoeLwGw귵`4ww~fWQ~Wk?w}Ew;So__+_G+:Q"wK}T~kQ;F).d{ S]9\ZdY9;B3rOYSl=wĕeP$&&  `vF~?z?d WV1 g).xSWV̎ Ci9a)&tн%{A Qo]uy9eL: 3ZsCDIq"(JGe8\{ݨbZ-Q-#]Ǥ/DaUQ8tҌ"u[ba؆n+g$li5EQS-HR0T)Pm$=:p4tN$vʼsU{m ӄ*GA1ZXaT`Z.ua'pߟH =8zB:Fqs*9LV΂QNit0;']%y癭*G蹪{7 m 'MPبgU̠֗.L'PqXʆ -T9s 4c6?6o2Nv:4;N;`b(4ñN ^Wm'}SP moiF^fwKo-RsS,Fiֽ-./ $SJꮞ9ޘug$la}1wOCt` V1Y0rpQ4quĝ6Wp]o]13Ɉaʚ]\`ߑNZ@GgPӋ<GU!W %(jAQ.‘ Xٺ쌆>~nSW!NZO)euWH\1##is*{(_H9ԌTB'vRYp=DDDDWB޵ۡSlG+Zۛ Oso9KSV5 mcuЪb] Y&ҕ=w_ʈz2Ԍh|%F-4ط;B%jGՓ'B<^SZ\m C[/g,JqUʙJ){!nMFq23Rނ/+RrPR3HH;I\~rNADDDtgѯ $wp `޾m&|}lfL5 />fZG?UNqm Q:XT%b#Xj7QvF,x -^z&Fi}Z#\o̪m_ ǯ%c?=?[Ȫx"b<͢8,Jj 4&QbQJa܍rRGI9mq!ºˊ$z~ 6d4tYB#""""U`Nǁ~jDt !""" nț-p] JuDtUBDDDDDDDDDDDDDDDDDDDDDDDDDDtDDDDDDD31DDDDDDDBYyì_=^p1O0["+]b9ǻ\h=Rx̓RSt߂KqT݅ENDDDDDt.fVuJ}&%s8IZpwaF\YWSaa@'2W/^jKK_H݉Zamvˁmqţ-LeSY^Z#nuFSO1-a*h0e\Ҍһ 3R/grW&) , "-fݟmaճIdtL݅ENDDDDDWW޵z # =7TnS`0ܽ: 3~MVovLjFL{ݵ١[('0 nR~(,0Fz'rFA4 :NKSiu0-.X`L`ڰ=F`0e [P݉;y!Xۋ)+lBXf: ݺ Vӈ=LmtLtG4&F4ÉʹdѸ0 0R[aQr5CTT#d FvZǎ~S(OӒ.ޝP7A];z(Rju@`6_{OQ\06%u˪M`3PT:&FWfF"Rwa+Ѯ4\4j~!C43JޝkC`”5d{av4Q[#ݓ{xnzfOZvkDDDDDtEg=^86n4ژ0|ēve'h4} YDz}l/gaUP FM%?ad@~hj~waFL=^MqE)<=$&u䠷 =`QJ" w'""""" g[SDDDDDDDk hr,/E3_5+I$TSn]Z)̕;q|u0l4&̱1 SU)s'""""+Z]Z`N n#g?д@o] [=4sa: sHz m~&eB' rO.0o†B݃cZp3=vcF  `vQÂSQ%Ԡn2:60@(NTU NR@ Y)ErP9R(6]&y*G\\<̰gsb8X`^)SZ1~*L8 b>З vO Ug7h}6u^z  zbFE}FEvP00M}QguqP:,m 2ޒЩNDDDDD3 y`uoE'l=@+aʆ֘I#[w:F}  9 É\].0#aݭ*AQ̍$~4lϦ 6Ef8/hFDwyDIt2r9LDDDDt^nv85Qʃt1I  рk TL`G8_RI=ȓlL nA}vc[0iQY=TRơSʝnb0EyaЊF G+:J8E `4_ OQ*'w gMTJYimc #1mChUT8L-τu(|"q2J}^mC_Y@9^]piϝ尡?֌pޔ֔r&m""""'J1&. Dف C6}?kv{1#af5y6 $ _5·^%_-m$Efu^zI~(S 9lp'=[_%e:tѕsi~9ڪbi|t8&fk\v#0H3<`QȻ)깰.1[Zrj~Rڽup{HT\p]nhz"" C@DDc~^ zi벅8f&""e\ԣUυhF*C#L xpw NPb0g&2z(Qi`N^z mJ&[,1_t5iY53v˘ѢjhFQNp8ЍFO(#R*%хKE[lmvRzǂ\sᴠRÿ(#7[Elг"t-Ʋ.,VS\eձފdG-*Qu2JM}vӌREDDDܵm&lnFnFnetx-`vToä[T5 :c&R‡ T.- A8l7g70RΫnҌׅمwUsCn*WF',7r#7rez ""$`bY29l™egfх\?#_R:%ѥC@DtiY0 yI5qvk-M죱Ɛ-^fpoke6[o]1?Q$""|0"Kg}b۸|#Ci'!#z~d"<~(E\P!cz  7k'K.(Z -lqAaпB"0(x/ $@y25mb-ߢdyXH}\s9޺7ygFHc;v c1C`LvpRb~w2ņȈhR EXGOq\e>xb7؜+ 8vȇS ߫BPEgh?45Ə|ѷ7(Jz?Z2?]tDk4.[H6?> DT.OVg)P[z]5AS+j.y|oL.!"y*6 Ax3 "sk^tXbBZz:ged ѨYxބ(YP,)%Ԍ5IFeD͊JUKPݟ[S碅0dhaw3qndz`)^,}}O0RdۻtȇO)xX`vk ;:kQuDb'yCg=|8o)^ !t`2d;eC;>j5zFR[w;j>ԛ DX=~4?3$ߘC(9m%QƇ=fK 4PL8A9M\g=-_V&3Ca &3B4ee*:`2w]bb^O~s7GJ@NX!z|+f_3?Hm~|&:/{JG-sxski\be +{5t}۟Gp$z׬%**&ګk'm%i!*"g~I|e͙4t>N~hoDT[/Z8AxNIE(MkeSSO0R=$m^$btBCR[3'mz2rŋlsAY_k=\IzĄ?C`9dly'q1A27Y`a/hniyf[ g絻SĊlKZ Nm#5Ճ{73b0̛ ߅($q. ‡o`T$D].1ƤaxdQKq!B!B!B/Gp2PLP1_'w}}yX,t7ww7K?޿EeCGPg chНOL9NF<6""=[>C1Nq-i&[Ɉ}˻gd= Uo=UJR~@-%_;0IRen_>ܤu|a "OmxZ E6QH8[ W/iTzS Y2.m}g޵̈́!Nu.wk\UhDL{ۓDql;s4l:bϳ#'5CɫjoU2C ԡ䈩klZr/&nGQ4g8/bB#"*e϶)QȺZB )C (5sXvt&^j& RB;mΡXdnwzk`2^? IDATlj<,{֡XDzvd)S8B-{JEE\D@ʪZ[  ǡ p!6=k\C3rqmK@B!7'b]uplip<'rwke~~ebyg/,o=l8(z㸥)W'׬?V EL)`X=qZRVTҬx:տ.|%E=:r쐸b=]dS]YnU9l% z:yDb^/uv;`&쇪+/]}4~fZO*/Woiw^3 z%bOY!m/w76o1ꈻvWQ":([}ryƌYH~'kFg8O'GM|2{Z!š[3#ְkx,`[2):2}g8'a?WJG{r 9ˇSz@^+mv;ٕjpsb%Ersf\qV\2 Z 7̇׻"GP|%N|xynwͫY1#[+^f>$ W:fzmʸ:S(E3Tlwe9zE<'3D#ݺ7]c*?46'd'KT?]goըZK&.-{uM(zwF`ޖXG\96nGs!t Ѣ*1jd~˨::s1$-F:uq̺lGD#bz7q[ bBL{_%"VaH}8"{QfC~O~qasCK6d2ֆ͇5::!|2SbډYxC1AĄ7`h+hˑ+Dyl0b)i*2FtZ5+XI3]DYx޵t^Sm}h.47BS&-L)l I$wThͽۣcW{X|?{hGSOZjG܍Y!^Ka q27 :mnV>ۼy(28OD阞_ᾸBFccɿz"ޯ]UwDUA x`aSLNЎRmvy6::x}uZ. ۼccZ\rd谊]ɰz0-ٸɠ[ϱ4+iho||8)Hl_WfW഼fKi9pp卾L"%5E7b zYf6ME{вłӍ:kB2\Mer+99h <2U5y"*B^\HUƧ;'/sMMZR_#ߣ,1kB/_SLMLNdo&/nvqum\'ߟ|6kWLҷR<&2]_ 3KtZG#*}FF^z^>" ՞?IQuevh!jlg͇_5>?Lu:`7E f`|gCCYt4Fvk2ֆ0/ܝg0h Hc2Q<'3j(4u9'#sYuzޕ&LaCf~vS3b )S(M:,ZJ_U"fnW/_+dzd(ji:>GCGm^!jyƌ@=iO6i`Z ;n'6tkof>èXrǞ.N ΀YMu}+O30z" w%sb󜢐C͸N 3#D+kdDZ`=<@FƉ`0"x eַDNwsf}'m%1Az!k78n:ID{頇ҊW|Җwt7]*U4ǃ͇$fW""{uRIe)j+сa*_̿wDTWsWUZm털/\Qm㏣13x‬DAt@}!݂1{ƟT]ur?\k@YÛ.^~䜙ة)2DK)!14TPð=bm뷐F{B'U4 Cg աQLf`J8{7 u9ur$MՃ`KdЭdg XݔZ*نp|2"R%JJDyOyϮ)f ϖF*%B.󦂂ąSP_D.c>~]W?k!=XRAPtB VŪlα~~gn`~EzOvHᚢ]E=c|K) {.ߎӟr:erhCwU @GPgx3|'IA j86`ve} L?ү_ggQu@G>S~9+0 wZ)+;Y kɬtgVƝ7`g; .mjy||j="Vn~D31'Yg ՖkY.4.u4@32X:XWDLQk*|$:F+J.8Uvqo/0~W-d:(Э* mLUP_6Ggh+v1gt7oiz{o -VVVBMyGo#8Z3j!@3H3^j& RBF)Eង-oCX$JH5sمwTJej?WekT8٩GS:nF."Sc؋P/>_:|&*?d?_߸B}*5J5G;qѱa;o*X*CGXsn[L*X*߯^7NJ±|75u)UD*uBrŔkr?W~-8ۃPϗN=L|^jKL(,;KTqI~Ltth/Pa?+l!\d1kp1۲&sH: "=/6T3hWa2jPun3sح/klC-zsGg8U,.Yg3 .ZkrTS\ZWłpл;|xS. eyN<˃_6IT*d2oGaC1AqAAA8vN6Ҧgkh9]. H(\\rz3NDs6ܡe24+ *;#`aܵۇtRAꓕK8՗;z?jyqn_vj6O>Af+Y?]0,r׬ȲS+F5d>r}pI>m3Cn'zCuLӽ.6 W/'wOŁ֙ EY^<0^M~xJkSf&Y0,vgOd|W?^=}-sQį+ky1U܋|t˦<{.XBf]d1kp1ٯϯLV3T`/kձ,)tdx5Q=TOu6g@)ϕb̆ܜYIA#^+n e^l #3-;чZ8|x LHS3qƞg>t9+qsk^ej= <_[O!Vȼ2 *2tZ{^t('cj~+'3Dg䞽8"{Qfz$ztЙzj_;plܢ=j?{F]6vbwM(zwF3UذwQGV]SOMOZ޵>Z20ruԓu7]c*?YJ"7KM?ɜ YƇL܂?Ѻ#3pYm鏵}"^1g|\QbښYxC1AĄ7=7N!4g6Rր<-ool.]p XM;yX=djI!rzMt iQ.%^UY+]dm`=쓕~}Jueoƒ*QE_! *+WHԌ 8_17bb߱4+i;-k7I"+WWT?/}cE#wnq:vsٶxBT{N>nR7Zr! A.g=ۯVQ96nG"o$:>\dd/^suQM19qЩ['LぅIA\hhܖ;^3cy՛pRvg'(r3teO)|8d2 |Gɴi{i)f>3K/dSldwXpRBT}L(S(MQauw6}e$}(Ca"eըpԞ?I{į+Sö/kKm/Z;Ij6u^i%$Q=2Uą&ETޛ:߿zX3qSzԗ?KFξTiU3#396Zb!+W/zJ_`@|3~n6WGYGtk+B/Ys̉k^nOz''p}D玮<axa<'3j(4i},}l,qn~:NFvqV!7m*;'81z4S(4?Ϭk}Xe Ŕgޝ2bsԆAFe\? N.KDDbDG4U<١~xJ LT5,\0xCb:xI7NJm">,UW~ _1_2.)(8"kT>;6R':Rŷ  5ӳޗe&d vd@G̱|ëAer\%V\LiԼbJ5+kn3c˱1c-\Z9LFߒUס#Eѭ lj~v|HXmvY˿h|:GrǞ~-N ͅgZބHbBH!|'ni$rsLFS3jAؕGbg\x遲M*κO ANɘ?>L,Jx)!B!B!Bp))P,%Ta w{۞?eQP)$$(+!$I$ד@-13NJ^Z5zi=/#TJK5B/yרܿt˴%%ZCΆ Ty8$xi 7B8""rX&OǓGɻN!J8)]"'[U$3GsAQQSCVTƌKDL{9|vxJFFbf-/&I̼V> %DD9W8ϓxܨ*dv5NW$]A5'o1XҶp܆zdck(9'C$" d#.j$׆bl>lhVI2 v\f}/&IcfO STVchmo|X )b*=nfTCoxsh,jOC!B8B-ub3DDs6Hh'iW~2Ce״ߩxD։s ▼_ie!ODzR$BsX*lL/d>Yu0SprJf&4CH+P.R8Is]P' ഼=`IKB!o͇H\d.T2 _J:a8I᰼zJa"'&AP-_g\t5^LƓ̪l`)8Y3˭!Gs'Zg6ކ0$7ylTed#4'ҝ~$CO6;ytY'Uq?Q}ZL#Ofy0eT0fB{TZ'רIredo6\OP 0x 667 Q2$:BnA>Kp,;!Q9Mh2N^"A w7GOf1`Z4^LOj`> 6[&ANFBz@A"1Ab@>X3y"Wt}o ZOPŢޞNbI֙96n_}!u YeT# N&ɇ ;徿A(6Dڦ ` /u$χJ(}8~kgaܷqL' PR2AUmk(&oo QutZd7<$[(ki3Mu\ BW~"HY 5*d^7!J#$xJ!5rzMgQRR5?h[.*fbTh!6Y83C赴iv7eLMZ=Q'_kI:ssAyhmaIϊ W{ȒҴ; {gaItd;{bCZүRKIiiS1]Ҙ^KOG[ބhi'Oćh!7'm4f,Z9ӥ5/y[j˭yڏ2mT|M8J,'C>CUf2Z䉨viiZ e %a3]i%"& {Ž_67l*/֒2уwb=ʰ?H˴N'r-N{g!aˉБg`ĆZY!-makjX5P켔{qy__-?8z66cpIpYglvB29JQi~>4Oe|8؈^ gH%S )\L/Z@RBJ'#-J\ J.Z$B2g ! .UıJBmA8_.g?xx_J̲&qSpN 瓝}&:tUg6:;<0툩J"e>ށjN$zH]ϸ~NT-fu|..կVۥ ܔΰ!fUaOŽͦ{۵oɌ 숈[Zժ=;R607a8#q~h-{wpY?n I=7zRe@NɑE.|z 4ɬ}5׫#Rzksn| %T;\Ӷ,RB`2^/Qݗq ٱTj,q)Q~*߯RZjq1k;z,*|MN(|Xs݌:U*|,_G:xT ]_Nv}Bq?b GMW8psȱq˲_OWǺwmgюPӅ([|'3u^:|&6@fSCluZkcZzeTW65)ėdf 1ѣ)o~~ R1-BEKw\k-3 =&H%}kD-f +& JAƢR(zQJ(DGFYesۡzN2=0\1PApTNZ(f-Z24CsT'833;T=x2K8VNK|C{JYHeaTHٙ.D$4]7WNIkl{CnṊe%/7NZ \N{.ZQsN  ^DDmHeY[^Xj(96lf2 (5FS!R#!MyGtf|Uޡㆩj~x;Y m{_H Jag1G/6$"򽨾gxwX>o䛷9Ldtكw*R׫GDb`S'30ȘNuY(w&w`;8\̆#5T}mOHl&(.P(9n^׾f-9~N}0Ajtk,\I\)Ѷ{ddn;NߙN?۽b᳇\Uvʬ˻RiXg.JTv>|936-;aa,_^]*5s.cOxqPLXg2 *%DD6ZzPYO8Jxn!8V\^vDȼf>;ʬ nj+h#lm%yQ1!4e4r\t:-z=k2e6˾eK\ЙB)➡bk"#]sN^ωA8&ISd~j [D;b~״MƓؑVTjOh=$ ŔunFOv13+9wcG7J9)]j0eOik=C{2ݔS:v/?X~v S"f`|,K+RUScկ^|;jsf,iF3 =Lf1m͕{7N {iCn͌V.i)PXw"x$ʚ3jnWs7(\<'CTNEήb}yl``eFKe!+, 1OBNЂ3[>+4ɑ stzA39q*uy_պoK)+wQ~&ߢVDB͐*_̭36SN68 }JַHrwМjm]١sG/z߆6O16oqr:Wzisbj^VeK&Ĝ‚+ )&C|'3uM۫ԯ%2O}w?&ԽݒI.-]e'>ykri-7NvTQ'vBE%Ls.|nھwP"Z'c1opҸ)| Q dCvEb=؈KpÏb|8o(pY/no;it_Y},b^wC\(XR}`WWLf4ùgnե"-l tPD4+ks}eg`q!dj>9f&%}J:=im&8+#՞?3egMp5;`2o$ `20B9O?8;ؓT}FP mB'|ϟa9>/΢^aG#L`Bs'?ϧ2` Zny_S҈.fB$B275lU^X+I}d{..Z6k]t#=S BZigr2Z.Qsŵ4xm0 ڤc7ڳf+O\mF^_J̝-)_vk MoZ^ogug86q矎Nu}.QE{bCeW{Q[1YVėday>;Y֡iqV%tv.΋1!UDue7l2ƅ#uɜ4Vwq֎¡ez:3X$wl3oǃwWM" E˲(y;ӟg>yq NDiL1"Ph97.= LסXҙ۝ e<%Dg+%k=Zd%,0I$LZ"s-͕k4?g#;Ds+]Idvy2 ӏ0?y)ƌY?W#{Q}4h !OrGUz]m|6̟.Q,E5fy׬ż:ubc.PδTVÜ!v|n{s\iiu!TxJD?T-M/ko[Em2whH mUګqi'OMUcf&3u쓗g)S!yHQ""MyG̗N݇|'wM:wHtTAn̓SŁ劅f6Yꋧ]թo2 F dFőPz <JW/w g6MeTqC3.ߩxŝgef^ʒ6 QFy֓}+8c2Ns^B851i\^o(ÙzFzCJ sּ^)T3q6ބ[<12΄2:b 7[[:kI+mL5g23i\H{r|sb}6 >YG&'}xj?}_JtL2[}y\'';.:q价U"sSq\?{[^*?< {_UBƌ֒i=m*hD:=콃AӱqY-U DMOZ޵D.FZ+zQC7LUkJ{*n0q[:+IaY/,|0OӠzEFwq~]6৮x2K&B.dF4^w1&3 @$&E7󔶼3&՟W> 7l\Pr4䥙 DS7%&䈵1!5H,%w瓲Λke^;O iK8ε>`%rsS.R8))y>)N\"wKe(Vۘ.[vԱo~iʫ6=Y:W/P?4~[:rneo8 ӕ }GXNʼn ͝cy96W* Uw6hB=vsSٶx1wZjG܍Y!^̕17_z>J;u:3$4@_ IDAThmdwFж;fd]V:/;sdGkE#wnq~=2j2ƅ#ʼnMN.FdN U!Mf=m[dn޲G?|7@T;D|8Noƻ'icfj|{+#!ikZ*-msłӍd'ٙGS]oS$)l}Kƅzc`u~14'*7I:sMڟJ}nt5*V1d"+W&uYwG/kT~kRů+SCӇdgj`z\LTou?Rs8F{'Dw^=I =]{dq{RuaD^?25RW׍#d^>2bq0H띛j|ߙfw8v6GTBvG |k2Y2*`G}5p$X&.Fdus6y/&c'smC> 8|r-^{:033Me޵tYC>OG<)O=sG̟b3bf&W,sPcӷ@j|qBKk%NBI(Cı1c-ygiLb+bKƓ:*P퇧2kX9>j1Y?5rFG>;NwP:%t鰸j+E*[}rIOG&K퇧KVn;kC"繯~h>^9rT&^xl.Funƒ;IT{-QT5BI)J>S)^X+Ve|b*է ݿ5=(l~vVvČ֡cŎُ^YLw]C;R19&^}qDF^uHdް0 ;2]dޑ`Fwq^Lf@4cMᤠ6ʻnp6>g^7 VOLfN$"xyU|e͙He5ϼRsMʯl>ω`Di놘Fdex>[!<lcRYJ( -DB S(bӸu|YLC{^5p_Hw[LR~i_~r!k),=DZ彽J:NCuǃ9k;u]nT~ƩSQ^u胟9Xk}jE=R.3㝆jIEmnѳԦ߿qg:IwI~Rըh}x@tBTdn2d<6+^?G`|f!̴#;U?vi]paGI.-7=Ž[LL avgi2BqnPJ^ 9ߙBk2!yimлٙ<6"B*Ÿg>yAPܨz?9V/_~<;h/y?Eeߟ/@gamdgUko9c?|">M(!B!B!B!o\lxJIQ@xEoqp|w`KS5Lڏ1"I"X9K$I$露xJTpZd [31ڔ3ݧL5غ@BJ7F; %v (xI2Ԅq8""R[!_[H1N!-( )%YL|&o>H'KK!rQbAuQ&ʘ`(/(dLg{6Ț0K~6!M=fdFNID(Aѱ2K jM7^)}k#"9]UBIbé6fHRb8㝍"IDqRaÔ Exs{{f9mO̦&pqi?&EL<3e*+dZlfSuɊ.7l3 s𕡻ohJc~B!JZ "ZrO]FSEGTʐbJ@$IMv}v"̦L헧li#ld(8lN$;t?CBDJU:Q7}DDIiQ+YH_"5),x:3ƭ/"N5 `éTs8pJbc;!DT7%():l-pjI㑥7߾zXOR(}UAxK _9ZqIb< Fuk4:޴.ѬCjmn VMb1F{GT=V,C Z_X"oa=N3cYJ9HD)' ~k "1q}>.ׅK랗Spj>χS^cgĸ-d|>Za͝y1.yڃoDV  ;`Ów %j)m{0)4"b:B;5g6nFXEd[mWsékGsB;V)I!5E+{Y/\ DE/uݤxv3z0FГdBabϷ-ӦU`LN蒤omΈI{gnitd{.|CR.S3ܧn>]̅'G;BRq X4pʛՂ&)d=9-z9%h>cќ`!ټshs;KHՂm.t6'kkb#(;՞XWUWL o!ZQ$flz0Y)w}89R|21aSVstϙްQ$) y S#m`x `ރ:u7 nTR/y2aNh*)S\ĂNEB*P( gT8GdϷXtjHB1+vfni* 'MfeNS]#Z" D CG gpqihb<ʮ_ᩣSGa885a>bצKdK/X2H#K\L]>|+7gJ U^\5_hffGhFދ寯!T3ba-pzNwRbLg/EuDTB#*e2 粚kyR|yHvvİ'NIRcNvDD DE#`c #RMٛd\R(yH`uGU2 %TBy}.iOI (љ́4$)To\d\R$7w)rs[K)ajfح>ўg-pϖ0Y)1o>m9eg~ɛ`ީPȏot"NgjࢺY*p.0Ç)DIB!B!B!B @>x^Қ B8c~rwߗq/.\H[w{pQp/~ FQtaP#Ʉ#f^O>F>DTĂrݍ$Rk hGdi?uXOzTFz3~̻=$TH?0wڏa= +5z`t`Jw_><:ĭg E޺q<kfq 櫣nDWW~MT)փ5C{Jz%gšYnJJ;T93-9jJt"5D[ﴯ"꟎:>b:2kG]UoKL7)#f0ϛtYkg1 zܪ.Jvy^u Em_hnȇ8Qlm<3OUQiO!vV6F L7BR&&a^L%Xb]vI QRWxWL 8ܕе#ԅkzZ{|5qs􃉗ϋT)wrDt:pXڕbB1uyR:2kGN%ԗ|p u 1{QlG~D]@-#Wu,dvئ8%o{Y~V-Ykz.e#uy t[ }i__*&[bfvB}'At- R÷2&;gP,M|8 ºz~LWM{+) "1.eySVШjDDݦ _ܔNB+cښ'"FM6IK^jhݝnnh/%uP̼gYm~a.Q|ntP(-H1oew=AuT_sPen`&Q*yzg'ް:N>? zk>^<\#9-Gܼ񣯾MGWWjyʍR!^OPo7V.|svaF:;'{Nzhw7xKaKJ Hdg;n(8r;#WrQzpzտuuNu죥vخngc3 4hƖ:yfhC0y3]4I?J!]s]ݮp>†Tq'{Sy_Bz0uDDۛwQI(؎:hY?*ߕǎO> o?DvκhSY[pAYZ05}g>jnxЕl\?EOfPeJ'\~6L=sGL13#:(8XfdhdQZOWzZκ)+cFFW@1EBE;*[oB؟8/ϺvxQMtp;m IDATl*Z jc[JX=G;䤶4t&dNT΋ص-4uTq~n,ܪ{\9ؖwmU;7^8m5CXڑEZ~sm:}>{☩8;P׎=kGͩ|ɏ=~u_0" |f]d:F>t{ieyxJSyxlj7?bP~IV3`3g?=S^/!psN}1^drG f|'+"bI R^^v v!~vV<+ŸqCoKt j# j(zi۽;7JϙWޝA]ө]Vb̑zݤ%o.^G`(A ͪwn1vL:3ߘ%C[F:bBͺn[~! A} taYN.6uˌnc7ɦ=ԐEKXvmu%b/̻09p<t@Nd=P^o4G.N=F:=Z|W@aCCT4Y)o֧5}WT!!Bu׎PϦv#-^ӄɢobDmseB?aIRH??hts ̹o!33NpfLO'2e)/9KLohMY:Y52ό>rLR"RVQ&k=/d׍/nʉF5);LjJלUB|̧_:_~g=[S|>]uR7ȿt4+dWHQYGDBΘN֝%X?yד򽫎 0gݞ^U wz)w縮~PC[i&v/&?fiS-}>{Lt]*GTH;v=%2fT!/'84C [܏Wf.QG)w4&樾vxv yf2\vM)L՟m896#ro-L+LrdW~ܘ.WnӛsW-n,~*3R09(ƬJmn.ebB,$WDzg{F2^B+y>pr=5'YVENYi ĺ`lZ)oV50.&ćזc2$zen;.R:07y;ߙ+>N /di0ŖyF˟LW ГvYN/*WMF4k0Mom\&Fʀv6HnN7q'6rg,#߼Ed2bqշjJ/r;=pd187I$)I!P}Z*fuLF,lǒcNrH9|#j.Jl9)c|Qk:b7痜\HR qn}EΛRZPn7>);cX׭|tnx4Gd^.7[͊HrU/C$N^R+-PnCqira:B,߹wՉxOR5=}}ažp0l4Զ)+ 3zλ:.9=j2ԂvuO9][vs7DׇIr@,Uk d}JUA_iqoYjqCM=%Gt <6?o_)6k2Mev8ql2) xije{ka6cF,F.FW{NeQ&._;R:NI^$K@tVe9noqERa1֐C̑qg\޼<oeC2N2p3ao|\U-iMz?TZݼ Csdݐv-e0N"[6~߈zVsۺ(dyUSc'hD&_;U4uiC ǻT]QG©/ *U~"KG)OqQQ˛A!1!嚤9[]21`!ǐPT4#kkۙ%5>5>kΦLyMP"K^/Am)dW>=qTzj0s@=:Sq}׶tNOvhINZUyjٸr䵧3ڥ|I:ZOAt5P j7WDBE;*Uֲ_|f"Vl.a0l MSxyehIu63bm*o h9cښ'4kw*BG}Uk2{eo[#*tdf*ҹ=:Vϔ9FȥEZAی\G6A49-^d1$e=uXt!#0\R@*n$+˲nEWH*$O B1GO6׺ڰ Lu+vUb=IE`7?nC+Y%H>R&p.I!Yf69I 5[9T"7g4L*!8+,$IS~.o(.ys/Eu#t:hp\f s!edÜFqGu_RIG9ˁ9 s2Hq_ϿyFխi}f*;3RoTǿzw@GP\<񶋦i2\v|>osbu__Ka&IuMF.92OkHt{acfTOz>_$'c1/8 'vt#},}N"fv>P=>ŸO'ƋBt5P3to.ҧ|j-u-y::_f@37q&N_D:G1v"kQ_P`_;nwqTuQ½u'P[%zڵ2(+OƪV?Mz&##:F1.Iض 3Ç)DIB!B!B!B Dq wPp~K$wS[Ad(~II)%$"TxJTpZd [31ڔ^$,Zl] !FkpL\ #"*e( qDD$5*.Q!CbBZP[ߩ=.RKđD"8M|V'OB$ł$Rˇ)L1"Q^nM!'QȘlO9Mal2B]{Ɍ("()PZKceЗeU@NWg7^)}kێhP-$m .o-6jn=mlCm)U*ƛ3)$H(&>Lp_TH7׊q[uo6,-i4ns;.=<;>E"RakydxS1aěh8ֻQN\0z C_B!|(o?EB?b&sRV_՟Rr%s0pX[q=dɇI Kי]gYtg3̈DӒa.܍gns€*C{Hp%sR^&$=4~$ƛ_Қ"Pn7"& 1*(6vBZ&sj75T0fDT⚻N~ldfw *3$3|oIml@ZQ*R$l:N^I;p,3;!Q)Co2A$7DȧK'3s2f_i?lMNP`5r:I dD$ E$ )IRBV"spܺ,$/zod`E[_f+EG.k` yR)Id Ƈ Pݔ<hÎ#"vﴥ>1Yڿ;|$Ra\q!NIP Wz0UKa0 7]щVt~fd7RhPHj#5_}IHu>wKjb?TDTT0mDGc):,%>̅ऍlCx4*țAAr4񈯘l4ST5:+C)u[Ci:EBd䟋¬g3}~qSN^Db<%8g))|\] [WH/dc$)|">}z'q[|N;b\fuxk㉬v)'oJ>0Rd`RhN!NE|$aQ3tg3GThXa"R6R+R9Tĵ{QcC`9ɌR+ 攤Ҏ"yҕ,|"κnRk::uFEǡˇSBTGlqbKfit&3!~ˇos}Y5Ly~+>+֗,mb{15R5;!lP/inZJU/K!gQ&P("J¹&`bT*aA='eN<1lTh.szQ#o2(ebIx+??XCHĸ"uSf0JE= IDAT:XQU-^`*oh$J>υ4e46L٢)I?si݅$Wj_HF>|8v5RuQ<1>L&J B!B!B!/$Thb^[}Emu mmݹǻ[E1EaCЭp!yDެ8CCcȇSJXpS&3B\"~,(Dk6:5&;60E }wK jˇ\; B[k'AeJZT #bRA/EᮄZ.MXO}a5sc2^_d ͨ>/TX:=N䈸Qy#Vv%؅j[tO=Vꃤ{9/RMr?LW篏{3|YK?5wo |}j[xSFڬ!^,O5RRY_}mnVF~amNFH]zDtz,#TG>*u[#3a==%={xDWVbWlO[́u+VR=Ge?_WRDb\Z 򦬾QՈM1AP]e)'!%W -b5ODě="y3(l7FbW7B:(B^ ">'e%J{Ͼ'%+jU:b Mp\rѥt`H=M*UΜ]=ˉkEOY{C'Uoy3R5?_6wto݄6oi ` |GoF)̐zWߦ{+5.66n]&zMj+O Y^8#WrQzpzտOwHѰn-dܻĭͦyd~4La_T:&)^wOzAp{>V p>zm29l d{o2q1.I!*P\:nOf< S^;<nKDdM;l_rr!I%ќ'"Y'_D)%yկTm'"eGSob]Rf7OS{DNyiD/Kp*4\U@vf[y?3[`jP}śD{Jn&xf M]n^O "U QA)wiQ8[woq`a{]s[re:?]HyѴs&֐3fQVƝiQA;.:qNF3Q޺wl.sSEtj%KݍgTxUq*!@8Kkok|qW':]}ÿhfZ poya Rqirt7.Cl27>S9I#Hy3ز_-1|6ws$o~tVo,>3676«Okҥ\=b~HvQ\;sDCzkGM NhhyC~р.~OB8>1H UձT+OU|Sݮpi1lKNmY.PRÇLdZ` KNBq!#}Էr U y]C9_t$oXdxGkĸ(3q4I|ˤ33Bns32]R'#tMھ|՟"c'4[},]t5P jK[ wg 2T{yGez-4uΟ8/Ϻ6ԒΨeDG6;-9Η^MT_ʭK>2zeowf3 m ʭמqƭZ ؍\oړڢOOhӮg?Uf'Zҩ<٣^uЛRD٢O5UWSTzlyx€udxCewu yǼ3[Ldz#NfpSJA QcF5Mᐚ nj,̀0usU/ek4kŸ"Ӑmo=|2blUn5|!{}U͗ඃ^0F{)| ɧ qV>wG$n sM<<7 Do k^@&&3DV-8KEv8}IHxۉh$[nRN@&1 tG֝@mqMjw͋dq>>w}5@]z4U6J@n M#%G ` Թ9;p7֝;<_VP mBrہF/.\tkdu&tnR/7Ž"ׅ.6\w]i # ^X]iN,I yu7Z_ؼv; ͉RmKdM"_ީ]Ԯ:]~`iY i)7͎i`އ9zld)mQuAbz T4weYuAXf. tP(yL֦ɢ?kʇ*ocG 27Q_T?ѿs==%={xDWV]fxn0c7&#"ڵKT= cXcUlO?z='6=&&W닦%sZH7smnMɶZ>d)<[m~0y*e3|YK?rqPYK+̮VM!:6'tB+U 9xՕ᥈񈯨/E{E𚯨(΅c֐^bpOZ72:a8s[@ib)'u6Z35oT8hzY%t;'zr%o~t6-qTwΣwTM9/;4M4 .R^}DT*b7&#"5˽X>dIUՅeln\8O-Kc? :b=Y?`ci}h -ls?^y*/ҳ_ W+T)%s]var&1w9h<"ewttj z{Sjeʿ|3H'T}yW`|c,:Bݚ!]sT_OOhqYz-jD|xE}P(ՍY˕ zf3Wo 9:nJ/9)<椐J 33kH?|ĺ`lZ)oV50.&ćזc3Xl7ޟ~a=^f"OGPy76qN\uL\u-R.>$zgmbȲ|#EeIbGPLB;`a lt59`, h@x%UM7d\P(Y#T:  +f2݀T"#Me8`Pe0`޸~skT?y$t߿MzݻہDe*eҴYhoEMeBX2>SzMڇcE֑98GG'~4U jːqf'tѺeZ1o$|5nzdǹ?q0 :W bL$"%!l{e=r;}GTLS>,Nӊϥz(+|B%f I*!cG}SJBX@jS'"eKsL㫺ZϨ7˼y2pқf%$z9]^fm$gN,^R+ nQoY2!MZ P%7{3H'ikz6}6Iؾm {;!()9:4~g(TK &_]9yŬ=ԦIMgMs&_E6wLMq@`mʕg9x Me&xf ' %Q7J0?(XTL+'/E:?_3'vN7BA#ӌ¹Zsp5A%;/qm VE͇z9A!"oMzyBEo٣4n<^=]Q8)-օFE{|f2HRJ'XhRB^nזv񐎈g>֑^]&YhNsK6w_}hg߿8-JSkmSnyyzrlr>J}KL {R& =+Eq^Y-#+;c#Y_?1vj'ZS3b>q2iӢVrlr?v !W;ΑtNEeq_Y>J!Oe76:A~S/y'kq_L2)c^qˇ_5{]"|޶MV}r3݅q-.P *[O[SuA^>"9ZszK~9Xa`QS۫yk!{R6\[{Ȥm8BMٸ(gNӶ%o 6$E蒉 -b[|{33\S}P>lQzbM}~3==?fSޣڅ|xŗڐ W 2qgSRF8{5=CQnnnT]hxNT w=8R9moJx df߲Z-^RRD{b\,xxV :y)G욷u?bzsmZ:?.d&M$j.jtHx M_w_tR: oY¨^M \Q;1Q˄|e,` } *UƋxc}v*{yb'gf'[x5rT+N Χ^ئsnL⪣Mȿ0{tjz|$)Tlt# IDATPMJH޸dJ"+DNs#H˺-rEDLҽqM":M| 9o lEx7`q{"8^*Mnm~zP\uxWSg͏ ;K_ztBQR_o엣\7>}qDSDMtD}~ctF{wS[iӤ iZ VT]j!'f+Z>~ i/BnFp(0q;5S##LGT 1^Y"fs.8GO^v'bF4 {+_|g3G{8_qscw? +[D}h|k|,n޹o|-:0IaXCycԋ3LJ)D B!B!B!Bx4SR%Te$3I y ;U/ u^j?p$$]$Q#1U$R:=T SPS!҆HUJ Ж@q"1F+a7`tO$Q!M#""%AqMK)gjEJz8r('qu 1dh>DN"*zt.afo0OsI2泹S2BN"z3Z_LFHkμY> s%Scml Z"f{kWIYkh#p#4XCSH@L")VY=N֏֎CcgB$I$$JS2UcbL{V=͇m5+iyZf1<ˬOd4:fHȬP1]%5Zf7^ȴ!YzfTfC{x{5~4B!.4#Qg5KD4$yRz2#4K$y9J?Sy6jHR]"kv>=<E"4Vac}xS1a֧$ejLh8VmaU-y*sShn Cb\B!|(o?MB?f&sRv__kJ>a8IᰶyIU7b$37o/&#$3g6wṁ 5cڸnsپkBCsH ܛ o/"d;o7(F$$(ԁ O(A: ~?U}[L;!-39ӊ*EBT꧗9HO+;g0EEc`p`I@Z]dzH8t|vݗXf.w(B>B;W"I"o`3MtdSVz^~14ӑ|֊I] BN'IᙌdD!"%AJ*z~QD~>M`E_m3Ilx>3ƍo"VU`Çp$ng2c}HmJPLRwt[`०pYc{7߾v_MP(6AI 6TF}RacĈ w4:޴!ѬZ>&X&;{B5Q7]/ՋXAVAAXw5^`͝y1&y3ZDϵ6EgrY}'GD++B@i=IiU|8<@zܩ=Dy5f."%hKG"ř3,NF\[~],1')AeNIq#m)2ϓeysVp\ygl2fSOғٛ=ඨNVI1;[˒k79#&9Λ-]R0ӑݚo kɺBNQKu%mյOrIuz==Rm ϭ '-hB֋ӢS2T+E RgKq>ז3v~c3bPf]N9R9&k "Wuj,wZSk^|>V#ګ!9'V闈x~қHL')p!wP Wh0y~i/h-@͌e̾o#8}tOj;f|ۢ3V:xwlZH[9X-DGk1RstZ}c'= )u8 +Ur>u%{֓ԕ 9x\录HD7]{9qP)dٳqm D޵pvd`uORu Lǝk ćIڐM[dyoeIy~AAuDG/"iLE}eK㫪1Ҟ7 ꎩYM-D?Pٍ;{_̾ռfs3ӲGOtz]ؐx-'3=slI|@DD<6BmΚ`yE@,ڛĘA3ML3gXyc˟y"~>D?Ahc hn,km; '#d?uS0.jZ Wf:ߧf1P:,%cLOϳJYe!w W༢ɪi*;DdsAzX`u老L.6 VE\{{q?u[2S5'<̇czTqL~|[f=t~4!^ީˇžy^Gey~^[ffv|&{m1XrkhK:# 4z7%*HsRșWgD%H>B:p.uO2R݀o^аL/G g$i?ud'TˤB uz:l!```bL z({#IR%I,¦V޸ִ$Jυ4 cΰL^ I`9IHB!NBL$LRycKB w^ wlZ-CݖSy׼fOz B48t,zXݬ0\\T7KNEq[`0E|(!PB!B!B!BR!‡K^aIRg{!{w]yT*Ks3w}w?:EeCGt 0<"oFXޡ$z>)d$Bz=!%z+5Ȭ҈e=UC!W^)>n] M$L}.)>ݴrrOȿp;53ݾjZR7 լXN섔w~/)Y5γmM(+{f.#ѦYvٯJjWij6Ԩeɺ*%bȧqAhj!0> 3iY nQI!R[NF\[j=aqM8c5GQa` uRefN=د|M=zpv9BoC`n ُDCGdq}KåfG=L̴5Ⓟ ׌Ē?+ԉYfZ4v9FyDlъ{K˓ߛRye10ô*QpvFMA3_]x/_|tPm⭴Uu0'Y_3Q[l.iJGq)Յɓy?j9M`Xgo?t8;whݣ͜p2+eZ͆8N?_r=fVyrBZqI4I qą$IǑŘ$5p*TOGg7>v.KƠb,%%IJ13oOVBB O\ҝ%r&=ӅiS2qNbdyyݑxF{|.ɑ_v5GX'&8n^vx"IԷWQr1rζ|>zN/j9<|+'Z.X%|Q*M݂ Mܕ['qi|>O8 $h[8gG4ci^*ƴW/nv\]>sg揕2ߺi H}~cQjO/w^?u 3D(O'w;wQyʭtQ_+K|n#td3&e7Y5γ^ΫŧGWc]ѦYөvn!o-vf^W%zՑm' UYr3%bniww-5#D_]NoFV_^[ID7} "+aYސ'Ԗ}Ԅ[uAĘ78;Jʊ'"FMٜ6HI^j(e{6瘛kI=+-TOKx[-ՎaBS2>@Zt:\ WyEljH֧(!,^)?l֗cUmMϣ]Ojr߿MzݻہDe*eҴæ NtkM}2qqmfw#Cn2q 3^PKw^S\_X> h!Sh+߲]!Yt~n|6t߿9S9}gCpxgnI 3rmfUtv7x]5(Ynkա ;ƍwBn4P/&? W(ѫ?,td#UPf5EckgܣD ~stxtGS^Nn7r`̀bw6tc=]~_~K':|Dl;Y bL$"%!-+uS{Cr|wVdG^[EREk>[Dlii|UfBsHm,yjNb]') ^NVWAa5^rn]ndZt-*7~1Uz_<JREw.>6[v/ds7v\Q]7b[ Z%tyxKG>V~h8hzH5=>l}JU#AYEvgB[ & 5|'#dxfN<#p4~m "Vѯ}v*{-YrLЎJ |dgPtdђ &_]m٫&Y~I)MQ,gxzrAŻj-T;'օѦY㩧w{3ڗ7~+R /Md>B!A!KNԞq}fuB!ܣVǰ9wD$BՔ墊w[ 3)y/R{Fլ˙6Y{gWYHcrqK',n~K%/; z OeB/P黁ZVw#3yyzrlr>J}K}l$0d -S+v/|d"W ݢ4l,SS[ҍWm6zpyӦ7Ֆb>Ϟt/c7p:\~m⦚]wFl,0OiGf\zٛ:);co9N0sfgL7eQ\2bŅlz3Bv2;Mz|~o%2M=%bC9w\ !Fۏפ?1f!26iL W༢cD$zžܶ;ZOL׫o(:}tL~p/bT/3`Էdz.FuwqTſDuFp1]Z&t|{aVb!qK@R:R'&F wkOϿ=26<:3mBS;7 lj[gY [B:p.E!Yz19I i$q/ɔDB y|No7i9kqY*Y+ma72 oOGJ/BK û_&o/gR""*Mn&nf¢2{Dtd[hO/ ߗ_ >ͤ<0OlS*,ޕ"㇦8i&:"R'3AIѵ{0mJ6m ʹAr]Nyiz[o$.PwSy;eߴ4KMf1KļVa7/=:!(ڋΥ~gT?1nҋ5oH7}f7̲u3kꇭp:G7#`I?mgΦyzzI־P>J|X8W^Xvjko>M\"vL{?_:W-dPc>jŘԏWq] ov PGt>SsK߮y;n.t\22 7L]Rϼ&.\HR(ƚnD 7>.Bh?oeqxj.Bʇv%0w|V|j< IDAT>CӅ۞{4V:#\22]"{0u'em݂ ~y߾7wz{uGg_?A zͅ읟ڽ84z#3@0s}ԧX2Xho>V~^c|8嵏dĵ% I$kՄWJ@ç"?=2|;]Z)Q)] VjçDY";ueqJc3'^/vjaK)CTnQT^ M"B+oJ<خYvw~/<dY%g^h;:j޻p!tRw᯹wDqGvΦq1۟B=x3cj_0 0.}ZX&Vz9o3>ϧSҦcVB3䍠TH PkFPH}n|Ut^iT0ܰ묺Ղ zz: t+L{L㫆%JTJ mտQV^۩Tj(2u^ю><NjKNVk诇_*eʞ2nNwSE2yىw?z=Y׍ ُy,Obga )iq[J͌RUZLszݑeljwlCheE9=VtͲ'}8]%r/D9[TR;tB3wS:bEMc:2f*N[qP*5_篃R?z \Yp1q9۟>}5L]E8s%dR60 ;BLg_j$gekOJ+W1фBo?*B`x!Bu1 I|xŗW 1[H!8I 't un-C]0\>~G8dCb,%8g!|\ 7'+Z!1,LlZIt!wp̪Q 9^k&˜*k#tr}%g]$%ே?ĝm#I~OƉ?^s5sWr:H]o5z!/J;F=\Qvquv]n?vԷ%*sƉ]QڏV-_?'a3;rN 0;+v>zNt~e,Eqw%RDDoJcЏ#:[-tČ Pu`w}ea*x|~DF?wЏXw8ҙ'ɋ']97Zz3kRt StD|xž͇ ͺjBDD5K$lqY[Yy{b@ U\rf!/2^{|-Ė_C|8ªj޺oL&MX+!q"1&eyCVPkjBD-Ӻ 2C:9J [_ϭxx"bd4 AaĘ=cIf|Fs-io1St/L$oW"ŵaT2B|;KBFFX=L(!,O_M8~@(GQW$"rp[ ,'zX KeAG6 SqGoۧ?4)s37wnmtd*0C^sPiv`&QJՏk*|Qꚣ(ѫvH'͙K-a`ȿpsf. K@\%'z fAuR $I"RB0^e"H yq/9gy~Ʌ$G1^Y#_D)%yAN9UwsHւeomt+K83)ox/Xw-ؿ0{tjz[@`{6ad"zpys΄[_O)M8N>sIC>+L2Y~pP@%0>$?;<ۏD/J?gnf F_~"a=om M/&SheZ&p+cOuV01"騕 zU ~y={Vxh7GwqTgꆛ䳉WQ3ar䵧\J9`3`2MRSy`f4sdrVgj~ 5Gflԍ !uBB!%!sψZGᵛdD/v<^hst7=.QB#* \yPbIC5!+!y^Z)Z&FR$e]Ɩ_ 9"G"&^uJqM":M| kפVjECS,nOdgڋUŻM΄fU~!.P̾}~btF{哊wS_]cmnC]@`Z_h;"*ssTs 0q;5S-dQ=Se+.zUgO/S'}6)avY%:vmnbf2S`vu]gD?vu1\K3{G3_&o/[4gu:z~d>IUCvg.Wf\jdc{}b9;t$)po]>J7;r6OĹj0~NS7euTCve5"l!ЧpWmcRwRx;xǯjqK߮YJ} >.t0sˠtP ̵tcTAGf..31I2?s 0E|(!PB!B!B!BR!(&"q Uo1p|{`CsՋBO1$I"Uh%I$%oxfj4gU%:mFg6L<)NpU )ҵt+%PHJ (|f&GDTHSi$∈HIj\k )(%aZt^"Jiz\]Bb< $E| Ǭerl.&񔌐ߩŴ Ҥ3oOfB$DD X-(cѼxZQB dˍ+d5N~8ȑeW)$m & 'GOkP!yJVzt3k!EhnLd0%M~Q5!1V?^+ƴnճ|[6e_LFHcfO UYclvl5EFZD^w[޻^}fu_> !B HTrr;ɧnrԭ^-LD^ԅ$D^ ,bDWj=O.GwUXr;dl:TGLiF8IZ%3%NUjPOe 4r>LiZ1q B!𭷬U06 Mv̍JFHQ}Um2+$ÍHdɇI [7]Yug36̄DӚin] V,>УEfۋH>'ee"NM3 -x&)2 u6{x,)oNiOUNH{N⪾ke|nI QB0>voB/3$ PHj:%#C–ǡ䕴뾬/2sCҤ&$Iym{_iDȧ'{7G_i?lVLNPbr:I d$$ӽ4E$ ) RBь>"H1s]o f!|ы޶?Ė, 3oܸ 6[/B>j1ZPa 0|8l}'NJRLv]&1ևD@?$zM_3^jJ'{]5jB0q^NJ 53[$Fd07]щv fd"_42D$5ى;ҭ1Ĥd:q0ܯ+BZBE jf^sDŽv("<kA@޺qQLIQ!8i;0I FPM%b,'j몌|+uڭF_F]^v6ft;rE a3BS}yo/rˇ'cI/9 tr]تļy9%ڜ 'Iz|>u:$$o.=9նi̋1ɛ"~=)z<| {{I  6ÚVuȇ_>˳_` ǝ3MkXӮa:#R26ɽ|+R9dĵ{PsB?^^攄:Җ"-<^ >,|kikU 7'y&̮o6$={ 괩a ӹ;`h!,vbߙ㼹/s%3٭ Ѽ+ĺL˜zz:897[_O=<Nz3ZסE/d T'R7[|-mg+%Ɗgru9)+\|K6ڋfJa-*hs_SziM{iE 'L]4klL]YSd"yJo#uw0uĞЏJÅA׃\6y497MF0-=U ϼB[t"m:ޱ;k!m7wb˜ ٯy֎hVKFGj˟ X0DԖ$D^R6d T5T{V֓ԕZr6'{+4o21/Ṣ;eJĵ%{li9W=IIrv@?a6z3uwz9(lNF$jCF7yZo͊录'Yyڻuw #G4A1w-͔@K#0Ъ;rP4@-ol)e7nq~1Vf#Ϭ6>b\K~>]nCuaCV3ϙ^3G$)YH$"js|X+ 4_u0GvT%ƤNigd"9[$ QzGUGDucYSn۹^nP8 %Ayt!wVo 4܁>6هf엌LOϳ2Y;~+p^d4em+2\!FP78`=ӨMC/cWfu|wOFST >9$Xħ6U\YOzG+ zWe'f޸.8/QyYޫsŇW|֣?ǡ7e;y'R1toe;Mkɾ4FK!g^P(" ¹U=HuzAJw|31?osz?P- ( Kߗ~ـ51)D`"&II'uFoShkk ]y^ZӆH(>4Tm:3y)S*'#$~tfk 8I U;W0ƲS-E 5\{Zv8`4򙾌0ܱ;k!̶dVKLj ieN:_f#=q6T)d$Bz=!=ވϩ$cRkhFd~o=(G )JR`m n{𧚐a,gaM"V y] V@nNHypJv?/#iΨa'-?j=1ZşrZ0}tHꈊЃ}"eqJc QR*IٛSol9=LGgͧY1MGf-Tefc=t#fgG?cy/lO|}z:ڃ8ͨ5+iB?PC {`La-,;B.6Nl`^ Z#^,*z`({ Aa}o>n%tm Un:}Jiszg=Vd:+z_|6G-fFwSa*WRKsm&9uF^>Sb4ƟgjV IDAT*dH_ԇ򠦷"=N6ѹx7><*Ztÿprmʇ!n8%5}xDmt6Rm\7'Ż"}[͂d&TV^x_ǵo#~){b^:=7Hm jux|stdyeg~c=t#f7~v:bL!**CTఔ2HЏ ǩî=pZܡ`OƯ [fHkc^_j$ge3a<Sg)8]8I ՖLunya):sěKOZl1dCb,%8g!|\ 7'+Z!Y{0-jHX*kŗO=eGrJf{!kNrzES;dyoeIxF -,@~1lܞ,>-Yv_s_ 7O(z} _E}9NDߑ]aM;D'_m9l4p"!/w ,'ɋ'qeώ]$%ே?M?qy]BopWnM_pihE+辩Nr:I˓E}GR3KskWWg\WK{o^oJ7FWn ӛ- KG%jϣEb2olmn [F?+yP_?|?mb:lO|N=vz% W+6MCL=|xy:}/nCE%b i\L9*pқU-8uAnLZ%>WBDbLZ >.Մ[uAP]e!!%W ﭯVV<<12o䍠AbcIf Gs-gꂀ's{)ijGHB+RxF ygg^)?l=щMUQ'ѫG74B{w;0wL,]vZ5k Ek3cnJsˇw=5Dw{&? W(ѫ? ֪/#TR`]ה- -hF7zѨ2I]&n1ln܌޹A9*~ٛsK ՎpFG- _(ecM`82`&(]u\u~{zf^÷ۼf kt1&Ipe#bd`%3}+!uf+B`~6\HR q4H:oJI֖:Y ѽ @Dʖ㫺J&nny<5'd&Za&$z9]^ 9 'ܺȶ+7ys -*/JOkC=_J8o";/Lѫܵ9*n{Kz΃UBiAЅX;6L2}v*{yb>I7E?!MZ P#wOh}$$ecSR¶=kܦa%dfh矽ɪ*;co9޹!GJ}^vpc7?~+G_L*}7PH's-w=8Ra蛻3Gڳ4X㽿'&GԇtATޮHF,|*!x^>jL5Rqx~v=y". ЙC^8׏C~ƨwUW}z:ڃ?^|u=MfwD 3CvB.l?yiAa=]0hsQ11⭅̵rM26iL W,[ )\9VOLׁ]W/4ZejƽReSS«їx7|] T +S߾9E:)QC7Q|>}q41\rEL?WƲ_+ܕ['=?V;T *vqߟ(o=wՄVge2ZS'7xNTE߶-4a{Miq2 7!J Jug!3dݳUq訶Oh͓6td^[,GGJ[-7vD-1 89e&M$'\gaYSM=v1/0rkpRbopr1So%b N\TMB;\Jr!~Ft˸.-y+xR G 3\E&Q֔Ƌd%C,A!ܱj)._hy/;3v=mԢm6}`bn Ƞ ;FzP@pf9wQ?Ό` 8" Y%-p҃΂{y'J};qG8}(-ٲ00T[_~U5vUCf l}IoP42|B1!1^}h~Sm^ϳՁ͠ǁõ8QT.{l0a|e ox~;pC`5Ex0)emfXwF;7~ {Q/nz_jv4o<ɣ&'o? Cu-pO/o~.uwUN=jkq_T1vݫ[}hke}P`ƭzV=LnE2)օg:c:yJRD>8ÜCfO׺Tqy!X|2:QMo̟Y'BzW^>u}Y7MdhmyabvYZF@'u~rs_/)+/yg壣ML-_4| V]eyiH}pr7c“uf12ɣ*jG\[{ÖG6ꗖMg3jkߴ_ar} xm{Õ~rY\PGyoӇwVt?[U`Qhtc;4z dEY ^o(bdїSUf%߿۫'n6:kjɈl~m17_J|kv.TK>/,cTj()uL+H%?Z7MkȔyN^k;I7ve>zw[ wGPP Qr~)C8%l-)#wu{T/,<@^*+|90A`^`Zlvw-?f乶'摰-7{+מּjJkff[lY.!%65\qoH\xq+#v޵v}bTJ+ZcJRr-殇8|jxW.YD\.ӇáE7O7Ȣs[ՐWz~߯0#0d&"Q:f, wG#oOXnzěMOzbIlذɖR,Os>PƓ:O"i6p]*VZ-=bE ֒1l{; HJvT*trQo#峻Q~iz%.8,M;9\?r˕/2ץ/wuMsvuGo]| ;bԎ.Ff'_;+cW;'y~2zg/'.M`z͵/︫G?tu&/f58Ɓq`7p;}˝|Ł/ 3ï\˧~4FZ1!J/W[D/^)#~v$7]s>";B=2k@(76&kP\Zj_^i甧@,{k[n6pNJ}Tef=9=zf>1 hA k7&Hһ/U1)Y^ˍϙ#hP+ځ8|7kCemhC@Ÿ핕[`r| e5_3ckbIbJI osG̦Cf@YO/$+5yPV2w-Ү{-5za~p!x52 ퟥ%Ѕ2{:ikdoc۴ȝ63 LAIK,0vɉKtK3{w]kQƓ \J(fԘ0]yՖZ~Z}mM?-^5kxugޜV[2͢1radgva魮rE\)Fѕ zh#R0&\0 !k=C|;<^/+W~ fZ>y?m }fӾ J>>47+!ePP}/We6[gBXքhxe|Mʈz/C+{ݳԍJ/fdoms>iIV.H si[k{򄃲sIiH^Jk4ڤ)ʽKg{Po42j𿎘0Q[^UWk.e/V4HTH }[|WjsXю~ Qu2 ]}Mw|+ TjMã$[K[AsӅ/ӗ3JSF/ǩ.6\>ΌS5yI믨_FKco,n`/M7}YBcp;\ñ:o}XI*ڭ#xgw-?-偝_~Zxo;1atd&<wn`/@/ߠc_. ːܿ{7`yfƗVwn<4dcoخro= 'N^@[½ԃ͉̼'Ty2p/h]/Z?O+nw3,1z 57?mc'SɘW4yduNE2!깹|3VD1U=skTAGfӏ/svd\j 1t2֟g]>y9=We9ܢ/|H~drP3gt/nsQݩk/T2!sRLIXb$ɓ7byd~q-/ OzPrOP7+iO-J_> ^s1@G#╋UU{wvWgKgu_TW=)FK+۳]ZxD^͙ǣ{?\kIMrtbͧCW uTb1GrL_beDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDǐbQ_%(G d @2 d A $""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""o1YH"r<IB!bѾ 9 y׋'""fo1 X zJG,b# ""`I@Dtb>ȧZd5x%$iK)peS#OH0X AѝAԇ V() ay6G"Q8PfM4ngKbb#/lN `5TnfJ% BDDDDDob2XH¶ڶdun-䘌dbHz )V_E,*!Fl-0iòahZ-_v}ݵTI7mK13 f IDATR{Qw' ky٢z"""2ϬM&h~@2N'fpN>mP MVTbPo궄86VڀY6]ݨ-Ǘ'4|ty4mD=ꌨ%*J*mN{+Nd[GUAo;?T%+,@vNDDD]L ꦑO>KvlAciҘny:4D$rh5E4k7Y6LwvA2JE$"HE9Ck~Gd DDDtd|щs r Tk)'>ư-~E4UW2 ݶG"/fݭP:l~q$jkmAt^R!""N`DD''\]y[[嵴djrru_m^e1Gi oeT§;Ohw RxLw 2ځDf<|N(4ֻDʟu=$""""""""""!&3iEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDb$lK,ǤniBAN>+"AI'UE=}EutNTHKEg*Ո/%q[[1b~Δg"$⭛bl3$WFWuX[*T_k;Phb9ybKH 2ߓMz yRm #26$Ր߿{V/pn>?"r9}I7R}JEgWGhԄJz*̾ d6@Y JK/Մ'^[YRӔ?l!+bZO1 WU%rXwlKzAp'TuVC[n-5Ep}1;~RLfS>Ck~,VGj-5|3"'mEHgf=?)o^ b$/MgolSS@4m M%n5vig^ q&]$ `In[R޴Ig?j) R6T(B̊9eSicIEQ2[6ۻ_Ud[huEHgƚ`lj6m[5O}EC ѝ7Rܪj6ݣR#)Xu0N pUriWu`%=s'To6OE@$[M+o8JS.snT͊-nԙ}>X[gok@F:ň|:nQSެƗR.$yb7tZ4i(,tEZ\8z%fI6My&e23ݭ7tDqa7 h*@䬺WMnUỉZhefتN'MÏWԕf㛫isѲ{$yd?MNFVԜ ݏ;]c#nPkwƪb >bnjBZJ&|t(b4*Z|rgp>(ŨsDtt7wR :z"[!)2\IFe|5gl/."Eg}Mݒmŵevķr$g$Kyӿl[XM!f^;~Uls%F}ci*'׫lZutqm(KߵJ He*uɧ3X*6rؑ:(j8}@>VėVhu9ED .f#Q Aí~f':$^1LH_n. "j(0E٫DLnfȱ٬ 08}Ԥ+ӕ4V 5\•tm٤Ƿrrا&LJyʛ6,'qB!AJdub U7u͍765BkWi^Ы4M;bZRtݪh̛j{gOtB$ueCd_Z#HGDDDt4D JG}E""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""5AW Jg @2 d @I&#bO!Ĕn5OokBO 3LW)v^sfo Ll|h\PMv[ٷؽHV[j̘Nw3-MN1TtK@c+*R(O1'~J%QV]3`+MsV\j?zBjg6y-̛Z,{Q6-棟f?m`X6v [^߲{AaډS~7d@Ɲ sPVC~?9#aF}WgpG 5pQ7{_J|kve>zw[ )0PJ(_N-5Rv]k=A@[Z]gOT]G8惝oJk}RJRr35J RfwnSе݅yOjjhso-wLjGf-Pq*;IO n}W^%di93{Pj!Rfw[)o<;SKy Z>W*K}9EQ6VR~soj᣹Uz }zcʛfg1 ]5pXGN\~{<>t;ơniZzQ6 OiL|}v ޛs ËE_NU E_Ip4q'1e9,@˲,˺RLH-zݢw ˬۮ7O@gRSm̊ǷTf׀۲/o݆˗'/fYS8G1\?}W:^dLyV_&&s˕G3/~H7 v0>ɏgl^Mǘx::f)-?-\X1ݥU/>?i_Mj WJ/nRyv陸$/y/EQ|W e).ק_?goj)r~AarJ ~=ow r/[UyiTO2ftc={.j'a7[%P;YK[ƸB;5_MWw_ cR|)18 ݭn5n}OIFj&Nڱv\Fi3d^24Im)jtZ9; n6JHi[j; :0fp:PB1cJ8ragt[hn]{o 1"`hpW Y >\ͻ^ )Y޲ۘ9w6z'3NI>}8q3lo]|u[n+\;Hyl÷Aҹo˽?18,\ 4Ѕh@9Mr֮{ʇ_w x wo~^_#G v~oe"RZO;vh/dYԄ?׍qH^f⬣:u,L1_T>kl.yu2VV7Tsn䧼\>HR]V3*SfihItfՇ{0kf>|51r8j(~˓?O 6pÅP|m ~ / ]B7=Crtkmz2s>aqJUYo]kw P=w}ܻH~ )inݽJ})Fv g&j3cFPM|mnlhy=CjDh_y5{i̷PzR}EhsI*%mu3*!n~Ҳi EEVg'9f>K٘Y審T~Xl 1vǔ[ٍm%TsCn?GO2NG$wi>miLߥ> .W`?ko=rbQILL`R(WޛiϳӇx斣Ù2KFpu cmy].T9mO /K(~EpރCd.xn_hX?bt( ?=HG_Ty8o%_FKiOchrB[),370qw͙Q[/ HÈTU"1qT$PVCtްGf鞳=idrY%d^g1n6/x%cRzq:tfy!X],?-ఈҋ ]a#wÛ PrGg/'.<䞤ir0XngkӇ8̠c7wʼnOv79Odwk/iyJ O|aѓ"L!FK[찟~*)4^\¿מ4nfO@VQ<槺 +mm ʞQ>iYcg6Z~gGšmf~|bwC:iIb{ ֻ7gELNwFkO/骝UcL_ ]n#g~J)o |eȐJ K]M6`vS-ڛ*m?M?d?ppyeF-6kT6 O9eƞjh΢i'uo{ ǝO :&l$xd-/ O\L~H'a[ۃ2U拎0՗m?TGvcgluY*'ӽ_"5V?aZ|?6|!l7J-lዩu־Jy ll;)ouGH^%R[BfO}#K{ߢ=vbSl{QM'|1ri=ٵ_m'#爫a _W҄fՐO=hHv>?uaYEgW~߿ '#"v)t|)wYKa-yOjjhsoܭK(STj2`nMݭpwདྷH<殇8|\}p`kg'}{\9 v麧80'FBgoPPR^19eKϳj=`>O[[~?QԡCњ Vqw@ )u`㵟cRCDˬniO^y2#0~M(Ţ=mQ$YtLXԹx_s6!7ŗ5 ̀ q%g i!,˲,VK1Yn #jzwfð-lXfvյԭB)az?Y7yKn|?maq'1Sˇ3:7Mݭ/'cavK ~Aa/pbtVNGxyW6 ]]:Пi`mX痆~k^U}(NJtEs=5r*v;>m;8]CKQˎ?y>9/Ld^0ex_Mj WJ/iߪ};ji{Q'|]?+hB+qYl豊D(ϓjܜDxP(!~f*[Hqb$*_C,nbwqp7-H2V3w֎w$n-5b@BL;q"[e/ ?RiLW^ )ݿ01]cvvo}A;]:OmFaockPzF[ֺ5V 7rgyu aP{0~/koUf1''(=ǫ3(as+iJ i,yWIbR(w'Q*?Zݸ*<^ 笤|󴵥k̇&YM5 \;BeXkV;@AW{hz)/VVYIZµ^l>ʚjq@jt[EϋQ[8Uf{'>_Zq'![ *Wuhݔ@AځP"&k?Xn69(ӈ^o=0P1\ɕՍv@S:T؇'9`Ȳ:9!(K=ZֿrPM7M--; /9y4<{R)R`#RG]Ql~%<B7c㿚s-7~ԤyRO݂:Y?3snjaj)7Ҙm0ou6&`3_hɯ}S*yk>4^ݽu+0eޭghn;:v?veV>Yz?r5OևUY{z_nY۴a'ŧ#jU $[aYSt~I#?z}b8([{&K7y%fO\g-/Ly֭7|=8>?m}~Ww͠ǁ5MG.L e()ϔgʳg;2H19,iO i'FU~@2 d @2@"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""!ߌ$mo-")7n̳:$drf;W!'!8c'DDDg[L"":VCyFߏDQ_f.wiV+1@M`)^ ɦkR!\߬.!8H*}ubpoa6 OT2]։*ܬWi?鈈NFL[[IַݕbM~TY@ iU$kbR""ĈeV1mX lME6XC Ԯ*m)Fqo>OTj5>dvAzvh`T晵yM8@2ہVIliuj"Iʖ rQL ^MݖP*P0K&YR}QN4hG紻AŒRI i`y/ yx%byVdqZm'L)O:=oɪ@2g ""8DnjKdg˦Tm9Ϡ6OrFDSfmT&ˆ)Yռ{/HZdR H3|; g{IGDD40" @FmٍEI1m7RO |a[4Zh* ?em6`y6n唼G ':롰bf{퓎h`DD,\]O[[djrru_m^e1Gi oS§;Ohb RxLw 2ځDf<|N(4;̎c *WlBi%!&9IъΧىI&~b$)1Gob'p~^yODD"@EӣN):ꆷX${R,:}U9Ǖ9@ms4|c &iE2QRLMv-U-U]W*'TzXcNSҭ¢9b7cf͓j*X~SVC~RGoZsRW ȩ'2bʟ%R,:8B;&]WSavkxp ՐOZ}rZ- EuM!:M=jۙq~N(!eNmy5\vV.JXwBKzAp'TuVC+WP"rIF}f )&{)ϡ y~ivnMmEHgf=?a^ b$l{Ivv4) ^& /n5^g^ q˄IFAG+fazE`E8) R=6T(B̊9eSicI5"EQ2[ܻ_UdiuHgƚ`lQk6m[5ORC ѝ7Rܪj=R#)Xu0lN ?U i^TNJz*\[Olve%rIz*&n}__ V(B;C7wtϹQ6+f~Hco9i%#^sL]Z_W6K{i4҅/jXhqH@`yPm H&xf23ݭ7PDqa h*@qUỉZhefتأN'MÏ)Օf㛫isѲG}$yd?MN-VԜ ݏ;uݰFo/jfPBXUY!n|V]ʞ]Mh%^VwXE^FY{BSn޳gwŽunH8Nʲ6@]Nyv4;X;{#ɨ,PEQ,Q:V񞶝`E7_TBA"QPƗktۮfLߵNiS 7*=7Vm~4O,+ U*5u'wΘo䀘]Soˋfֽ&9߅_k|81m]s,YK4LՐUYJ(R2n+wW:\7ݴs>ZE$ '#eoꮌ{*|ڮ OG딞P 0''X\2ֲYZs&^l^l\]#q),چ~!"XPvj:oF|vMJkla14IO)i+-#%q6qw`E8[v^UۊicW+v=WbdїN=VڟB{rצUں>S/!نT]T꠹0Q4p8J[R ÍÎ֙P*8$NFܼ;0s_Oߌ~Cnn7;DEaB raۋD#3RLC[Jd9f.u?%3,ӷ M e~j"3B-/ ?<;L'qB!A*Jd U7v͍7?Bkj^}5v5M{֍;bZRtݪhQ̛j{gs4A):Hpu6)%:H|]^/{(GN) i'FU~@2 d @2HDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;b$5)&$&2@W~MX(Iya`v0;%;nkB ~mpa͊@DoH7nG"yw1O cܛٕЪR;\lH2/ugZ=h6b?\=.(K=к[)xe^G{7oBaM`Y}eV+㍲}˓yգf |㞙0ٽRPM|m%[c@d1SXcۥ[qc`HRVH15%<ݕ1ɷj"X6,ԡ;]z"!]tgY օg[,F6t^ssPVC~?)H0ڙOlubɈl~m17_J|kve>zwo! R^)f[.?H *W[Mn)l½Tjhsoj᣹@{%U7`n>"{_{>9kaq]_h@*B~,ȢsjI.J:?1bWg+go88~#23K1Y,˲[S,d1L$Rf-Jqw;[j?ٰxZyJdDB5גWPloGb䦠nT4fE_gw-Uu~?^wyhfe>uc|N+V-]s~ix;gU{'0QrɣT,LL'5:a?A:LyfGj.O>LˑY```x]qc;qvWc*/>?Ѿ|8Yn 㓘tDeR.Ky?϶]V,Ou4\,ޘJ䓫f K`z^v~C+T*ټ9m?;jlnE:Ԧt[dϞa%dqIzʠ4&ŗ#+~}Zn1nTuK1&#L.cbqX@iUKMw=ZN&[/ ?Rikx;@ ̑\)F-#F&~6Y ڬ.8ݎ]{o 6vɉK,{iʛmfG7kGEcW3Yq~+Mzi?ѵv鈵풱a~p!x52Nˋ}O\βp-4>Sue4էg<!~+aqރ~w=GGZd5ˍʆ͇qR@*oXYGuX +6|Q/˲On4Oy%L;ݵ:O@|H(h3Mdr4$/Tx%2׳\}JC J okדwL]VpX}ԣ;bt8af[T<ڲ7ؒG_%1I ޝD< |kXHkf>|51iŨ_ґk+Bk<$|v ߼ |o0ɻ`yfKv ƨ]4/aU}Z)6_-o8>IqC5IKe~zuf+ MY審T?Xl ۼkwL%љ؆[隝gw/ n釿1Zڪ .Йl- #xw0:rg8^j=ѶQ>}xO%F/ߠΎNdvtvNa/CZvw9+ѝv+X?(M]4cٖ돾b_F. dbTKh,'ӊ`lX\_=B<3 L ]zoE賱/Z#Y|[VQ*8#drWX)!J&Tv7kB>["ĕԆ-Ӟl^0S9+ۨdA,rĶ &ݴ!mC5®[3x{}f&Ud@yW1hy(p:xv3ReL߀hY7;b i% M~j4e-\/,NߪopXY_<]'+8IR=|lёbۢ+ɦb oDj摩x|dBKLnYevt|TJ|~k`~:[*̠꾮 P'%nOܙ;0?}F}CodS] g,˦vC:Pg3u%{3fmffr81ңgy:ZI`2sCB_VT%U1}*xdjCqQRe4 ymu\[.Ǔ?4r>u_ёA ;=8?:t|0x>FG}"auHohX>U5Ovnj17D`BjorB[ҿTn 1):Si -M-ud3z41֪BHJ'e5^Ш''Om@uPT%ªG[~bL>ٽ^#:Rt6>K? FgQJ>ݱO/欢-;<:PTG1?>k+p/R@2k=l^(Y;߬ny,ol2Pq?_y˲+>Z\W~EDkOefof1f_$^;Lg>Zp%zK|uI*URy$ IDAT@j:31iqQʎ:Rn~lFSlWu8,yq[ @۝lS͙m1ɑH$34>zkq|TaڛζOK 7gIMx<[na#Sfq+6|s'1]VsZMznΛ_iR|~q{]ũNLAwgI8 H֝B^*.֘vcK/h=Y+8Zy|:`nk:G{7]xG.ggD$߅ ?۔"񁚬:R4C2sŒ/rߒ݁3m7WTjcZ:(ye[Rgs=N]-\iǵQKyes~.}}9㫎_^ZzUמ̈>?cS@1Rjқz_^/Nv;< -$E]:]xJJ8Nԯo`۵;MunAmdN.nc퉪YHX'ΒtgzDdzdNqsՕHzqR:>'#S?VZ6̃6N1GV'n7 ZH'l)"OV$ǣs5NIbl8yqq15HoN^ܜDG}h=JjH{Ƹ%{=;a9=ISߓӠq燁®IK5fͱ*ٚߪԳGO|GwǺ~CDjܜEzKg$9 M{E^F]@j:H::q/qk;hGu&6':lGhAZ̯҃ 6oB9g%y%=H^rFb}s?(P+j8EKʍ@_ծνnڥwDvgZgo9/9!1AꜗZvEHwV`&=ˍ#vaot˦þ,ѫZaqj0Y]ټx5*jN7lL?Yn40qI m'g[\;M.\\ZlF"hk8@>zr=HW&:_"޲|cjC=ؼM+sY7t})Xrn6_%NxK~{;oOWپ͉Or&|{%Ko@GZ#y( LcWj{=bNQtڒ<|G9s=I.do.$gw%]0qWGwy_O@X̲]t2'kz!GZ~dݱЧ{ ܯʍs~E1e6+)_ӶWC#j募E[e[4vڼfߑOU#IWe=1Xo0{sXV0J=ݴܪwjႮJNۘ޴S(|$;Ƌ=B5<2q}q:)"~O _8kymO&]˓rKMp\mHUBU?Pk6GsyPT/Խ s{GR-9-L3\CbyԽqGDz{jwJ%ImgYI"3CWΝ7WgzAn""t춧g n˦b 3 Mx6OVWftZ.?hPSk/zU|HXu_Sgڦ#jͺӻ K9W|d6*KA#Sӣw"猧/oW՟Ri`h^-&RD*J֧ %=ݻc.em]Z&3aWlJeĬ Dp!'OOU'W~):ƚel~4IR;^6t if}L9fzvLz.…U==:WT"YҿT/chgh̵WǡȦcChb|H_ގ5f摌:hE:Jh:5Eop :!Ir.#S2=Z 9 $@ $@ $@cuY|l_zOvmIx,yjW puD)<2XFIK"K!to%KtxX?< Ϳek]êg֍s;HU4݌ݪahփ^ߏs\@slpmkx,n}tBuֈmSQ1k2^~q͑4Ijp!7yx:WC_-7HXq xZ8ط#Eo% ZH^}r&Y{H_[,cw:|2b_3a|zROΎ14=,5bm(##_-egyLOotk톥zVk>cw{ 3V)?(t4sE⏬VdӚ@!b\<l4LvV2 3k;"I?< UЦe]28O}AoN$>:}a?C1qq|uMM5qeT6j{[j-_Δ}0;Y,?Q}uFwtVhfŲpmVM1KqYZvwczÏ|!_?(dU!o |=^t>WȖ+6d_'BزHRʦb Xm &-[g}o>{gsAonW_HjV0c)\S炪h@p&T.ѧJ4Ppֹ%7[mN+_oZ !F9=ciUt%䵣ET\PNz!P1g鯶3=~TOlθwvɇ3ob>_-9]_Rf䳩W  q{]C@_`(xQ??Ylm,pBzb)U6S AyYt`eONg'y V|շ{O(:-I=:RTH91x{,$`xyçKQ teAdSy9pI*ޗaEތB)O򅾼 LzpTOaÀtzu~/Z8`bxユl+0tZ.t@[]6f@)b6͠,ړ_rY=oOz>/r^y4}Ǿ5Cyo^w:W}֩ T 뺮z8XAo'Lz3R;Ǵ9Yl-w+ׅoUll_与 fWuto̯- ɺGw?)Au&hN]T;x'OGY]u/+P`OOYDɰ\Hl Ȟ;tSOpòhז )txS ՙ/ՑM:{u[- Ձ΅Mt}aV\i'qzY@k-͕ܥ:Jq5=5޹[}Q`*E?rzPVqFR:j,S 9$:cjy:y[$h=+Zk_~f0}}.=.K7YY<-o瞥YB,r%^ߔ(d=g\mҁk!E$٦c[RI[ ޤ(dVƇ .DE9g1~^$N }h(<֘鵥7Qτ}p(@ͬƇ|ʛ2swpBaI'_>_uT93u:33\~!{Ϳpd`.qͫX~~?>[X-T.|ZH&t(/I't6@q/s}Ed/^fםL]Hbdٛl*N}t:{ύpp{ao=cae`ےΦ[H7gKb@lYc{d/^t}N^va_owoAE}?0ʥ_+J"cwt?ynHQtʣןe$@ l㈅{w,4Qzޖzre?ޒ@޻e:WVO$?r>| %`\:;λ%~fXOyqK7mvwgbU J"ڒݤܨMѮ)NYt2֙ $@ <@[3ĮY&ݯ,'/>1ONk>wB!}jˊg7wfD$Q03g{y-,/a4͊Pc@ $@a)p:G-EZlg NY)s4Z;CGd|לz$'oW.gU{n u_G{d֙aE4;,n}eޛ+{_8ʦE׉y@93k6SӠ&dª=%YYՁUk鵥r켴V|g>sWI{"&lUʕR:h.EN.⭉ lJWE4ͷ1:IN亨$:Ԋ7BD$:;?䨯t/ h)̘tavFT&#wR+n-n^ ^a٨OH$1:I$ojWq 3̙cOԏZI=Nٸ\.5#]7֓Ist{̘` @GMoOD"ˏx$ܔTs+)jTW/>N$ 3Й3ҭ""?EgK&r\o󹕔vu<͔Vh6oM$DD-~2=\\Li sn%59x{L?N]Pndj+oJRF H V8r^lb8I H 'M eT[̋Fox713o Z9Վin*'%4EEfř9si.(2*"""EFDE"iC"e^5m#2g} 49km]Ȕmf&En$DV:9%_ aUT bsi1%o-R#99PԬM M䎈,;nkrF[3n)럫iWUGF׍ dVkpGk,[ux͙^qk#ƫh:E7b)G,UEs8_>trCE<w)* N1(Hͺ̦2Ю}V%aLv0ED""kND6,KjsVMA1Ed\FD|4EyyJ%fNeDE2l*8AIDAT1N9XY" YZU1|l>ODRf¯2xTͲ:P>; S̥~f%;bUs=M6-,Mn;{&mcr2+y:]m IbVG1gn(rg.ζo sȹ&"")""2"2m9s"(2*""旖1K"+""")2Q~>K!E"oAs^'"{;\6}eڈ|K$Q"y 0+2[1?͘#یKgzqu|8:ݿqNX&8z?Ϭ+5҄HJdfnZ63wk<<ݺ6φXdZdٞ"Ef7;SjfIʭZn=}*-2%}8 Z)G̩UrӲ&jEC(Cf[O9l63["E7{Dd& m:u+c5!rDzz|~i4!2^[#riEz.Ӗ[C1?+|՛;ϦTp-^so:~◲>u}_oFn_f=L{LIENDB`ionelmc-pytest-benchmark-5edf251/docs/screenshot-histogram.png000066400000000000000000000665351471041671100246620ustar00rootroot00000000000000PNG  IHDR[ IDATx\S(U6B sm\]׷&GlW/anŏ:kw Xo- kҫЕnkC5#-ZZ VE!HI|o7o7ysru3Ǔ8)3. @h  4@.@hEdq#1UWϝ V,3ziu|&uy]QzAAW;4/xua}ݮ~|c[֯N_L N,8gń‚$Qe55w#}H%uv(HlSd* ׫- +u5.ks?u7MMͯ2֮Ɗ輰WyܰNTu]}a z=ah촇%MUKs5a{Mx_k6FR!xGGCYG+k";{KuAs_ZqcWߕ@!}puj7!fl+(K=*[ZЀc&"k4+'E2%<}aavdIW8>>~zdZJk*ŻniZ^@[R1m$ Eum^ѷښVǯۮMG/0?#_Q[F7z+v`_Pe">*U[2|-]cb%r7؂%&{v:gTHE`g6 b(H[[a=FUYA2WRv"t-ik憒+;d~uW7 vE]Gٟ|{Ecf]ւYU&_kc+u}1L>}JD_w"+UviijI>Yծox$m^ftVژ+=ETeƁ^ Lϗ63MN@geg/э#Y)"#]чU᱖]_"2b=`},`~W)?x#-U]թZ3 2~+P7!E꼦*h^bKJSUo x>鋯pTO+:r'R{_vJM&+5eNY]qZ_sqjjVQmˍFV}YtU4 _K54K~M }]i]MW#9L2>`5VfKsYC U5]I% ˂ m'CF5hu%T:l }._wŒMW:~CJbWt+VȈ%hL*nZj,"i1%/#ߍT鋓IsKtM=#M"6!5c-xӔ#ߕ3D VJX8=D2R9Mq}u U@v}N5i#߻5٩"&KOnBe:ѵ>nJEþ@&|ƃHZ>訲{Sz8OK+U#zN҈~.8gl9N#4n7QW_a֤fK~ܕ*[W]9˘CڈcTe|XߘRWu~ǭǬD eD?0!XtS@g̸l9]/4)4*ui #w:jm_cWkyȿ)5tbUVu9,ս!. ۟L`MR3tV_Y~RZnI]gWc,ٺ$Q-.(L{sX'+.O+(N@*¸1LT0LU֐>5]g 錘89:/n.0ٚɯXQi]us$> 8dkRP\ӗXLzp@dS;yH]?SUU&xnMʫ51ִƎ4jqFA7F" + @h 4@ @ @h 4@@@xL _ҥK ŋ0SpmF7:= pA!@h 4@@ @h ioo4R*Lifh4Rah@LYtiw*\RD+Vuph 4@@@xC*zzz^~0-|ƍ0&ggL'Li&4}g$@@hq @ƒ[8-]-)֣Gڵ= G?h"Ν;;Ǟm6P!l a6ʫ5|j SZ#@~ijj9sܭ9sZvl+ V^_;wu|M:ppE; { m+ Klo)I:TUTJas*)=jJ:3e46$UlSTHeMW~ᇟ|˗g̘{{{݃^NrΝ; >T3f|?|8Z=9F[@q?1 _ZT *:oZmh͉ ^sE;'Rq[/\SZĬS2, EU Ahk)jTWo&XV7ޠjժ͛7I1,ƾu +nߺcs`9AFܣ_?fzwOVa&[LQ)ERۨ)NDĺ3̵:ervAYiIYMn7ZB^eAUEH.ٮ%?F~~p8l:R(sjsGjuw `:WK##‡CrrƍCD!8jxFM62M\:" @aŊCq,t/ L_"xAbQ[84@=?Y}C{uƗQaZd:hH8{zz6mgffAM{4%?ζ-YVXA-tRwO=رcҥ.RեKr-m4@ @tO´_~dd@_pa-nQiE₡'ȔW;i7W$.0A\ @h @D0-mŊ9_҆iɊ/L{f؇"޸%Y׷Rm-UFCF׎ӱQSg=l]pkto$Bd+W~l܌v2%9FtBr{hIר)tT#? BDlVUgސJЃt Ι3gٲeZ=z1… -Z~"lٲ9s[8 sH4Aur[CX Mj _ZC[\xqtkssb@I;&R^u?o @+ԼV|r}:ycu u u}勐:&RH(~9x}ź+uN٥2zqc-6vU4[>}qo4oPٸq^C1!6-&7as6'F6l'Vi8HG3RFh{GcI]ueX֕Шq>HJʬWo&Xl@P,@+sjsmU<ָ+{}nڰus&[kp"bkmԬ1~DVunZ5Ox y\:ب٠%? 8}zhuݚ)3Dmy}k94@ @ @h 4@@ @h 4@ @h 44@ @hh 4@v}n|uTKZVYEU&I{ZrjuIڢ,ZUTkvPRTbHeNMwwwwwXL+STɨ4Q-e[nCTm B tBO#@5뺻׉\[TT{M0wڋkZ)ڢJ}Z}NYWҐTQl)11)S㎅ ̙:c w9s愩uƌ?\Ӹ]=DŽsFH4AurZ'R Mj _ZC[ ! 縎y@f͚?~ 0* tkw OkO</ 4{ZhTx}źZt+:>}qȱv:V}Nt:Vt&==07ntk(&洵洵9l|bmJu"gI;HzcF(~ٵ&[Qd 6s&=M-;4ZeJ)"FMF]<FDh:DV,;sZVs:Wl*DDTfՆ+#ǒWY`UӋ?c{959#]7@{Kj:z gr k/h 4@@ @h 4@ @h 44@ @h_O ǒ=h4cr˗e*ИT|INNBӧHnnnȗ|ҥEY,}Yiii8:O?uo~3˿_Cz,((뱳e˖]v<@#d IDATS%{?^xp,n1  {mnn=/سgWՙ3gΝzjWh\G/_޳gϊ+͛c'f{Б?=3mZ;ŋwy K>vn-˟:u#;&Vwq_zlٲps\Ͽ|!_)Sb~O[ߞx!=?88st~qƴЇ8?Z4bתnΜ9Q{ٷou400֗x±yW(> Olܸs p:4ʹ~:uT @>oΗbpZqKt:d2f*MWYEU6KtkjuVQAKRetj G-"6ܹs"2{lϧ9s5DZ͛Ӈzhppp^^m[/\?44?} ]t=%q[Νꫯy]xsLj]|]G׼a:Bx|o7.yW{{{G7 =k{pΜ9_AK0u:6' _Zw3g@^[y9j a FG [ZRD$*?]#W3fZ;Ҵ50ז$4`wxhi0f*O<ްk.ϚyzB!"˗/jÇ>wu{dԩS;w|ѢE__ߤя~+x^s]w裏z=/ pmWDd߾} kZ'R rxҥKǏ=?rrr<7eħP:uΝC?ӽ9^:uTkkk8J]p9 yt7| P{/׼X A[8y|eeeeeeiu~v^N_ѭԱ99W 꿓ov5 [mΞ3<[Nge{KI{݈9\JwZg4t5%(s3e46$UlSTHeMW^j͛]jފƧptww{?rHJJʛou*ݻȑ#>>Y `0K}'N$&&ݻ7~Er߾}/{{{۳gϽE[om۶m/={v֬YwR/Fyw֯_y?FvuDO^|y^VֶbŊI{YumIK_",x(=>udu}b S5Fy^rΧpXt}Ùbs$"`OY[Oܞ,gS)! t~}r}Ve-f&}c}zMVRQ!@ (}$CDD::)ݽNco~hcVk4y|uM]\U3'UTUMҚZ3b(@+sjs'S^S>21~xgX7ouR(Z=\t}tX5$rt>sz|si;gXnn\];4$7Fu6.hXyyE ~)_yz ?|ͩSRAHV{{{L_"魷zоbRRҥKô9}}})"9 I<ūÊ ׾/}KQ|lջFOyo4\ @h F?7E+|ԩA_[n[hsv˗w{̙/ɓ?6n8p/< ؾU΄W]4Ү[C!Eن3 bÇngϞ>͉0@{;MLL7of]]}SsоbmOY͹3  |_Gh曾Z~+_>|/{ p@سgϽE+[om۶Wݻ,YEѱqFCW4@@4KWը[0 4@ƒ[80Z}M7E ӣG5c=pBǎįfַU[ne*2āW[lD"r-Ș[ω{{{oy@}/ҤU$$Թsv6aH#]K.Ȯ]̙gɑv@}g/^tUgɒ%6l`#zqlkɑp@yxʩ-]P3nLuP7ꁁ?7&퀺m"e'Wb$@;LU:mMW憵ՖbC}J~fu<]QR\x~uL:uɒ%{ٳgxZ=xĉ}w}cn`Ps=.\8{w}^Ϯ1W8|H̙3811O?R09s+g%KvŁ{ܹsW1'"O:GՎy@|͓YPӦMDdܹYPS`SS… N?GGPT{KI֑J|RO]&'YĬ{nqkMr4Vڼyʕ+aU׿z}&*ٳg߾}^9oΟ??6g޽GoZ Cbbbm`x饗F?qDbb޽{hs_k>o޼={zm۶}g^Ϟ=;k֬ݻw/Y$6cƍO…_|1cp_qqqvZlYm{O^|ytS||s=/})6=ŋM7-i hs:Y}Q7s?jo|ԩS:iEvD?Ɣ9].\0zd=ai(L".KZX*ͅsMv⒖;UJiisJִ:>>> gO7wĻTDjRǧU*K}_#I.[3sNDƉ(4vw=z y獌9 GSx\~4^>hԭ'T- + cs#VF5x_?N:u 4|Z?矆vKN:Ή|S~o3eWT@~GP8p,~'"/?+WZ @h DD@z7hm6 R˗/=z4?=r@>틦i4#@ch{.]y/pApvɓ'h9O~[8~ @p]|XᄏvZٽ{'msLl۶F٦NO?SL>h.ņz4hѢp,;3L/˽FWAv FWufϞg{qK'zñTt7|spt}w"@R||E^}Ր/gΜ;3k~}Q>d{tkݦM6o,auh{w뭷F Gcʔ)r˳>%_xqppPDf̘5OII|gϞ ǒwi3. @h 6X*++ EfqcX(Zឞ) @1keeeX0-nAjqƨ[yqpMs̩ ǒ]:L˿vm.] Suyb @#LN2%L/޳ p\8}.shhhppPDMڅ;ΐ/)wXÇl""6lC'~ @8No|#Knoow~D>o9VO>juOnǒ?抈`WBW @3g΄)لɹsZ4R*X̙3% `|;QΉ@0ϟp,˕_z饴Пtqnniji4t\1ekrtأVVk|/a-)әl uН6mɒ%Xr__돤0Q-Retj 5# :KRqqވm; ww7YL߁lm(-NNZI"ͺňBBDr3>cdpk"bZN3 Amf-W֎4m8̵%:/4"^wq?~׮]s .\'p=zt׮]AV`VVVVVVHZ;?<-rܹ=Ah[]/m6zNT'5dȫ5ڹso15J 91P ?_)Ё<71p S>{G}=h2}]˵Zm8Z}ѻ=wޏ?W_KBR` $"F?ӧOٳg{&z]wyO>ijC>}=dɒA_\qҔ~ofs gܭ/Y2{lWr}FD5<Cz#:y֒%tFx([-""Zu]{G#3e46$UlSTH"DVZy+WFT'lڴi"244tbls];LmN[[[ X4?s_җ h\"f(ŹZED%~&^syfN(2s3䊡L:ʪ3"".&oF}ݮ__4J O=T S?p>S5;vXt) aВZoru% 2""ΆC*$`,===/ ǎ;233?sט|m7/|ƍ0bnooo6spz&%@$l7>bTJAk_BP SOO돕+W𶶶Л6mw2{׮]?Ɲ "=@jp)p4 VX144D?@thl9O&3۠1ҥK7r}{k֬q9ws=lٲt mggWYB .;)+Vh4fff L- 'nڴ4+VKMM]x tİiR׈Z..XWkuTUT^"s[iqkKt_i;D]sYlA֣G;v=pEuٲesq8p?9֠:9!,Fy@^!,k/^ܜ(P_)Poo:G sÆ "}WŋDc t.7j獐:x#( 䮎^9FTf:mmm&ߡ]'@Z)и.\vhv=Vmvӌ5$QU_A biXݔ{-Vڼys wK/p|TedF2ߜz^ƇJ%%j[8^4 M k\R|R[lL6f^&h\bҘ>c+V(--=};?IQBw;cтL K"RWlW--^髍l{g _ ĕyG;_ڵG?c9sK?p~ޢOWNWα ZCnh?2va&{Sϡ&WKaaa(2ӟnݺ^B\.}Q:p}h}@Ӵ_w;3\o߼ysqqÇa@VQUuppK7='\ʎ @hBQZZŗx<{ikk[|y{{Hh٩Uu˗ !N:/> s$attT$-hfUh 4@ @qoKSVVܥw{ljAA믿^PP*=ৼ±(o /e_2= !ۓ|>|q@$p:w}7 /@ Khppp~@۶ms='ضm[0liisd%D^HiӦ;w^'\4 w eW5kϬFǎKۙǓO>iXdd Wrbٱc۔>#+V YZQ[ou׮]MMMN:vHhdXo>6 6̬~!h  X {1՚988822$h裏>|gݿرc 4sKN_" @h 4@X h|W_}l6/Yp'KU6_|4]n]ro3TWW߿޽w}7ZEyБ!HAe^k{ ohǠ)]֡C&W;>>k׮䚍7 !}١!/ĕp8R#ۅ2(0_d9\ͲAEcIaOKПѣG?b~~~2&k׮)>@XPݗ݉ƦJ0X]>νnNF;XkwZ%CfW[ZZC566>}z\OOyB\ y GU!PJT^5Fn$W%QBz ِB!PZZO[ߪڼy?sh9꫶y⒥s07W"n,$I:r$I{-,, poB˨9c4p-4@ @ @h 4@@ @h 4@ @h 44@ @hh oYWׄBhр۶&'gj䬫?=@mͦ_}H$=Btl >H$>U s7ÉDbY47-`p(iH8Zm5 !pG"PcJl8XuIm2z"$h\{IJ7Pl;!J|!Ix,Rd5>w$X,TQrPO6WM]姟~777s=i+| _oBl玲\~}KKn_͛b+xFd΍ʈ̹Ȝ/܈p@q@e!u~@>@y-ѩ-Ɓ.BU[ڢuG/bNmkvp7ͱ7޸~}ki/_~˗/W^@_‡կ~71^z6NnDȜ/܈̹T&P<|Pz9r@]T%DBWYxx`E1(jWۖS}-t+)?Q+_$i-_S7}9.X*Xr @K^ΒWc\!MXpL s?OwS57|Bve8_sp)±~SUw+r?-ߒrru)oF?uKc:5$4,&Ƚ7L 6+OOO%7`)'s߆GgTcUи|d֢9Xt/Q%+0=4:8кpt )\q;Ws4@ @ @h 4@@ @h 4@ @h 44@r)]T~U!h_CUVG)]rVR4\rEB:pdlswG.ք7466 g~z<YBr4B&a if ǢⰧmz̙?h0VZ5g}G3i'OϤw:+Swm}ECw-l'zviʴiӦ;wC۷oyyy%%%/b[׭ W.`w^]ͬ ;&mOB,;-BLNƍp[ot:x{ٳgʕ,3m(9~ǃ XŞ6CjImLg\aiFIkBhA4>Omܸ1&O<13 }^uL6U\iV۶ DgmuW{WUlu;8Ϝ93?* =^Z!UvUιh?M=x իV&<::ZZZJ/Bw}ө+>, =@jll/39qDqqΝ;`X?ꫯJx'h 4@ @h , t{(>$麜?3?}r|MQܚ+jAA//[lϞ=,뵞ONV{85?iߟ\˕H$BPnnb֭;vxGEc9wv?/$n⦇t'cY \UUCPCCC2= !rsswqA=V}dÏ%ӳB]ug{QFRB7ͽUU_zVF7np%gqtb!&&&os⋏̿p:4Bl+>|wꯞ[soOH]ё%cLfLƗ!8[\rddwyuZv|Z_7Z -g~yږw 4>b{ӧEg!KL?$7_|鲗(oGhݐ$^˞zno;t 4@ @h 44z*l~ZufRUS6ݥh??@='J|#ccc+ϿؚB^o"B -jMj^%̟#!U-X4 sg?. S,ΦNZmn ehޝc"{Д.O:B&a6ӡPĉŕ+W:Ι։P(4zё 6lܸq!ZVZ5 ?装hݻwojlݺ5uj^V'_օօV(Z_E NsպCMrE=R$T078~Oh nᆕ+W]6ںlٲ [uٲeVJ]s[S ]k][Jk]Je]  bP%DB_W=wve؏g_y9)5MBDZiW7mڴsβ2>MOO_Rws%k DžBS*Uv+Χgu5rnIKV$w.DhUDmꀱ 39}1_V\7`̝MXpLTU}>dɒg}>S8z4>>.={ne˖ٳ@UUztt]vO$.ŷ. 7:::66688\cǎ\UUI"XL\L7>>|dZٚ4`IN:BB0KiiwܑBl64,>@GyddddÆ B!zW@L IDATJKKEYdoobBzW@,oM?5h 4@ @ܒD"A/zϜ9OW\#rJ~;믿K? //•\.s4@иNi}@$N7dAaDdQÑuLxUVڧ346긜`  k*.rt:TapLǯ6)oV\Pty5ҺqoM)#~wqжr[K ڷmK-t|!4]nW{<SU\fUVl:~encK?Xr?VhgKb7{mN˫>n74L=..O4fùbb2Q FL*~ಛn;{TE݁}rAdPIx;+%]>޶6{9t|*-ZIۯdxF nwh!޿CxwW*P˗ք7tz[sS/'xuڸ5&DFʁtyڦƴҨAZjv( 6mӺWp#\cB*]͑˪Ìf7Y%Mm5VCFĞ|ѷtX%!ަ^GlvtIhVS}\4 !td$FU>뭑YdJGֶCz}{3^7X@e MN]舎!1hH[ĄlvI]~nS$03qZu)gJ-}Ǝ*٭f\d6lL|mqJ=V$Ym?.li$Z3o~?6X*zѾ-azL(7Ya=;L:Ѹe`H`$;v8*V$ud0Mc !9s/_r}B(g!ɇ/ YurDӳr:dj$ZpoSνVj[M֚(Z3-Ks"l0X_nM֏m7K)r(r([a4}yRl0QNДk啟nPy ]=|pdj'/Қ5uަζrޠEeRQwX(r(r('S^w"Y3=H f]!І+B-Io w" XLi_w"]96v[qQPP&p,^/'dž}.W3 6v{WQPP\!jڽUX[:fFz}ǽ!]޵"Ѯ-N,iq%V痡)r(r(rI!z}sk*zj)+8zxʍA?!Q5?GdOHGGꭔC9C9C9s6v`TuJal.EiB2(' 2&;]BӌzB9C9C9m2&1/Z?W" ([a6Ԍ-M,]m}z?mz[)r(r(r(z ŕ_%v=.jt(g .PPPa4@ @hh 4 ău9k;4Ks8wۜs8 ;+vAT5 cEGL999͵$hȒ[s0qN'g֘ @.Wv:xmMNNκ G7>ܶ&'''g]fOWDc\_חq]pr)6Y]mg;<%sKPpHI 2[+p} 75D"h,3w۰7N G[MłEbw4@/|C5$Y#Ĥ=MM5vl6U:?dpuYb7_7%M{|;ѕooKII:u)K& OhҴBfI!Hnp 4.iB4(Usrrrr%Ú18{ڐZ*ܱ ѓ  pCp2yOkbRƌ$IݓK2V;c1DS@`!b!bɺܬ5ʌ ڸY^7Nh'Ľd6=}:Г  jpc~>\`F3\4!";D1?񋱽sTT)UŢT^P4jI *y>u]ʂg#>ADxsLr4R:1*:XwzQmDK/mg8q9"Id5+gv/g5T 7xbl9Y%fsP8o! Gy嬦ee9ɘ L-qzTGJ٣ 4Zj4QZH dwK$]K˷x뽢%#͉H-iŌ#y%$)ҪVɤܫus;f1Ւر3bZ3QrV%a춒KDrM+EN[Q![Td$h`[W͵lK YY-+De:y,Vv+Nu]-> Hr!jIjV(cNٻZR3|WK1f,뺞Qm֒ULص,/Ruc8]Y9t09fݼ[ܭֆQPw"6ԨVy W] 8`ֹL\c6VЍbԄT۴f mPtiԛj g<Х޹.X+n̋n5yJĭd7R6c9cС }?kI#J31aR2֔Z&YMP |%g Ӽ"ˋkGA1`e5}QPp9 !.LqпӞ%>LZPm'f7({0-2 (8)N-,Ċ̇U3SD$zBdo:SXOm$g5]ךrV-U-XO}5oS3DJ1'a LVQ_zdt=}w;XB1GE1(n:-B㗨Q<if~Qd>> ~j 1AMQֿ ѓiTE׹dje8 %mU 2j q d:_.DO#vR_6,g#Ѧ~;j<JF 9.5/O%E$[MFcN9Aǚ̲IKnq˶"uH.\;lv\:T[skiX;qGjI8b#Cy?,F;?2 ^oPұq8sMԐ9a(ܓGʫL s|VeTv[G`A߻=bl:9=1]Ȅq_}؂䝏Og'Hg֧H]LB}z1q8s!ۓGp;}xVӓ"jU ikT-jel.I4dU%-A$IVL&%kyw[jI.f<)u&R9w{VMh U-dy1BJr5Y)zgǵ!KF:C>HUjIOoƸ7t=Lɑ%W1O{p fԩsb0h#vg<'j XIde `{ߴämɰ:-t^M<@x.]^!c<u>"IsySZ3QsOrV%pgQԧQLDr3\e^Z8J9` yx;;حY*~EX}IRjw遽s;agFh|P$ܓi ;+2Y<)""")TEQ*ݬlLbG1U(c\YҢ,݊*ֺn]3l݅HTjbPqʫ֦J&I.ӃNR/>.`xa*50-Vk~Mo} w VsԺ5FSd$9Thjb9{R(tFOOq?hiRg\&,; ݦP<;.Xl2z2ӓ#yl8G>+5UvO%:L2a,{^?:˫S^p}:!Ӻc705|u?w V"$>z3䜽k֍Pa(Zw: q_k:pfwjإiǮUk"ʋ)iP!"j5d"ñQo D2QjE&[:ԭڦ5@˫Jqލ1iE0Ҳ>tZ jnAY5R2#gMO}!Rݛ=Ȍ6*JvO%0vrޘhsv?ݦVcKfӚs.nc7kzg9`] Pݓ#.DCOz{SBt*# <&؝Uvv%;%=W̯B} HOf.⚮Gj<3 :Ҡ'hqL$!x2bd&Rs,^0}It5Z "9NhB%QsIuXkT@=p$W#'Dqÿ8KFEkljg1Q7g#]os2 p\ǎ)wӧf0y/-3j{ceV ez~/gPρ qՒez坚=TkԧOyRBe.ZBGijŴPN}G66dAWFahdHh3Ɂ zꋝy#rv9Z-U~lc]OGm3` T]y͘ "#IFYF-b;vs?Rk}է`\/ E=%$P>|u/5CD})UXFh1Otog=vC&u2N=y g8+;f#9n?Fӝ:3Uz4B; bR,ax- yvOf<~#αO͔]UGp Qxs ;H AǚLU ^!9y>b/?uHguoe"*+%]~cOu*^!u 0Xͳ{(d&ď(/_@5Zdl T3Nx $|P$ޓG{Lz0Ԓ>ߊ;i͈o!jyĝFNj!Fwuu<4O}:~MA`@}B@f%Nez&/bMةa=czK:/~mFf:/,Esz|9}_<>Qu@q~6CBi2i8 q}ܓАKdN-q~}J6+J컦. ub&!V.D$g\2BDίyt=\ձ&Qmǵ9vꋻt<=yK$EZj3앻B;!vXUDMP1ڨ/u>YkY-tklSIpڝY"O݆nMߪY˽=Mvnq*uɯ/1KuDr9Ď]uZ{*[~%]}Z-ًf7s!tޕY{Ok%_XWK^R;Y+g5;=e>- YI<ބx9u6ouהZg3ˌL2K{ZYqf 1+ȼ}k;p|x:EnKu.{lb> .%BpXϊ6ٜR&"5!6WEFq'.]b-dN97Л:YIsbef.q`j;e]""Y^HIsՐ;yZՒ'K> a NhEb|J]ܻJ岚Z?./KX;1Sɤ&V DlvH2'<7ʧ҃~BÐaO{:-c60`}y;L[Bӎ.t=yF~~6p5;LB%JDw7%ȒkM,f K-eՂR4h;Pj3l[&އjN-I&~ y^%-!/Kg%{6OtpNE52.ԛdJ=雐QL+j,DDj*$%rI坚(%h'dr'["Vx;Y Qu坚]MQK=XU*y d0Ͼدn-aW+zSrZPL`Ns/+%ݚg Q]Ι),t=CTTjDغt=39.їb3KtVbՒ`BZbNdsZHw62V:fc{PYn8\ItI_!5٪VkRL`UJ'-_d. Q 9OF+ob# cl$>ڏ:N}r5 _>X]>:tt(Jhl zYb/4Z>|?&ZE,6'gNyl ,#v/N+D]-a+&L}v#3!갏܋םc0"aU)t0ƚbj8)?O@R`z;kc1H HP<c1 *I88MDM&#DԪoƪ%={U-YTX7!嬖[Ɏk~RKzF""t=؇gr_]չOkZDiUdR3;Z;ؖZ.IՀ!6_Uu 0Y16IXEQDjI5knW[-(EÊbZ)Z; Y,aټ WƁs^7Hn ]͒9 ld,(CڧGyUR2GC;䬖QU+faORKzy=9+QDRIBqn\&2X]"e*(Z4[X#o&4ص5Zإ%IȨ7t c9.bZI{IY:QL+RZՂ(☤t.fՠ/7 JXEQXη`aNX u: ):!j߻ֽq$ˋ)c(#Q4.ZՍ@O&픉 JU~F${;gM!hl 04,2srj%9)g5]xRKhwv5ZRo2XEIɜnek>ԛJլ]{+d|ki:%,U3+O.92pqW\M%#DZS.G]e(Be96+FBGO" 8PWީ1JcjS-qwՄF =kOwr9kFKJV; =T VznZfBqdԛdJlxiy]+J2!7泦!'u f;cz$]t~}Q]$QZI13rL46VyS|ܸȻ&3K,ZN׭u(`ϽFie"*+%]tt=CTTjHكj´g|Ve)^KDj=:5 @yGR:;m7=J'I w ,8j9wPK0݁4ĜmU 2*ZVu9.)sa(' ę"޸MO,X DK=kT]oB3K6V_O/37?zJbfoWԪUi'o鸴ޖ w6NSDpfQVflf)w?Hٗgb(pWzoc?ܾ<__G^\~絹,/cǸO>J]ee~.\Inً˳KZ[˗Z߻8uNd)0_^4k n`e]ׁ=_KzOf.j)cjaN-P ]ذ͹b;7#ɔʏ Ֆk 5eyv F8ԃ5ZҲԉr%oWSHnLy&%J y/se!t1\NOj!t=CD _j!݉TS0ts[yN-IVZbhʧ뙀J7˹*'0 Up_RF1=_~ϋ&BO**~ ৤z(+JnOˎ6(>qt U0J(((L"Ө8YғDD*T'jZ-[KUJzTKV%ew*i ""-6))Y˻:RKߡ EE4Y%ZT&-G?9-ZRHԢ jv~$2y+L:B nYPI'oy֝鵟|) JTII%*eIzؖI$Hw쿤ZY$grn(Z"]gY'= =|Թ;n(dݧB,B,B,< y*Fb#4gb2S֚5st JHT-XjT&Jm[%=ؼi]WO(&J9>QIb;'+إ\DB,B,)~IWk1M[9Z?yc . 9&CsL*ubmΪ;*̻&t;S)AdP3B)XvFa$^")p% eس:5DW6HJZQWEbxDS#^r[~OVW)[7s!LN29JT6(B따_<& Uf%iʝ1+~ U *n[UO9zIvC'ZC"pM &FLjB!Dxʽk9=Rnq+ׇʫF!9k415[Zup':ƜcrGT^-{1 O(DDj%&FCu };EDjE5BR*iwb3iEY-5Qe7)FՊ&T"ej"Kcob8&&+(>i *0iEQ*5sYMrfvԪe(qsRؚ cح_*cC}0On3RFgIvL$EZj3:vUBzSt=^jdĽASgԒhTd_-kC{l^ީerYvݥLj*VhRChb&fLlX9 Ik2ތ&(5<'3iu:#^<.*]9b\&f71 'igZE)[p/290v[%"aL%;̥wv3zB!33׭Uŝ Wqd9=g3OP[6y,Dɯ% U>IwX7U"m*Z$(h\&ZbZBjB{Rܽ`O,u=*)۴,rA};E۫;KՍFL&۟F0QM:.W6B}Z}fz0*>R2zTsux&sȨ7{5]LDH É\&f71 '[={Vϥ,/F\W'u`ԛ pP@M$Ąax,D9=IOڦ WKu6gd -q(ntaӄx1V#яWK`@O;n4\h 3 >3tۗ/cuF[DD2nf&?.5k5tc՚{̣wS;U%}'x;<͔&Dbs3a8y+DL\[nU "e\FGe{:(⎠Gy5SĘzHbw/)GnTJ~7#?kʹCOB> + 1i| NxZvVW.RcӚAGS 3V,g5Fͫ\|p梬ʋ̩M jb b춤{5.>"'}KM6;SK  ф5zRgGv Zobi:)=i'Z&ӓDj&Z3yp|]CϝFu9z;/zo⩋IG8EhU [j*Tp3lb|Z3d>$^LWJǣ5YGoS:( =]jFRe:7BݭNS$k?&3_$z36ӕnVeQܬ陞 Kw=:;13&=ٗx !P>n#=h 4[~'0J1Ϟdm ^B+ROtKmm>gZݻs>']u-szɧcUf&s.fݻ@屪9sM64q ,Q6qP1GVGóRvW ~e~!5ū3vp{ C_np[5]V2ssޚaڈĂd%͏Ye^}1"=Yh+٧kh1MRyd2{CxO;N\6*]jֿԒi^3òR %;HA-"Lҧt"{ Zݿt9V5ߜtYM˪2TKZ麮e%z3'+!¸vM3:vDˎ݅۾Ĭ' ~N0pchҧnw»7?a-잏< 8Ხ.xs#8s[u|Y6~ yŤyкY j{G#4`="ɻfW*j4cg2\US*w͈DJI.6 j+ӛQL+;ىWjꃢ%kg''XߝO7h,ʍ!4e@%)F>M0KāG^\_'9)w3|Lz3fVealMc#9Փ}{5O'Ods;8}Ͽvq\Ej;d xuH-ݪ95ZRїGM%V|cG9yy1"e،DѸLDK UXF+ԹcʹPND\jZ_3ϓ7!{t'%fBjB9(_kt*~3O33޸~3\|(%t'nT:3Kgffo+Jw|M*?Yre]h>o܉Xoͦ׷x _]{}yV_7|ͫـ W~>#d4)M۸<-kZ;(N'ھ{Øb{;fz[3LyFiɁn"؎o{5GXgS5|LbŴ(Z jrΆQ+H4hYrtcg2;_(ߚ9ZΌ=imU;ߵ{D2ѪЬލmh6.=y"Og7_]7΋>}%׬)pJtImfuݼb4njrfApWeZ'&mzO 1qͺ9w+3rGWn?٘){jT\3t=/MDd^\3kG,goh>8?F9XM`M0kk_HO^7 M0'>d>#lfBݧ;&ZpE7Zz~!ya|c /^~Ջ7c"׋=&m߬lӷ3fԔjr#\[_nӫ:՟=r_?d,ӧ}fƺ߳Oc箸pBt>t'o-:׍UGD+ߞs,Sv'OՍ1f4h>҄51'ỷ=K_oYX'&Ö߯zz/{T88b>g~VӲR]f=1ֳִ{Fd%~?-Ηx:ޙ^q%7~txwo-~BѬzf{/W.=NA^s &::GH"d~Vʝ}Beg)Pu_[(d%GBcVhio#A ytCB9H;0d'0=yfS^qUz;;^ϫ%vp?|ð?~x#b ]!']PѵD/; cAnǴKOݪhb41h4G0 0X9^ש@ #"w18>Sw닲/4V>M641Wc|[V^q=f9&;eҳT|o~np&.;;>:>1÷zvbW8ggcXK΄2KqztfG6?.{`s0cZ;ġUyEKB6F~2e9ÐW"y5A3+O~u5~rCPs?Qcvˎr핟Aoퟵo^ ЧΎ}V~$(D?6W}w NgwZnus͐/C~O(vo3y0Qi^ob4_&Kpn`S0SW.6=W(oQjSzfXsȣoIŏ륟(kGe'Vs0ۈx>sha8`6v2}҆!'K=yɻa{sO-=s!T#u, R'Nv@cM4^~8޵ח;3ڽR![8 z4?KLޅW};7}7.K~o/<Ƨi&K핕{t~5U:dg}ȅ[oٿNM߰Yy=663OK%:֠κXF ũzDo/O"F>Z8uUɴ/=skS5|⁌=lTV8hTXbZ\lNrv;=*d̚0g@嬦gbN!v?sbΚl5(ˍ.XDԪvfIkvݠEOL*4+&;Qwc0|X wjCl=~zN}w񿉧ŝYE/Jo׿ZHom.fܾB؎v]Ͼ<ߙk-˴t{tHFũ>Xn߿X^Q}6q>~ѥzMv#j}.ӓWH.8$9N,IS.ִhyP%bW͂כd&i@r<Țc'{z3PgO<E#Ncr3t:g|籼U=f]O8p${57fnmM5sZw}N؞o#GhO'u~B^qog~H|tBP(o>aoɨ@PvF_1zFȧ{׼0dyoN5'peI'sjsm8kSoU|S~6/ RKI;9;^\>2@] ;z>O|%Œv1!pNtDxd}}xF1m&Fs92 < 1p6a&NbP,t .6lNF6DKQ h#@9q9ky{Ah;mv':7*N70 1  %=PY-Q2 cj[r-k+~wݻ ^@^Yo/n}F7pOݓdO=\CBSdZW[3Sc!.n\\ "ڿk ~O7Ro_<۳PtD+;ն~{ mo<Z]@[:+r\/tںI Povk{{uޑG,?lvm醳%uxk[S5*9{M~\[A]X CS~VۃօO_0“= EhbU-FbB=tc g K/Sf:_:wn/`/n 3gZkn"PD%)Qsg݂naUy!9ǭmikeuhz]]s` lc&Įvw8g[a(|DsLnPO.rV3=Y1}f, *є~e?t]H$eO]f7ģ^O3#H&LjvnVe>hpkU}2O>X<-dAS^cN,4}G^\~Rjr#玮\l~{Q}n܉<ѣg/~k{&.^K^|xgϜ>pe7̿:xQ,}cy}~Ջz=im̿zc՟mSn<&z3_8N[_ǂ%r%/QϯO_o;hZ߽-sw~?oyG_o?x#\:[{$|Lxd~5m7)җty'j?71+B:iܿҥ dN?z5#"01Ѩ cb.-ʲ3qF13%-gՍrgMkftъ.D,9IPUx[jEYoVW$g.8γ9=ICU]c $>ZkW7c6:+zVDT@ ?7eƳ?Wo)^#C7Dο{bL}3ssKK="{bzN|&վ^oy#umքu݅zO]N=D-ًǡp;/ާ/?Z>!^K[+W7V~u!Nbtn}"\⣯.ϞJ߻p?җD4+~%ʿܿw?xh\0ܙrJ>%Y-nfo]>Z C{ ̄W_P*>Kߝÿ\rDQЯ/ݚ_+q^z/} ѷ`¹P q#L!,g*9ƙ3^1<Զ71B08TrN(hctZHVIT.JFS."v?gOqˋΌ(3\O,Ŵ(jU-((ߞȶ0XB0yRkXwj}|꟬p k3tn[jg•I^JgfimzE_q^Sk&z^sPt]߻r癆17qOꢵDǧU}:kt*~3>kޗV__荋7n|FoҼ^Y7O׍Q2DoAgzb[sܙӴ][YMyOFNqs^>/!ڥ[ݹw9[9 _|<[Yi_ڵG~zk^ι6֐}7|NKoB Cc WEQe33D ~y䍥嬖N$D~Ybclfb'?{Z[-e*5w@>Ԅ?NmQi=̅;t"͞@ GO2}g:3O\3 Գ4kfCn?|yb: 7++Ϧ?vgq+세?/~gNv}Cұi⡍O_Jo׿ZHoT =J[k"cfآ(ZE>xTzci9w c{Q"^ 76gތ$S(B½yѶ4`RkXۿv0̅滮vMQNg1-􏞽꿳{Ƒ{hKNDH!Ck{ouV0dsz!> 0q#$JX13v" \X! nڱ4aKcq,}h6E}?XUկJ803*%:(3SuĒir[RvIK7ַQ%N `(R~S|8,w횃ɹ(yQwrѾ\= iXn6R>|꫹I 1P!TiVv|xC 51F0o*d\h^tV]#&SMjH /W^O}_SS]͝.[ i ^ł^ԃb(#murkfV(MU䷈HZ =t`Uzs)ݍ\r ]ͦF6p%ߵ7=Y&Wkx!--sдyrA(o]huL-mS-;3x 6CC%^uC1\^NT U;WD֎֝ݔ8"fNr@cUL]*܌i%[aDɼ 8^Xo? unuC}V.ㆸ_BN~YDqiEGwwV{ah?"bIvXP1T CZ&jr'kLfV%3UG 4*Y񕢊ju(MK޸TIo5obJwNzZJ92SG6DӁ*6Ѧ1e`E%K^dY2+66Jt#[ v-r ZJVfȴq5@ŭiٳLkUiinVw@W Y1 yzˠ+3R: X>vJ Ē:&Z ĒW\'3B(V~lc2%3*;d'= -~\Z ̏\q6SG4 bUށ*LRi'̂]DȍWY3GZqXaʄrŭb1/*Qm&mdLߜbfݻE*f`e\z;y{e q]^'T+|Sbȳ7kWնNȕpMۮ̺Vl TKƢD2Hd,P砯<ʍT7F[H)mcGV8 +v/=IN80nkGb3+&;ǽVMLb*+OY8S mD+J?K R= *6`RH+F0@ÚPQ)Ǣsm& Ua`1;qwVoe3'UuZm9t+[>O'jd=w5|c%촪kwu@h-=mvOM,e`0S !yWUX)Ff3DIC[++gnapfw\I-Frcz$Z g=;33^_Yy~=ef#rd5of3|)Ee)2K Q4X_ζe[s}AH85L?}΢X,"޳~-%~:t+^*P u7Еz+q"ߋx>uiW/.]w_>)pE)͋c< .Qybfc@j,[ \z>_$%Z+L`[t0 "/?|k29}~tXK~)O/EP4y[!sm\U1*1X1:mkA[[ޡ;;vlKso'kzFwJ5l$7NӃk%tG/iv\^_2uEY ={.;[:=9QGU=7x̘ٵ9Mt^u2dbpܫE%U]P,3ڳrũDӫD79'>r\.*uR܉*>_O?R6m0fwt1zՐT5u};uWt괬Bba yU.!窸[gWmH~*''w$e+Z*jCTlbsYb3Gap UöqU[:Z2Q`봎]-=l|f6wFMd,ϓ<}}d[vK*yT%'=NzD_Vv˛֥on=m<%hbwY`NLvbZ}KZ+Ln3:޷$' z3onϽ:=)܋yv|/C?zvӣߔvpW4^j~ٷXW ]H+mϻa]~NeA+[/y?rs 2 CU\'_d|*=b+Z*`ΠO IDATPHq|űu֪:d}j\)s4-I>fh6P W}#ǖcT,4X;=mDm&?l@S &Yo3Rh!VOV-RTs%nvYi#3dvEq&`ҹ 'eqQGYyĒDSbɣƨB3$c=-.>qw4s{*Vt5+ٲ6n9SGXT3H&t:ՓUPh2Pu0 )|lE 9ҪU(=GN80n BZwm`e!;SťX$?{hL0{sEgHnSh^qȢ{h&wNGUSĤ۴*?c;pUd!3,8.ꈷřzQcۡ/ލ^`rk7qI=+[OΩ`08|0 sJ59$8Or@L)42!"Nrhߒ]Ys 3˽JzFo7JP#Rp>ؙYi,(3#)>/3K),KI }\vG?o_q ߌQ^-{×hX,"޳~}g1tOnz|}K=^@n?+|' ERũa['^(<]g!|46MnpC |BuC OtB.V1ש~У1*WoՏ`|W#z 26d̮(.:}L잼cpO*mu<;TwGwNimr`]jJn.CM'֗oY44ԝU@`v| vUO8} 0Kb LfF'ky>NwYtzrԣ(znB1Ki9:: 2{V1)@VAAIU ˋb_%]=4v76ײEte>$osMNuVUy=`;GŜ:܈YOHL{HS9qg4aZn6Dcs=U +#CPG0,A}ilfby([@U7ڞs붛.bX1T :a-dDvR P1T CZr`zݏ<.\Wu|\ȹ\}2w7^!)Ge)h:Eh/`ȴkt5T}5193xMRNqy-R7낝n)ٓ<7ߊmvVXXG͈Qx6Ti 9*fJq) @(3ɵmj6NDiuXU1.FjJ\3Pmc7DׁX2H0*vǖ>)nˣBaJD^a-8+ny]W\܏+[%(3)393vI/ѶUk걮⎨TsSOҊwq ?.%}ؘVP,O*6}Lb-qp\)3 Dt҅TTwVYȆi3c.R' uTl'Shkx],N|r3V6kuT#`y^qY>F>ƃ9qNNM,e`0S !ybwgJ qFxOwΖNOjTU=7x̘Θ vu2dbp-,(:(e Vs"=l""ݧS)]xG*(OOnNOݘZ_]LXUq%CdL02S#Z@ٴ[:TXrwy5~A vKRv9)o"3,\<{@ՙiskq,/2Uf^teߙgh2hⴈQOEr8M:B bwZtݦ*{SM=5H'y*M+8gvk݁Ƣ:i5xsnDBy*iOlc2eJq) ʜd=ƵMWrosō%3Mhs=ѝlZP#Pƨ'smܪzHk8.W|5Nvy8_i҉MPq{V CG*:aX΃:T'ĮhWlWn2 m7]BŰb:P1u4Zpi¹ LpXH;ڄtCP'O%2iC؝+\w #vEyh:Eh/ճ.pM(|V]zӑi[JV'AJWAkw& 8q3[̹/׾P1VMc\3-YIRN{4Kr4޸~f2CG"|SʛŪC 9c#N[y*E+a?3+nǖkPr RjUնbr#i*ʳ75YJoR2 YU2reӞQLPOcrnO3Ԙ@ל;Giy!h\6dcIެȓ%@ T;3j͑=#Ūaw;"bт-(WER/~У՘Y:2#*ǥ64C+!3b7>b!GZ?RFL|\chq #3 .MCnA>K%-4K[ߔd'Sw80KDɬd)GRYwKYOe;y" (;}s}^? OHeq\.kz)[˼;JzhxX,N Smv[x`mOKt+uiuZns?G=njO\Wù (䮛5I[b{z7T^+hVG tZnNOݘ2jShA<[d/\e&w$U++q^6)8XA*ǥv3CS!bML9Sȩ#-S`6L)=lc:-gq!Ki^ޫ8?وFʶd"JDo{Kr8M\,L_ʖseY)19uE}НVs7{7OU?/rvF^X~ٷ]/?Oڦ2yen7gң݁!{z"-(~/ S=j؎ރk޷TboDU/?ܫ#H8rȽxUD b^eDIU.DnzCظ5]ST&> TI;.KUk2f:2 |ܼ8[k<]uH˔: TY\\';?1GDs34{ֲF{"i˻ϭe=@S]mnSf6YkRh[M\ӝt-)TR d2;}}xUGYfp w~OK`^'Ohu*=U~e IDATwƳ)Wr_QϏZS-|5+Vc랚?P̮/Ymߊf34,u\}N=IkW1 wcݪ6y#SLL-PON rL#+kdj5h։#=[dd/^m2c5*6sϓ~%9Gpbڜ.,9޻8עGңR~=1m&Pwd|Z1;xvFrC#ҏxyH}KCh!W,ysS?2r.F 9N5'uf83iT LX8 ap.""&҃kj7%y Qv :#."ljdCY a\6դynߣS pY򩜉Y%@>'фMum/Q9DM,c3+nz7˰* Wyc@b6IW\xۖi[YƭqUĪ>HV"{Y׃&-$J?*-N#R{k*ƙib*,4t;" ˔ê<^A,nɔ7&Mz\+ViڑUfț'>Եk{@GRvq3Lg?V\{{VJc{ՕF|5TkDٔkes7Gx)Y1\T鿍=:8?/ .WRa3,gEv͜3 Y$ĮghF=)Ffao:ޣEoܵe'7JRtP_IDD]O;Al0+m@b6IuV\K9u]x3Pmڜ*1[%:jS16*ODBrE`gxK{ZY^Vi5NL܀Kx@[&"*[JlIc)t*<Ŕr|spf+rhWPO]-'Sr&Mz0;?c:rK͐= O|=kVW4:eS}K`0[+`P E-#r73yu`419+~f}`RxrlT>v4N%YWbI%PۍSmrrXRDOF=d,KDپ?ÞyC=7EL왎O8З׫o@Ww6BDޡi^b_#?=zux|oz퐗G^=b6\g{W;\w*kS1[ ʛZ S1S۴*V_s@{7L+oÞ;mɔm Ły=ma۽[<{fȜ'>̵ +2zقE3FJ[Owʟ-/JLJ|ͪaG::(爈IQN Rپ}Dpw \ 'JNl":71G݁:;Nr}rĤ3KN&cO#D岞2zgh"fzU >:GrbJ"Rak|^gݝ3OQns(}@2_ ˧=I~t=yG# OGw~>NR+#C R6ͥdQz<+˫m}F\$zUv:BݗXUbf[1BwK4^$˻J?2&WBUo6W/ƯR~KqH~O4wMs+D:Y-h'n=^g.|p7 Y'Sz ,lnw!fXͫTUiچ v7g.x4:}ڜt:MF,!Lo`|&;V>N + xDe24:Yưp蠔]*٥2ӝ<|>yʫ'Q9 |]oit,T&wrO=_0;"d$X:iF|Yb54t{+"99(ch`uz h۲EfJMR6EdUzc$+~WC=Sp1mu cV̬H/NfK VCp * )eǫ;G]JLW=ڷ?5GTا7ץTneGzװ&YiЩ;h 0C΄ԤcHvl=)̛I_tuچ?,x29@,9[wi\ef#Aݦ܄Rߤ3P,3L}_ )i]8kZ8ɮ-9uE}fb{Nz$C&{cJ"w&ْj ';S8p+ÿָfUOaB=SJiI}IohvڇY^N1yI>nut˲EftsTlM) @5ӊ|9F :t3qt=YOR*~w <#^vd#;+ǟ]8}}5S^~\pKg:i7PN_ĥߺLo73$ք˯gfx#֛!cYk~8cɁA`';?1GDs3$Z3hzFd_+ ;b@+;eg䖞> ݒWv=} ɯԁU:QP+ŲO]ܓէL|)9rw~VA+܉χ#4ZU:q)˜ot-"",==w~a59_(~eDEªID$s)ڽKojť&-]r8mP1:X?Q+fSķ[jtu}=Zp1.ى_y+|W=Ůo/V 䊎^mw3`[Um= R}ۦ) gNz6C.fֶmM|b=IkKkzacQ}g%yGHEz囈skYR* 'rwCUkgg$gVru 3%'GwsK`5EvR1R#ߢAuw(7%)qČɸˁSU> \e3 4]4UדHZ =tzW*f"3i>Vjd*Inբj8W~Pi]OUqbMU2:UG*fֳʗ#mJ-˺^qJ)B,mL|ɖ] F= 2pMl3dL9 5 E5u!\ۘbHoL MǥJ_{>0W9!%1DŽemӏ-6*v[8EV|ln[mu!*ՀƊ3te3`hԂj b49Z|@"D @"D` (\ޡ۟?M/־͋,gh+`%!zmU @u^b9ڜlCh% ӡF.YQ-yO^?ep wKמٜg\ϩ9fʢNڶ+l1XG xݱ˻CG>\i)?u$6'&CMkG*mTf[5 <7Ǹl =wFԭf'd@cKcg*M^K~tP3k7̗Ѕ͕푏ϊ-zXGY:N[M y=?'ҤF5B5k;_xs^vv<Ѷ'_l ͰFEٴs9ϜǝOrfohGfA1o{2Xa6\/joq'34Ҙ!dǖ.l''8l.y7swr!Qm"zOϟߍ*kzzǫJDjHWi3g;;KK͕nkW`Ȯ`\Ff궍0]zȰ,v9rMψ66 B~1t{A+;*~%| ;!)uR(W/T^68v~SDgB<3ƥԃqC%ޓ-W6UB>W"n97Ѹ80{`O>6ƹr+봖 6.zK7ޞ_3]F]%ߜ?4| "|&T~Xƃ"u+KHGo_67o#a'effy{gD]Ӈ /VHk#eK tM] !~~ttׇ^"y\߽ic{{o`N*b b;`Ii{  Ks) /]Dtp@z_+>p[["n}1]}=E6_8A;šz>,>OaLh1(3 poUyƸ$n\wR=0{yCΕC2+joqDw8GZ|l:CsYT>~B9Bj=0.;M6C tMQ< tph[Ύ?yr[ez(/@#a*QuDpAR{.|^/y\oNEn[`妮EU> t~p%%Vg,Bwt\JJAk:?!=ϭ[_}|菛tSӻܢ:O?a#GmcHH⃀4xb՘3,8AU4.fO9Czq`gq`XgB9NVfxwtgδaGLy/sg}[*]3w}G"Ci,|{R>Br[/F ox^}G/_]p5NRSuuF!쳽3JWvJޮOuHry'π~sY !ljCV-!wWG>/ !5qG=}WxOgOu?yn??}NSׇ^{nuPpuS+y׮Ý <\7w{^-0 U: .yP\M*p8xLt-p -*o gR•w 5HT\#ვ#IyKj_D|m&C=aibxMy̍ΒV y)r֔Cww(rݷYB&>+wg_z7nKcumVA5e`(:QŕD]DnsĄmiTd;t,ŧ{N3 "V ;*&/c\QGmZrJ|xz-ߣ|dR8zsjܼ & cp*=O;DBR5yVZ W"Mu/3bvqfr=NC'[r&d%jl7]^n<4zaCJ9D6Nj65K7z4):vquR6W~M74S @" dNn<TF|,6@"@}F>?:U{T7AV^=wъf|[[slX7с)9?iR1?MC d=utṞ7m; ˨]qC3ï.Ή ѮrlѥԹKΛtX–Y&|ӕ.rn4CR}D͎V)'qܷ pu>6[J4kihIDAT.笹$,OF3_0DTz>@+]Pp `D4@,99!"Ld6CMׂsD $y˻e h"=.C(HG=dRw?8NA@<3Al$G|3:33xs 3˽㉨-& 󻣡(Q&y8|lɬd: XͮeԮ830H(;䥸J y:3hh`}68Nl$ ~Cwt\xrio|>kwn-+ F):ػ@|l=*TZvr#!J+۰ם%4]F$W!* b\W@ *mN1%V42'3Yyc}K{pHR9iexVqу*ZyUe'pV)"-qٱPyqx=EDgNFJgY8 UݮMF,?n>rFϴ]! yzTyfDKhKѾsfzɍ1Gqyu# PTpRL"D.-)gy1h(JkȻ KB<3,,k@fc3/*Y~iՔUoT.MNZV^.)5C4I4䣆 dTшhy(yT+|DDJJH1m$C4| X9O^L"Z#Wn .3$_V̶K^'d~*L^ y zFM滩&rʉ{`p<M& 1$J GvC;ODVdgn'Z*:$""MQhRuhNq\FhYZ Z#'"%T/QKDO9iDDA?A|!I6SiZE+ ʣq>QZ9Kޡͫvg[v$ry{YuPIUu̴9jy7 mz@CT{sBe q5~ޤNA:n&IENDB`ionelmc-pytest-benchmark-5edf251/docs/spelling_wordlist.txt000066400000000000000000000001551471041671100242730ustar00rootroot00000000000000builtin builtins classmethod staticmethod classmethods staticmethods args kwargs callstack Changelog Indices ionelmc-pytest-benchmark-5edf251/docs/usage.rst000066400000000000000000000316701471041671100216320ustar00rootroot00000000000000===== Usage ===== This plugin provides a `benchmark` fixture. This fixture is a callable object that will benchmark any function passed to it. Example: .. code-block:: python def something(duration=0.000001): """ Function that needs some serious benchmarking. """ time.sleep(duration) # You may return anything you want, like the result of a computation return 123 def test_my_stuff(benchmark): # benchmark something result = benchmark(something) # Extra code, to verify that the run completed correctly. # Sometimes you may want to check the result, fast functions # are no good if they return incorrect results :-) assert result == 123 You can also pass extra arguments: .. code-block:: python def test_my_stuff(benchmark): benchmark(time.sleep, 0.02) Or even keyword arguments: .. code-block:: python def test_my_stuff(benchmark): benchmark(time.sleep, duration=0.02) Another pattern seen in the wild, that is not recommended for micro-benchmarks (very fast code) but may be convenient: .. code-block:: python def test_my_stuff(benchmark): @benchmark def something(): # unnecessary function call time.sleep(0.000001) A better way is to just benchmark the final function: .. code-block:: python def test_my_stuff(benchmark): benchmark(time.sleep, 0.000001) # way more accurate results! If you need to do fine control over how the benchmark is run (like a `setup` function, exact control of `iterations` and `rounds`) there's a special mode - pedantic_: .. code-block:: python def my_special_setup(): ... def test_with_setup(benchmark): benchmark.pedantic(something, setup=my_special_setup, args=(1, 2, 3), kwargs={'foo': 'bar'}, iterations=10, rounds=100) Commandline options =================== ``py.test`` command-line options: --benchmark-min-time=SECONDS Minimum time per round in seconds. Default: '0.000005' --benchmark-max-time=SECONDS Maximum run time per test - it will be repeated until this total time is reached. It may be exceeded if test function is very slow or --benchmark-min-rounds is large (it takes precedence). Default: '1.0' --benchmark-min-rounds=NUM Minimum rounds, even if total time would exceed `--max- time`. Default: 5 --benchmark-timer=FUNC Timer to use when measuring time. Default: 'time.perf_counter' --benchmark-calibration-precision=NUM Precision to use when calibrating number of iterations. Precision of 10 will make the timer look 10 times more accurate, at a cost of less precise measure of deviations. Default: 10 --benchmark-warmup=[KIND] Activates warmup. Will run the test function up to number of times in the calibration phase. See `--benchmark-warmup-iterations`. Note: Even the warmup phase obeys --benchmark-max-time. Available KIND: 'auto', 'off', 'on'. Default: 'auto' (automatically activate on PyPy). --benchmark-warmup-iterations=NUM Max number of iterations to run in the warmup phase. Default: 100000 --benchmark-disable-gc Disable GC during benchmarks. --benchmark-skip Skip running any tests that contain benchmarks. --benchmark-disable Disable benchmarks. Benchmarked functions are only ran once and no stats are reported. Use this is you want to run the test but don't do any benchmarking. --benchmark-enable Forcibly enable benchmarks. Use this option to override --benchmark-disable (in case you have it in pytest configuration). --benchmark-only Only run benchmarks. This overrides --benchmark-skip. --benchmark-save=NAME Save the current run into 'STORAGE-PATH/counter- NAME.json'. Default: '__