pax_global_header00006660000000000000000000000064134350166240014516gustar00rootroot0000000000000052 comment=ee0c44f7fc277393fb7197817109192051a1fa15 pipx-0.12.3.1/000077500000000000000000000000001343501662400127205ustar00rootroot00000000000000pipx-0.12.3.1/.flake8000066400000000000000000000001301343501662400140650ustar00rootroot00000000000000[flake8] max-line-length = 88 ignore = E501, E203 # line length, whitespace before ':' pipx-0.12.3.1/.gitignore000066400000000000000000000001141343501662400147040ustar00rootroot00000000000000*egg* .mypy_cache .vscode build dist activate __pypackages__ venv .DS_Store pipx-0.12.3.1/.travis.yml000066400000000000000000000005561343501662400150370ustar00rootroot00000000000000language: python sudo: required python: - "3.6" # - "3.7" install: - pip install .[dev] script: - python -m unittest tests.test_pipx.PipxStaticTests.test_static # TODO figure out how to make this run on travis # (https://github.com/pipxproject/pipx/issues/25) # - python setup.py test cache: pip: true yarn: true directories: - node_modules pipx-0.12.3.1/CHANGELOG.md000066400000000000000000000053561343501662400145420ustar00rootroot000000000000000.12.3.0 * Add `--include-deps` argument to include binaries of dependent packages when installing with pipx. This improves compatibility with packages that depend on other installed packages, such as `jupyter`. * Speed up `pipx list` output (by running multiple processes in parallel) and by collecting all metadata in a single subprocess call * More aggressive cache directory removal when `--no-cache` is passed to `pipx run` * [dev] Move inline text passed to subprocess calls to their own files to enable autoformating, linting, unit testing 0.12.2.0 * Add support for PEP 582's `__pypackages__` (experimental). `pipx run BINARY` will first search in `__pypackages__` for binary, then fallback to installing from PyPI. `pipx run --pypackages BINARY` will raise an error if the binary is not found in `__pypackages__`. * Fix regression when installing with `--editable` flag (#93) * [dev] improve unit tests 0.12.1.0 * Cache and reuse temporary Virtual Environments created with `pipx run` (#61) * Update binary discovery logic to find "scripts" like awscli (#91) * Forward `--pip-args` to the pip upgrade command (previously the args were forwarded to install/upgrade commands for packages) (#77) * When using environment variable PIPX_HOME, Virtual Environments will now be created at `$PIPX_HOME/venvs` rather than at `$PIPX_HOME`. * [dev] refactor into multiple files, add more unit tests 0.12.0.4 * Fix parsing bug in pipx run 0.12.0.3 * list python2 as supported language so that pip installs with python2 will no longer install the pipx on PyPI from the original pipx owner. Running pipx with python2 will fail, but at least it will not be as confusing as running the pipx package from the original owner. 0.12.0.2 * forward arguments to run command correctly #90 0.12.0.1 * stop using unverified context #89 0.12.0.0 * Change installation instructions to use `pipx` PyPI name * Add `ensurepath` command 0.11.0.2 * add version argument parsing back in (fixes regression) 0.11.0.1 * add version check, command check, fix printed version update installation instructions 0.11.0.0 * Replace `pipx BINARY` with `pipx run BINARY` to run a binary in an ephemeral environment. This is a breaking API change so the major version has been incremented. (Issue #69) * upgrade pip when upgrading packages (Issue #72) * support --system-site-packages flag (Issue #64) 0.10.4.1 * Fix version printed when `pipx --version` is run 0.10.4.0 * Add --index-url, --editable, and --pip-args flags * Updated README with pipsi migration instructions 0.10.3.0 * Display python version in list * Do not reinstall package if already installed (added `--force` flag to override) * When upgrading all packages, print message only when package is updated * Avoid accidental execution of pipx.__main__ pipx-0.12.3.1/LICENSE000066400000000000000000000050521343501662400137270ustar00rootroot00000000000000MIT License Copyright (c) 2018 Chad Smith Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Copyright (c) 2014 by Armin Ronacher. Some rights reserved. Redistribution and use in source and binary forms of the software as well as documentation, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION 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 OWNER 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 AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pipx-0.12.3.1/MANIFEST.in000066400000000000000000000001121343501662400144500ustar00rootroot00000000000000include README.md LICENSE include get-pipx.py recursive-include pipx *.py pipx-0.12.3.1/README.md000066400000000000000000000636251343501662400142130ustar00rootroot00000000000000

# pipx: execute binaries from Python packages in isolated environments

Code style: black

*For comparison to pipsi, see [how does this compare to pipsi?](#how-does-this-compare-to-pipsi) and [migrating to pipx from pipsi](#migrating-to-pipx-from-pipsi).* *pipx uses the word "binary" to describe a CLI application that can be run directly from the command line. These files are located in the `bin` directory of a Python installation, alongside other executables. Despite the name, they do not necessarily contain binary data.* ## Overview * Safely install packages to isolated virtual environments, while globally exposing their CLI applications so you can run them from anywhere * Easily list, upgrade, and uninstall packages that were installed with pipx * Run the latest version of a CLI application from a package in a temporary virtual environment, leaving your system untouched after it finishes * Run binaries from the `__pypackages__` directory per PEP 582 as companion tool to [pythonloc](https://github.com/cs01/pythonloc) * Runs with regular user permissions, never calling `sudo pip install ...` (you aren't doing that, are you? 😄). pipx combines the features of JavaScript's [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) - which ships with npm - and Python's [pipsi](https://github.com/mitsuhiko/pipsi). pipx does not ship with pip but it is an important part of bootstrapping your system. ### Safely installing to isolated environments You can globally install a CLI application by running ``` pipx install PACKAGE ``` This automatically creates a virtual environment, installs the package, and adds the package's CLI entry points to a location on your `PATH`. For example, `pipx install cowsay` makes the `cowsay` command available globally, but sandboxes the cowsay package in its own virtual environment. **pipx never needs to run as sudo to do this.** Example: ``` >> pipx install cowsay installed package cowsay 2.0, Python 3.6.7 These binaries are now globally available - cowsay done! ✨ 🌟 ✨ >> pipx list venvs are in /home/user/.local/pipx/venvs binaries are exposed on your $PATH at /home/user/.local/bin package cowsay 2.0, Python 3.6.7 - cowsay >> cowsay moooo _____ < moooo > ===== \ \ ^__^ (oo)\_______ (__)\ )\/ ||----w | || || ``` ### Running in temporary, sandboxed environments pipx makes running the latest version of a program in a temporary environment as easy as ``` pipx run BINARY [ARGS...] ``` This will install the package in an isolated, temporary directory and invoke the binary. Try it! ``` pipx run cowsay moo ``` Notice that you **don't need to execute any install commands to run the binary**. Re-running the same binary is quick because pipx caches Virtual Environments on a per-binary basis. These caches last two days. You can run .py files directly, too. ``` pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py pipx is working! ``` ## Testimonials "Thanks for improving the workflow that pipsi has covered in the past. Nicely done!" — [Jannis Leidel](https://twitter.com/jezdez) PSF fellow and former pip maintainer "Just the “pipx upgrade-all” command is already a huge win over pipsi" — [Stefane Fermigier](https://twitter.com/sfermigier/status/1093073303521116160) "This tool filled in the gap that was missing with pipenv and Virtual Environmentwrapper." — [Mason Egger](https://medium.com/homeaway-tech-blog/simplify-your-python-developer-environment-aba90f32dddb) ### System Requirements python 3.6+ is required to install pipx. pipx can run binaries from packages with Python 3.3+. Don't have Python 3.6 or later? See [Python 3 Installation & Setup Guide](https://realpython.com/installing-python/). pipx works on macOS, linux, and Windows. ## Install pipx ``` pip install --user pipx pipx ensurepath ``` to be sure you are using python3 you can run ``` python3 -m pip install --user pipx pipx ensurepath ``` ## Usage ``` pipx --help usage: pipx [-h] [--version] {install,inject,upgrade,upgrade-all,uninstall,uninstall-all,reinstall-all,list,run,ensurepath} ... Install and execute binaries from Python packages. Binaries can either be installed globally into isolated Virtual Environments or run directly in an temporary Virtual Environment. Virtual Envrionment location is /Users/$USER/.local/pipx/venvs. Symlinks to binaries are placed in /Users/$USER/.local/bin. These locations can be overridden with the environment variables PIPX_HOME and PIPX_BIN_DIR, respectively. (Virtual Environments will be installed to $PIPX_HOME/venvs) optional arguments: -h, --help show this help message and exit --version Print version and exit subcommands: Get help for commands with pipx COMMAND --help {install,inject,upgrade,upgrade-all,uninstall,uninstall-all,reinstall-all,list,run,ensurepath} install Install a package inject Install packages into an existing Virtual Environment upgrade Upgrade a package upgrade-all Upgrade all packages. Runs `pip install -U ` for each package. uninstall Uninstall a package uninstall-all Uninstall all packages reinstall-all Reinstall all packages with a different Python executable list List installed packages run Either download the latest version of a package to temporary directory, then run a binary from it, or invoke binary from local `__pypackages__` directory (expiremental, see https://github.com/cs01/pythonloc) ensurepath Ensure /Users/$USER/.local/bin is on your PATH environment variable by modifying your shell's configuration file. ``` ### pipx install ``` pipx install --help usage: pipx install [-h] [--spec SPEC] [--include-deps] [--verbose] [--force] [--python PYTHON] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] package The install command is the preferred way to globally install binaries from python packages on your system. It creates an isolated virtual environment for the package, then ensures the package's binaries are accessible on your $PATH. The result: binaries you can run from anywhere, located in packages you can cleanly upgrade or uninstall. Guaranteed to not have dependency version conflicts or interfere with your OS's python packages. 'sudo' is not required to do this. pipx install PACKAGE pipx install --python PYTHON PACKAGE pipx install --spec VCS_URL PACKAGE pipx install --spec ZIP_FILE PACKAGE pipx install --spec TAR_GZ_FILE PACKAGE The argument to `--spec` is passed directly to `pip install`. The default virtual environment location is /Users/$USER/.local/pipx and can be overridden by setting the environment variable `PIPX_HOME` (Virtual Environments will be installed to `$PIPX_HOME/venvs`). The default binary location is /Users/$USER/.local/bin and can be overridden by setting the environment variable `PIPX_BIN_DIR`. positional arguments: package package name optional arguments: -h, --help show this help message and exit --spec SPEC The package name or specific installation source passed to pip. Runs `pip install -U SPEC`. For example `--spec mypackage==2.0.0` or `--spec git+https://github.com/user/repo.git@branch` --include-deps Include binaries of dependent packages --verbose --force Install even when the package has already been installed --python PYTHON The Python executable used to create the Virtual Environment and run the associated binary/binaries. Must be v3.3+. --system-site-packages Give the virtual environment access to the system site-packages dir. --index-url INDEX_URL, -i INDEX_URL Base URL of Python Package Index --editable, -e Install a project in editable mode --pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip install/upgrade commands ``` #### `pipx install` examples ``` pipx install cowsay pipx install --python python3.6 cowsay pipx install --python python3.7 cowsay pipx install --spec git+https://github.com/ambv/black black pipx --spec git+https://github.com/ambv/black.git@branch-name black pipx --spec git+https://github.com/ambv/black.git@git-hash black pipx install --spec https://github.com/ambv/black/archive/18.9b0.zip black pipx install --spec black[d] black pipx install --include-deps jupyter ``` ### pipx run ``` pipx run --help usage: pipx run [-h] [--no-cache] [--pypackages] [--spec SPEC] [--verbose] [--python PYTHON] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] binary [binary_args [binary_args ...]] Either download the latest version of a package to temporary directory then run a binary from it, or invoke a binary from local `__pypackages__` directory. If running from a temporary environment, the environment will be cached and re-used for up to 2 days. This means subsequent calls to 'run' for the same package will be faster since they can re-use the cached Virtual Environment. In support of PEP 582 'run' will use binaries found in a local __pypackages__ directory, if present. Please note that this behavior is experimental, and is a acts as a companion tool to pythonloc. It may be modified or removed in the future. positional arguments: binary binary/package name binary_args arguments passed to the binary when it is invoked optional arguments: -h, --help show this help message and exit --no-cache Do not re-use cached virtual environment if it exists --pypackages Require binary to be run from local __pypackages__ directory --spec SPEC The package name or specific installation source passed to pip. Runs `pip install -U SPEC`. For example `--spec mypackage==2.0.0` or `--spec git+https://github.com/user/repo.git@branch` --verbose --python PYTHON The Python version to run package's CLI binary with. Must be v3.3+. --system-site-packages Give the virtual environment access to the system site-packages dir. --index-url INDEX_URL, -i INDEX_URL Base URL of Python Package Index --editable, -e Install a project in editable mode --pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip install/upgrade commands ``` #### `pipx run` examples pipx enables you to test various combinations of Python versions and package versions in ephemeral environments: ``` pipx run BINARY # latest version of binary is run with python3 pipx --spec PACKAGE==2.0.0 run BINARY # specific version of package is run pipx --python 3.4 run BINARY # Installed and invoked with specific Python version pipx --python 3.7 --spec PACKAGE=1.7.3 run BINARY pipx --spec git+https://url.git run BINARY # latest version on master is run pipx --spec git+https://url.git@branch run BINARY pipx --spec git+https://url.git@hash run BINARY pipx run cowsay moo pipx --version # prints pipx version pipx run cowsay --version # prints cowsay version pipx --python pythonX cowsay pipx --spec cowsay==2.0 cowsay --version pipx --spec git+https://github.com/ambv/black.git black pipx --spec git+https://github.com/ambv/black.git@branch-name black pipx --spec git+https://github.com/ambv/black.git@git-hash black pipx --spec https://github.com/ambv/black/archive/18.9b0.zip black --help pipx https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py ``` ### pipx upgrade ``` pipx upgrade --help usage: pipx upgrade [-h] [--spec SPEC] [--include-deps] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] [--verbose] package Upgrade a package in a pipx-managed Virtual Environment by running 'pip install --upgrade PACKAGE' positional arguments: package optional arguments: -h, --help show this help message and exit --spec SPEC The package name or specific installation source passed to pip. Runs `pip install -U SPEC`. For example `--spec mypackage==2.0.0` or `--spec git+https://github.com/user/repo.git@branch` --include-deps Include binaries of dependent packages --system-site-packages Give the virtual environment access to the system site-packages dir. --index-url INDEX_URL, -i INDEX_URL Base URL of Python Package Index --editable, -e Install a project in editable mode --pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip install/upgrade commands --verbose ``` ### pipx upgrade-all ``` pipx upgrade-all --help usage: pipx upgrade-all [-h] [--include-deps] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] [--verbose] Upgrades all packages within their virtual environments by running 'pip install --upgrade PACKAGE' optional arguments: -h, --help show this help message and exit --include-deps Include binaries of dependent packages --system-site-packages Give the virtual environment access to the system site-packages dir. --index-url INDEX_URL, -i INDEX_URL Base URL of Python Package Index --editable, -e Install a project in editable mode --pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip install/upgrade commands --verbose ``` ### pipx inject ``` pipx inject --help usage: pipx inject [-h] [--include-binaries] [--include-deps] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] [--verbose] package dependencies [dependencies ...] Installs packages to an existing pipx-managed virtual environment. positional arguments: package Name of the existing pipx-managed Virtual Environment to inject into dependencies the packages to inject into the Virtual Environment optional arguments: -h, --help show this help message and exit --include-binaries Add binaries from the injected packages onto your PATH --include-deps Include binaries of dependent packages --system-site-packages Give the virtual environment access to the system site-packages dir. --index-url INDEX_URL, -i INDEX_URL Base URL of Python Package Index --editable, -e Install a project in editable mode --pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip install/upgrade commands --verbose ``` #### `pipx inject` example One use of the inject command is setting up a REPL with some useful extra packages. ``` pipx install ptpython pipx inject ptpython requests pendulum ``` After running the above commands, you will be able to import and use the `requests` and `pendulum` packages inside a `ptpython` repl. ### pipx uninstall ``` pipx uninstall --help usage: pipx uninstall [-h] [--verbose] package Uninstalls a pipx-managed Virtual Envrionment by deleting it and any files that point to its binaries. positional arguments: package optional arguments: -h, --help show this help message and exit --verbose ``` ### pipx uninstall-all ``` pipx uninstall-all --help usage: pipx uninstall-all [-h] [--verbose] Uninstall all pipx-managed packages optional arguments: -h, --help show this help message and exit --verbose ``` ### pipx reinstall-all ``` pipx reinstall-all --help usage: pipx reinstall-all [-h] [--include-deps] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] [--verbose] python Reinstalls all packages using a different version of Python. Packages are uninstalled, then installed with pipx install PACKAGE. This is useful if you upgraded to a new version of Python and want all your packages to use the latest as well. If you originally installed a package from a source other than PyPI, this command may behave in unexpected ways since it will reinstall from PyPI. positional arguments: python optional arguments: -h, --help show this help message and exit --include-deps Include binaries of dependent packages --system-site-packages Give the virtual environment access to the system site-packages dir. --index-url INDEX_URL, -i INDEX_URL Base URL of Python Package Index --editable, -e Install a project in editable mode --pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip install/upgrade commands --verbose ``` ### pipx list ``` pipx list --help usage: pipx list [-h] [--verbose] List packages and binariess installed with pipx optional arguments: -h, --help show this help message and exit --verbose ``` #### `pipx list` example ``` > pipx list venvs are in /Users/user/.local/pipx/venvs binaries are exposed on your $PATH at /Users/user/.local/bin package black 18.9b0, Python 3.7.0 - black - blackd package pipx 0.10.0, Python 3.7.0 - pipx ``` ### pipx ensurepath ``` pipx ensurepath --help usage: pipx ensurepath [-h] [--force] Ensure /Users/$USER/.local/bin is on your PATH environment variable by modifying your shell's configuration file. This only needs to be run once after initial installation if /Users/$USER/.local/bin is not already on your PATH. optional arguments: -h, --help show this help message and exit --force Add text to your shell's config file even if it looks like your PATH already has /Users/$USER/.local/bin ``` #### `pipx ensurepath` example ``` > pipx ensurepath Added /home/user/.local/bin to the PATH environment variable in /home/user/.bashrc Open a new terminal to use pipx ✨ 🌟 ✨ ``` ``` > pipx ensurepath Your PATH looks like it already is set up for pipx. Pass `--force` to modify the PATH. ``` ## Programs to try with pipx Here are some programs you can try out. If you've never used the program before, make sure you add the `--help` flag so it doesn't do something you don't expect. If you decide you want to install, you can run `pipx install PACKAGE` instead. ``` pipx install ansible # IT automation pipx run asciinema # Record and share your terminal sessions, the right way. pipx run black # uncompromising Python code formatter pipx --spec babel run pybabel # internationalizing and localizing Python applications pipx --spec chardet run chardetect # detect file encoding pipx run cookiecutter # creates projects from project templates pipx run create-python-package # easily create and publish new Python packages pipx run flake8 # tool for style guide enforcement pipx run gdbgui # browser-based gdb debugger pipx run hexsticker # create hexagon stickers automatically pipx run ipython # powerful interactive Python shell pipx run jupyter # web-based notebook environment for interactive computing pipx run pipenv # python dependency/environment management pipx run poetry # python dependency/environment/packaging management pipx run pylint # source code analyzer pipx run pyinstaller # bundles a Python application and all its dependencies into a single package pipx run pyxtermjs # fully functional terminal in the browser   pipx install shell-functools # Functional programming tools for the shell ``` ## How it Works When installing a package and its binaries (`pipx install package`) pipx will * create directory ~/.local/pipx/venvs/PACKAGE * create a Virtual Environment in ~/.local/pipx/venvs/PACKAGE * update the Virtual Environment's pip to the latest version * install the desired package in the Virtual Environment * exposes binaries at `~/.local/bin` that point to new binaries in `~/.local/pipx/venvs/PACKAGE/bin` (such as `~/.local/bin/black` -> `~/.local/pipx/venvs/black/bin/black`) * As long as `~/.local/bin/` is on your PATH, you can now invoke the new binaries globally When running a binary (`pipx run BINARY`), pipx will * Create a temporary directory (or reuse a cached virtual environment for this package) with a name based on a hash of the attributes that make the run reproducible. This includes things like the package name, spec, python version, and pip arguments. * create a Virtual Environment inside it with `python -m venv` * update pip to the latest version * install the desired package in the Virtual Environment * invoke the binary These are all things you can do yourself, but pipx automates them for you. If you are curious as to what pipx is doing behind the scenes, you can always pass the `--verbose` flag to see every single command and argument being run. ## Contributing To develop `pipx` first clone the repository, then create and activate a virtual environment. ``` python3 -m venv venv source venv/bin/activate ``` Next install pipx in "editable mode". ``` pip install -e . ``` Now make your changes and run `pipx` as you normally would. Your changes will be used as soon as they are saved. Make sure your changes pass tests by installing development dependencies ``` pip install -e .[dev] ``` then running tests ``` python setup.py test ``` If you added or modified any command line argument parsers, be sure to regenerate the README.md. ``` make docs ``` When finished, you can exit the virtual environment by running `deactivate` and remove the virtual environment with `rm -r venv`. ## How does this compare to pipsi? * pipx is under active development. pipsi is no longer maintained. * pipx and pipsi both install packages in a similar way * pipx always makes sure you're using the latest version of pip * pipx has the ability to run a binary in one line, leaving your system unchanged after it finishes (`pipx run BINARY`) where pipsi does not * pipx has the ability to recursively install binaries from dependent packagages * pipx adds more useful information to its output * pipx has more CLI options such as upgrade-all, reinstall-all, uninstall-all * pipx is more modern. It uses Python 3.6+, and the `venv` package in the Python3 standard library instead of the python 2 package `virtualenv`. * pipx works with Python homebrew installations while pipsi does not (at least on my machine) * pipx defaults to less verbose output * pipx allows you to see each command it runs by passing the --verbose flag * pipx prints emojies 😀 ## Migrating to pipx from pipsi Although `pipx` does not provide an automatic migration command, it is pretty easy to do it from the command-line: ```bash # install pipx with the recommended method pip install --user pipx pipx ensurepath # you may have to open a new terminal here for pipx to be on your PATH # migrate from pipsi to pipx pipsi list | grep 'Package ' | cut -d\" -f2 | \ while read -r p; do pipsi uninstall --yes "$p" # reinstall everything with python 3.6 pipx install --python python3.6 "$p" done # clean up rm -rf ~/.local/pipsi rm ~/.local/bin/pipsi ``` If you want to do this manually, you will have to remove pipsi's directory completely then reinstall everything with pipx. First remove pipsi's directory (this is its default) ``` rm -r ~/.local/pipsi ``` There will still be files in `~/.local/bin` that point to `~/.local/pipsi/venvs`. If you reinstall the same packages with `pipx`, the files will be overwritten with valid files that point to the new pipx directory in `~/.local/pipx/venvs`. You may also want to remove files in `~/.local/bin`, but be sure the files you delete there were created by pipsi. ## How does this compare with `pip-run`? [run with this](https://github.com/jaraco/pip-run) is focused on running **arbitrary Python code in ephemeral environments** while pipx is focused on running **Python binaries in ephemeral and non-ephemeral environments**. For example these two commands both install poetry to an ephemeral environment and invoke poetry with `--help`. ``` pipx run poetry --help pip-run poetry -- -m poetry --help ``` ## [Changelog](https://github.com/pipxproject/pipx/blob/master/CHANGELOG.md) ## Credits pipx was inspired by [pipsi](https://github.com/mitsuhiko/pipsi) and [npx](https://github.com/zkat/npx). ## Authors pipx was created and is maintained by [Chad Smith](https://github.com/cs01/). Contributions and feedback from * [Bjorn Neergaard](https://github.com/neersighted) * [Diego Fernandez](https://github.com/aiguofer) * [Shawn Hensley](https://github.com/sahensley) * [tkossak](https://github.com/tkossak)pipx-0.12.3.1/generate_readme.py000066400000000000000000000022701343501662400164020ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import subprocess from typing import Optional import getpass from pipx.main import __version__ from jinja2 import Environment, FileSystemLoader USER = getpass.getuser() def get_help(pipxcmd: Optional[str]) -> str: if pipxcmd: cmd = ["pipx", pipxcmd, "--help"] else: cmd = ["pipx", "--help"] helptext = ( subprocess.run(cmd, stdout=subprocess.PIPE, check=True) .stdout.decode() .replace(USER, "$USER") ) return f""" ``` {" ".join(cmd)} {helptext} ``` """ env = Environment(loader=FileSystemLoader("templates")) template = env.get_template("readme.md") cmd_help = { "usage": get_help(None), "ensurepath": get_help("ensurepath"), "install": get_help("install"), "upgrade": get_help("upgrade"), "upgradeall": get_help("upgrade-all"), "inject": get_help("inject"), "uninstall": get_help("uninstall"), "uninstallall": get_help("uninstall-all"), "reinstallall": get_help("reinstall-all"), "list": get_help("list"), "run": get_help("run"), "version": __version__ } with open("README.md", "wb") as f: f.write(template.render(**cmd_help).encode()) pipx-0.12.3.1/get-pipx.py000066400000000000000000000005361343501662400150330ustar00rootroot00000000000000#!/usr/bin/env python3 import sys def fail(msg): sys.stderr.write(msg + "\n") sys.stderr.flush() sys.exit(1) def main(): fail( "This installation method has been deprecated. " "See https://github.com/pipxproject/pipx for current installation " "instructions." ) if __name__ == "__main__": main() pipx-0.12.3.1/logo.png000066400000000000000000000127721343501662400143770ustar00rootroot00000000000000PNG  IHDRMzTXtRaw profile type exifxu C1CLTR7%ʏr;ee^B=.P&殹xRrlRYv7]10RѨY4Syc7?N, I iTXtXML:com.adobe.xmp ÛsBIT|d IDATx{p7 @Q0*VtEEmKmMlckUj'mmCmV e*)#Ubm$> Pa1@r{Eox%7wɰܜ={9g((((((((((((((((4̡c߀WFw[w+Ab*e errMt2 g5\6UOO;#{>"v/0d˽p8Ԣ8'ɿ ].J9,N >ȳ] I3Y(7z~\xYcnR\js@Txa $$Zw%e_pp ?$$|)|̌Wn8|) -LŃ#\j @Z$}-cw~g< ֈ.W;o0$?|k&Gс(*%|˖b0~cϏv@x[^ؖAUz اd֤Q,8pdkσWJH™fC]E^ 9X%1 Dw=1ZrvL)P KCJϤׅd&~aQOPˆ6t^7rºÛN=I !p&hI2/wFJbKo_z&g}Nlt/s֫y8 ޾̣} [CNl)9ZHXo(6CH]~4.bK%X/xo]s|q7øӿ/%Z I"so^R.ia}>E' mapK'Ml}̸3o#`ƿP#\@;7j-m?ql >(۽;f C=۳F_ÂgǠ- CMI6s_3{^9l ,7hApW+=$߾k=*\Iuǥ~dʙ9L0Uj~{]/,(pymDbz7U.?pG8[A(@<…v+.fۍl怙7DN!u4b13J*[7[` %upYԧZFڳ ]t.MCLL/Ol{fIoI$TcS1Ї1kDDnG󲵇FA6`eƗ v֕z]_{T[;

YzwW./%'-$"+qV죣 O8 ~%࿔9ҵ]+,@p&Lpn9'hwg@ز6ҮNt`¥b^t5lCE 1v(hw@io.=mO9 ǣ gD-]r#g#w";di눼T's9gݘh&Yʹ Ű}>5qF`[ gk ~#5Hwvd}@{M0ՅlčG1~N_wr+=GXHaer-]f^ f#] &(((((((((((((((((((J,kIENDB`pipx-0.12.3.1/makefile000066400000000000000000000004651343501662400144250ustar00rootroot00000000000000.PHONY: build publish docs test test: python setup.py test build: clean python -m pip install --upgrade --quiet setuptools wheel twine python setup.py --quiet sdist bdist_wheel publish: build python -m twine upload dist/* clean: rm -r build dist *.egg-info || true docs: python generate_readme.py pipx-0.12.3.1/pipx/000077500000000000000000000000001343501662400137005ustar00rootroot00000000000000pipx-0.12.3.1/pipx/Venv.py000066400000000000000000000111361343501662400151720ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import logging import pkgutil import subprocess from pathlib import Path from typing import Dict, List, NamedTuple, Sequence, Union from pipx.animate import animate from pipx.constants import DEFAULT_PYTHON from pipx.util import WINDOWS, PipxError, rmdir class PipxVenvMetadata(NamedTuple): binaries: List[str] binary_paths: List[Path] binaries_of_dependencies: List[str] binary_paths_of_dependencies: Dict[str, List[Path]] package_version: str python_version: str venv_metadata_inspector_raw = pkgutil.get_data("pipx", "venv_metadata_inspector.py") assert venv_metadata_inspector_raw is not None, ( "pipx could not find required file venv_metadata_inspector.py. " "Please report this error at https://github.com/pipxproject/pipx. Exiting." ) VENV_METADATA_INSPECTOR = venv_metadata_inspector_raw.decode("utf-8") class Venv: """Abstraction for a virtual environment with various useful methods for pipx""" def __init__( self, path: Path, *, verbose: bool = False, python: str = DEFAULT_PYTHON ) -> None: self.root = path self._python = python self.bin_path = path / "bin" if not WINDOWS else path / "Scripts" self.python_path = self.bin_path / ("python" if not WINDOWS else "python.exe") self.verbose = verbose self.do_animation = not verbose def create_venv(self, venv_args: List[str], pip_args: List[str]) -> None: with animate("creating virtual environment", self.do_animation): _run([self._python, "-m", "venv"] + venv_args + [str(self.root)]) ignored_args = ["--editable"] _pip_args = [arg for arg in pip_args if arg not in ignored_args] self.upgrade_package("pip", _pip_args) def remove_venv(self) -> None: rmdir(self.root) def install_package(self, package_or_url: str, pip_args: List[str]) -> None: with animate(f"installing package {package_or_url!r}", self.do_animation): if pip_args is None: pip_args = [] cmd = ["install"] + pip_args + [package_or_url] self._run_pip(cmd) def get_venv_metadata_for_package(self, package: str) -> PipxVenvMetadata: data = json.loads( subprocess.run( [ str(self.python_path), "-c", VENV_METADATA_INSPECTOR, package, str(self.bin_path), ], stdout=subprocess.PIPE, ).stdout.decode(), encoding="utf-8", ) data["binary_paths"] = [Path(p) for p in data["binary_paths"]] data["binaries_of_dependencies"] = [] for dep, raw_paths in data["binary_paths_of_dependencies"].items(): paths = [Path(raw_path) for raw_path in raw_paths] data["binary_paths_of_dependencies"][dep] = paths data["binaries_of_dependencies"] += [path.name for path in paths] if WINDOWS: windows_bin_paths = set() for binary in data["binary_paths"]: # windows has additional files staring with the same name that are required # to run the binary for win_exec in binary.parent.glob(f"{binary.name}*"): windows_bin_paths.add(win_exec) data["binary_paths"] = windows_bin_paths return PipxVenvMetadata(**data) def get_python_version(self) -> str: return ( subprocess.run([str(self.python_path), "--version"], stdout=subprocess.PIPE) .stdout.decode() .strip() ) def run_binary(self, binary: str, binary_args: List[str]): cmd = [str(self.bin_path / binary)] + binary_args try: return _run(cmd, check=False) except KeyboardInterrupt: pass def upgrade_package(self, package_or_url: str, pip_args: List[str]): self._run_pip(["install"] + pip_args + ["--upgrade", package_or_url]) def _run_pip(self, cmd): cmd = [self.python_path, "-m", "pip"] + cmd if not self.verbose: cmd.append("-q") return _run(cmd) def _run(cmd: Sequence[Union[str, Path]], check=True) -> int: """Run arbitrary command as subprocess""" cmd_str = " ".join(str(c) for c in cmd) logging.info(f"running {cmd_str}") # windows cannot take Path objects, only strings cmd_str_list = [str(c) for c in cmd] returncode = subprocess.run(cmd_str_list).returncode if check and returncode: raise PipxError(f"{cmd_str!r} failed") return returncode pipx-0.12.3.1/pipx/__init__.py000066400000000000000000000002421343501662400160070ustar00rootroot00000000000000import sys assert sys.version_info >= (3, 6, 0), ( "Python 3.6+ is required. See https://github.com/pipxproject/pipx " "for installation instructions" ) pipx-0.12.3.1/pipx/__main__.py000066400000000000000000000000751343501662400157740ustar00rootroot00000000000000from .main import cli if __name__ == "__main__": cli() pipx-0.12.3.1/pipx/animate.py000066400000000000000000000021641343501662400156730ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- from contextlib import contextmanager import sys from typing import Dict from threading import Thread from time import sleep @contextmanager def animate(message: str, do_animation: bool): animate = {"do_animation": do_animation, "message": message} t = Thread(target=print_animation, args=(animate,)) t.start() try: yield finally: animate["do_animation"] = False t.join(0) def print_animation(meta: Dict[str, bool]): if not sys.stdout.isatty(): return cur = "." longest_len = 0 sleep(1) while meta["do_animation"]: if cur == "": cur = "." elif cur == ".": cur = ".." elif cur == "..": cur = "..." else: cur = "" message = f"{meta['message']}{cur}" longest_len = max(len(message), longest_len) sys.stdout.write(" " * longest_len) sys.stdout.write("\r") sys.stdout.write(message) sys.stdout.write("\r") sleep(0.5) sys.stdout.write(" " * longest_len) sys.stdout.write("\r") pipx-0.12.3.1/pipx/colors.py000066400000000000000000000012171343501662400155540ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys USING_WINDOWS = os.name == "nt" PRINT_COLOR = not USING_WINDOWS and sys.stdout.isatty() class c: header = "\033[95m" blue = "\033[94m" green = "\033[92m" yellow = "\033[93m" red = "\033[91m" bold = "\033[1m" cyan = "\033[96m" underline = "\033[4m" end = "\033[0m" def mkcolorfunc(style): def stylize_text(x): if PRINT_COLOR: return f"{style}{x}{c.end}" else: return x return stylize_text bold = mkcolorfunc(c.bold) red = mkcolorfunc(c.red) cyan = mkcolorfunc(c.cyan) green = mkcolorfunc(c.green) pipx-0.12.3.1/pipx/commands.py000066400000000000000000000516011343501662400160560ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import datetime import distutils.spawn import hashlib import http.client import logging import multiprocessing import os import shlex import shutil import subprocess import textwrap import time import urllib.parse from pathlib import Path from shutil import which from typing import List, Optional from .animate import animate from .colors import bold, red from .constants import ( LOCAL_BIN_DIR, PIPX_PACKAGE_NAME, PIPX_VENV_CACHEDIR, TEMP_VENV_EXPIRATION_THRESHOLD_DAYS, ) from .emojies import hazard, sleep, stars from .util import ( WINDOWS, PipxError, get_pypackage_bin_path, mkdir, rmdir, run_pypackage_bin, ) from .Venv import Venv def run( binary: str, package_or_url: str, binary_args: List[str], python: str, pip_args: List[str], venv_args: List[str], pypackages: bool, verbose: bool, use_cache: bool, ): """Installs venv to temporary dir (or reuses cache), then runs binary from package """ if urllib.parse.urlparse(binary).scheme: if not binary.endswith(".py"): exit( "pipx will only execute binaries from the internet directly if " "they end with '.py'. To run from an SVN, try pipx --spec URL BINARY" ) logging.info("Detected url. Downloading and executing as a Python file.") content = _http_get_request(binary) try: exit(subprocess.run([str(python), "-c", content]).returncode) except KeyboardInterrupt: pass exit(0) elif which(binary): logging.warning( f"{hazard} {binary} is already on your PATH and installed at " f"{which(binary)}. Downloading and " "running anyway." ) if WINDOWS and not binary.endswith(".exe"): binary = f"{binary}.exe" logging.warning(f"Assuming binary is {binary!r} (Windows only)") pypackage_bin_path = get_pypackage_bin_path(binary) if pypackage_bin_path.exists(): logging.info( f"Using binary in local __pypackages__ directory at {str(pypackage_bin_path)}" ) return run_pypackage_bin(pypackage_bin_path, binary_args) if pypackages: raise PipxError( f"'--pypackages' flag was passed, but {str(pypackage_bin_path)!r} was " "not found. See https://github.com/cs01/pythonloc to learn how to " "install here, or omit the flag." ) venv_dir = _get_temporary_venv_path(package_or_url, python, pip_args, venv_args) venv = Venv(venv_dir) bin_path = venv.bin_path / binary _prepare_venv_cache(venv, bin_path, use_cache) if bin_path.exists(): logging.info(f"Reusing cached venv {venv_dir}") retval = venv.run_binary(binary, binary_args) else: logging.info(f"venv location is {venv_dir}") retval = _download_and_run( Path(venv_dir), package_or_url, binary, binary_args, python, pip_args, venv_args, verbose, ) if not use_cache: rmdir(venv_dir) return retval def _download_and_run( venv_dir: Path, package: str, binary: str, binary_args: List[str], python: str, pip_args: List[str], venv_args: List[str], verbose: bool, ): venv = Venv(venv_dir, python=python, verbose=verbose) venv.create_venv(venv_args, pip_args) venv.install_package(package, pip_args) if not (venv.bin_path / binary).exists(): binaries = venv.get_venv_metadata_for_package(package).binaries raise PipxError( f"{binary} not found in package {package}. Available binaries: " f"{', '.join(b for b in binaries)}" ) return venv.run_binary(binary, binary_args) def _get_temporary_venv_path( package_or_url: str, python: str, pip_args: List[str], venv_args: List[str] ): """Computes deterministic path using hashing function on arguments relevant to virtual environment's end state. Arguments used should result in idempotent virtual environment. (i.e. args passed to binary aren't relevant, but args passed to venv creation are.) """ m = hashlib.sha256() m.update(package_or_url.encode()) m.update(python.encode()) m.update("".join(pip_args).encode()) m.update("".join(venv_args).encode()) venv_folder_name = m.hexdigest()[0:15] # 15 chosen arbitrarily return Path(PIPX_VENV_CACHEDIR) / venv_folder_name def _is_temporary_venv_expired(venv_dir: Path): created_time_sec = venv_dir.stat().st_ctime current_time_sec = time.mktime(datetime.datetime.now().timetuple()) age = current_time_sec - created_time_sec expiration_threshold_sec = 60 * 60 * 24 * TEMP_VENV_EXPIRATION_THRESHOLD_DAYS return age > expiration_threshold_sec def _prepare_venv_cache(venv: Venv, bin_path: Path, use_cache: bool): venv_dir = venv.root if not use_cache and bin_path.exists(): logging.info(f"Removing cached venv {str(venv_dir)}") rmdir(venv_dir) _remove_all_expired_venvs() def _remove_all_expired_venvs(): for venv_dir in Path(PIPX_VENV_CACHEDIR).iterdir(): if _is_temporary_venv_expired(venv_dir): logging.info(f"Removing expired venv {str(venv_dir)}") rmdir(venv_dir) def _http_get_request(url: str): parts = urllib.parse.urlparse(url) conn = http.client.HTTPSConnection(parts.hostname) conn.request("GET", parts.path) response = conn.getresponse() if response.status != 200: raise PipxError(response.reason) return response.read().decode("utf-8") def upgrade( venv_dir: Path, package: str, package_or_url: str, pip_args: List[str], verbose: bool, *, upgrading_all: bool, include_deps: bool, ) -> int: """Returns nonzero if package was upgraded, 0 if version did not change""" if not venv_dir.is_dir(): raise PipxError( f"Package is not installed. Expected to find {str(venv_dir)}, " "but it does not exist." ) venv = Venv(venv_dir, verbose=verbose) old_version = venv.get_venv_metadata_for_package(package).package_version do_animation = not verbose try: with animate(f"upgrading pip for package {package_or_url!r}", do_animation): venv.upgrade_package("pip", pip_args) except Exception: logging.error("Failed to upgrade pip", exc_info=True) with animate(f"upgrading package {package_or_url!r}", do_animation): venv.upgrade_package(package_or_url, pip_args) new_version = venv.get_venv_metadata_for_package(package).package_version metadata = venv.get_venv_metadata_for_package(package) _expose_binaries_globally(LOCAL_BIN_DIR, metadata.binary_paths, package) if include_deps: for _, binary_paths in metadata.binary_paths_of_dependencies.items(): _expose_binaries_globally(LOCAL_BIN_DIR, binary_paths, package) if old_version == new_version: if upgrading_all: pass else: print( f"{package} is already at latest version {old_version} (location: {str(venv_dir)})" ) return 0 else: print( f"upgraded package {package} from {old_version} to {new_version} (location: {str(venv_dir)})" ) return 1 def upgrade_all( pipx_local_venvs: Path, pip_args: List[str], verbose: bool, *, include_deps: bool ): packages_upgraded = 0 num_packages = 0 for venv_dir in pipx_local_venvs.iterdir(): num_packages += 1 package = venv_dir.name if package == "pipx": package_or_url = PIPX_PACKAGE_NAME else: package_or_url = package try: packages_upgraded += upgrade( venv_dir, package, package_or_url, pip_args, verbose, upgrading_all=True, include_deps=include_deps, ) except Exception: logging.error(f"Error encountered when upgrading {package}") if packages_upgraded == 0: print( f"Versions did not change after running 'pip upgrade' for each package {sleep}" ) def install( venv_dir: Path, package: str, package_or_url: str, local_bin_dir: Path, python: str, pip_args: List[str], venv_args: List[str], verbose: bool, *, force: bool, include_deps: bool, ): try: exists = venv_dir.exists() and next(venv_dir.iterdir()) except StopIteration: exists = False if exists: if force: print(f"Installing to existing directory {str(venv_dir)!r}") else: raise PipxError( f"Not installing to existing directory {str(venv_dir)!r}. " "Pass '--force' to force installation" ) venv = Venv(venv_dir, python=python, verbose=verbose) venv.create_venv(venv_args, pip_args) try: venv.install_package(package_or_url, pip_args) except PipxError: venv.remove_venv() raise if venv.get_venv_metadata_for_package(package).package_version is None: venv.remove_venv() raise PipxError(f"Could not find package {package}. Is the name correct?") _run_post_install_actions(venv, package, local_bin_dir, venv_dir, include_deps) def _run_post_install_actions( venv: Venv, package: str, local_bin_dir: Path, venv_dir: Path, include_deps: bool ): metadata = venv.get_venv_metadata_for_package(package) if not include_deps and not metadata.binary_paths: for dep, dependent_binaries in metadata.binary_paths_of_dependencies.items(): print( f"Note: Dependent package '{dep}' contains {len(dependent_binaries)} binaries" ) for binary in dependent_binaries: print(f" - {binary.name}") venv.remove_venv() if len(metadata.binary_paths_of_dependencies.keys()): raise PipxError( f"No binaries associated with package {package}. " "Try again with '--include-deps' to include binaries of dependent packages." ) else: raise PipxError(f"No binaries associated with package {package}. ") _expose_binaries_globally(local_bin_dir, metadata.binary_paths, package) if include_deps: for _, binary_paths in metadata.binary_paths_of_dependencies.items(): _expose_binaries_globally(local_bin_dir, binary_paths, package) print(_get_package_summary(venv_dir, package=package, new_install=True)) random_binary_name: str if metadata.binaries: random_binary_name = metadata.binaries[0] else: random_binary_name = metadata.binaries_of_dependencies[0] _warn_if_not_on_path(local_bin_dir, random_binary_name) print(f"done! {stars}") def _warn_if_not_on_path(local_bin_dir: Path, binary: str): if not distutils.spawn.find_executable(binary): logging.warning( f"{hazard} Note: {str(local_bin_dir)!r} is not on your PATH environment " "variable. These binaries will not be globally accessible until " "your PATH is updated. Run `pipx ensurepath` to automatically add it, " "or manually modify your PATH in your shell's config file (i.e. ~/.bashrc)." ) def inject( venv_dir: Path, package: str, pip_args: List[str], *, verbose: bool, include_binaries: bool, include_deps: bool, ): if not venv_dir.exists() or not next(venv_dir.iterdir()): raise PipxError( textwrap.dedent( f"""\ Can't inject {package!r} into nonexistent Virtual Environment {str(venv_dir)!r}. Be sure to install the package first with pipx install {venv_dir.name!r} before injecting into it.""" ) ) venv = Venv(venv_dir, verbose=verbose) venv.install_package(package, pip_args) if venv.get_venv_metadata_for_package(package).package_version is None: raise PipxError(f"Could not find package {package}. Is the name correct?") if include_binaries: _run_post_install_actions(venv, package, LOCAL_BIN_DIR, venv_dir, include_deps) print(f"done! {stars}") def uninstall(venv_dir: Path, package: str, local_bin_dir: Path, verbose: bool): if not venv_dir.exists(): print(f"Nothing to uninstall for {package} 😴") binary = which(package) if binary: print( f"{hazard} Note: '{binary}' still exists on your system and is on your PATH" ) return venv = Venv(venv_dir, verbose=verbose) metadata = venv.get_venv_metadata_for_package(package) binary_paths = metadata.binary_paths for dep_paths in metadata.binary_paths_of_dependencies.values(): binary_paths += dep_paths for file in local_bin_dir.iterdir(): if WINDOWS: for b in binary_paths: if file.name == b.name: file.unlink() else: symlink = file for b in binary_paths: if symlink.exists() and b.exists() and symlink.samefile(b): logging.info(f"removing symlink {str(symlink)}") symlink.unlink() rmdir(venv_dir) print(f"uninstalled {package}! {stars}") def uninstall_all(pipx_local_venvs: Path, local_bin_dir: Path, verbose: bool): for venv_dir in pipx_local_venvs.iterdir(): package = venv_dir.name uninstall(venv_dir, package, local_bin_dir, verbose) def reinstall_all( pipx_local_venvs: Path, local_bin_dir: Path, python: str, pip_args: List[str], venv_args: List[str], verbose: bool, include_deps: bool, ): for venv_dir in pipx_local_venvs.iterdir(): package = venv_dir.name uninstall(venv_dir, package, local_bin_dir, verbose) package_or_url = package install( venv_dir, package, package_or_url, local_bin_dir, python, pip_args, venv_args, verbose, force=True, include_deps=include_deps, ) def _expose_binaries_globally( local_bin_dir: Path, binary_paths: List[Path], package: str ): if WINDOWS: _copy_package_binaries(local_bin_dir, binary_paths, package) else: _symlink_package_binaries(local_bin_dir, binary_paths, package) def _copy_package_binaries(local_bin_dir: Path, binary_paths: List[Path], package: str): for src_unresolved in binary_paths: src = src_unresolved.resolve() binary = src.name dest = Path(local_bin_dir / binary) if not dest.parent.is_dir(): mkdir(dest.parent) if dest.exists(): logging.warning(f"{hazard} Overwriting file {str(dest)} with {str(src)}") dest.unlink() shutil.copy(src, dest) def _symlink_package_binaries( local_bin_dir: Path, binary_paths: List[Path], package: str ): for b in binary_paths: binary = b.name symlink_path = Path(local_bin_dir / binary) if not symlink_path.parent.is_dir(): mkdir(symlink_path.parent) if symlink_path.exists(): if symlink_path.samefile(b): pass else: logging.warning( f"{hazard} File exists at {str(symlink_path)} and points " f"to {symlink_path.resolve()}. Not modifying." ) else: shadow = which(binary) try: symlink_path.symlink_to(b) except FileExistsError: pass if shadow: logging.warning( f"{hazard} Note: {binary} was already on your PATH at " f"{shadow}" ) def _get_package_summary( path: Path, *, package: str = None, new_install: bool = False ) -> str: venv = Venv(path) python_path = venv.python_path.resolve() if package is None: package = path.name metadata = venv.get_venv_metadata_for_package(package) if metadata.package_version is None: not_installed = red("is not installed") return f" package {bold(package)} {not_installed} in the venv {str(path)}" binaries = metadata.binaries + metadata.binaries_of_dependencies exposed_binary_paths = _get_exposed_binary_paths_for_package( venv.bin_path, binaries, LOCAL_BIN_DIR ) exposed_binary_names = sorted(p.name for p in exposed_binary_paths) unavailable_binary_names = sorted( set(metadata.binaries) - set(exposed_binary_names) ) return _get_list_output( metadata.python_version, python_path, metadata.package_version, package, new_install, exposed_binary_names, unavailable_binary_names, ) def _get_list_output( python_version: str, python_path: Path, package_version: str, package: str, new_install: bool, exposed_binary_names: List[str], unavailable_binary_names: List[str], ) -> str: output = [] output.append( f" {'installed' if new_install else ''} package {bold(shlex.quote(package))} {bold(package_version)}, {python_version}" ) if not python_path.exists(): output.append(f" associated python path {str(python_path)} does not exist!") if new_install and exposed_binary_names: output.append(" These binaries are now globally available") for name in exposed_binary_names: output.append(f" - {name}") for name in unavailable_binary_names: output.append(f" - {red(name)} (symlink not installed)") return "\n".join(output) def list_packages(pipx_local_venvs: Path): dirs = list(sorted(pipx_local_venvs.iterdir())) if not dirs: print(f"nothing has been installed with pipx {sleep}") return print(f"venvs are in {bold(str(pipx_local_venvs))}") print(f"binaries are exposed on your $PATH at {bold(str(LOCAL_BIN_DIR))}") with multiprocessing.Pool() as p: for package_summary in p.map(_get_package_summary, dirs): print(package_summary) def _get_exposed_binary_paths_for_package( bin_path: Path, package_binary_names: List[str], local_bin_dir: Path ): bin_symlinks = set() for b in local_bin_dir.iterdir(): try: # sometimes symlinks can resolve to a file of a different name # (in the case of ansible for example) so checking the resolved paths # is not a reliable way to determine if the symlink exists. # windows doesn't use symlinks, so the check is less strict. if WINDOWS and b.name in package_binary_names: is_same_file = True else: is_same_file = b.resolve().parent.samefile(bin_path) if is_same_file: bin_symlinks.add(b) except FileNotFoundError: pass return bin_symlinks def ensurepath(bin_dir: Path): shell = os.environ.get("SHELL", "") config_file: Optional[str] if "bash" in shell: config_file = "~/.bashrc" elif "zsh" in shell: config_file = "~/.zshrc" elif "fish" in shell: config_file = "~/.config/fish/config.fish" else: config_file = None if config_file: config_file = os.path.expanduser(config_file) if config_file and os.path.exists(config_file): with open(config_file, "a") as f: f.write("\n# added by pipx (https://github.com/pipxproject/pipx)\n") if "fish" in shell: f.write(f"set -x PATH {str(bin_dir)} $PATH\n\n") else: f.write(f'export PATH="{str(bin_dir)}{os.pathsep}$PATH"\n') print(f"Added {str(bin_dir)} to the PATH environment variable in {config_file}") print("") print(f"Open a new terminal to use pipx {stars}") else: if WINDOWS: print( textwrap.dedent( f""" Note {hazard}: To finish installation, {str(bin_dir)!r} must be added to your PATH environment variable. To do this, go to settings and type "Environment Variables". In the Environment Variables window edit the PATH variable by adding the following to the end of the value, then open a new terminal. ;{str(bin_dir)} """ ) ) else: print( textwrap.dedent( f""" Note: To finish installation, {str(bin_dir)!r} must be added to your PATH environemnt variable. To do this, add the following line to your shell config file (such as ~/.bashrc if using bash): export PATH={str(bin_dir)}:$PATH """ ) ) pipx-0.12.3.1/pipx/constants.py000066400000000000000000000010241343501662400162630ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys from pathlib import Path DEFAULT_PYTHON = sys.executable DEFAULT_PIPX_HOME = Path.home() / ".local/pipx" DEFAULT_PIPX_BIN_DIR = Path.home() / ".local/bin" PIPX_HOME = Path(os.environ.get("PIPX_HOME", DEFAULT_PIPX_HOME)).resolve() PIPX_LOCAL_VENVS = PIPX_HOME / "venvs" LOCAL_BIN_DIR = Path(os.environ.get("PIPX_BIN_DIR", DEFAULT_PIPX_BIN_DIR)).resolve() PIPX_VENV_CACHEDIR = PIPX_HOME / ".cache" PIPX_PACKAGE_NAME = "pipx" TEMP_VENV_EXPIRATION_THRESHOLD_DAYS = 2 pipx-0.12.3.1/pipx/emojies.py000066400000000000000000000003221343501662400157020ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from pipx.util import WINDOWS if WINDOWS: stars = "" hazard = "" sleep = "" else: stars = "✨ 🌟 ✨" hazard = "⚠️" sleep = "😴" pipx-0.12.3.1/pipx/main.py000066400000000000000000000402201343501662400151740ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import argparse import logging import os import shlex import sys import textwrap import urllib.parse from typing import Dict, List, Tuple from . import commands from .constants import ( DEFAULT_PYTHON, LOCAL_BIN_DIR, DEFAULT_PIPX_HOME, DEFAULT_PIPX_BIN_DIR, PIPX_LOCAL_VENVS, PIPX_VENV_CACHEDIR, TEMP_VENV_EXPIRATION_THRESHOLD_DAYS, ) from .util import PipxError, mkdir __version__ = "0.12.3.1" def print_version() -> None: print(__version__) SPEC_HELP = textwrap.dedent( """The package name or specific installation source passed to pip. Runs `pip install -U SPEC`. For example `--spec mypackage==2.0.0` or `--spec git+https://github.com/user/repo.git@branch` """ ) PIPX_DESCRIPTION = textwrap.dedent( f""" Install and execute binaries from Python packages. Binaries can either be installed globally into isolated Virtual Environments or run directly in an temporary Virtual Environment. Virtual Envrionment location is {str(PIPX_LOCAL_VENVS)}. Symlinks to binaries are placed in {str(LOCAL_BIN_DIR)}. These locations can be overridden with the environment variables PIPX_HOME and PIPX_BIN_DIR, respectively. (Virtual Environments will be installed to $PIPX_HOME/venvs) """ ) INSTALL_DESCRIPTION = f""" The install command is the preferred way to globally install binaries from python packages on your system. It creates an isolated virtual environment for the package, then ensures the package's binaries are accessible on your $PATH. The result: binaries you can run from anywhere, located in packages you can cleanly upgrade or uninstall. Guaranteed to not have dependency version conflicts or interfere with your OS's python packages. 'sudo' is not required to do this. pipx install PACKAGE pipx install --python PYTHON PACKAGE pipx install --spec VCS_URL PACKAGE pipx install --spec ZIP_FILE PACKAGE pipx install --spec TAR_GZ_FILE PACKAGE The argument to `--spec` is passed directly to `pip install`. The default virtual environment location is {DEFAULT_PIPX_HOME} and can be overridden by setting the environment variable `PIPX_HOME` (Virtual Environments will be installed to `$PIPX_HOME/venvs`). The default binary location is {DEFAULT_PIPX_BIN_DIR} and can be overridden by setting the environment variable `PIPX_BIN_DIR`. """ class LineWrapRawTextHelpFormatter(argparse.RawDescriptionHelpFormatter): def _split_lines(self, text, width): text = self._whitespace_matcher.sub(" ", text).strip() return textwrap.wrap(text, width) def get_pip_args(parsed_args: Dict): pip_args: List[str] = [] if parsed_args.get("index_url"): pip_args += ["--index-url", parsed_args["index_url"]] if parsed_args.get("editable"): pip_args += ["--editable"] if parsed_args.get("pip_args"): pip_args += shlex.split(parsed_args.get("pip_args", "")) return pip_args def get_venv_args(parsed_args: Dict): venv_args: List[str] = [] if parsed_args.get("system_site_packages"): venv_args += ["--system-site-packages"] return venv_args def run_pipx_command(args, binary_args: List[str]): setup(args) verbose = args.verbose if "verbose" in args else False pip_args = get_pip_args(vars(args)) venv_args = get_venv_args(vars(args)) if "package" in args: package = args.package if urllib.parse.urlparse(package).scheme: raise PipxError("Package cannot be a url") if "spec" in args and args.spec is not None: if urllib.parse.urlparse(args.spec).scheme: if "#egg=" not in args.spec: args.spec = args.spec + f"#egg={package}" venv_dir = PIPX_LOCAL_VENVS / package logging.info(f"Virtual Environment location is {venv_dir}") if args.command == "run": package_or_url = ( args.spec if ("spec" in args and args.spec is not None) else args.binary ) use_cache = not args.no_cache return commands.run( args.binary, package_or_url, binary_args, args.python, pip_args, venv_args, args.pypackages, verbose, use_cache, ) elif args.command == "install": package_or_url = ( args.spec if ("spec" in args and args.spec is not None) else package ) commands.install( venv_dir, package, package_or_url, LOCAL_BIN_DIR, args.python, pip_args, venv_args, verbose, force=args.force, include_deps=args.include_deps, ) elif args.command == "inject": if not args.include_binaries and args.include_deps: raise PipxError( "Cannot pass --include-deps if --use_binaries is not passed as well" ) for dep in args.dependencies: commands.inject( venv_dir, dep, pip_args, verbose=verbose, include_binaries=args.include_binaries, include_deps=args.include_deps, ) elif args.command == "upgrade": package_or_url = ( args.spec if ("spec" in args and args.spec is not None) else package ) commands.upgrade( venv_dir, package, package_or_url, pip_args, verbose, upgrading_all=False, include_deps=args.include_deps, ) elif args.command == "list": commands.list_packages(PIPX_LOCAL_VENVS) elif args.command == "uninstall": commands.uninstall(venv_dir, package, LOCAL_BIN_DIR, verbose) elif args.command == "uninstall-all": commands.uninstall_all(PIPX_LOCAL_VENVS, LOCAL_BIN_DIR, verbose) elif args.command == "upgrade-all": commands.upgrade_all( PIPX_LOCAL_VENVS, pip_args, verbose, include_deps=args.include_deps ) elif args.command == "reinstall-all": commands.reinstall_all( PIPX_LOCAL_VENVS, LOCAL_BIN_DIR, args.python, pip_args, venv_args, verbose, args.include_deps, ) elif args.command == "ensurepath": paths = os.getenv("PATH", "").split(os.pathsep) path_good = str(LOCAL_BIN_DIR) in paths if not path_good or args.force: commands.ensurepath(LOCAL_BIN_DIR) else: print( "Your PATH looks like it already is set up for pipx. Pass `--force` to modify the PATH." ) else: raise PipxError(f"Unknown command {args.command}") def add_pip_venv_args(parser): parser.add_argument( "--system-site-packages", action="store_true", help="Give the virtual environment access to the system site-packages dir.", ) parser.add_argument("--index-url", "-i", help="Base URL of Python Package Index") parser.add_argument( "--editable", "-e", help="Install a project in editable mode", action="store_true", ) parser.add_argument( "--pip-args", help="Arbitrary pip arguments to pass directly to pip install/upgrade commands", ) def add_include_deps(parser): parser.add_argument( "--include-deps", help="Include binaries of dependent packages", action="store_true", ) def get_command_parser(): parser = argparse.ArgumentParser( formatter_class=LineWrapRawTextHelpFormatter, description=PIPX_DESCRIPTION ) subparsers = parser.add_subparsers( dest="command", description="Get help for commands with pipx COMMAND --help" ) p = subparsers.add_parser( "install", help="Install a package", formatter_class=LineWrapRawTextHelpFormatter, description=INSTALL_DESCRIPTION, ) p.add_argument("package", help="package name") p.add_argument("--spec", help=SPEC_HELP) add_include_deps(p) p.add_argument("--verbose", action="store_true") p.add_argument( "--force", action="store_true", help="Install even when the package has already been installed", ) p.add_argument( "--python", default=DEFAULT_PYTHON, help=( "The Python executable used to create the Virtual Environment and run the " "associated binary/binaries. Must be v3.3+." ), ) add_pip_venv_args(p) p = subparsers.add_parser( "inject", help="Install packages into an existing Virtual Environment", description="Installs packages to an existing pipx-managed virtual environment.", ) p.add_argument( "package", help="Name of the existing pipx-managed Virtual Environment to inject into", ) p.add_argument( "dependencies", nargs="+", help="the packages to inject into the Virtual Environment", ) p.add_argument( "--include-binaries", action="store_true", help="Add binaries from the injected packages onto your PATH", ) add_include_deps(p) add_pip_venv_args(p) p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "upgrade", help="Upgrade a package", description="Upgrade a package in a pipx-managed Virtual Environment by running 'pip install --upgrade PACKAGE'", ) p.add_argument("package") p.add_argument("--spec", help=SPEC_HELP) add_include_deps(p) add_pip_venv_args(p) p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "upgrade-all", help="Upgrade all packages. " "Runs `pip install -U ` for each package.", description="Upgrades all packages within their virtual environments by running 'pip install --upgrade PACKAGE'", ) add_include_deps(p) add_pip_venv_args(p) p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "uninstall", help="Uninstall a package", description="Uninstalls a pipx-managed Virtual Envrionment by deleting it and any files that point to its binaries.", ) p.add_argument("package") p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "uninstall-all", help="Uninstall all packages", description="Uninstall all pipx-managed packages", ) p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "reinstall-all", formatter_class=LineWrapRawTextHelpFormatter, help="Reinstall all packages with a different Python executable", description=textwrap.dedent( """ Reinstalls all packages using a different version of Python. Packages are uninstalled, then installed with pipx install PACKAGE. This is useful if you upgraded to a new version of Python and want all your packages to use the latest as well. If you originally installed a package from a source other than PyPI, this command may behave in unexpected ways since it will reinstall from PyPI. """ ), ) p.add_argument("python") add_include_deps(p) add_pip_venv_args(p) p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "list", help="List installed packages", description="List packages and binariess installed with pipx", ) p.add_argument("--verbose", action="store_true") p = subparsers.add_parser( "run", formatter_class=LineWrapRawTextHelpFormatter, help="Either download the latest version of a package to temporary directory, " "then run a binary from it, or invoke binary from local `__pypackages__` " "directory (expiremental, see https://github.com/cs01/pythonloc)", description=textwrap.dedent( f""" Either download the latest version of a package to temporary directory then run a binary from it, or invoke a binary from local `__pypackages__` directory. If running from a temporary environment, the environment will be cached and re-used for up to {TEMP_VENV_EXPIRATION_THRESHOLD_DAYS} days. This means subsequent calls to 'run' for the same package will be faster since they can re-use the cached Virtual Environment. In support of PEP 582 'run' will use binaries found in a local __pypackages__ directory, if present. Please note that this behavior is experimental, and is a acts as a companion tool to pythonloc. It may be modified or removed in the future. """ ), ) p.add_argument( "--no-cache", action="store_true", help="Do not re-use cached virtual environment if it exists", ) p.add_argument("binary", help="binary/package name") p.add_argument( "binary_args", nargs="*", help="arguments passed to the binary when it is invoked", default=[], ) p.add_argument( "--pypackages", action="store_true", help="Require binary to be run from local __pypackages__ directory", ) p.add_argument("--spec", help=SPEC_HELP) p.add_argument("--verbose", action="store_true") p.add_argument( "--python", default=DEFAULT_PYTHON, help="The Python version to run package's CLI binary with. Must be v3.3+.", ) add_pip_venv_args(p) p = subparsers.add_parser( "ensurepath", help=( f"Ensure {str(LOCAL_BIN_DIR)} is on your PATH environment variable by modifying your shell's configuration file." ), description=( f"""Ensure {str(LOCAL_BIN_DIR)} is on your PATH environment variable by modifying your shell's configuration file. This only needs to be run once after initial installation if {str(LOCAL_BIN_DIR)} is not already on your PATH. """ ), ) p.add_argument( "--force", action="store_true", help=( "Add text to your shell's config file even if it looks like your " f"PATH already has {str(LOCAL_BIN_DIR)}" ), ) parser.add_argument("--version", action="store_true", help="Print version and exit") return parser def setup(args): if "version" in args and args.version: print_version() exit(0) if "verbose" in args and args.verbose: logging.basicConfig( level=logging.DEBUG, format="pipx (%(funcName)s:%(lineno)d): %(message)s" ) else: logging.basicConfig(level=logging.WARNING, format="%(message)s") mkdir(PIPX_LOCAL_VENVS) mkdir(LOCAL_BIN_DIR) mkdir(PIPX_VENV_CACHEDIR) old_pipx_venv_location = PIPX_LOCAL_VENVS / "pipx-app" if old_pipx_venv_location.exists(): logging.warning( "A virtual environment for pipx was detected at " f"{str(old_pipx_venv_location)}. The 'pipx-app' package has been renamed " "back to 'pipx' (https://github.com/pipxproject/pipx/issues/82)." ) def split_run_argv(argv: List[str]) -> Tuple[List[str], List[str]]: """If 'run' command is used, split between args passed to pipx and args to be forwarded to binary """ args_to_parse = argv[1:] binary_args: List[str] = [] if len(argv) >= 2: if argv[1] == "run": start = 2 for i, arg in enumerate(argv[start:]): if not arg.startswith("-"): offset = start + i + 1 args_to_parse = argv[1:offset] binary_args = argv[offset:] break return args_to_parse, binary_args def cli(): """Entry point from command line""" try: args_to_parse, binary_args = split_run_argv(sys.argv) parser = get_command_parser() parsed_pipx_args = parser.parse_args(args_to_parse) setup(parsed_pipx_args) if not parsed_pipx_args.command: parser.print_help() exit(1) exit(run_pipx_command(parsed_pipx_args, binary_args)) except PipxError as e: exit(e) except KeyboardInterrupt: exit(1) if __name__ == "__main__": cli() pipx-0.12.3.1/pipx/util.py000066400000000000000000000025731343501662400152360ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os from pathlib import Path import logging import shutil import subprocess import sys from typing import List class PipxError(Exception): pass try: WindowsError except NameError: WINDOWS = False else: WINDOWS = True def rmdir(path: Path): logging.info(f"removing directory {path}") if WINDOWS: os.system(f'rmdir /S /Q "{str(path)}"') else: shutil.rmtree(path) def mkdir(path: Path) -> None: if path.is_dir(): return logging.info(f"creating directory {path}") path.mkdir(parents=True, exist_ok=True) def get_pypackage_bin_path(binary_name: str) -> Path: return ( Path("__pypackages__") / (str(sys.version_info.major) + "." + str(sys.version_info.minor)) # noqa E503 / "lib" # noqa E503 / "bin" # noqa E503 / binary_name # noqa E503 ) def run_pypackage_bin(bin_path: Path, args: List[str]) -> int: def _get_env(): env = dict(os.environ) env["PYTHONPATH"] = os.path.pathsep.join( [".", str(bin_path.parent.parent)] + os.getenv("PYTHONPATH", "").split(os.path.pathsep) # noqa E503 ) return env try: return subprocess.run( [str(bin_path.resolve())] + args, env=_get_env() ).returncode except KeyboardInterrupt: return 1 pipx-0.12.3.1/pipx/venv_metadata_inspector.py000066400000000000000000000072441343501662400211650ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- from pathlib import Path import sys import json from typing import Dict, List, Optional def get_package_dependencies(package: str) -> List[str]: try: import pkg_resources except Exception: return [] return [str(r) for r in pkg_resources.get_distribution(package).requires()] def get_package_version(package: str) -> Optional[str]: try: import pkg_resources return pkg_resources.get_distribution(package).version except Exception: return None def get_binaries(package: str, bin_path: Path) -> List[str]: try: import pkg_resources except Exception: return [] dist = pkg_resources.get_distribution(package) binaries = set() for section in ["console_scripts", "gui_scripts"]: # "entry_points" entry in setup.py are found here for name in pkg_resources.get_entry_map(dist).get(section, []): binaries.add(name) if dist.has_metadata("RECORD"): # "scripts" entry in setup.py is found here (test w/ awscli) for line in dist.get_metadata_lines("RECORD"): entry = line.split(",")[0] # noqa: T484 path = (Path(dist.location) / entry).resolve() try: if path.parent.name == "scripts" in entry or path.parent.samefile( bin_path ): binaries.add(Path(entry).name) except FileNotFoundError: pass if dist.has_metadata("installed-files.txt"): # not sure what is found here for line in dist.get_metadata_lines("installed-files.txt"): entry = line.split(",")[0] # noqa: T484 path = (Path(dist.egg_info) / entry).resolve() # type: ignore try: if path.parent.samefile(bin_path): binaries.add(Path(entry).name) except FileNotFoundError: pass return sorted(binaries) def _dfs_package_binaries( bin_path: Path, package: str, binary_paths_of_dependencies: Dict[str, List[str]] ): dependencies = get_package_dependencies(package) for d in dependencies: binary_names = get_binaries(d, bin_path) if binary_names: binaries = [str(Path(bin_path) / binary) for binary in binary_names] binary_paths_of_dependencies[d] = binaries # recursively search for more binary_paths_of_dependencies = _dfs_package_binaries( bin_path, d, binary_paths_of_dependencies ) return binary_paths_of_dependencies def main(): package = sys.argv[1] bin_path = Path(sys.argv[2]) binaries = get_binaries(package, bin_path) binary_paths = [str(Path(bin_path) / binary) for binary in binaries] binary_paths_of_dependencies: Dict[str, List[str]] = {} binary_paths_of_dependencies = _dfs_package_binaries( bin_path, package, binary_paths_of_dependencies ) output = { "binaries": binaries, "binary_paths": binary_paths, "binary_paths_of_dependencies": binary_paths_of_dependencies, "package_version": get_package_version(package), "python_version": f"Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}", } print(json.dumps(output)) if __name__ == "__main__": try: main() except Exception: print( json.dumps( { "binaries": [], "binary_paths": [], "binary_paths_of_dependencies": {}, "package_version": None, "python_version": None, } ) ) pipx-0.12.3.1/pipx_demo.gif000066400000000000000000007326321343501662400154100ustar00rootroot00000000000000GIF89aw! NETSCAPE2.0!,   "! """''('('('(+++/0//000//0/000/333778878;;;??@HELIHDMIRNRNSPZU]YUQXTa\@>?@@?BBBIGGHGHKJJOOPOQQSSSWXWWXXXWWXWXXXW[[[__`_`__``a_a``^cccgghhgghghhhgkkkoqopoossswwxxwwxwxxxw{||,:=J$>)?'A(B)BEPHQHRVN^Vc\`WaYg`haic->.-EH-0Ɗܑڼᖑ㘓ϿͿˆk H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0_=&̛8s"Zh͚J#/X|q$ϠC[9(1cP%Zj5e'WT^+iWrz-ݷ}կ[q\Xaxcx%_y/fÞ9[y4ʋg6թ)Þ וLngz%sZ;8`go.cҨin>]:sїg_=ygWϚ|z7?լ뇥% \d,)eƂh!)PPa!P׮J ^[̦E[l$ .FN;QD!ŖNkmĠ! C@I:RI {"'qJ(;o;(rد ll*3¨m6|G4'è14jD?gaRJ*҅zuا*Q(v)vY``"u7hMxߥ}mxC>w?>9k9{>:'~9κO^{N;N<:ԁ) 01":`kӧwB F*'/O>_<t7x#` @t$h P^ #ԧ,0" ,E#ի%*LD%($0 gH8̡w@ k90F0VRiDbP @@.z` HFI҂(b8 (1AE =qK(>bQ&[( .v@O**J^" 7Nzd($bp#0^BR$Z򖸬 @J 0䶰5R!$rIjZԢ(хhk(Q0 # =* c6Izk!'Bx r @JЂMBІ:D' BuӢE>KaQaT(G&n(MJq NEK9!әҴ/LkS”a ;Xp 0-a1,c*Fi8'c ?1qXC1yd*OyW$wHf1˙\>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrN9̀DG|@4!o@Xö$4  Є 3 lGN~^ " Tk*AiX\> N.\^#!HCф9Є h6DӹuhOگ5wЁ7>AE֐9` ih: غy|A@>A3uםqGOқ,J:;0&@uy{}F<6@/:0Ο}#Ͼ}S'|Ё9w3P;\sp (?{'|P~gw釀O}8}7~V{qP Mo`qgWpru'w:!zJwhHP |G.w P||@.g3h8XWgXgrtDŽz|n~Hhgg{}8g{s؉h8Xx؊8Xxk VyhGi(h f|h 66~拉:=:j.x xX5X iExi8h ֎hhkЂcxh Dg׈|E )ihlhi||hi!y@iyh:@v|4yvwppWt p WMx&iFqWq =y7UxPypE x@L9u']WEigHooDo7o7p|֓p`9xI9h o+ "h@9pSg4t o/}֖)~ig"zhp$~ƚy{FL u9Ng䈓ȩj4yW vt4ttC'PuTx,ȋkg2@uSWurRgIɞ(ٞ{W}9$hɟ}r7s7M7s s>tBwtN*hptuFx.G *عJgosɐn2huPsZW~ hPD~FOtEף454$od7E* fj jcY wzx'puV| ywই'z| w o|}J q7:prr|yw4w}wC1|x}fCgtj+y~Ag~֪JhZ}W}Wg`~OEx̚xgy5xyЊo۪x:gwb|@{{`yGzh7ywK xС':;8[wrW{j{O}g| Yh-C}ا+|pK9|jt7{0Zh0+EP}iէBKEw~GZ|ɮ^ j$p;tʯ6~&|x[b;n}-xgur-uEGz ~~Gg~sƨJ hiʴDȭW: u= | P g[}w:hV8xE ɈgfYg_v -T*Xkyٕiy&8ȼ y˷;{'tI ֋!8%Ȟ+0(4gث:JoCȪ0{j8gR lPo?[wiZ}o{ &g3×cX"w^(aֵ~wtKe8&m*Dþigghhg9h.(h|&7b7|FL,h܈ͅx xǬ{ (j hhL̏Ύhh,m$9hLvxMVЃ8) ]}х "=ҕX m !M,Kh јP 6}ӣ?@h mҙ8Bnz +=J#Ӗp 1L=TkgSɖ^Ym U=dk*WS̜<ОN 霗H-e]vjmv|j 3M}׆}xz<kk& ӈ]ٖ=jK,`t* 0Mח]ڦ im~0& =۴hN]|_īZ OMڵ]ƽhͼg * 1}=ÁЕ0-h ={O-}h =]}>^~ >^~ ">$^&~(*,.02>4^6~8:<>@B>D^F~HJLNPR>T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^閞зP kpΗ.` Vʤ` nT.>P^䵀J>F^>䦎N@ A~ z-؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogС?0PiԩUfkرeϦ]mܹuo'^qɕ/m &ND !Fl>"w"ď'xէWߞ}ᣟ~/B~ Ͽ ?c0Ap0 0 //C@DC9Q,[n몫N:NXaGQ ҄R0H$D;RhҺ뢄2릤J)Բ-K.K0-R1MN5;ۤSHA3z^3mS2-*!!,:8  :::CCBIJIWVW^^]dddlklttu||| $ITEme;j驺.uQZitKYLW2" `X%&#HA`i0 u+aa,(H,?B)`c~")'w |sx2"D'J#(J(*!!,H8I0BR%i[`ZE0:L[1@(e0 `|36ƕbIk/*$!,O8 ! !+,,445>==FFFLMLWVX\\\fffjkjttti Uhe㥝ʊU6ջTLR" Tn(`($ A7KW + r 2jb#"hMFH&oF2v"1z:3q(zA*F@3&)*!!,V8 ,,,544;::KKKSSRWWXZZZaaahghlkltsu||}@pH$z<fYlrtz6eGSm.OngvF/ @!g- ,.HKgC Xz  C PCWXXsZ` BgCcKbiBeh_lBGI_A!,d8  !/0/555@@@NNNgggxwx|||v UQEYHيZiUF)f F $ D[ AHœdANA108 `M K %/'gb%:,3]G->e/B')+!!,k8 !!!+**444=<<@@@HIHTTTXYYmmnsss{{{t @UeٵUhbueVfҥ4oG\NEdh8_BL2YrX娕dDNڎDD$ldP pS;  zt#@-C9$RI . Ͻӫ_Ͼ˟O_=qp `ԀB8J@L Pgi?mnOCi\J=zO ZϠ*무j뭸k+PLC[K, (,L 6"-B J =. a[0`[;kj㍾,Lr22 j H0 q*,#-kƦLxi <$"Y!1aSL%e(4TLZeE; ?b^bEHAqӟP!<`Y3br!#s݉WVnYqv'\'tM;$< >߽:+xSpȠsN䔓#k *lY2NJ騧 0- )ΊHlŋX<҉I'!*@ bCNǦ3 i "Pݟr};&G@Iˎ۾+lz Ǣ @dG(NݢQ jGVA6B$Zv}̂H. 3TݥC4/H.t ֆ`-\l~9Et8.0~*^#$QW|f:\h=xBZfV3 pjSJ8z:`;Q%Ԧ.5;~<5,C"B*΀S!<`p枇 @ 0r0F/ݛPBh| $ "B(A1C 2!2/lrϊ;{QĈE7= ՎC(95lA۾73ϼ[ĈA؍<qӚEx9sW&~{ٴ3uq O^L!,"     -28  !6% """+++0//333;;;Y^#-Z@#B( O. \5@??C?l@@?}^aBBBGHGGHHHHGJJJJGUPOOSSSWXWXWX[[[jXN`__`^```_bbchghllllcuopossswwxwxwxwxxxv|{|7:)Eijk}zEJW[ [ be]\f }k n x&v z(™ЗٙŞ ͗$Ǣ$ף!Ҫ$خ# $1#!$,3·~)..84805:2@CZ\FipvcchźٸH*\ȰÇ#JHŋ3jȱǏ N A\ɲ˗0&xb(լXGE/2,X2%:CT-R"S4dHVXF XΝVS*UE*e LJDM.`nF1?^X!!Zt;4oE rc^, E6 6mx<rQh\o|6j%`z]Pvw't xnFxG D B 5"Q16  ~!@ zQC D$>T@'*p p)(W`&y Ux&䒣\U',Ih4rA mD(hJ\'B,咠HdW'bVbtڹ:ɚ} •Ynh g1Z@ C4 "`aхaGp!d %$ۍ]P)x;IT&yk(PIh,bcBBA+Н %A氫x߽[k0žIڱEL% Tv*3n&Ew0R(Mꟑ\3p !z}kw C2lؚ+6`w؞/(Q('"0Jς_O =:@߻.|f=ATB$$޺W7o"B9d6 ND  C萇=d {P|Y@'.P:|{K(`H|U|*`Jp"*(,IZ| _ qG,t!sH8D @>H*bX nx??ka@! m:̡ gp>/`X Nn؟ ɂIyWA!S} JD%6QPn"cA.PCRoȤIڭ*kJK#u1`c!gɰ]m'LNlJoV83 g.6Z($H@~t#e^ 0R @ƀ5 cp# 8JҒ$ A)E&D! IJj,5Nw1ħ< PJԢ2H]*T :PMR]TU(XͪV1Rծn` kBT4bMZjծupP_TVbΔ^ʑv*PU"/ةlC(Ŏ(+U%j:Rj5Ϛ6 &^PUBe=l @Tk"g[Ҁ aj[v֮dki\"UmsWJvTVX /Q!K,o;GFGGGHLLLOPPPOORPOSRRVXWWXXYWYXXWZ[Z^^``_```_cccmmmoopssszzz@.g kFNw[$qH*F093B{N= zb`$t!a!tg# ysay-g 40%n$ca&a"4 oa!r4- m4aņnta- a --$$(4(o40gr4'0 puݾy=8FbX 2bĀ€8 H1bVrbd-ntaŭ/> ہl={ V+n ۅL2q &P0-PBw0@ ne4, #2ТдZH"P$LX⁀ll[?@?@C?l@@?}^aBBBGHGGHHIGGHGHHHGJJJJGUOOPOQQPOOSSSWVXWXWWXXXWWXWXXXW[[[__`_`__``jXN`__`^```^cccgghhgghghhhgkkklcuopopootttwwxwxwxwwxwxxxv|||7:)Eijk},:=J$>)?'A(B)BEPHQHRzGZbe\f }m x&x WNh`(™Ԙɚ"Ǣ$թ# $-<#.!$-3·~EH)-15B[FisdƊźݒڼᖑǿͿٸˆo>{ӷ%K+x0l5sճQE*̨@W|IQE.$N-}9SP9a,ћEmj4&TR 4ϫ^vݺSfu{Žt?|q{Ѥ]{7z+nǠ>Qjrtk ͚tCMӨS^ͺװc˞m]oXkiyQr8rdJD[7pMسk=u*Fp6b1#)L&وο( bJyS; v;88 q|ljhq(60_3D*F`=dccxcZTZ Y >6hjmsj(difh7NM$cMV1D=;T᎒dsAP Xjɥ*y椔Vjiu vcKy9AьJj* <O<'(⭹3%"tqK+3k6;;:KJ;>mVmR˭f[גnʻ-{/jk. o˯[0pl ;&q*1A X3 'L4~C.q|3~7m,mN H@n8 ;: d6g0;qud 3~0'$!Q ,55t qhBP= ah!P>$PH|M!D.&qZĢ+B[,E5q2H:x̣> IBL"F:򑐌$')VBE+^ VB+bKfrd(GYJLj(IiIW2)_JY*g`2%. Le󗻼3uiKa\&4yLfFӚl4qf6YNpzĦ3)Nws';NyJ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:Y<TZU,hu 0@X dЂZF `!jVW}"hDނ &X |P yv$yBA0 -4 cE Ŷ %m#k ޖ=pkT\4A)0F@_-Е, Th0U `Hn@gm{ PY/O݀6aȀĞkڂ`HA3 zPs80 ^ E6@f;"H00j[&n{MrNejZOA+R8*hZ&BmtxoXT *E1~Pxzr)`ъ3U,@Kl[ؤ-hnQ GTE+t SH&|N8Zt5T+YApl6ƛY록k]V@Fw~w@ u+\]hU@t‡n[G*VUdAJX Я`4Ra *F@/?U[|@xfJoAE·~C1;@G>JEkz%8` 9+:c|cZ[\v{ Ae8ր]#GTccds͠W@( YeYY2~Z3%mcRW d@UP's`ޕXFGve Zu|')@e U[Z0 k :GP) 6(F.Z\9`HCU%ph9({TR_V]VqZ^ elW^  e\u_҆cᐉpglj{h[D报Gg\F]E]5|֊'%^%mٕv_eP8J؊ȈfwsXZZZy'PbSz8b;6bޅ FGx^ȸR V `{6u urfta蕄 ॐI]P k<`W@yHu~%P"&` Zz- (avs 7b'+yu`WneqYha PiiՓ#6= % :U)POE%~TVa*c{d x %taMfdIgǗ88Ɨ~ي` ~eP}I Hfyd16c5vc;Ɩ?b0d ` 2Reg9PPXIhw$6ha GPZ‡P]Rɕùl9Pn)Px c#6|'fmfmi&sy˷^aՐxt'eU)d`٘iV#i⹟eg`&fdxhflfis&PWL F \5h ڍivb`ޕe[j[ cXM)Pcg: ՛`p59bV!Y f8:Pr6r+jv\6 g@֑ j͐gɚbJju0Z%ie\ЦhƠZɥMhkZi@Qj;RkP'uj5U esb,hijKr{`r  Ǥ`yP]jFiZKP *r^]  SS$:PPRHPWf%rP ye)P!:|f*l*P_pJpHnfRpծ&kƯFWƞKmӶn:少jkPۯKT: ";$[&{(VT. <2;4['Vww}xx}W%yR5^y^G zcgVhuzvergWx5XW[ ZWyյ6+nZOXȀTeZP5eBeG#8}p)h[d\Yu:wUPZ[+8u[\BcK9V YP(u0:P_ŋ8]ӈ]a^ڸvV_rmɑ+Pf]$ [Ub /`@`CGhyՐf\ۓ苽 n 5ǗD ƚl hvk,jP J'qny YgwdѹdV |@#Z+[\ơfcVf f$g:zg eg6gFƦ̐g%I˿[7V^ J Jj c3\ƭb?[jQPlʮlvf\ {T"fLEJ层ȊȌȎȐɒ<ɔ\ɖ|ɘɚɜɞɠʢ<ʤ\ʦ|ʨʪQZ9 ˲<˱ʷ9pʼ˾<\|Ȝʼ\T;pw`+{bKX_k5+;]}XwU[`[6PM 6л%5_LabۭdL`jJ6Zpi(:|ÄрJJPM ]&=SLPU=қ{Ǽ.=4]6}8:<>@B=D]FmnBJM.JN K-O}(k)Y-[}^"a-Xխj#1 1p-ns&1 )V-P|1{kU؁2ג=ٔ]ٖ}ٜ٘ٚٞ)͟-=Χ-P=Uį]}ۛںmҽM@.kMȝʽmɡ$=}!![=nܝf=]}mkP߆f-P.e$P 5c@XEY mn .nT`lP'V].˶\˻ 6~8:E PSl7{p8%2J'0+lObSlhVË+8*) lO45 L P$ڂRIVR}dYXޗR0 k2N˲L4%,>Ə>CnVE^Rw}~R"%PLf.ێP R RRNeI(^ReX Qlx2QyLP d.Qk.U[Z1NeY+u)Ownu+g4O4z]> ARe& GVWUY* vPʳXЦEd9S %6ּyEV*Ɇz?o)r:ܢ~S ? ei ɣ`vw*\.JR(.5L`6SN+&df%t]ֹX F *hiBqJᆛnnL LrpdrT'D=ygfdQNqQܹ TN[]D -T(rl-p.11ZzzR1dAh `&,r:fܹ⤈ncȎOBERj'evP*<d"j܃/ah1 "9ylp#vuQ=&$ 7ot{}^=nNKty-'A7gTO 3M &O"H'!Kj f 971ZDp 74 hUTcD P8v6WO<7" v4E(EsK` Ep+hC$><,b!> >hǴHY  HǂHY Tx1z0\i A@Z%r!42R[Iy/dPDaHCZɆ݇FkZ6u  Pd{JKjlA Ob2^3/="* >O O|LG?GO2&dK EH=rO*5Gw "h0pPG@2FDB!SMD3P>PS` 1Tp.q)%, #=|ud@*CpiˬF5TzՌmNb@jVS!׾9rYӮd?B GD"4H4BPBՂ^8@a<5 9E(E1CF/H"l1TM¶ka)[U ;n[p!@\>+06iTjPozBJR H D#%a FZ/TjyM+D#[0E odQUqlp$ FaZ2LSX[5| bxՐ#YK7(LMqoUrM-wY#I Ao9cf3H&e)sH9A+t3 $r APCh&|9{ NL*ƁpJYPp-iB1>{3&(*!!,: """00/545::9@@@JJJOPO]^^dddlllsrrwxw|||@pH,=$g1:'QutmA2Trr@·h0@CmB^!RL e LSvzElC]HRCeBBIYBCBL!]CB {saKpKUEr^sjOZlSC#I: !,O !"!***444<==BBBHHHTTTZZZllmsss||| $iY^e;f),aଥs@FXrBEesˆ  r"(C ç@ I&#vk#2{B "w^"0@=x/bIa  ]GIT,4"R2V$(@&IK)+!!,]CCC[[[hIa稔̒'fg0 B)$G d1/ 9Wh 0`IK4:8@]łu0Z^准5儈1t˜XA[ /<0VY!,k  ! ,+,444===FFFLMMWXW\]\fffkkktttk eUvcVˊkeVᵋfdb(`*@Q a.P%W *@PFD bQL0`z4F'18hI3*0')'!!,r ...444;;;JJJ[[Zaaakkkttu~~w @QE]䨚*Պu Y:JO](FS`; FA + =ƒxA@F Fl?k19 T7M"#BLA&,35<230)+!!,y *++555;:;KLKSRSWWXZZZgggmmmuttz{{u @fbőcƊp=Wn׽'`6 `Ld:W*b\ ԕb(@^`)4L aBHK \ (PG*?&7E9F>f03(z(')!!,  ,,,444===A@@KKKTTTXYYgggmmmssswwx{{{@pH$n<$gSl7tJjQtbt CbxxDu L s  ]{PmCB]HLCRIQC BQ!]mC RK{B  KjKBDgl^mfBG_d! JA!-,  )))434;;;CCCRRR___bbboonsssv tM%4Ɋ;Q XV3 C^c8BD r(DGIIqDdicx#_uB/"W(/H-mB N#7@,&(*!!<,"  """+++00/433;;;@@?BBBJJJOPOSRSWWXWXW[[[__`_```__``_cccklltttwwxwxw|||@pH,Ȥrl:ШtJZجvz@&6>h=ѿ]' L {DWMCBGCj!C&D wJvC F'H+",w'C!!HB,+w! d=HbEwE^C "AB C !`9eZpEP4x -@AN8l H|bbA5!< 2 B"Pi)` {"p5Ɯ8ȷ!!r*rWH^! H.ًXYDd- P )HW#,+>P ;'RBe"20]X!(!|6JH, {qXQkt"J ѠAs"W%`,`PL )PBq=L⋐} M%%L )|PC<5 /R96S #)DNB9 9Uћf[wC'vvN5@mh}K Ȣo xVdVʅgY§-x騤2,Pꪬ) 0 a:*. jʂ 0i.ʂ&]±Z b- J1kv[6K+/f[ C ..60A!<,o;GFGGGHLLLOPPPOORPOSRRVXWWXXYWYXXWZ[Z^^``_```_cccmmmoopssszzz@.g kFNw[$qH*F093B{N= zb`$t!a!tg# ysay-g 40%n$ca&a"4 oa!r4- m4aņnta- a --$$(4(o40gr4'0 puݾy=8FbX 2bĀ€8 H1bVrbd-ntaŭ/> ہl={ V+n ۅL2q &P0-PBw0@ ne4, #2ТдZH"P$LX⁀ll[}*4(xD őЁ<   2AVI#BCTTPE 1 1nԈU- B ft(DU aǖEP# evqRb(["{VQCnX~!lw= .&nҍ"C8e5zaD,z-@ O1 (H4ܴq,6y=IWկ.F| dH _@s>DGF 84"‰1T AGtsH!rwt`yH<9 F#_#% H #;ˆh $Hym9X@MQ"(=W#7 HU|?8#OygX YJNb@T.(^FxZA/ z :c Q9CSZW],p?&D"h]&0 :2‰H*#"270@ ~ K4&k*"גf\24*Jnm:)".SxzDQ.2@ /PLβ6HIĠWÈz 29R",d^t22#\刼"Pl.1سTF(/,P@1A9` l#v"Ē"R@],i˝¸ ݈+777&|@ോG. M=ݛ.!-,1  !000XVWhii&t$!;,1˭!-,1 "!!000VVWiij&t$!-,1  !000WVViij&t$!;,1  !000XVWhii&t$!i,) qc0I8ͻ`2P(blbp.lxʌp" dl:ZPZֱpLf0,Pdt8$(x\w1u&uh !,&;U           $ ) !  *!,'/)9' 6$5-3.:/=,30:0"""'('(''('((('+++/0/0//00/?8$333778787877887;;;??@D. G0F4W: U?Z7Z8\?@??@?@UEVJ@@?UA(SH"]P'gKiK'jN*hR!iU*i["t\%}clc*l`=yd'sk4BBBGHHHGGHGHHHGJJJTTTVVXWXWXWW[[[__`^`__```_```_cbcgiihgfhhglkkopoppossswxwwxxxwxxxw{{{\ijrf'v/v0w0ytL~~.<+517VRϿ ?hS?#d;X3r%D; ;-s :Y`-Hrqcanf2PAE3[D+Ѿ3P/W5p\e ph 1C3iL1涐nH1\%dqGS@!Z?O(d<C#^yt6e;| G/hdP B<b ~`.9,Hi ?j:bnEJlD18ȐF 9 [4AcM6ފ{P;!WӨ#ȣAj&:$*BI|5yea!P ,{DI:e `R!$rկ,\|1bfjfȐH1/SC2C ZKMrB$~ nJԋ^QՖz xKMz-R۔45PF"D&%~ $\YڄcP#5HW4a6$&g"̀r#̂bd,!F{8 +$.R27&=GsJxA6%7$SEH41|~!G G|AM!#>(@}CH쁁yUЄ H[uF{x$P0O`OP%E1$QNFQtNƑTP(O_|Q&5$U%"(aA|"GUsQՃjO}(X$V^'ш#qXX5,XVW5z#]gD!Yyeae{UĂaZ ъ5he76&q[[+4p G]xؘڸ؍8Xx蘎긎؎%1vgL[LFwih([ ).m,@m`mOh&Ķsf6sH=hC3WsdrtG6(H@ LGydxlxwCzy>>$#0g(E?I䂥%@"q@`ykQ4Utx#x1O,a+XXYr5|UYy| @%q S 񘍹 aEP$ P P  əPI `|F CɛI81WX@0z A& "Uיx-oH0LRp Pߠ Qɍhq&$4EG Pp'Z !ڠx60ppRkd6j 0y@  0>Мp@TJ` !CZGKNJX 2 0)6Ppr,cj  H`  `PPsZwb ':'ucv a:`0 t *# J3k XMl!?0` ~A)@ITi $%xK: Q Pv 0j E'g`LWF@<N 0C k  [5:p !!;a| q@ a4;!9KJPIWs%L;U "T"VZ0W_W "g˴bb ضTrk˶tKrKWqYpKqy[S 붃V {b 2[\ vC`4+Q˺!,j&%%444@@@[Z[ccdmmnm $99$=RH2JwF ֆDIc`E CqB "SVC‚Qx9Hhr27_zw[B(Q"G5JFNUG`'g,!!,o;HGHKKKOQQSSSWXXXWWXXWZZZ``_bbcllkoqosss{{{fXMYɚ3ZLT2P)5lbk)%t {0w'1yx~s*."j'+i'g('z.o). .}. ot'" l " .' ' "*go"  t-''+'))**,*(uAފf"p.*u +7G$|@$: >pc>hhyț7ܠ@%c:( ]h!B̥$IuΕ6|  x *TNd0Bp;F)#"|˷߸&敘D &(D$PBd@TT1R4._-Td">C]FE23"#EF4.6+5FLJ†Üٖ̗$ȡ*˩4ԩ#׵/׶1 $(0")3HսEԹ[·~ѶfE*=+6*6>o~DTWAUbuDXFjtd̉ϐڸω֌ܚݟH*\Ȱ!A_<84PjܘŁ`±$GQ\yP%˗0cʜ S7, 4Fy@h Ϡ |ӛQ0-MԫXj-Sž r+X",ǪM ܻx$1.IޢToCJ0G Ce<'29G jԼd2x a J80 ƦPnb+= 4 `k`[ݺ/c"LX_/c }>|fShtބ%K|r![&L oAQ"d;ZA)7#A5&Co#.0=+He8=Tj=@b~ʑHۑ0CDIy b T8p)̛q# +d@yО!^  j&: ɌCD "`*j饘dq *ꨤjꩨꪬ꫰*무q;j׈4kT6;7>M:Qn8]ᦋm6-Tn\/ڋn{Rk(^*G,Wlgw ,$l(,0,4l8<@-DmH'xX`Q],3 \bPDV/Iؼ)R_Ee4 xve<oJem1&8ɔ r yye~LH0+0A畆0d~4.Po{#L}GY[A2Jc7@̧ -;HOШQ_ qSOg@SNG4*#؃&pM!C ( DZs)z8Dcq`0Q *t 8 )18Cp6FqHL&dvHD"6 ̉BS~1|C ְpȒi*jcT5i [HrF& <1{o d-;ًV+^+#5@\RȆID+)%LwװF0~ @bx *K\28[JBbJ#%dn0 \Ќ&/`d"(ۆ$8$p) RIs/1rż=5j>3Mwd,)ylRC@qi 7vdnFH;GN tӦE<]!uh,b^؅+D1l'4 ;MWtvC%]&NA"Q&İ۲WE:&H=4iÃ۹/!7Ȅ'H W@b&'2xΏ3$@59d43u.o$. /^0ߒmuƁXulI|ۯo/z/E(PRt&Y7HB{Cnĭ&:щMdp hM2dJ;bB$[ϼ7 ha&I8G;KC6yN 6}˂fTOG)mn#r3Aϳ!`#ˀ!'R\AUЅ@%}IwLZΨ3c1'ڧjVts=]) j_ BAgU0z!TC#;允s^;I\\eWU[zr VKSumacVe==`ϧ`ku]dc v Tb&#AL9y8Fe=8[6Rvcn6afb''gt AggUa"(hf\67t U~_6#m!hYlf`-Pl sll0k ؄I fb&+$Brm,Pl(pr+1As s`$dBqBqCjpp#wV&) mboL"2W&5BR"'7ؠxl?n#juUv|t)vi&B݈7BF8e.e9Wz GLX*0yQ`_}0 =<`L`kzG{bB1hR @,Y (I,>jp  ^,?v4*~a s3Q acBgQP @7Q|۷|P gUPЁN6![Knӗ &QfGL|@@ϰ@?71nr@ Aj`&ClF9XUZj9n|~_4{Ne -?X78k'W|wVsT{%xXT|W$5Fр1V+U ajP %C#(< jD"  P"j$ћ0?9XeT ̠'PU` {`sj–_*50<\rXg'0A]i^[DNZ# 0BPJg0Z CW_@% !EaFqAJPBj`eҘ\-f!5pZ{ހ' :\O).le"] FڹVab[*9 KwGaqd d ZfX': Aɰ !B_sWA=(A gn`'qb*}ө Bg:@Kbh!:Zf)]*&h JΠYzN@)ɠw<K1 \ezwzF+&}g:@'mkllscP"mK@&&FB1I!ִ[?}=y6dAzVɋ6s"𓓉Nh!$D`(j3meJ\A_k,bHRs85h؈pʈ(rhppd&{$[ !'fpUq,ːL=)P@ؐpaG;?qt`&3B xkax!;j' ܐ5Odb +aG#_%1g["D'!97LM\Hɰ`mFq=yī֨Ưf Al `8glW=3;%8ںWhɹ~"g*ɹ=}\;Q$Mg4v=ϽՇfD$ŴVk_kckW`Z{]ܝ޽HۊF|@fֆdҵĠEUnbQ]#эZ XM* @kqCW s[qqqa)G N8&xe 8sk$ b5OF䠪0T*~hB~r5-Qv ^6(u 188F)aa V\2wA-{+E7'՗ VO̔+|I\Ȣ}5L£~*1+T@ B]1Q8b rP-cW(bؗ,쪂 |gA 0ݷ RߥXmCR$&ҌAL99q䧥*:D#s,1(>1>?+W K _* `   tO  OA,E @I q91oזP {&Q?0WLq M@KEJ ] so0Alř*ocXOqUA`?oI dUIa ; P tJO* top  AgdbŀU\^5o ` p B! p_a#8 dСvb"B;xmŋHI)UdK1eΤY$q d5 1Lda<+zUU+DL"jWaŎ%[vQl0+= HzRAJ9H$D%M8é~ &le̙5o\ qQlC`o]zr[;0C%M6qR (oݻsѥO٠/C)'4pae= sD@E1%xϧ_}*͒$Z!3@T6ؠ#pB +B 3pC;CCqDK4DSTqE[tEcqFkl(;@OSUu=&ΓArZ 24L k'ٞd`o\Bj6[dյ[nVr9 l"StrdQ;aXr5 x-b}!yWh\3l oqe|dA!i B !eޕ1`Zg~g&3Vz;ء2!Ӏފz&ł.]`hHgL[ o >HiY.v;ǁj[/aӞ'?%4QAA8OFThE-zQfThGѷ z4|0(H7/o:KippHZ[i(wz23CzT&UKejSԣԻTSBYK ϫXU*oi]^PٺUsk]zWU{-`WHl@D`"y%=lHA#lc?(%]eKDhF MG [jZV] gqmo}[W6MMb2l1`!n16$ xFR>50V"N!Dku, s TrB"ȊĆh@5k~ 䨆ь J_k(!w#CB:e" 7fv"y2`0Zbfoh.RT6pcXaTYA 1Cd(GYS򁊻*WrCܺvxa \"d\If$ep|ː;G8v9eHYYYF 8ޘwekzG|d(>VMLL$ PfrJm}8@5͗!(0~*0`h1̕Nr缨xQk$۵¯|l[?bI_?ɗ>T(~ORvO㺨?8G?H!%J? !,{ """+++333;;;@?@IHI[[[_``bbblllvvv $y]YwmW٥nq60,U&vS'V6#` h(F(gz!X"2 ј: KNX/a4;'f#w|`d2#""CQ" #'4,eN94N'Q'Upc(M')+!!,{ """;<;@??\\\bbbmmmq dBE E&+Rotd7EP$ $>T2x,6j'J#KDU#ŁKQ*4(yMg %?nT#G.z$f0I,:2&)!!,%{  ;;;RRRddekkk|||r DMSMHaմmi]qe51jQSa1rP*>@8qb.Ԅ9X >C?b C4-'9$ts<^|B')+!!,,{HPoS(V[BQG(C*ebAWMfahz#Q)  d`rBȲM!,3{CCC[[[^ :DFLr4" xWDᝧ$ؒz.`2ɥ@pIB(IV 5Qq0.%!g0҈h2x!,:{  +++//0333787@@@LLLZZZ_``gggkkkwvvwxw|}|@pH$j8f):Ky>RM#0¬R),HfV6Q-+n3V&L:&(!!,;s         % 4  %!8' 7+71"""''(('((('+++/0//000//0/021-333778686877887;;;Y ^$-[>>@?@??@@E* I1 F3Z7 Y=@??@?@B?lVH@@?WF&gK|_jM(hT%u[%}bmc*l`=yd'rk3BBBGGHGHGHGGHGHHHGJJJIGUOPOPOOYYY__`_`__``jWN`__`_```^bbbgghghgghhhghhhgkkkldvopooppxxx8)Ejjj|{G[Zffqg&v0]f |l p y&tMx +=+5GLJ†Üٖ̗"ɡ+̫5թ#۷,׶1 $*1$)3IվEԹ[·~ѵfC*=+7+6>o~DUWAUcuDXFksc¼Ɇϐٸ؊ٖݞH*\ȰÇd"B1ZȱǏ CIr`O\`˕0cʜI&ȗq-͟@ ʑOF*]ʴi̞)Q"EթիX)'OZÊkΣ^K۷uivg]pݛ٠\ 6)һu +^4AA!\˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسod+V4 E[A z^BI{`w]/xы~A@T^w}x Ax! R ~YxpN2d`q|R@&hŊ# dܘ}@V=| 0#&= cT teA@ 4^{qpN )Ыv M 9|=%8D t6dH-+Pkm4MzM7&  +i2PAb+[f/} .T' 7sBS-.쓏;h1CiuUH'0UPeI߅7(x$hCpP,Rc=Mo!C dŗ=TLVW$uB:z*$Lu-+XwG}"A O (~B|Ar-qTtBp$ %B$%@R\460K6Aш !d!O2dp3\A A^!>*!;B! GJҒ&{TF0@C J=@2bN"G::<HX#L Mx G &@`RYHKMqEAJ5*})X!(eI4!*%!)"4DQ4TŽ'd)qYFϨHSKҨ:%@ T#0TdA\2` ]H2Жʬ +ȓ@QIw,@(COz6 )t8v ,ԡ7|ꓖP=oH!tcfP+ΩXvRU^{= I %Ƌ eJ,5Kev^T rJdH"Od7dKI#NƪY5jQ] c_EupUVGER[V`q`4sr-le W2CpaCc=QI.FhPFB Ld>L\"7jK]8yb d8B:"U-J+璔? +jUXT-p%d{qL`@V7({9(FS}y_mKh_]s+!d=P2% 0@_1&%5# 9`.9Y/gFpf 9GMRԨNC# g76kLnͺ7P\.#DA߅ ,0(26<Ͻw#&eYh(^s C*TߡT{0Ј=-c3ڠLc(7 j[xD*$тL kYK %(H0_DpP00)L'Ei]_5L0E^&_X*'N+ieWlXBVivJ4.5AΈͿ{N 9G zyUYޜ Rw *?,FĨ]^3|j# ` ]圼#.mM )" sX];#жO}֓eyYɥ 9&k#|kLxW ~A`.bSG1]'lɳB3 N%QWaㇶ w&k%k;>C<% r( € p .h` -2fS$7Vh|+&oUN3:"= xxZ kDATc!gDErpKq*4x#4BVtp&qOBtRdCh dGRb^Ē[ <)h%{X;(r!(Fd@h'pD? %2ɓ#c+w3mÈ1т %Ļ<6 n=cna++Y0<։g*V?׫=Diٳ;+rԻ{RPFCql5F[FfA+DobTR B6І@*spHZh Bk_,I**_X=j)LTUb)QQowO8dvd@r\O#0R{RA%3wR4ʀ=k! kZRnS־܊яGA |?l%]&镁HsKLOIt йQh fg-ټȬ߄ѡ8|'Y<|AYR{wԣqB: ~MLoA)c$<:bC}J~@KV  K O   @@ @ ea>]^Rd^ApEp I zN|^EGIpPw q R闞5=pEJ@ 0@ ~^჉뽨' @~A탾1~4Lq(Г)CɘK;p q}^* Ho ]/ Xp\ Im,t `` B^ P,_pt0 %Y#iNiOM)p 1s GCo pK> UϲTVA;0PMP ^buP YJVO |E 9  Rv tP @|Kdq ;pCF ?p  F7`nn?B'D??_ֶbn)_nnݦk4Вc 8@ "XC%NXE5nG!E笔24(; F{V`K &R 2gI7),DSM22< ͊KaZMϾvHiծe-Lb pY!cŊ0akiJB8JhxZ\po窜<&z[ԩUf6D2l.+[dzIA+劦I V;7E4B9|ۡn{eZ'_|[d,xαC)N-gC9@ Open;),%`2pC[#2Qs )+qI6+ a8g4FAhJ t@" I#IDp`pJ*\ +{.p'nĻ2+,G =O=PD} &j4#Ft@i Q0uHӂ8SECuT KXHUuUV[ I]uVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r pMWt]wmW]xݭ^sw_~_x` 6`VxavafAj "ภ,2c)bqKL, ,c JpUN2/ˌGdLL@ǽ,k.씎k.l7Mʪb^& -P,Vlz132ß\RqWq RT@5ts K+SMVt[wuc}vkvs}w{w/x_ 嗯Sm-XK+~.^6ey_Oz`X!_W``aЃO_-xA fP`=AP#\F/<V f0tm7W y_1,Eq_D(FQSb(^[>ԢEnܪC3jih-1ZHXGrȃUґ6RW5*bYlTYM)"ZEsTԔShjz" AE嬮vU (*[O*FIURjG6\7Uss_5Fɳ9+c*}8l*@8}ET&FphBWЫ /Oz¥4yXȩ C)|k\Z׻u}k`[&v}ld'[fvU j_\X.eImk UAzᘱ喐»2 &4;(xAIu鳌Pid",/>Lw{~' PBpcG,:e=Rx W cME:*@q1Bsoj8hء΍99ȡ+׏ dA' mPh{"p&}9QDt 9dSp4E;A´`#\sz9MU|6_ykLW]#6Eحӗ^G]?g=g[0=Ev?{ɗ_??̟~o?~!,Wa        % 2  '"9%7+81"""''('(''(((''('((('+++/.0.0./000//0/032,444778787788876878;;;Y ^#,Z??@?@??@@F, G1 F4Y7 Y=@??@?@B?lXG@@?UD&]P'hK}_jM(iU&u\$}bmc*l`=yc'rk4BBBGHGGHHHGGHGIHHGJJJLKRPOOXXX__`_`__``iYN`__`_```^cccgghghhhgfhghhhgkkkmisopoopppoopopppoxxx8)Ejjk}{G[Ygdqg&v/v0]f |l p y&uM~w+<,5GLJǚە̘"ɡ+̬5թ#ص/׶0 $)1#)3¨IվFԹ[·}ѵf*<+7+6>n~DUWARbuFYFjtd¼̉ϐظϊ֌ܚݟHA\Ȱ–-R Vðŋ3jȱǏ CI# b#&V1!JʜI͛8s(ek5v Jѡ0:PXilB9 pL҅=BJep ۷pE[Ċ!EK%^L,i ̻w_ʔHa؁$Y9ϠCB]!)m*mɴqus lʈ^vE-@ksͻ uѾ m uxp=;wp|kũgnĞ6MW cpvP@ߠpj%h ^5k!gW7\ݖcE@ J Y H&d^XNt@ TAJfy9`IRU)hlp)bz#$-00S9|CqywUH6MCwDx,( dD 9v EF;*BqXd)B 5XBo2?&ClV &?)~Y3$D{O. 2Ʀ J)<8``ov9ULbk(O[$tr!<(PXPD(:%ь;y`͎ (Ǖ c'm瀤\AyJ d @q:&ς`qtLJIOgB =  D(DqRA8(ϐ;ipF|!$F hrdg$?WA5%n!rME=g\P,1݅<# 53Uh! R0`dc_d22-Sfup00i  Um440Q}]Ds/RC! 2cv!J [u$FQese::;sfpvU; ;M# HWD}A9(z qRЇ1xT  8@5D4@ScW:'R <(VgF¶EHlhgGx z4bK#2kIŽDFy8{ Ч PH7A׀߰ !߀ zJDp DSP&tqv 2HF/4MnǴJYA$nn$KJbLqA΢X@vÆCBz@ !;Y$_#tDSU?N6(XybҕBqqQQEpPR~qPR/P 3r2R;!f$ "!PX $Hc2}/51$Xre1}& 3k(@ 8;JRtL""OYOE|i2BP|u%#$mrtt4s0G"U*q-UQsY ABYRo F$z1 A 0%6ڢ.|IGljXcVsSPR.jUCbR,L[dZFGNt[pZ[eXK5A:ι`#gFeUg[ѧBq%x|$gu$]U4!cg[2^wv%Q^р*ezګ TxŠx5q)W_nrwIVR`6`HAJ)̊ - GEy!auG`&Ò\j"3lE*mѯ1Q33|g3t57AGcĀ䗰h{|/Wc&bwA84c3RҦ5ʹ 3XXy54~>0;!o#`؄qm diMje!J_dN{;M!G[k?`38{+fl;S|;YnjƱAħf%"ryEYqrsiX=Wr5Z\8(g:){'Qx!r:s偬D/\MEW1G[/AȊ%x3)\:)S^żFvx&Euܨs*\tZ<*ꡩ()KiǪG<\|E5+ :hcdzCbvUxfGwffBH9˅}a Rj[iqih֞}_Rmkf l221j.1'd|뎑!L 0 } ^YK@峰 H`G6] t@ c{ UQwk.+JaGA@0CP `~ib/KTµK >P% { @aDK)WlASF== D@<@ N~ߌla~0>?܎`^'>. l ?_?լ7fIct@6k;@I]a-c@._. POHv}v[mM[fNPO9$}>{Ҳi+ , K\jWoVY:=]ll3ڠkOoOFcnYnV?y~1iAnv WQ q*UrLsjAp.$qTss|5wlIwFe%uZB?_?_幯 |#HP`A*C%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnj(lqE18pvm[lmX܈_E4bDg0hpXv1'qɐ%KܢMJ_СAVcam[BD{a-B!lٷk212Ϣ!6`-!}zu [׎z'?6b!3v`5 w8?á MjP s/A_h' 0C 1?Q8,(Vo[|!]cq1pD @lHDRH&tI(rJ*J,rK.K0sL24L4TsM6,0xN9s;턣N;hϕ*xaAQPD% EI$)"S;7ՔS8=T`ԐBjXWC!UuuUa `uuP5XdUvYfuYhvZjZl|alŨ7#e>\*h]vyL]x!Fxz^u4`Vxava#m'^7g1yGnc8d=f9ـ_N`kfsyg{g4xiR:ZK1:T4u7:IꆸmnvnfSZHo|p 7pDa z/: 8qH &@)r5"&= oஆ`ݡR;r]ӱ2 ,-kJsCl7 !J~!磂/P9r9ȑFoiܡ3~MiM֒T)oo % #Fb n CxBP+tWB[9y\&7':toC3Y,ќh.hnGH9$7b@9}>bCؐ g (.u6΄6<3df`#R1# P)@H!u  G5 ģ7bDT1O/45$v3I B *SWV2$+ BH\b! L,0фfyFc-q'{R6 2i}Dy"H9"F<.ă?[&3#d|ЈL 6 ̩@<0wP4P;`%w?4' HNџ "-؉ yP $BحvI*PzT&UkOWԥgljS1&V:S&a? VuR5gEZF5$dYabUXӺWUAjm %a5BS&*Uc-{YfVlg=YІV%miM{ZԦVemk]Z؆bI x!kkfHl{"-I&uSZL4%iBaex1(Cmlg ( ]0U-ȉp!$1)0G ߈GA84"{7_ F'/vpdrɵlxT^p*cXIZDd\Ƒ7 D+^ >d:$ {qoC SX(#t. rH1-,rLG&F_;/!xST$4idYthHGCHw`DC-4I:mh4#-Lw •>֍XԷ2A5#F~wݵ|c <6oCdw?+wp^?=Ԏ?jT{ ;} 0,?[sW[;s|m { p5Rw}$e!0Ӟ^#iq i:(c8{dÇc7kC6۠8k z$ <|xa| @@@t69Az+9=@,@Q?X   $<0B"` ۂc@xة:Ây*p&d(3ô#+n(;p\õnPAƃ4{4Ԥܻ+9Ĝ % ":D66=pt/lko dDzpۋM\EӷԴLOt/hK)0Ld4ο:(9DL|Bx*p!y\.OPO(Ob"a#%d'D\O@4UkHh$PlDi 5#iPxPIP P ڔ!4Ɠ* J P@sX4O[P2 }ѓ-$Z5ڈC Q@ҏpExN-̉06Z5:TyPPpR-Ո!:B.(*ɶ@gD6]ALg3ЍHqOX) Q˷ʷqP;HY0p.t÷2k7x&zӋClwTy˩M@}58%*8m8Q0l17:s99V8YUkYmaݜko{V!%kU;p& 3;Xo0p muC+0PVj/rݺ H#/#kW#hWMX;*};[=;+Kd<ǃ<<;>U=ϫkMK6X٣ِčEڻ伻YYxؽ< {hxghȎ!FK 3oWK";?% 74IK\[Z0tE[35#kB<$}|B@8u$tGk@BDJLA9¾uAd,<+Ó!@,cD ҅Fբ3|#6)p]ݳM5$- +WlHC!I\Ļ6BY;ITDkDEU6DIvD-ĆNZbFH?YzkrIeLۉ(S'm؁ct Fi\0 n .F޵F74{,FI ;'rb2{̾d:rmQ;1 3UÂlT>3QZe` dLUelMLo =M$<٤!M=vVgwMKDbח"Q1>d ϏSڴ7A@>|ՓhfHƞu凡SP`ivҙ0 uPgҚP }!,o;GFGGGHLLLOPPPOORPOSRRVXWWXXYWYXXWZ[Z^^``_```_cccmmmoopssszzz@.g kFNw[$qH*F093B{N= zb`$t!a!tg# ysay-g 40%n$ca&a"4 oa!r4- m4aņnta- a --$$(4(o40gr4'0 puݾy=8FbX 2bĀ€8 H1bVrbd-ntaŭ/> ہl={ V+n ۅL2q &P0-PBw0@ ne4, #2ТдZH"P$LX⁀ll[ @?@VH@@?TD%]P(gKkM(hT&u\%~bkc*l`=xe(sk4BBBHGGHHGJJJOOPSSSWVXWXWWXXXWWXWXXXW[[[__`_`^_```__`_```_cccgiihgghghkkkoopopoopppootttwwxwxwwxxxwwxwxxxw|||~[ijrf&v0yuM~-=,5GKJÁ۔ʡ/̫5ض/ֶ0)¨IվGԹ[ҶgE<'+9>o~CUWASucHXп͉ϐՌܚݞHA\†Z%#jȱǏ CIɈ+TL Eɛ8sɳϟe&@*]ʴG (j4h LU$HY^EEĢCe`e%G6$FdUybV[W^$pթϠEv)y! jx bO@X^贡B X2ԭ,f^Fif% 2f_ڕTdEfb.2+O~XdڄϿA PΧGmB8K3o*Amz$>Ќ V805/[oܱBDB8P˦ 2 ? ʌu@1V(1 .Ȩd3\W-T`  2^r369KQ.L7-Ҥ,,zRt TVUtuAf5t,*oNvA*LKpmwg m7Pq߀.n'7f;aEITm8hVm{t&=zPE@t0`$XLj2dKe7jx; O?dE? ݌ 51VYp԰~/aA2-fC9_YgAC8} VUdOl֭-o e삗\/gZ9m{)AB~/1KH@!_DB:x +8|ЁZ<@G,R f`~ ]Ќ~t f<Y @@0njdm#ORhz=%QH:QU`^e+4JrCJ] Ż-rJiNp"ѡю;P89v]fwHޑ񐏼'O[ϼ7wv0e2OQ+O,`z>o=TFy:Q;AtW+xaAo{-7 ڼx'FuP~J>X?YSrL*|AE;ÜUG`łJ 1s1Ncw q?wcBu~o0gxugAzwC<"tdG_a7DE'X?x4Tpn$QAT#H!X~'s~`HK$HKZ@~`IQHH1hP$R4D(BR Th$Y`Ԅ taR!J68t$J2qhwy\hIBVh$X@Kr~V&*s#$R")VufPx^hW-*(CJeRCR+DiUV#]0#P# 5X!8]0%hXU#Sf2/%U.O1XRxf/"h,%U ̰% X-q"e$X"zbKc&hqHrajQ\"'t vY&pi(YYX'ap1 ΘY;Y눀q~Ifcs@ 07Ƞ&VZ_q%86s+Phx^k2Fb++_pArv0,^CG &ٌ`0 p "5,$3K%Hw6!PJO 9۠ ؀ O{K۴]KC*aS/& 0G z{k {os[b8Iuah`D a$aB w#[1 p "@ [C ,u0-H 'iK0  P P ƋH0[8%T %丏/vG" p  LcJc9Vz  ̿f#G VW&XhJ>50 z [&*8F! &!{A == }D@<ģ=8) r-mK޻$ELk?ka+ @ 7} J!Ȑɒ<ɔ\ɖ|ɘɚɜɧVA}Ӌ%01 p˹쁉<(ĴiJq*tY~xm^2rZE,0O ͼ0ܜ <$" |*>ˋ~rc`xwx <L(Db$U%\ː`yX:>Q)w ɒ0\9+a*,Z=!xW2A%h# Yr:0 w N-O/r@0'!d%PkFcmuӱl3N#t*`6Zr-y׊Z؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞh i ]ڧ=ڡګ=ڟڰ۲=۴]۶}۸ۺۼs+tp$sf)`۹+L1͊gAd?a fe"@2Xi}Q$*R>՜A$*&1'ҜKn-%+qo$4~8N5<>@B>D^F~HT:'tt@LPM>TnRUaB+_.dK7Ef^c\Q0+r^r>+t^w>q{>o:::9@::P诃9P臎N^~阞难2~,8~n0ߧn,i9d4 g^~@dU1.F`~R-? ' *0x6{%@,{ڦ c._68:ohxy!NBӨ1,v# j3˼lWwAs ?+alٽQ,~jV=WߓMN)%>︰3qQPV E\_rZ&>p;Þe@7Aq.=?3A I?ʦϢ;?__0=@ABWRѮT~1=aDJ I$Z /LN$ȿ%jEpTMJ*!!.!Y/5Pߡq `PAd.dC%NXb6Re !E(F„,a! "C OA2C8҂ٛ:: A8 2NA f'Pq(T(gBye\' ~PG, :_8]hAbXm:T''b?År&*>я{ u(D ~`mC1ѡԨ tD14mMmT ƈԏV-EA=NZU2bCj@7P=IfWرul`bB0 W >*Q@*̣z&G zMguQ⢩퀇 ڏ)mADV%iЎylUiړP-n?@ۂ얹{moe[ݢí؀rZؾc$iU, 2Yb QZQ}>-` zf\36;IzBbBDDяƍ .<\ c3Q#$8t䂜3Z Bv YfG3| d!7q bcq/|Q4&?ɣR<6 ⱄCϬkd7PD<`%r;P8rmzy̘!G&-QEObKu2_MZx3Gԋ~cխviHdpp$0v( /hxtʲ,~1Y@Ҋ!+|ьٌ KoU6n!5HLCiQ[r͘BRx0EAnpUCwG{icSa*@桳a#1 WU8Gm oym~e&>g,|6B  Hf0K.BHQ7aH# -4 5I$i19 J6cM|:bԄ2=qVY Sv$ ;⧜cE0#o)G~`l<+lPx;_"Yk'8=p{] !7 ߆#YAn^طpWvHoǍl#4I1{ c_?5%r*> @@08qËʟdy  |S ,H I3pX03Gȡ(" \!ř ʱԕ,Z,-xB,J"=6* !XxP2*a;3p3%U@ !1C> ?ʬ#:C.Q95C7 DD: 0Q7>C-?LÈx%[2HEjG @k$K$.e:R:%QNl%X[QDX…ȥإ\0$^ 1Vx"Ã(xub TgC*i:X2ha mLFz'4'_ا"f ǤG }꧇Gu(4Z((:)d )`)"~@T)}H)"HJS*b*++)I4Ȩ"~ЉZ7{AkD+ 4"Ϊ0UŸCI0ap@Ir*BBYPB{zʇhoK˺3jJrZjؚ@-:"/242LR.Դì.Z/JL;S0ƆQ'xwK;,ӑI͇.@ 4IˇL(00 ˬѰbXqtK4K+f0I;1J֊3~.ɤ41$C ;4&S~PmM[+)I~`%M ,7 /8,Lܬy?+ _$ o$ 'd6~ Ec;[F@80ѱѪp=B]>d4X7.iO3$5SgiB_82Pv7K 8z: \[qqq r!r"0`@e+-D8""6^bx a~x+G.KS[肶x -;\5oΨgVPp(_a|?m B{8HiVY(HJ6 u1iОVpx݌1џY^YaHY^ZhsrvXvnmT q qpOYom&up8s/sWikr {s^~qoYsv~oxAmx7x7afon2'ovt>y,qiwmwyH!owGoqC xr/}y@vtww!,o;HGHKKKOQQSSSWXXXWWXXWZZZ``_bbcllkoqosss{{{fXMYɚ3ZLT2P)5lbk)%t {0w'1yx~s*."j'+i'g('z.o). .}. ot'" l " .' ' "*go"  t-''+'))**,*(uAފf"p.*u +7G$|@$: >pc>hhyț7ܠ@%c:( ]h!B̥$IuΕ6|  x *TNd0Bp;F)#"|˷߸&敘D &(T2x,6j'J#KDU#ŁKQ*4(yMg %?nT#G.z$f0I,:2&)!!,%{  ;;;RRRddekkk|||r DMSMHaմmi]qe51jQSa1rP*>@8qb.Ԅ9X >C?b C4-'9$ts<^|B')+!!,,{HPoS(V[BQG(C*ebAWMfahz#Q)  d`rBȲM!,3{   :::KKKWWWeedwwwn 4=DBTT>$sm&Ab @NT1bN $2"D芬j@E%aCU  h'"y.(;5)BZEX*!!,:{  @@AGGHIII^^^lllsrr||}h HNꐣE<1PNS5.0=$G8, 1@A$`04U:bRI1 հC^7l)G}w<*9;B9z)DT`(?)!!,A{  ,++333AAAHIGIII[\\```lklttt}|| $IYQTTʮk׍Rˍ?K$IJR P<iz$h$&e5 iA9Dwy{#d1vxj;~ 9BREzE D+,w DO7COJac'QJ(*,!!,O{ ###//0555999@@@NMNPOOdddxxw|}| $]W][\vjin[F(TG X<9q.a@dR!l: pJ[Q G"y`3# "O"(&I'D#p_)#*,!!,]{ !!!***444=<=GFFLLLWWW\\\feflkjtttn UY㩦+Vv|*W[&XK#"8 BE]0\R# Ul=f@:5bʁ5FD z"=#3<CEU=W2T4JE&8*!!,{ --./0/434;;;JJJ[[[aaakjkttu~~~q @U]YVYhZ֊jV `髛 Xd.C±NUi@4$Gv±E3W4L Rw* %5R##B0:0+D<D(*!!,{ +++555<;;LLKTSSZZZgghmmmttt{{{v eaYYbKk&kFS]`KBP0&i`¹`VE"%g:4Jq<6q G A*?X;72@&v,4]S'D-&(!!,{ !! ,,,333778===@A@KKKUTTYYXgggmmnsssvxw{{{@pH$j6 ):Gl>g\v-& N٘ A@cQ ?M v   aCB[YjC}GIC BjC agbB  gVDBH!\VkB HJLA!-,{ ! )))000788;;;CCCRSQ___bbconossss 5gERXU]1N֙G&b$XP&` ۳{,D8,T@c$"zF_:;oV:' ,) K#Z.9.(!!,,Ws        %   $!9' 7+80"""'(''(((''('((('+++//0/0//000./0/032,444778787788877887;;;??@?@?D. G0F4W: Y=@??@?@VH@@?TC&]P'gKjL(iT&t\%}clc*l`=yd'sk4BBBGGHGHGGHHHGGHGHHHGJJJOPOPOOSSSVVXWXWWXXXWWXWXXXW[[[__`^`__```__`_```_cccghhhffhghhhgkkkonpopoppotttwwxwxwwxxxvwxwxxxw|||\ijrf'v/v0ytL~~.<+5GKJÂܔɡ/̫5߸)׶0)HվEԹ[ϴbϿӷkE<'+9=o~DVWASucHX̉ϑϊ׊ٖݟH _ *\`,HNx!A$,j4dƏ C\ 'b $" dɐA-zЁr$$h H"͓ '%1 m=W Xn|'<SJN;F-MC*4f.dV_  TG jaA jZsGL| $ Q6x\11LbKUL@2zq%UE``ܚ4pʠ|1$@j 1QzH eK=zlWH:_5Ll@O0 92-v-+4?p(?RЌ? iF @8Wq1WF`gFO9mAhe9w=A HLD3PL3!ьHu ¬ l50 t-e^E5RD=ՒdZ&C1 i9򔑊?i4@p FAuLQU_A N c CşQe_z n/pF3%5E 0*aC|71.顓q3DK*h5u[U06B#dqoW%\UY cL/*TVH.4܂OOl>pRW ;ˮS?1ZD1KK @'׻'d1@j[ H$dAXn23-MlH =1k# $|8,`U,.x1p8-O>09?W/@pc%̢8Qn < z_ZQ@/RYk\;aԌ[P T$ 5=sAM*pݶBo6v{k6@ :]9`S\q>1R(@܄RH2Be5!*Q&KɃ`,qĠaE Lcl8e*dԸ,xt,  *e͡@Ak\b hh ɣŀ u{tm1Vܙ$AlRCx bA h V DB ҵKje hXE++G[$V|Yͭnw -kglC[+:ЍtKZͮvz xKV%蕉[((3Z(oH&iJ}C;/藹j/}T| ^1G$*E/H&򔸖YXJS*_))H BwWO_\҈%} qEb:E|#A3bPe6 p`9 D>&8IEx:2,GNt CS2[2 <0OkE??sz|d;G3Z>Wb52&7JX K82Ajt-**V,c@rhOʾSZI;;b'3M{ NժflagZD6y߼)9mkBjN1^5F/\L^AxծBHAi 33jsB1@pu^j9}`sgӱbz~C2[-#R2x$,\Ƞ>nY/`կNa6:$NzNЊ?=~kywhel4=y5-Hq}q܅%JJ I[\2|(gzƽkubEi /tTקp"saA U2w'xƾ.IH2##u[H3DGn]JbDFQsL܃Ͱ"=$F`pGhr2#GܑF}@X.3~.8)ݷN5QDTTNtOE0PoM޴cP%OMH8s F<4Y8TˢT"'v{F}L%p%P 4Bhdaix8uVDOc(a}Kj%l6TuVUW"ai1VH+H+e_剒.sb]9[$|8] •[Șʸ،8Xxؘڸ؍xf;S]FP&hq8'S (rl$llDU%rF,fvur QpCrY`r(7@BsO ^{ `KHz7fk7v7c}Q}.||vz ~ 'B)a4@&8YHH$pC9K&BukH+HTHd]wEbEWXny$tiXxz%ȗ\ @A G@% 1=P   I dYP@0|pP=p ; S90TUX 0z`aP lٜ)S)xT,CE QA`F@  ` 鹞)Y1xf?ep:Z@`EP> JЛ *ʑV(H-&%T2j0F8 tY* DZ0 4j8<#: " qc] ` ?! p3Jfjݨ9r%y=Y n!` @ Qp jCXAgi {az180p a*@ tӐLI$åA60vpaȪzOc"xYTFBx^E`1d*55{;4`:m{ jay pY7 ۰I* bz (K)02;4[6{8:<۳>.LUBd~2"3@Y 3.x&nPWKW;Y˚?]Y Jx)lNjnfぐ-'wL (ll ~۶KYc+a f'1GrG/NZ1R0[05YP +Be[^k5' ~Vǒcg/IESq 0[N++a PS4& ] 10[ K^ɻ QdLȴa$q&1 ѽ2[G dL ,#PHy Vy iȕ:ЅaYT +$,g@BXGQE$M@XZ<:FmߚS'c+a]^>a J&o>t^v>a]V{<`nENfaྀ莉 au 6 \`z4 ~>`ݚ.霎簄U.Cpu *rWN>$Ε]2pK>6u,X\t JV 9Gr$>)IrK a|y˒%]xAԵ> ?o{w)i|y ?nqa_٧NŎ\|x.C>J.#[-?L%J]N.ܴKU[Aoyev/Wnxe鋮 ]Vc+[%`;Z_ihU.lֱfypr?Ee,Dru_|1>JZ"e%ڋOkk {^/)?_OkS8ZHcO_?_ȟ_\&öSV VpH5bآ8#q3dWeP,kEweK 5^ej&SQU]bJPA$>)#`*X+<9j͚y8G!E$YI)Ud%K! \ᰠMt0p1"vyVxYUYn-a+>zfVЦ?<[09)#L[p-jp8_ʠ̱,Q;zhf>0vLSf *+٠54 JiԩU4XG2X7 rnmb RS6ɕ/gL5k4䚥\u1%5 LH${gηٮc>7utsW+&@TpAbA#pB Y J$.pC;CCqDK4DSTqE[tE (c"0qFqEk y#w,C驓 U\ر$c/T$Яua͂lM1*|sMp B"7& ,R (0`VH c8R!72v*F$j 8ȹu`1`ԠJ>,漃b5hYeZoyMZnm[ H%.RIRV3#Akg;vXvm~}b^(T!DB2{",*sH j<ؠۍh"  _(x)! c3) jw`\_yG _ahva)NCuZ^m՟d;[Yg鷽&h "h.h.HohƟyށɑUI&|l86hfj.)>g hf[hi}j@ H_*C4:>w$_=yhy%X[11{yYjpw$*wYAry|^]'9I@ x=lVU/}Pp(8|XOBÒA<@aOЙAnK F s L}.=,-4 ZѤ k7A+?H5.~jᏧu1Jn! R?2mя`D_P.{4 G3=Fҍpu22x;Rȧ}26h *ڑ":-*yba5K[Oz2_x-$'|ѐFBC(&55~U[Br͠IQbJ9k.aUGyR2.H=s5:Ƀ#:bIsԜNhZ ߌap^};&0oRCGT5? >= A yQ<0aX|S70ԪOHN\jw!KO5|Mq@XzD=Ӆ#+JP/X[VOnqEKV]J\bMj'e2PԈ 0y33yF TMR ]$#.0g,jM98rbcPT2,fjB"f ([VvfՓr:MhKҌ4mjִ5Mlʜ86Snnb{ w Q6>w[㑶xNq"T^LǐGiдzI {vI %^`<)ye(M]I O$@ =4FgB)bB-π)IQ`ƓJ)X 8p($r8Əpr:2-)***KBť+*wS=jǜBz*""SԪ{(r[,FbT,I1c Ǫ9 X)ۻ,J ,2ě\:HnlF +(r. \rb-ʈy-",u-JҺGb.y$ъK\8` $ !0)̐`d̬`5JsC0i0|00 /$<  1ڴ9S$MC4 d7N,NL:88C$ La48JO6В h<%h 0r@,FMᔽ4HꜹóUQATu{q5d[ } %Bi5W)(c˵1e2= Z##%9<]=$GZ@iu0:ցɚcؚu'˴w9# * *883Z],c,HaȲF =(8 ʽx%ҽ#ih(ZhOŨ h|h2x#,ʦj8J" U !y0MzX(ۋacu,ЙӰ`=N˕bC$@;7i$ gA%ZՃ@s$JXxJ:${$X@z@pr48XKx̜x53O\5HXt& $T('bB(ː y8jH99cAt~8'y[cUH pڜ\ࠥj&tPR0,G[8HOZdR.eS>eTNeU^eVneW~eXeYeZ啐Q256xX͈ n/U[[N摣> \5]] :Lq:A尓NfU ;,HP[l[8Xo_c͍T8U9Mq8{Zԛy&@Ó#_p#xѰ 3Dha@Q>S]tDhoN!V%s td`@ftLIiƊ^꫸M~jjjjj4" c #58Qj30 nPaC:^HfQfC7\+-k(s2K `164a)D^O3eͰ_ScȂӣ3;8;XP]ؠat@;۾9X9lȾɖ&jf#LjvݾfӢv(dwΤnM`G K~LN>vgjr@givj>svr(vv9wovtoGwVoGs?wwo's`zf|Gr}Ofv'yx[b,xeswrH2elwzxW&w\k_wxX&wsHuy7veo'w!,Ws         %   '$ +!+'/)9' 6$5,3-9/=+70"""''('(((''('(+++//0/0./000//0/042+444778787877878887;;;??@?@>?@@C- H0 F4W: Y=@??VH@@?UD%]P'gLjM(hT&u[%}blc*l`Y~dqIl\${.Lز/q@0Lf#,9TZ ޠ0-@Ir4@`QggC~ @JЂMBІ:D'JQz (CxVhvC$=idEWR) -aiK]R.IFvZJԢnd} byH³uN _T:WծrCցʦ gA0nkšֺJ׺6vka>Eo@VuQ"ӿe#,`}j)Є:`b7k7#50wDfc Frt5@1K]˄nwp*c p븜Mk)K:7 E$B PFSF( B :AxK^"QتNې IFph%B4!9rj’)@c;A!z\ (`#jgw@}Ha] | g'O[ϼ7{Q⑋f-tUИ2%JۢҁRuڧe>O@, 2ސƴ>Ui/uqC頂 "zd4-J3P~;@pPbi@NUZk+* Zo (P P XkUP(P#TdE܆Vv0 kU9 o56]#W9 Ѐ#XE>cNgݶ j x!z9C%~E3t0+cXk#Go9XWx>P@($g"Jt E@nR .pY-YV )UqqAX z? UCZ%!ZU9pZZv $u U(t%nԉHHD%[!5Kd  !8a-PU𴋾8XxȘʸ،8Xx(Ojx ȍ؍؎8Xx(yV{{çDG|{ WQ%1~~4%)DSL| O9. 1~,-xs"9e,S)3h*7X@7ht hoT؀[ ]:Oh!hx{ .xa$4; 8GrYliP {9Yy٘ Acie0yIəO@i-p-КI-cOQ9I9ٛ)ٛO';tR9љ9Yy虞H/u 5) ;zih? QΰPEQy eh:Zz:ZPڡe *P :U j* Pڢ$0O%:tE6O<ڣ>@B:}aD:3pI,Q:OELW[R9Va;_-_[z(=Tnzxz\H㸎y:6eQ+ӞJVQ`)/ڨB-$JvL)JaJF: ~IXJe-:#,:AQwS,}vRj:dG@0:2YwyBBgz48ӗ"D{اڧԀqtҔ;v:ɡ򄰋+02Wy1~3:Q B4cJ,Bw=jg1ӂBm?k8lyF I{J'DћIb03]yG|Y=1p a|!f[5P.1b-7503^h!F J}G@}hu%SW eqՒ{)Ǡa]۰ R xr*p  )_{nd2O-۰ 3`C PwؖxׁMv  oԸ[f Br^؍ԃ1ی tsﱵ qp mN⼉!#%(Ӌ}='?$6#M!1 bh 2%PFp 2 ,5  e'߸C AߔU.2jߤc-2::`3~ .(8]0ާQks2N$n( M:ePS4 **: VJ UB+Ē)ˈ1YcP 1QFadԂؐ ԠAپ4p!hf> r- 畢 mW~vBt@s^3}N_0# F> 0K W2s10c4RAF0 r-Q z葞6.= Fn@qm@ ` ^ nQ 4j > ( ;ä?B~a[*$.OB E/N_Y_`؊`pz}+= [hBy7Em참ΑPC6m0 P bUu2i"؋udy&(qH _5,\afij+>d’0ny,Ru_|)@>;8qe|!ȟ~r bngػ&j;8|{v}7r,P(㑒 `b},Dl_FU w,fTZ( f@1>KiV|f}a!r߁=y_1@>|e?n_%{H>$XbDeJ1%{h #t0p$ue%D 52 WL`Nv @ - Sޠ&g8xȋ "AZd|CNjHz[t퀈/ϝi="֡ ʏ>ݨfa׽6DuWc2KA>`ಈ2 gQ]iOQFAg\ɵ6X; GX Jnu g70m6Gr+d׭#Ax*:uUDWĝRI 2ZȌA.7yu$/Y;ĉx7%js|g8vyZeh^Yo N"y! $W~ (F06JMsFoa}EıIK/@HTQX?Aq[Ĺ 6R/';G=aʂ)rE+Qr |Eȇ~؊‹ȇGi "AȔ{XZS6T2#kqiT*=H[У`KZw pv` 5G1ر4ؙs1ӁF! %2Ҡ1K7 ;0ؙNk(F< xD4툂2P$ J(90̮_t ܋3KLL\LlL|LȌLɜLʬL˼LLLL'wEa>YBQ7L܎тXYsMԍ `!ob /ȓ,[p 8>!Ԩb(4m#XHPqAlW?X")O8Bpibl$m"4#dZ>\ݘe>Y 9ĶbPm7PG咥=Zp-a(K­ҞP (JdQ5ȁQ!R#=R$MR%]R&mR'}x`XxRdҹ59< 96-=SH6"434+;92@75 p9 P9J铕KMCPӨ6ev< TYTys|ePP|5Km2U @#hsaxX~iyHUmͪA4ਧUA bՁᔜ@[U@xؼt'+=1gpܞYmx*6iNFCc5S$tN8NX m 8rUeRE.сvEW/{] tSgLXL >ʿ@\p5j5jHJߘCuZA%I|' %,¤WO7O'(wJaHPo+mRRBf'-(PڰpИpF PPв=2@[-j.mrr<" }#wyÑ{-mrw܂]~) xHQE;|\('L݋U|X^Q`1%^ٴ2쭏፴"^=_ 5Ҏ+hXDx(x=N00@MP@s`S נּ1,RR$0H %~'0O aR!2E R @QP?0pN  "~?@lHݮ=GDP FPxN(p(|.rNPc0c4c&!:@VԖN]7eSƁzkI 38. Tc* HU`# {VnV^P (SfRUvUU'BiU֝⫡cHڄ!<`jVv(?0QG!aRP{gyNMq.sNuV\vWx >ݙl;cgWcAЋN΂IXTpQ$௠L8tht8D@i.i$`#gm#-XmSZl?}Ef|*$俇H|2JYp%@6ſpIiЃTx~Q`jWF 0jii&nR#L(2'DI2: n"P&4&0>@APPA ɮn u/kԵ=YRy&QLuX m*͆Ýĭ)xFFЌUH#$ K=KGxkXfnp' ݩAi\2(Zrj ^eSZp/{x\]u"Q=Q]Q i!8%J #F`p'^i^z޿qg^6^D">3. P,& RX[Fp %h"+r0oxXwI01g2W3uh$s6o3m9s(]xwI=Svu`w@8]x(7gDQQv(JHRn֦sCLц}t>LuY ;oSUQV\sYgȅ4<7]_7W?va7utcGFw0eOR1 ہl={ V+n ۅL2q &P0-PBw0@ ne4, #2ТдZH"P$LX⁀ll[pc>hhyț7ܠ@%c:( ]h!B̥$IuΕ6|  x *TNd0Bp;F)#"|˷߸&敘D &('A(B)BEOFPHRHS[ijrf&v/v0ztLVN^Vc\aYhajc-.=,5GLJÀٖݔɡ/̪5ڶ,ֶ0+>.-IֽFԹ[ϿҵgDDH<,0+9>nyCUWARbuHXĈܐٻᘓ‰͉ΐǿͿȊ֋ڗݟ H*\ȰÇ#JHŋ3jXp=A~Hɓ(S\ɲCxݓyOޱ3cƠ9&L4gkn"AAk'Tv>KJ&U1}uϦB,ױQ<+5١]eKVShVZuߊ[v{XƋ*.x]y)3,s̗srᘝ7g:]#g\{p߹oY|xDӷWfȔ~r9QrOHaO8N 6F(Vhfvh9` \ ,0( S|8Q: ~ן"0Q$dR8PF)TV"0?İJ1ra.1X)dig^a _# d#0K.Vh*蠄 L %]M}`czNhv駠zx8"sYg0HJB!kRPꭸ)/h/x )jyi`Vk1A*|c0(~ 6kP<J6ƫ|C 7K6/b*߀G,nkF~Hu[Kl2Ei{7B/,̤()Dmtc9jJ3:꜃j#tUsN:LR5옳NK9gQM5_˭6R|uހ{7ቷ}8t;8ڍ=8[7?ι띹䦃^zᒇκ戏y꭯^x(m, ϴ,?9 /е~:ҫ}Oo_o}O={=k>O;??/~~K30&2 #414 ?E̠7z GH(L!e 8p )Y, 1z* H"HLq܈T`9~йԤp0` H$j,,`3E.tp3fذ!8F8 IH@:bAE+ Ĥ9̤&730 |K0DZgZ?'gIZA0p22 #,1@(`8XAL!^ĥ4Ijr FFkz 8IrL:vD84rc'>L{9)x7 .8±P2ԡ߀D-jo4ԡhEчFThI3zR!uEAґԤGaZӔ9MYT?)J ԥ&NjLuҩ uM)Vժ\QUvugͪXzU"U_}Ujֵhk]VUq[Wխ+_ֱM+c;군(F7z hGKҚMjWֺlgKͭnw pKMr.W@E*VQ Tb ) JŮvVvI7/{ ^xw/|;7 W /`XN asXp gfO| O).q_< vM,4qY2Frcd0vr\cWFN2le!yS2`hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεwkX }?3w}ņsmi mc۽MnQ{BF.dqlZXB9٬t;R8f^s6'1'~PsԜ𶼗t3pσt!֗u |^u3ށ.eg7y\(|fJ hx_hf( vYx/s93 t gV VxfbsSNjcgy xrgv2H q 6㗁!׊ Ç8h vpH@f' !x f%H@fx(|xfh3!GD }‚~%Yb((sGAn }yahw%8X6y{}kՖyqç8XsCf(Ws׃ L)>f "xt'l؀Gq XmawK}nm6MtK0ttQz0qip#7S٘f:9#Ȉ' @| ( xf ؐ w;,XyjΠ0bi&yl(הE(f@PZzoé~5Svu؜2g@B:DZFzHJLڤ{(@Sw·vmv5'Ys}um[`bggpxޗz ͇,vȉczxCllXr)؄Oo;YtYz×^ j3IXt0h4th|zyIq dfq8)x9Z@JyY 5giiz9mE KʡzJ(ڮ)'Zgf&p`f.oZKn@ig` @P p m ۰ h/ mf'pa$#fph!<+h0uvhf h gpnVGK۳Zx{v@hofsn0 0+ jFfk\|}txWvgvc F@'f sf$ `[ 5fgָ۷۷ wm7w}f g  pY*f0 P`T kۼ BL1\F`b ׶) j- )q}0#tgflf)VJۺm)kgffe @oFff|\ɖ|f ̽vtɛ|ɢ^~oF<|T* g:Ϣo' #l6d|,~po% "7+-)f[X-D=J.6@7um՜-:=z`cWP JY؁9,a i*a>ɫZِ|NzM炮gY^y芾>^~阞难頮qK0꣞<^9sꦮNt.NPw뵮O' P.ȱN/N<ʾ͞ўPGΡ0ڎ~>^~}9N ?OY.~0~ "?$^,(>.4_*:?0>@?FHJLNPRiXgU?/o,g`YoZ*gy~dܫxafmkOy[ϊs/mľ?_|߹m?_ ⁏fȏlܗn7gZrᬡw в#mrLb"ݒi}f6>f6|IIt \wZmaI}fKWo ٥~t,-ťhI?r HJ \&}ǏHK,͹u歒HO4xD%MQYzO^: N?q G__]"DH)腇M=T"1lO"pµx"Ilh)2H !3m6PQVl]tH!*zB{*YmQ)(  h]]VWj5&tEvrZpw\r5\tUw]vu]xw^z^|՗}}x`'%%xa6x‟ bxcݕ;vcKN`;NCMv\#FVvf4,0g>SBIfV>gjziR,zkk{l6lV{mvm{nn{oo|p 7pW|qwq#|r+r3|s;sC}tK_L:*; cX+IZ}#iH0{Տ`wt`^5ETxU%" xB[KszGs\xIld%EҒLW4INR$e)MyJTRJ;D*Ij9Y~d -YAݍᯋd#L2Ie}9? f]oIJHMYs%&^ $PGh lp TFaYK`IJ:I4pKh LDi0 C0GFd8cB:6j UJ%:S@ߑ)E`>yN`찥/EkJz҉<5S8Q:N5E9' R̲{AxSV Ԡ`4M0/hO@a_G)ָb0 7aR7?Vv`|Zl|Ï@D7~PYE'DkӢV7*kBVy-v*[ҖO.r"hv{,Dma[ ֹbgBjGs%X>E< ڱ\`$=P-R_#–p8$"h 7 ~`Ȩ^وC GRc'D,ˏG qb X<渰aYƲ/LjK xç1DH\S6.?ށq46v"Z Iɼ RAh_V_-M",rf>dǢ6ÁJ{&ZKhJ7]1}+Btvx=q7icҀ#cO+HW|uf2`>6c5ǰϱr cRd)lm HF֨}kvh96ueю7E%'-Z͙mGX_n-{.5ׄbCwkߧ] o樚L0cfnGb68~>#R`\:[RyLŢegJiDIk{@ie{b:BXƽl|'=H.ߞ+~nAؓ+ /Wî1GsЍԟf#)R::izJGK0Nf'{%2SXyBMM 2EӮH Dٚ*2 jI׬l50heۮ"/F-l|+ͅdր}mm2|59=cKV'{쵯{|G?%w7BQH衿r: ,zh7?^BfY1 \68ъ@^@ ,A=n D8~:H 9$Qa(| 0A&ksOxqIl-*ʞ8D2Ŝ( (*E*D))((H z'[ )^*;٩***j NékF3B +8q8.op+R20 ;ҩ%P91,{0*+G t +LL#Ȳ,,Ҋr.:=-íZɞlܭ*15ܭQ>Jɤ .S|0/9ǻ0C#2x|! rH1 !IH+ l 2*0:0+ 0:0(s0Ȫd'˰I$>O1$;,۳3(< 2 )ڕ KH4FÓ۴uT (n9-ּ;;3=NK&³B3δJ 4+c[F̕ 6]KJL5N{!Z1@ZXKm5O#P>!6M$ȶ4 \F\"l:Mȏ#Y=۶趚NM#Q`6i> "8kb87+7>˷[:جRS8#3؃м3* *ў MK)$(C?:Q/ZѝĸթK 2ӘSԔKJ򤈯9 Rk;:JVK d;{?:>õI-;SRW :zkU;1m2 +< SP쨨@ڢ8Ph#֚LR$>3=eQ ̓km(Coռ3%kH,v׫O=+ꋨ XT7\K>JߺWW3YCʢ jեxY8AC $OR; S"eqX@ؿBҚ@} % C})AڹZ-[ [Mۭ@[m[`[[ 5SŽIٌ!( + x2[Q`1Yooō<꜈Z7ݪU$ "h* -ح(]ݍ]KƎl@y]$ "N :l`^^y*bohTڡ%PRPꪯc~؁dt%׊5Jr.` *-M$7 O9QcنLj1H1Oᜰ LpQfPndX]Ƽ;3"/#CP,$7Ӱ+'PTѝC_kz@uG"?@xS<9@M0kԢEj{jZ4OO}M͆N}X 8-MŋHh$Lj;M_` Ѣ&T#*Ii\=85~VX͋x sT>MSEP Zٚ4CPV{Ε5JJkV9"Yޕ(i-=ln8Ofk$z?gi5@&m"RqPn;Omm5ٓ XsuX2gvMo:CA@ʃ%{h%su(js;o-> tB/tC?tDOtE_tAo8afՑAF .L' K/M P Qu $JTQu z!=SoGNDL >qES_&IHD*\ 9'vk+"v R'm W pq~Ǹgb\|; xY\nW0>˯40j, v*olwɓi)%yf3.OX zSx%x D./8|$`Ox#FV>uy{((y?fLh"X=z(g)ρ&1"Aj}6T'j0u+(;-՗3U{9;*\=€[lQXvWz7G$ǹ^3$%J֋0V57Xц6om|o<}=?WqtA~i/AՈX8p/% B i8ȄJXX,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"Gb<8^L $%h `!>{,H$fΝ32m)ԨRRjE (0U-qXKaX $xxA3~A\^b-l0Ċ3nX _%HW`s+lh4i"A6ܺwۡI18S?p4RK4G6Ȓ/n%` yOڋ揚3FNzv 4sBPP c5h&F!$`A j!z -A ͉)*' `L.K /TwUFdd12d^B! m?,i#5޸Bb"tDx _PI$xdR] 55Лqw!:(v@$rv]Z)KleАXdEy`d% s-Y)@ )%A)>fC`&a@_B5ZC&lz;.Fi%b3⦝ "ꑫ$6K"yuVxʤ/X)&hprr*ȷĽK KȲ斂8}F0hH@q bz $LB "$!.J>07]Ch8F<"8)Ni"!b;!xG!H-rE| zf<#Ө5n|6∍mv#7lpCqƺ(AF6AGlxÐ|$$#y@jÏІ$3Mr# )N<@@|[hot#%.sJ $6j]ƤHK1u<&4)GUT #"G9mr1,ju>&:өNŠ6auҳ rIg'@? l^2=(B8f&mO>'6yэr!,     %   '"9' 7+70'''//0/0./000//0/042+777??@?@>?@@C- H0 F4W: Y=@??VH@@?UD%]P'gLjM(hT&u[%}blc*l`)?'A(B)BEPHQHR[ijqg&v/v0yuLVN^Vc\`WaYhaic--=+5FKJÁܔɡ.̫5ֶ/߸)ֵ0+>.-IֽEԹ[ϿҶgDEH<,0+9=o~DTW@RvcuGVĈܑڼᖑ㘓LJϐÿͿƈ׊ٖݟ H*\ȰÇ#JHŋ3j80CArIɓ(S\|ի6hиYF/˘3HOC I'|tg˔)]{PN_B*gSby+ٯmӾ5ԭWa[W]}w_hx-bx2{&͙  G^ً籞|n:6PG/_ʘIK=\8ow'ο??=wcѡ_Ιzvw>ҫ& lҨzs$M?I!s7Uda`UP1N 6F(VhfvaܢJ46J|,0(4:Ȇ4؎!_`:T`XdAE:5F)TVi%1C, pdih{:2 :H $Ӡ1U0dZ)蠄Z&13b ;w6=79酉9駠*mc >Bv HZd*뮡s;90`:02  *nN/[fΈFk# WHSȊVXqŒStkl0(C@N9  PE8a g;n;$2خkk2lK s8ä0DA vj(/'Qs:St騣N;JR'f9@묵6PoڎP#e6XkMw}zmwx>vw=ǽ8+8~;>9ߕ}8?ι{妃^z㚯塳N:㯷N螧;3S: 6-@  ;ݎ#wc_씟z_ߣ{޽ӟ? ?v8`SҀ:SO~Z,z GH(L W08a CaQ@9"HL&:,Lrt@c]Lr8H2hLc"Ё"Ffp?- VppHBL$!T r@jRNz$؋Z*` rY;.` A!̥.w"8AaE#(D!.pU`1̦6ܰ`8޸rL:vπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZZȵ?`e>,Z C|d00fh+bn{ӣ#7ы[@@/,QAbfu3[~6 o}ϻMֆn?x!,q1W|gwǜq{ yp^0z U, 壈5"`.Bz"<`΀Pg (s\,w9,'GO9890"<+ipf 8{Ao=SNt <sy/m "ϼ7?k'QP peK`*tӣ=9aP[T10أ^{"4Yf~]1;@,@`˜_o\+} >>-w\ fvϰ\G{w' wG}׀ysmİwЧ &ffGf Ԧ}<8`6|}8WİrEw&ȁsf+ -s+֧ 3q;7 yb x wF #x0` {Gf\wðreu~4H')sxzi a3 0Ax@ Qp8 S'ff03Xr)xxcVu' ք8-ȉ`H-p,=CQP 'tG a SfsK|xbqaV8rl2؆t7NJ{8&3ff/ipp v2~@ -Hx8fnǃdǏfvwJ|g,qxqx "@؅(fG8|eyn}(Y#w9טx8xf}kXfup@w萁r:GfE`F nPTxFY ws wX Ћց H֔ڗ^X}{ tQ0(O tSYz?:Yy =I8 p|ha3^ w~xY,ؚȈ gF2 0Лdu < s%ךVOk  3'uډrf̃fQ s8uQp t fIwi9ZUmYwkf j}zfؖlrvl s:$Z%*tGW&&m&02iBVb7:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^n7 @{0wg+wc'uͨwWm#r:tg7s'~ ~|u(eu&d͸q9LHo7,}#(I 0dy`Gp ŐXNrj I-:`ʪudx€j 8xP ڭU a8ݰry NڤaYס,z .Y({ + g`vf/i6 [pPcf @p p g6%{!:{h0 pV0c4f) `-P0hC[;[Vg~Tg熡buP ) fcl f^ bKW;t[gP? >+fPcaf. Ԁi@ Kf}[[m7tWe7s`F] yf&0 eFf `t0Ѷw}kz6P}P'!@` ^T;fp pڻذm{fc;ջ諳gfpxUia&lf* P pk}` ` ujf[ ~:a־ɔSgjV `h $, l [aF-̉ rmaafp Ĕ pf: ffEpG འ ~GP ">$^&~(*,Zf$3\Ϛ{7u>^gI`6.z} Q)$|Z?~H\GG=bKn*mX |[>~-%funkٿ-M؃.C|7 9ڠ]MMgşl螎rjIf-m]l=ݯ^~븞뺾>^~Ȟʾ4QQ<>NΎ̾pt. Y.u @Hk93Y.X΢uPNt _ "?=$p'R򿾒.@1Y8->D@Ao^HJLNPR&?WV=.\3>~bX_+h^(nGt_vxz|~?ifpbk9jrޫxfޓ}"*l?w6N?Χ?f1L\hf[w*&q6 }o;mc=/o+]U(fd v>go r FJL PcE5nG!E$YI)UdK1eΤYM3<@L2yWJL$&Lr`͂ni>̓ =O>-"TQ4sQFSD҇ e2PG4Qc5JPM5(Q"!@ttVZ褈&p\ڰøӜ25HĬuYf$RhK041&mA Yr,2`@'RM;cŢ3L,l3&ҿ^-L+`߬0肫b;xceղxdK6dSVye[vecyfkfsy&yz蕷}JGVze複ezjuZjT0ꪻzL6°oqijv[>7N߶n*oO.mp3 6q#b&r%|s;sC}tK7tSW}u[wuc}vkvs}w{w~x7xW~ywy裗~z꫷z~{{vHrhwe N4(yA%P;cʁz0aP<9vRZ(|rD$E`PpP2A ,^hX} Fn G*׿ 4HxE bEłtQ_¦D 0$ĈBjE8F(C$Ћ8,)ģ^ h@ (l>?iH$wR*o#PlALH^ #QW/TaqjהAV -wG-Z<;bLKd&q fFV5yMlfSf7Mp_4IzȡX%\ ;ѩNDA儧8w?",L9~)D h>q30XKjhJI8Ϣ&hK) pdM KFqÓ٫ d@jKJ@ f .'1.(DA;9HQTejDA>$ F-`Ԃd3}Jl)5"X%-o]*NQ(ᣣP+a@GլV:NO4ҺTQC6ze0X ZO8[06gYA!hQ(6b E8*#pbfp\%#@Gw.R>7]y{܂"}Sd;׸NEp;Q6QQC eopKv Cůq>tad[(m,΄Ba'~<7kTȊ" GH/BѾx#؉D *`_NDh*V裏(A>7G#'EF`I> 6@xOr)9˅h>sDyBKܲΠjn  ؊Rf`Ų1&OK#@ƨ );'.um.EVC"pG:$^;0u.WwF30Vw(aHp/]m5]b/{{EHpW/-6) n/m(܎Jԓ֒I!qIq0PKe+w"ܞH^ $ohNH$!繞qsUN~!7%"Q}hnWnV/ςFb)1,ňX֞}4M` |7E̼|2zQ,,(y =g7~7ġf(rbP4x_~A!LMjmh4~R5=L>g+r\7\vRE@ߋ}89|\0qoEvA{2X92;cp{;{Cp#?|s? ~@y՚93AqA;9 !x"8&A '8 xӋ&AB[B*Ԉ8W+B,B0 C1C2,C3LAM#Z0Œȟx&G\ |Gg H((x(Q$z }23UTP$- (2D6Eb'E꘩ ` B9CLY Z`RKX=#J j=kl )x@ƚR uܩVqrsz,[x A*ۼ*<!,"L*LX"z7 2FP-" PbsB! - RFtI4!k# E;Joଢ଼dʄ-b RkJ-lq-- IJZ溯誰꺮[ȮB/z0.b? cÔp/ /.Ä/3~aI(kQV(8 Dż! MTQ;%# 21;$" Ĉ݌ഢ\"J3l28 D;+<(p΅@+@uNE{9p:;:W;5dj= N[ YO1P;P^ʖ#Ќ$0+cN44}#Pw60O'6 y˶7 O'8 t $ P;Z[ PH.[# o b8I}SeN)컑+95>;kx *[=:+RJ%J-:;JԠk :(Oj +DM;TE'8( `d$PT( ^;'OR ֹ*:ۻͣ+T3<ڵ|7{=x<wHDi@<=:̛.۽wxϭ#Q B̬%-[hT[$]i;[>H &I ܆^H=VjsWlXǡ-XYӇ>@ !~P? <. ?뿚ݾY$T7v U~שP@  `=[?"0 S}m@ٳnÚ׾K䉌X:! -A #);j' >oL&0"hnWɩ a 8m8 rʉQX٬X.YMqqqqqq r!rՕ"*= na&r4<ڒ7vJBr*JYA)CA,FW 'm$Rahz)[#{g;:C>MPbQCB$f.t3D떡'n+;aut2Xtи#X_[ 8rR7ôU[QO>q]Ou`vavb/vc?v8IetvdLif.F$hC[0n'djGx  GkkDjb' `D?n#Q=G`)wQ0!h!LAdxIAKJ8d- r,wd-r/1g !o(6eW_e"!k187~ ˁ57DObU FqWe~O?*VWvzssRp?OAqiWS?* >xmSx*őH{q'pj%Xc #<*\_&TJ$B9M{_e{O"D/P~KG8 =N/UuS:[pXY[\'msSe_%mXX#0uY+o fx> OS\-m[xA 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ%%,R%̘%d5C&Μ:w'РBxģE^,2 ӨRRj*֬Zr+ذbǒ-k,„hײm-ܸr3@P~ @(>1a T`Ex=@C.43OpPL#"x")(R0[@EA1DeDET AH8JjI@- ( (EABtÕ>6d4"8(@'yDd4s'xzb\Cm@+ :(6$1ŒD Chͣ6* hCL/L 0 j3A/E4HyD! uʀ67YʩmSC9Xb ^\A\=嚋"=d-r-;/9+Тx#Vv *@;`ˀH/Ѫh7Π*dWpA//R:6Bd R '|X XS,3'[/I+ֽ2Zj 210 I-ek)萚`S0Da C^Kֳu4$jA((@rҕ[~W}/OG-}.KɮN9`+):A tC @J(!A,2M~َIV@}AP2=%A99{oU{R_X *)0Av UfsaS2OB _[K46KN0CA=P  5n})Npv+ ̶ⵯ~}N@!,{ +,+0//444;::KKKTTSZZZaaakkkttt||| $qe;Xv.3]$I8=- @!a*Ò8 J r`*#HD" &($#  kB#  26Sn16' "f(?@L0F/2"m{J0*!!,%{  /0/555@@@NNNgfgwww|||v UQQXemyau%F1jQH4a1CT,>@*8pLDAUm #>C? R?C"e'9u$&C'<^{Bt*!!,,{ "!"***444<<<@AAHHHTTTYYXnmnsss{z{s vgFbm1^ڙ.h0LP, Z*Q:^Ѹn0 HPA@/mBD( /.  ;50,>1(9[.9.!!,3{  )))444;;;CCCRRR___bcbonosst $MפNe;꺕U5:YRvIb#…M*7$ R0\ʅ8e[51Se0dp@idx";8*K#h.>+"\3=EA* Wc)G#'1*!!,A{ ###)))545@@@JJJTST___jjkstt||{l @4UU$EF5 GTEplT&7!0 &IJh( jE\bM,GH#h9Aq3T&G:&(!!,O{ ---//0434;;;JJJ[Z[aaallkstt~~s ebfi]Ŋ/ex3c0Z0^aXL/Mu sQDFGLHFFl`@9lMd %/l<"#?230@,*:=')!!,V{  ---//0444;<;JJJ[[Zaaakkkttt~~x UUVe]z"v@^ t+ X<@bLa1d6r SU1Qq-D'> R+##834&'<`V(<)+!!,]{ ---/00444;;;JJJ[ZZaaakklttu~~s eFi]*Z2a&nu,U`` JsHE0ȈxdhܖfP)A-& %'6#,?<9SU2];=.S!!<,zv          $ )   '$ +!+'/*9' 6$5,4-8$9/=+4091"""'(((''('((('+++//0/0//000//0/042+777??@?@??@@C. G0 F4W: Y<@??@?@TEVI^@XI@@?UB'UA(SH"]P'gKjL%kN)hQ!iU*hZ"t[%}ckc*l`*PŧBІ:D'JъZͨF7=X\Bs%\"'C /~a^cr<5x;CdQ3joPݣ %"zC4P $)$ZB /k]W/y_:'L [ΰn8<鋣≭ن 8ϘoG6VfKc=f""HN&GN^9Sy*ZŸi2f1mf6ۏ\!pL:x+<ߊfGH ȡ]Hȣ#4nȥS\i4=Z)ie`Y#ȩRZFh?e Xָεw^[u2Fr e_c8w*12~Xrp]`RA3Ჩy:b S1ԛ2uu"d YvELeY\/c*Rq=*gog}~jq@LISNm"Τ-p}9;3r7M!Gg1Ev_@jmg P@KVxw1B.-o+]*ǻN-gI}yO|a'3Rg3x2'dc3zg/9w ogD Bq BbJB/EMSUo}-FnDdyyqWryo2c'-!rXtsJs&K<-H6`%7N4 m8HsvqD7TXVdĄRwXWx}MxRrjfGGb| Ȇrx}|U؆i~H('zpiHf7Sȇ_膌8pGOq؉8Xx؊8Xfg8MX4\ at%XpDCyjx ys;{cwm7|ҌgTn/qc`FCgq7"֎3S8uq OkXuw>LC:߆ 獯sg>aV{ 탐!iz "TA" Chl5LwFwK`,҃u9owP `,+k-/yRE}&Tk8:iIR 90wFZnt;0<0 q.GٕI] NHbKDŽVkG1yIQA?F0G888e  ! < 0z)a5ћAqșLҁ𜇳7Hj)80`$ϱ0ED T )pGg$1KAEoy9õ P S 򉟙nC Ct ng͔) R *iyqG$YD, 4'ɡ b?sR ?jBɱ^5?) j`0 q Af7dpm|ʧ.y} jezA0AR AfA@~qZʁ@*JLJϠmp:YC"5$$C'X Q>ӆ>@7F7yq7@b,Pw)ґPPk@/\@t * {qo< JR ; +,R $Aҩ; Z{*?Z ک3yy'yIcP,B'Uk6kzAxg8't= t PtZ;r8)S{mZid[ IArs$аZѩm ,KS@w #mKo[f;Lҵscڧ{ۦ@h95sby*2/˓**DnJ/BSbz+m pC[DJ#bK0j#mZYABmʼKg{Z7`o ukۦ'5&|tq4tdGx7׿aںp{ *$|ZG@{1PPC"|)|I:fL/-\ %).i&oE`5Ba!dӜ2QԒ-AHlK R`ވ! Ȁ#vw0AACK&`%V]rMKB/bo :.,)E;s~%9Dx'yhKR޴n,]tuXL )d 㯉{k|{K$+^=|P DzX*A6IpNHX&ICCl 1|kثǽj;*>D+篏ի{5O\4u;Qz)}Ymc{JUqj]~L{RwTI$,\GAl,$F>_6 ;,j:PՀGQ''+LA0L/L8˰1\pT,UJ,J.jɕ;2 qqLƥ:M/Ǜ7o/sky`| /s K;eswXwu/aOȆʪL"[ɳHl|[Ώ,{3K'LlgGuI\\{O|l,U̚yͯ\ Xߝ 4pBNHE5Zcٙ!E$YI)U.48gK-5HMܒOA^ P|ͨ)FHNZUYnWaŎ%[Yiծe[!T+ǜ609s%9aы1u%_-t2Fz7k2ݳgdKpB:ܩFbpq;ϊ]&> +"jx62] <~:AO/Z/8$gpBin=qϜ0j]y껯#2Ev?y$?@;Ƙt1.F3 h:?, j'<"r >3x6n\*'m B=ɰ,f5ыڸxjaL\Ƴ1<.N6tj1 }6 gnThzR!?tL,Kbƀ!efV~7b gR$X2jƨjT7JW;D>58cJn/4@]xHG"11[qYx";b$hK  > jw8m =*t"6t&!D N jI:餃0pG:ԑuP-R5a_Ţe0|ǃD%Ixi!2rv?2#A E6dR!^BBGlCN|=B-OcB=-S ehCPFThE-zQfThG=QT#%iG I^}M9HiMIR$M Zo^Ѕx b"0e:9CY cXz)`dE>^,9&iWZT$-3թe:ST,Ibޱ-x4zY:9KPNGʴ8g]-QհFZqy-B̹C@r= ]bxktĵ= 25L]W?biQ5XdmӪ^pؙK@t )r[p*(XŦ^ȶX{^M TvC#mp+F<󻡬'>9 ʿI.Mkx5AgP[- rM+T-spfxsY&[F p!rǩFm1z{d¬We$^-av薷ŢcOKއnD״.qr\v's^Ο[Ĝ ==ys}Oܓ $h= I,D,^>}R,#BB BRS G` %dD~Rߓ(g8l j^y݀HP* 8!xlP'@(t?h4z X7Z*-(Vq{pR(LA ;0{0+6H1#M>ik 0)31-˰X)PJ @xp{9~{#3DC5dԈ'˵a "4u82 /LS6O; *(7S*9+3H" "8WXUA {`t^sVtEXEZ?82G+4JSKK+LkBk `?YO+" 5FXU(`P(ss(IGxxG(dTF5g:+k 4lsYi`,o$"h6u6cm+,PHXU`Ƀl N;<7d˷ձ/H+Dz;,}̂ ȄBE@TxT@E H\ˠTKʆ̤*11PzCв:&:Lb( OB(OKpMK)Kَ[ !꺯3# ;;X62HX:ںʭ 8Jbw x$  D8$@ O8 OX0O@OCc!&S<2&0C !@!@Gx0!XpPS 8G?DK e Q꼬 8QQQQQ R!R"-ҬP#ۏ@%1x$ Si)?`,& j#R#%'O4PDl*SdrT/D(ND@??-Srڳ>*DPQKKGT;w9y*3 aOC|b5 ɻхi+m<-`y 'g+]݉^"/S Jk,,|J,Kjkdab LҺ9Բdj=yLWxUyn ꬓM-No ڼ[h;OW~N׉B5ы:R֡վ6v9ݩ:\]=fX Y{nyێl&f ּzUa]ɑɐ_%La ntP><LTm9Š3κK*`ضKvc 3{C:*,nnq޶}}طkǀj iXoMNѾ7sn6zdg:^5oW:ZeٖFE^ŒMfC%[pqMXUQ)PX C MP?G$ʼn =uSq&[WC#%È'7 *W]wHv_r/sU%vX./s3uPs/g6tx5o5sn{-Wvxf=.$MVz7:SX.gWBRT4M4r@tBUx:wGVxutwIZ!9T|͈8W/XstOVgaT B!<,A \!,b"""+++444:::FFFKKKfff-  4@40,∸̅XL !,     % !  )#9' 7+81&&&//0/0//000/.0/031,777??@?@??@@C- G1 F4W: X=@??@?@WF@@?UC%]P'gKhPjM(iT&l_=t[%}blc)l`=yd'rj3FFFOOPOPOPOPSSSVWXWXVWXXXVWXWXXXW[[[_`__```__`_```_hhhnpoopppootttwwxvxwwxxxwwxwxxxw|||,:=J%>'A(B)BEOFPHRHS[ijqg&w/v0ytLVN^Vc\aYhajc-=+5GKJÁܔɡ.̪4׵0+>.-HվEԹ[ϿѵfпDDH<,0+9>n~CVW@RubuFVĈܐٻᘓ‰͈ϐǿͿȊՌܚݞ H*\ȰÇ#JHŋ3jXP<A~Hɓ(S\ɲwٓi/ޱ4eʨ9L4gcN"@=c'TLv>ClK(Y1}uϦB,ױQ<+5١]eKVShVZuߊ[v{XƋ*.x]y)3,s̗k糝v^ttөW&4j+3Ѐo7oW>rᘝ7g:]#g\{p߹oY|xDӳw h̜>;r5߈rSXaSHN 6F(Vhfvha9\ \x ,0( s|8qF: ~_"0xU$dVHqPF)TV/DܰJ7r!.7X)dig^a #$#0K.9Vh*蠄 %]M}\SzNhv駠z8`"sYg0JR!kV`ꭸ.h3xr )jyiaVk1A*|e0~ FkTL1JFƫ3xD 7O53R*2ހG,nF~Hu[Kl2Ei{72C3<ˤ()DmtSN9jqJ3:阃*#tUc:Lb5딣NKõ9gQM5_˭6R|uހ{7ቷ}8t;8ڍ=8[7?ι띹䦃^zᒇκ戏y꭯^x(mo,t,D9 /е~:ҫ}Oo_o}O={=k>O;??/~~K+0&3 #,10 ?E̠7z GH(L!q Π8| X, !z* H"HL@q܈T 9~й$p0` H$j ,,`9.~p3fװ79 IH@:bAE+ Ĥ5̤&73 K(DZWZ?'gIZA0pR3 #$1?$ 8X\!^ĥ4Ijr FFkz 8IrL:vD`8qc'>L{g9)x7.t7P2ԡހD-jQo4ԡhEчFThI3zR!uEAґԤGaZӔ9MYT?)J ԥ&NjLuҩ uM)Vժ\QUvugͪXzU"U_}Ujֵhk]VUq[Wխ+_ֱM+c;군(F7z hGKҚMjWֺlgKͭnw pKMr.W@E*VQ Tb ) JŮvVvI7/{ ^xw/|;7 W /`XN asXp gfO| O).q_< vM,4qY2Frcd0vr\cWFN2le!yS2`hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7NGMRԨNWj5x3o~uw^f 0!PAԐ J,Fn{= 9oҬkyQ$pqjR`Fܼ8 h,3OctHOw-$p]g7u i~>uo&{`x0p ,f6`xHfH0x7x ȑד8ɓ;DYz'@l|hfDuG fW| 0p N|egAFٖntc|lrh( 3`T9$ ~0yppciQ(ט Ryo9p >f ',g&I P0(xf70xɛ9mnFyf?hn w Opu xjn췖jV$9yx9 Cι yxY9ry0։ nx  נ0rffy׆oifJjit6&f'ڡ*Kaɢ0(u)6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZ/r$Giil o n`xz|ڧ~:Zzڨr8Y ٘y :ciD01W>Ixzl65ZcIl֪a9j |hpzꘔګ q߉Y Iيk6:X0yɠ頻ɮiʉ:g p) *湞)z3:f )f˜ ";$[&{(*,۲.02;4[6{8:9>>BK?kC۳GLKlP Q+O[pU[_۴b l3fK@B^~ ">$^&~(*,.09*>p8ޤ=gH=͇guRW䗹p= ٩+GᨫY3QI3 4wJ;f=lxp*y G׈@|w ~ ];>(jkJ+ė۰lnȉN 莞ǩkǝ.膣,K9XmQWŕXMZ|-G @`~5u /YI zyU|)@9ިIVJn>g>EyAgB.gcy|6_g9hyF f \`zFh"'퀶Pf&x0ogH|[WuWu@YӼ@\ZmvR]؜/g3/pYݎkN B)6ȿ%X g7 @9s x vz<; ]n:0O/nfZ yC p `Qguy x/V(+)XmC*^dNY @ @P( >p7H`@$Of6 ߟ f=0Y.oO2x=vOpO_>>y$;#b_…%O;K"'@OA%ZQI.eSQNZզ2u/be8p#U3hꕔ'`AJ+"[ 4CeϦjoH ^ )@g= қ7Ϡw h͇w~I1;{$*nۦl9n`K N9gs [6ҧw:i nXNøZyկg{P@ kϚQV%'C.$xOXl!刺vo }"XI<@vRH#~$CXkvN01mĐ`6">2Xt,񱯈pёgFč,qFv L>9+>8sN:N<*.03s,˧; С* P~JKnx*1$$G4;TmLyJu!Gϲu2$s$8* Ag=LO)y U`=N -# TuE0>x$6Ѕ)V<J,4:QcRt }DyQHP8!٠- c#Ip(j\ F*J8MBR|d)M#9KIR3tYK bjL|\l#XE|P 1w OIT`unRHi[OJ'V oJAE* U0rFWu"fcLXJfw{vUQ 7pNq MbC[yx[H.19Wp[hO 2/{'7$ N 9HĬTO g y S8z쏡L YOfOD xvͭ51g4CV|AmRk}]#T :(5lfq7u4uUnrޒĻI3\pj8u!גw.szS|@')nr\insyjz\ 󌢼|7=yoՃ&Gy|}ソX!|_W DXiOg}g_~}_'~_g?#(%NY"X;p+@|I؈1{ȏX!#&y9qXx%}R@X\A/9-ЪFU B ziA",d&i" @O"JY½&Ro 'X0'0R0;OkZp' ~(Cc"xx]b]z RK 2BG$-" 8*Cj:K"@Th$9p,ـP@u 2X؁%$B'z#\H =$XGLDjΘ0 p+DTUhS8H[R r8r*i-Ws%&ˆXT& K~yTRce YQ9!eK.Y%#ġe`fafVb>fä9 eFfk~$0 A i8JXmkFfe%= у7 PgXE2؇z@ }g~c[*[ CZXX8x 1`~؇Bii`۟8c(F8}8 :p須CgzhXCij^C%=ܳBDͽƵB ktz/iBsa$WA$ U\\']݉lSP`K8hzl&lMH%m*`* ݧݭr^K( }]֩Qd9ZVnVf܉! rIH. kNj N~E.n8:r/q%jiX474è_y0Mx<@ Ajj8pgܮon6`ah`y.{eU1XMĩT0 1 WF`%p| g?HpKGp@qgqZ^)s y4 Alф D-b"_ h<`Fp/wF`-fo5 cM}) 8%'4679m; h6@X=>/> DWtFw3]C$a$NfG6HIvu %5od$QGIٱ H?&sh( ؃1x >x(v@O]UnUS=I壘5uxf@wPlweF^ Lw}?exjGxxxxxxxxx?F]kXܷŋk'kWY`lkXx}JmebPdɘm}Vة񩩲kF/y&@{_\o B>Rlog_-fW(P$`,[O4` pO|(F/&4''e&0X%F,nSE1!&=Lhc71)cBٞ+44X3ၙgDxHě.60瓘~ChB*֬ZrʲV ^^H("S-U(ųb,  |b4m"2f]>z 1\jRl2f]ΝxE `QHԝOa[d$??y.SAXz3‡Jnx/YL6-_OK/P׭םHxBD)G_> ;(8PA'AB1@)A,L%[ZG  T ݥ妣'IЂeOxA>KM4dG4'MctdsD7&eneI*]3 0oau< ͬ%5JFʔ\ ./{f>I ǦpڥNJ )T鋘J)9/ Pj8H0idGXw~hvY蜥%/a,f}c%agښ;z|"dA(.|ͰMYZ"d* W.O1 on5љ ήõqTZJ iJ<1 v|*38{ܶT6 5C%xwrQ. q1:"4!5*vy7z@c&4rҵ(A,"dWSU Kr}tBH ٣[ZZ>vZ<؝A0WMy+(xZq[i~38^Ɲ{ CDr:\o@J朲uSF 85\6^{7>)A> _],*^e'TG=UE)>Ʋ?- \Pӗ &#MwW 0/2A3cR5#XNT1۔ 8 "A"dn~ d!ùv3Xȫfl~3OdІ>A!,d$* !!!,,,444:::FFFKKKfff[ dihlp,tmx|pH,Ȥr)4 BB3< 2CP$>ڷy]<׬(  !!i,~  Z!<,     %   (#9' 7+70'''//0/0//000//0/042+777??@?@??@@C. G0 F4W: Y<@??@?@WF@@?TD%]P'gKjM'iT%t[%}ckc*l`)?'A(B)BEPHQHR[ijrg&v0ytM~~VN^Vc\`WaYhaic.=+5FKJÁܔʡ/̫5׶/׵0+>.-I־EԹ[ϵbӶhDEH<,0+9=n~CUW@RbuGWĈܑؼᖑ㘓ƆϐǿͿȉ֋ژݞ H*\ȰÇ#JHŋ3j80CArIɓ(S\|ի7jYF/˘3HO#CI'|tWK*_{PN_B*gSby+ٯmӾ5ԭWa[W]}w_hx-bx2{&͙  G^ً籞|n:6PG/_ʘIK=\8ow'ο??=wcѡ_Ιzvw>ҫfnְzs"I/)R!s7WlaWX1N 6F(VhfvaآL46L|,0(4:4N!_`:VhZlaE:5F)TVi%Q+ pdih{:2 :sHr$`1W0Z)蠄Z05 ;w6=79酉9駠*o :Bv H\ld*E뮡c;<0`:1RC 3E *n/fΨFm GHUȪEX`ŒUtkl/0CBvw=ǽ8+8~;>9ߕ}8?ι{妃^z㚯塳N:㯷N螧;3S: 8-B ;#wc_씟z_ߣ{޽ӟ? ?v8`Sր:SO~Z,z GH(L W0;xc CaP@9"HL&:,Lņrt@c]Lr8H2hLc1$ЁjpA- UppHBL$!T r@jRNz$ȋZ*b0rY;.b A!̥.w"8QaE# !.pUP1̦6ܰ`8޸rL:vπMBЈNF;ѐ'MJ[g>0N{ӠGMRsZf<0p@S}Zָεw^&3 fh"p5qt" 83Ml_[ζmA@vt!@1 jV$"~&h Lnsη~14/P6GG? 3{ ySp:F0AY |,`g~ ؀{`F-4fLf>sdVrkvdfr P rf!f .06p rw|{fŇf}6(f c@0{ngHJ(\؅^sFar{ww @` )wh|++kp@$z0fvfyfXfA(f\fef}ff furff؈tfz0lf{Pn抰Ȋoȋ8XxȘʸ،8Xxؘڸ؍∋hfI BrNuSih`V,BtH  em@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`bʀHpGf ejjizozGl0vzxz|ڧ~:Zzڨ*r9 쨩 'bcH/ٓ9@)at8څb9f`)hɖeIk{NJ:fFꞧ{)wjfrI:0Еb3ɛڮiZg♃`Ή))jAc :*K[fۈ% b ";$[&{(*,۲.02;4[6{8:ېA3>;>BK?kC۳GLkP QUk\UM;xsj˶hkm hKtkk # Q{{x+{[۸;[{<ع[j[pv[iB{;{6ƺ;Kg⚼ۼ;[{+{٫ܛ+{[kK޻ k+{ۿ<\|8pIp -fL۠f<<9xf#$^&~(*,.02>4^6~8:<>@B>D>n)Bࡪ]c&ȁ]߈3OY1|eרΟ hf0>Iɖ0ں%gXͲ.L𚄙ݸʓd-.퓉uJȫ^`6 LxY=u -) ^mu::J9.l|`(IGf?_B)uv ffg#fs peMfU/P t0av@-}*ogfIMJgByWuSWuZMh֗SR;z= V=A 4$Pk'=GC:Q GWi`v5g `t?x>S)xObơ` /nBt9< /fA\ ぢ #ӆOm2ERaŎ%[Yiծe[qΥ[]y+"a`+p oNCFUD$Dp ঘ|X'X?P-0&p+i e5솩W6GK95n+t귑+G=;o*]9S-2@TpAtA#Kj(e$mlѐm(†xe 9̘K 7,pKBI]`{*rS($ &r'+\,^!JzTL\MҼs˿|KwNJ0:2I Zȝf=pQFuQH#tR<<3ʴ, ) L>:`ój\GHRT4;,#wI )ιT{K]lJwPٲKwZkjh !̝ f]Ƚݕ\_I2vWo4+zR|w_~w)4|N 4ƂQW8DIFHuaV"WtTƨm:^)YBcZ}@נ(4:'o-atNy=>9imxݺ@#V{mv{RsPC 6%mfWlis)0&Km!F]n ԉԁ#iJ} F;5r1gbI{<68gt$xN'Ql{wm{7..ѯ+T>^|/+~cxr/"ک@FPfQyȢ`=AP<+ℚRYJP3a mxCP;a}C QC$bxD$&QKdbD(FQtA XXaR_ xWX Af %lf '4xG<<½F7\.B8Y$tR.P) P,(тF%d’qXR-;EW˱<.=>rxw6 P#)I@z{cD("L|J0nE?UXi9YdɃwaTE- J.h`478EcJ\e&cXF&yD% 3Y k9JWN\q<4ɘZ>ݥ\i^-}^FaT= Rd wE+QFnUH[ˣFjJ*kBse*\OӋ'ۜA)&[#j+>Mϔ#ucv@eFkYٚL <(Ј6rAd+4O6V{nxf7@޸t#3X{ a(UtX?úgg!p?5!Y(4l_XGs\;ϭu1:#ؾ@f:ywCxאX?1-~(2 } ӧ)~zk~8.}ѿUdI^?`h_?o~_j 8{-0^ g_ @@,@<@L@\@!- $! c : 7`AU{ %& |aರ!6 T`[p\Eo+bR+Zr#"Ѐ &pDϐW Hn ]4;ztP!kG;1835' o $)Eț @UHi;R,\S" 8")¨HH4@tt !вD71pl"{ w[rꘂA |J{D2k )SY ț[(0P\JԿ/[8H x6I ap9hp4q؉$C) &1JK<#NU L{D +XH'`Ɍ;8!P*7NH`я` E[07#Ey1{2 |*8αQTLNɍ{N >ᅨ #VK;8H|wў񝊄>8+xSY є(uBȻ+P-jYeӽڃMYԦZLZZh?Z [[-[=[M[]##9؋=zѨ"d[ͱGbm GHw#[mUYGV+=\U""tb'j'\ P!x2jQ(v"E'7e94EՍ&`C"d%0gVљdZ]~a ;oJ8$cvaAN0X 8PY\] lٙ)YU9wecJ~! U;:_P %E?Qb%g@t^gًڶh< - wfg}^%0@ ЄD j8LX|g}=[V bHF @~0F  h}[h5~F.JP0Ppg~H.꣖i^ $a!C};< jxFi|臓ipF0kk뫖mQDm/-]h՛JCj} q=VM 1lj}C% <8{>O`lt^ +F,qǾ.WsP`[߷p̀@ߤE*=v0LJ0 lnolP.>>> oj ^akaB -^QwBV ך|K5ЄO?@>Dlql;pp p61bPa&wA3[]2QῌnX(^iB@qM,J`(]'-#U'5A+\1&b5@> HDH`m0_Ac3Ө8 d8sEl A^_CyJFHI~ 9@0@A2A*oYuHSn%'qVn3W&⾉塱e` ,T'\J].me ff/@@8 =@ xoyOv1fPKeFiN(' gxyf^~ agxyyyyyyyzz/z?z/K5-'e-'h"li  `&g&looPdMz? uɩf&e_M#*Ѫy_F/{wu?p}pEp)$&hP@UfN}v r(RaU.3& O#2N˄EOL?z7d-6E0sM3c4D X/?RUu huZ^8  EdwR^s/ `Nhfd-^/Baĉ-#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w@G$$ZK`'ԨRRj*֬Zr j|-k,ڴjײm-ܑHBk.޼z/.l0Ċ3n1Ȓ'Sl2̚7s3ȮnLyc@P@xL!}GQфN@k|WYÿ0xG~?J%dC6'wŦdՌёu:ߋTH CgR+uU?c2}-νcDŽL7$+{@P!=va} RCI@d6P95ƜfP@/NÒƬ<G=5 ҦicAg\<*R"=KDl[xG5MuOtZ8uYD9/NV֦^uHءpp-ITfrǸ7R&IdSTÄsyDLk| & ztuR?DE*O#QA lN";*}zƖ 8iR+\$E)!5)e qx( $7(%QS$\׺ t).q;,]zKQbVPj'.037 oh03\` W0C,b9jƄ?<+laӸ66bo>1kcP`%+FK &SV &nPC2,fBƉe1n'!_~3<0AZ|H:,mюKSіKacӞ^qeT2x,6j'J#KDU#ŁKQ*4(yMg %?nT#G.z$f0I,:2&)!!,%{  ;;;RRRddekkk|||r DMSMHaմmi]qe51jQSa1rP*>@8qb.Ԅ9X >C?b C4-'9$ts<^|B')+!!,,{HPoS(V[BQG(C*ebAWMfahz#Q)  d`rBȲM!,3{   !++,:::JJJVWWeedkkkqprxwwzzy $]ۥ^e;꺙6ziRIfa!0XNIB0XFD*侖zmA2*n: $u]n_#19%c>23#=EG#*"m)'!!,A{  A@@GHHIII^^^llmsrq|}|x $@#9NNʮ -ծݬA$#xHaA-'͓H"?(QuEv((b^9?Ks}.A+,k%ABH7@;,,X'J')!!,O{  ! +,+444=>=GFFLMLVXW\\\fffkkjtttl @e^YVYYŊ/%x3]e `\,EQH^ YNMT a-M@ ZXH&1h R+##834&'<`V(<)+!!,]{   +++556:;;LKKSSSWWXZZZhhgnmnuutz{{x eFya*^-2e&n.B`0 0E"HL()X )L( $a_8 A-&.6=?<9QEhC$.Q!!,d{  ! 0//455@@@NNMgggwww|||u FUeixfQ^Xl%eZj(R h,*`4  X0#0*0pL%s #fD4 Q>)"dr(:<)(<]|<&+!!,k{ !!!***444<=kSzC , 1Q $R P "!C$#^4H@s-mK2@&.E=  :(s,&@D8:[.(!!,r{  )))333;;;CCBRRQ___bbboootss} $Ia%e;*DUT:%,IYrB҄(X*H]6 !).J8ȠVA[/es! "<1@#h5@@"]461GBX@ }C? R?C#.94-&C'<_|Bu*!!,{ ---//0444;;;JJJZ[[aaakkktut~r FEVhTea1RיW(@`` %8 -VD:Rt1DdhD)n`R $/. :;0",>1(9\.9.!!,zv        %   &"9' 7+80"""''('(((''('((('+++./0/0//000//0.021-444778787866878887;;;??@>@??@@D- G1 F4W: Y=@>?@?@VH@@?WF&gKjM(hT&u[%}clc*l`=zd(sk4BBBGHHIGGHGHHHGJJJOOPOPPPOOSSSVWXWXWWXXXVWXVXXXW[[[__`_`__```__`_```_cccgghghghgghghhhgkkkonpnpnppotttwwxwxwwxxxvwxwxxxw|||~\ijrg%v/v0zuM~-<,5FKJÂܔɡ/̫5߸*ֶ0*HսFչ[ϵbӷl<&*9=wDUWARtcFV͉ϐ؊ٖݟH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ I5| )3dJ&d 5q|d0w"AB(7*u˔пfUvahXJ8+N 0j"IWIIIBLqT3L84.8(j88}׊Bwy~hEX,Y(*Z9)D+!Ph([j061)tI8+|?],A܀,u7 wqqrWP0kK@@B4$a{]@|$a#/X,9`1YgP4 .F d6) 8Df8@@gxcЁ vžbgfy>/;z3f)*Ѓ:D<ƻL!b˭ђ/+O-o HL_( t  RЂ` ,@B % K` ˒f5T sCЇJa3'CEH D,H|")Q,.z` H2h\ FDmZ+ǧQ@Lu̐ǩv}t#ٴ9ҎxPLe4(-XkeXe-L,PYHԙ6W"Bz5.gD9!F[*CبA8FhKK4MV`\eͥY9$gFָεwۦ׼QhF;"vI}l#akk^$?nC(}aivC-6sPMB[; dӻU %. MO;'N[ϸ7_ȥpCv)*28 R Q !hp:f)3 HHͱH"fe+q}| R\=t8rKLgexRo9ER̶KϻSvlz4})JB/"ghCq᛽|RĠ"b5A(J;+z 8bl}E56]hl+R 5 dʘS@~7\ri?ϼ"gaHirZ{~jAW )7bE0g`zj +'",pXn'(I%!P1qTF )A'Ip pP%PF(bhtt_"P! k7?9MOр2 / 0 t Z.o sƒ w  0 iF sX2 j( 07Qr jQ$!(Awxp|4"gAv) /Ivfp%,P  pI0 .rtAar$]aSp)qvfa(g (Yp1 pP@#QQ R j WPMU(ȏ! (-H! f 2Аq] ق X_Đ`*Q@Hp$xR !QZ&(|0`)gn2Pp6 &)T rᇆ)쀃Xaa,A!ٙzɗ1xYYY N'-$p+x/w(J +@Y,B "۸LיhWUݙ18 З&,`Pi3X#XЛ0j *] :Y%3H )bP,Z$РIJfYz0QŽ5 # }SUw.]Vq%"%/Vpɝ') ꂟfqW /'ai)קʙaH~*5ɣ;*PIi7p~Уjʦ_8/%vb^(&p)RY4b M: `ڨ :)zg:呐] z)KA]A!: yJG*_%Jj(-V%JX3}֚!:˪گ1pw0JM٧YPR Q @, q,}%1+Y y }+3xRГYYX:{:||45WY,[y pPb೭ (s3kh[@ڶpCh.|dq:P6U2K9Y.jIQV{+z  @RvJFjkP`NB1/ ۻp#WrR6_5! *Kx 8^%6GAr/W8!saJq¾! 0 AV  <p'C$ј !,M>:3A]qg` ta8cX8% yn9Ct@|D_rD[h!'zUh>A܅`t(*Xo qX!pa"҇*%ȆqřȆ^ o|vDPHjw!G"& p.Nvp+`uh%xK:XT]g$ "ոv؍\ \5˨W(IhX8)i 9A gC9 ;9hI):10!fQ2qޡ'מ_eae0T |7zYлg{4{Uyq Җi і suy|ʜ)9q DKmh:O)<3ԪI *!E"QՀ:ڮP: .$,r̒&&ݧ }Āㇱ+cW|ϗW#]N,+~sҰx~nۗ."p.*%aJ"98x?/BE[GIJRK|p^.-8 >g?U˾. ~1( a޷qazY r6-ׂ8[a;/R@ޱ u"!\?[ _G*2p\I` ug5D6 9 #I ௛A+ OFA on j@ 8'#r  %0+  N=`Q։2WXK|io 0qPЁ q&ḋR0 v! /&IW&kl+&,8 bvu/u:1!rɠ!7`H@i`@Px 69j}@I YY,)F=A@%O|6j\3ЌӰ!8UɿYrj œ ؁ .dC%NXo`r Z2pTKƩY=)HF A̅!$ͺg?'h({+ sx; [+~N%zs"Ufi_8|*7 geq, dQCB't%IR igСEf!ZV`d+h7iE)kH roc LP ?q~0cT ?Te:<cC6{*dO̩!a!QKS '#S،4 3pC>("#@$nip%;@'(3䩪,)~C(y *A~G (Б o&Zgî.~p|j/1FF@'t)H 5l@t b҈#! XLpPB CPo(L2_QGu`Q'$C@~t)*PB־0Zy,X(8ΆTHhܔˉArՏn 28u$fa2Ww+2t_~#e8,H[r1 >83 1͏|eQ{)w^Hxǩ_dͶH٩!eU$yt Ho_6P(FO! Q byTf`V`og@}}=B$&1v&81CЧJB"Ec$c ]\N!" '!,af86I|SF@n&JH֤#!k(h#cd%-!I![q2Xpo) 8P碱N=J-%]JϨaa Ú28* |RP-"9a,y̆qK2q$zȤf59T(Ϛ&&OnS$g9yNtSdg;Ib_ 5ȯS"|=П&edh?&$ '3.B$S4 F4 "G% ߤWG+Rnx@(B;M'uH bЂedAp%(E_s!8ARj<OMK 58!`VG$! j0'(#x*D a^x rHW'A (9hET{ 8BujYMqF-5lcE'^tx[VlSB؊,޶t؃;EbЅ++kj)!hw3 v#v]F"(p<— }?)͇j 3,8tmDX\zx\ZHHBTb5P$#HN/xS|""_OqE2ѷ;.?o4ڂ0׻J2+$ PޗX ܰd01nlp&c, QC+`N˕y9_rUTI0I4!4 ~,Zr e/#1 3BMse5jMg.t#5\?o{%V,Mg|ͦv}BMv Aև|~4 "$mdc '0w[nP{3Itmt  ¿#"Kxp~Ӥ┩#8^!!!\`[Q!OHJchf eZ1WK]%.~l`Y\N!0/)6%X 76F%"m0[FE؀Ml"tANt?7(сX?{->p@R2,c Z*W(.+"-­Ja.p.1sP(M` InAnІAAA @d B42ʏ%`أ%)WX<¯ ү8PB=/#2?(EBP0<4M R:LB0F2 D[BC2aS1,J  CD cÅ.1ЁP;?LL?T\VD%(3.غ2S:زx/<i"oxgX1˕245Fd\9KEo xFG;xH@@Tq,sLG]BL=c4^S5JC NSȳ $YI%'c98ċͰZA8!GCр&550|e0`#ʢb0<(@Bh9A:u{JI~Z$hDNJXKhKԬip˻K LL,LZ>p,V,7bsHT",(J<ڢb #:NbN ,YhON2ꪖC8T8j/"6$  D=PT L,6Ej$8H1 EST2 MдP6)EjzPYM3%m, 8K5Nzr fRq#-DsQ^4ZHQkr(5HT4V' Q)]0Ӭ2eRXZlg6dJ8]8EBK:u̼S=S>S?S@ TrDU ȐD]9.E$ TiTXT ˽8TQy':Y8ih96pp 3 Uu U5xUSMoIeq9X%VZ` h5jm֋`UՇX0~ "D :)YД:8(Ԕs] Z97x] Ġ8h*1.*,WJڔʫR N30YQ$+ڪ[R2۬ڬr++-5h>r?֮N#F)T㠈I[M\c!sip8eY.)Q$634YLܵ>9,b&Xo8-  |@`#y/50O]КJ1_uMDuyߑ@-b:\.4.O`Aja&`^]WV/°-Br@@` 2138ap '\aJia0]Z z`*4J#+t C0%h '޽-.,  10rg %%UOK Љ ,^ePy"v *c5 -DcP3hQȍE.-Q:V Efd9*Pz$ppXĈ( ( V pB # Sֺ'hőcO\6EQ\9FY0eȄBdBD *\ I6gqNb>1c>r^BEiUb3Hjm(Q"=h#D1Hh|^h+2{k$U3 QVjziڒo U%,K^<(I!t5AgbF) %y.(:WPX-bkDҠo, 3҄Z_,[0&3=[,(]ڂJX:g;̻0Ҵ ٯXYYԌ宼[X]`+о[d, ]!?=,N}8` !W-p,\ NV`h!`>LD/`@VҠb[jd1&/M5~#24C/=>5,0R]Nt@PZ[]nvgM@?@??@@D. G1 F4W: Y=@??@?@VH@@?WF&gKhPjM(iU&u\$}clc*l`=yd(rk3BBBGGHGHGGHHHGGHGHJJJNOPNPOPOOPOPPPOSSSWWXVXVWXXXVWXVXXXW[[[^`_`_^`_```_cccgghfhggiihgghghhhgkkkoopopppoopoqtttwwxwxwwxxxvwxwxxxw|||~\ilsg%w/v0zuL-=+5FLJÁܔʡ.̫5߸)׶0)HֿFԹ[ϿѵgD<'+9>o~DUWBSudHXˉΑϋՌܚݟH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKY`e K# Uk̹U.C0 , _`^\uBjR|̙-!Ù8Fhx`5ČcG"Bn]aq,X OXzoUZuf5kXw`N!Z0Xq8p 1dO*)݀Kyp0+@ǟ@ Ԡ@0CBR$l A431<{. t rK3 (B5='`Htb+bhh\`Dr{05'Hx^IY*.9PK  4oC2 ɩ r)b3ȓfFTb3tdr*駓x:f jꪬ꫰*무j!eQe!2d #񚑰 CF⺓_B m=j =qT$sHP[5v^ *Xel[NZZB+1sr,sfi"D܂,ܢ a5jmA 5@D@s (-KW 9,Wp˅†lcԤ4Rf4-5'|49;܀*K^!ўe8 .6l8AH 3Q7AH4C&w sC(TE? O;sq ;$K?doя!:`cUv?I'fcK>_~@W 4 `=>~7zA`GiojD5zD4{ ӨFN(&gT@{AKe8Ak` }qCAhF3>g$fQ `BBG5DV  Ʀ+xG.qvif?$v% d}6Ύ1ע{ ͐'=i|s&IsZThC5pG^Xf8c$hX sX h @T)L-$?ywMdf!wP{=NcK}T)XwI{*M2ZR~\C71^<+ڗ Vua3ӏ:x @Uz<~%jэ&K  Bqpx YFV^*7c=M[ALkVe=e[vՅkm?a`R_ye!z&BB\樷tE. }= y|LV, t aG9e&jQ2U6p Y(FCz|$ bӮuzڱaQy5P0wИ| ,E+ (Qq>a  7_0º8:}bg, g%)fsG`2{"&6L (B>'υe5ZOq&!lx]1a+PDMZ.Ԡ`qĞyfB^Zָεw^%lq \'T#;HZ44"U/>hWh}!,vPؒ%B!?`"$@ #I%j]ެ`ois 4CT CCk! HbFLGED5~X H*4ZLsH@xR Ш f0F-V.u+'0+dӓ=EUI7Y\lk h\̈́q34 v䋡w ӠٴE=T8݂f?nl|x=Rm$\uG "# F`ҽH~qvx`r&3}`B7ҝtk9#:iT<#'W9jX@!] O; >/zӫ^gWvOySF>~4}ܗ7?s?0 e=-GPPDU$+r  @`% DDF 2#!;2 %"#LC/Bm\%1CEDLA#6H #`DcTMGPdG`HVO$U]JbDF\E5OknNprDGtGyFK(EHHtm]DDB "#W )WΔKJPy>{q@ bTOK Lng`LRrLɴL'ĉ8K wKK0M˰OMRHR5NQFQOFUOuOEMMUPZPP&O 2I %!W.6< xH`偲 qn97g%y "*ǐ`ST!VC ;siaS QUjTsbJMUUWUAuXLjd%dVmWiVRHoUWV,dfHF (@!!x؁& rFzn%HKuZKIq9nuZbZ\Y\(Y6ܕ[)[Ǔ_ \T\G\e8^6]ny!l]dT]ݕ_]\U#`Bp=Ən$ IR:0(Ͱ,&y"#9!aN@aXI6v` a0a&V ЛG)sHbad!d[+W.]0c5HnWЉD?AfVCdGҹM+d&vPt"ePGϸb49R$Qgg3 )xzG  FbFZvivh r%j.c&/JbYX3$p-p:1;:kƠADZFzHJflSgiA Z qi)2PHL 'rt _= @1p nsq C ]:i lp M7?#_z㰔Њ"r$ FGqu n cPb1iSbs1s61 Q9S8rBCP$?tY?< *7S(3sZFXz W'&HW:$@ X@N 7|њ|3' |y@ E`@%`= =@G@vc`)$N0&*"WPW90;0${0C l iNyq*҃&C"'P W9ꠗϘ4ϐseJSez0L#~;$ e3TK(8Jѳ.G H '+b`3x h+_Lbn YB!@Pd(/7ṖplD Zd}J9M*P2AZ7u@ {+( 9zСS#L[U4pWP`@I@Y_őZF4ouNc=j? 8i`3 |1Nva1Q+nU?a9! E?'tRbZ0 f9"ZE$#k_uY>oSW# IS v:I*2vISJHΰ<2EMw"D6tHY$W)Ǡ\ara ׃JXN\IUQfg/5SFT^>Tp۩E@cP$§(0Zp (a+pdSP89zj$Z* .3T)iyrZ` ya:2$Dfql@Q#H+L 5*զ6#q iAq  "=$]&}0=b`=R '#:(+J `8j`!"R61y{ӯ•P !2[p ;GW۷dR]&U 0ta+7P3{ȹTpg}+;$ q Sp61|L/[0 r"U6z jl oq˭yM1#ʴ 9@ӣ]+ӜgZ|M }ȝʽ}V-V1o# Anm+5G`}e"Mrr^d} W!@ (\><*ьwmی:&K ͢0/9}>! eD `qFO=P P   ToXl5mJg(1P@P ~P= ;vzv >_ A`6 `g?|Dޠޑ?0)(P a  ܀ #oAG6`)Le1J n #5-1Jt>@@P :  `PSpAt"ՈSi얐& _S nf!Y͸KmaZde:9o-T dNZd@<*T˴V\O;E)g_}w{}Ε 6wW~ywy裗~z꫷z~{{|7|W}6T#D0T9-3>,9L'Hs8`d 9$NPo!`P e$,Y YЂ\P8%)K^򗋰ZY`A(MfJΡ F`WLLBcЈr"r--BZĀTp8[6NUESpd=_hnj0XTtEs 6g? m2["PYEVp f4ܛ@P!qnUT=ަ<Э괐9t!DoC2U"$`ΰST8DK EbP1090m4]1˧A,"(:<oQc!E5)NP^WL3I#O9PqLPbfHXR-n@ ғⅆ6_Œa x&FiKXT i5 3#TYqeA<76l+@4$M VW* 2$%& 2W;~Vr(:[d4wcּkaQPd9M3kx߾MX1lt;N lxWw#g\"ڳlMYh8Zg'B͆M-킆pFМ;;i2|r@g!pK>ɦ 9lMU,j|MIazъ #y+W `%1xJO {i<(g 9Fm{ܣeAm{P,eR*1JVƕ ?"4=V-4 cB(6a)jߠ8BI*8#*(>% @9jl w `y. k;0(n;čh@`B<$#TIR&P'h&v jyim ,7*A'q jڕ\+8jA$k $h0 ,q?˿@ea&tZ'1d@_' @#2”a dk9i B@BL8a8CCE Ft'(k :(ҫ!{/8餅R(8ID$C;Lt`8 kPB@L H?H\2l"+icFq+*h-GLAGcGudwˆG l  j#G¹*~qG 3H,҈GiکUt㈒tHoYI|IIIIIdI,I JɆb0. # x.u9P28+  oԁ* /t|B0:3(3."#;0ÈR X8񱗰*(!؅J!;{!< &ۥj !5(M@ 9K^;l&r"u7M(VнxC 7`~"+Y9sd[X1*KY@꼹׌9#K,tIHEKL`ۻ0?z;"#>Ez:#KϽ{$IN',=Q1=#>@3 EH=3JyX=@W%=[_"%ÿ]c"P2EAgG^ @tzT@kxD9sr&%ih8]xGGD=tFDEeIhō%k''QYkT,(%}ŇjӆSUc5VfEb'~b(b)b*!b<*vʏb[a^P`_3 :Wt6*7vH^"Ӝ~%`*<""7j <B~OBH. hM6[4d M 1v&AIR&1>-Z=}@EQZ}[EUb`NV&fcfb#~f܌6e[jfjfkxR_-%I"11b}1jih(M)^W|T4V`C\QV|98 ;}QIhJ1+؈N= ]"d)in29yn& :L`iQ=E⊱{b\疎c+8j &jc*7nOd (cYF${F|N9_+6>#iN7>n&v;%ZQ=e0yi\AVNM|Ql@ ^jO+[N^ Jd~gȧQI]bFeˮmݮ(Ueffg~fQf~n]-g\jkk8n6b|Wj}lnohNojlaoof$> l}ohNP[ߖnp p p p p pppqqrHq8qX _qq(s(rgqH?r !r8Bq@&C݈rP-Wr(ǔ&qJ/O%rt3YrXstr8_q ݈3q#t)_rC*shErqo!,     %   '"9' 7+80&&&//0.0./000./0/032,777??@?@>?@@C- G0 F4X: Y<@??@?@XG@@?TD%]P'gKjM(iT&t\%}bld*l`=xd'sk4FFFOOPOPOOPPPOOSSSWVXWXWWXXXWVXWXXXW[[[__`_`__```__`_```_cccgghghhhgghghhhgkkkopoppottswwxwxwwxxxwvxwxxxw|||,:=J%>'A(B)BEOFPHRHS[ijqg&v/v0ztL~~VN^Vc\`WaYhajc.=+5FKJÁܔʢ.˩4߸)׶0,>.-IվFչZҶfEDH=-0+:=o~CUWARbuHXĈܐٻᘓ‰ˈϑϿͿȊՌܙݟ H*\ȰÇ#JHŋ3jX^=A~Hɓ(S\ɲxᓉo^28kI6/L4gs$D Es'TLw>S7 +^1}uϦB,ױQ<+5١]eKVShVZuߊ[v{XƋ*.x]y)3,s̗{w^ttөW&4j+3Ѐo7oW>rᘝ7g:]#g\{p߹oY|xDӻ׆͛oش!;s$M?I!s'XlaX\!N 6F(Vhfvh9d`\M,0( |8: s~#0Z$[\PF)TVb0DJ6r.6X)dig"^ﱁ $ҟ$$$08 K.Vh*蠄 %]N}dszNhv駠z8#sYg0Jf!k[tꭸi/h1bC CE *jyi*aVk1n짪 jXd+*91 8M"CEd-B9P8`.JWlq-+$nK+E{8C1P̤4iH'ts9J{p8 u;쬃Щ*Xk:j2es;M?N谍p[=wu}q_ͷx~7݄;.7=9mK.8[yߝNys燃~蘯^_nz7懳3#7N|0=<ԴA+44;Dn;;_Wڛ~?>^۟?ӿkgkbawZ~$a pO}Rҟ,z GH(L W07xc Cb =-vfm"٨QHL&:P4 9nDt?c(]Kj8H2hL0%H l 0B?Cl0OkBHBLd!Xуn@bRNz$w ƀY*%CrX;-bE""̥.wK#8YCJ0!aZ~PU01̦6C Âx6IrL:vz=І D!Zr#hF#:QpT(8$:яbT%)E-zRpTeiHSQΔ%)JqRt5թKiS15KTK-*Tԩ"զ?)V T޴OVհfVkUŊVzoXzURue]+\*׶U}k^zW֕j%a:W5|a;ƺ5EeXʊ hGKҚMjWֺlgKͭnw pKMr:ЍtUH+PWuEuv/vWxuk^7-o{ߛ/y ů l 0}{_ p|` ;xCo1= Gx,氆1,c4F1[+>1E276ryOUqL%;9T f,9_06pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ G^ !Alr0oDPny @_3 L Hw|"`0: B %KLu8=!%g1P-LWؽߝ:*f bpԏ`EŮ|63OF_Q}>-gﯙ|uʧws~|l @|8Fy٠ 9~Mu@ub聩 '{{G4X6s~mƃ6@j:yFxՆutH؄NPR8TXVxXZ\i-gJ }u{bha8hg`zF3e؅rn:g>8g@1ggwt0 q}gTph88phugygXh؈։8է"au=C`WyhvrM@g T ,TdWumƊHg3 G 0x vWGf"Gnk6@TPt H8ࠌ:㎯ ^׎(| M@a3瘎|ሂ |ؐnj ِ uv0E% T1 @kFux'v`r0FGC}()v|۰- F7p{ה 2uVI|p6M@0cwb9XitbINY0qٖLlHucY{YKٔ{ Hٔ`,v MqgIiyF8MhI I'g u0yEwـ:f8yڨFW7~g| MI t ɎP~0k(lmULi)t9yYH f)ɞ(Xst6P H ( 1pfI g7Hz~n|< {ԩ(H` [f ]U d7xjY׉C:dʝk e`J y vZjP*JZ*Q )rpl=ׇI''0yju棘DڔoW{X|]wQs觥2vlJzzjƺՉIHXU+i٫2+7 J*sUڮ8~~|`׀}y 3uy(8ȜyJڝ7}( Kf=w}Hmv ʭŊ ߗ93Ġر~f0 fFv0|(@k炴o (fSK F9,hp֕(Ȱmc9yyqx@Nw|{ [ʶ QZx FKZ{8۠~ רWJ 檹J`O;(uf=xgkh9hb(R׻gʁ<9;w 0+Kǖƽ; wjkW |K;[{;g)r=xrƕpƄv?@hihgdhk`n}ܿr(s\ gg UˈnQ.i|,~Wwzf7+g_ ?[p=~q;>ŧF'>wDq𾫖KxK*8:<>@%,gMǤHh,P\T/6ĸ ە Wf9 fGF TzMXZkgpv#gwg燖 g, puZW}rK4D@# mlgV70iu,@͍ZvfXt6 kus8al EW|n^BZ|[(E @9ӆD : _{o iÂ7tʶT 6`V(tق=Qlh5z@bRbbe=l,LZp54Ѥ?tI4]vCǜ5lh \<6hWQ-[ jr]@~Oҥj+̆ߍƛoxanTEoq1u Z`& .d,m2pHd‹j\hWoK7t ȔshjM{w!_s*Ů~z꫷z~{{|7|W}w}~~P$Q$Qa!D@|B*(AM APFy $P9X$@E1M ta\UNa}J6yd%9ZP%$Q xE,/UbBfb"@ xHN"*A*$9? I-IBC<حªn`J 1M_ UyKp^h1I$81N7 4:@0A(B2 Bt DTDFtD2D%oh.D3V4ˉ,%.;X,@81;S*TUJ3+y"BY?0A@ >( f,gEpY4s4>k^¸(s @ǂpHj:40>D@H$Ht&HHHHHH II,Iგ`9V5oڨዯ=,ZH,=o[K)җ*x'5̸D>]/h$aS}z R)h0LiݽL xZ٢=j XJ\[B 㥭"%o=5//"ɤ3.5 SyLz@-tEMVEMB%J萂ELQ 4`.ݵD]4%QT 5 րV&%^5@Mڣ>0$'TѹMW G 52 (t0L'&>(B2‹)(y0UNR1#*൝0B0a~67nTb$wAHz1@dM D0rn ˉ=6bh$}((GZ-\;OM~MIFB.4/nЅ"WB* ΀nW庲͵1q)"c'2b ä%0Yd^bP.O`4nXO5e6-=Ӱ # dh#S.[ s9X1 sR&[\kVVf} G3Hġ9s0сeV|h.tdMi+(]՛Ei.j>jNj^jmj.jj6VQT5( k`9SŹ֡tUruF}TWfk3\Jf@ HXz?m* ؑ<Juռ\숯LKϦDˌiH\]˥SxS5+>=5Vs>6RܾL[bZEL:nNIǔ-a9`rgrRL*_ L0O_&m4Nc(a&9Hac!baT'hBAM>BaDMVdoBC/ yR6C KE%5U^?vNd1~<FNqIdg5]qf>2(eQ\ggTn.[>FFSg'G_Kmie0,)O*7h1'j>Ns8s9s:s;ss?s@tAtB/tC?tDOtE_tFotTmttJtIKwtNtOtPuQuR/uS?uTOuU_uVou;Uk[k0wX^xW~DKK߷^E}(4U@faePC]Mn`SmS=pNztu&_ewNv-w{J>p~rgq.i,oxxxxxxxxyy/y_*]yyy?ysMLy @ߔ]P?'Wo_ ʀL؀z?{O{_{o{{{{{8G xe?j"pg9|{'o||gh#07o||||}E{ҧP? }|՗Po} -|؟ğM}P}}}WR}|/~?~O~_~o~~࣐~HHTDIZ l`WPψa H'Óu0 „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҋJt1ejiS]Rj*֬Zr+ذbǒ-k,ڴjײm-ܸrҭk.޼z/.l0Ċ_@ĠD%f2̚/SrD^@z3ԪWQibm6HDп'e ʗ3onI85pz"ƈMDǓHv^Ƞ=B ҂\>iM>#wP e ]wA_0 zhhcT6"@MP}8#5ڥK cecx$IA0A wB@SQIuS\neQey&GHCq9'uy'y'}' :(z(X9ƦCQMiBNd@igi;J *8т*}~*ENīBjӰұ*knJdr=AbHBnˊkU蛑: w 0UNj*0q;.QTNl,8+-gHlTD6/"F&X6+تN0AD(ݜ3;9}-LoNo:ﱄT V\%L" r C(&!(!F<"%2N|"嗍)fS"Ǔnlc8XèlhV7Ĩ|q](Gl_,cGP`# "|wc ٗ!_̆!!IEhBX+Rw@E/ѓl)@cT!T܆7^)]ArH7YE^s.%̷lq\&4cjѼYFyFlr3)!l,     % "  '"9' 6*80&&&//0/0//000//0/032,777?>@?@??@@D. G1 F4W: Y=@??@?@VH@@?WF&gKhPjM(iU&u\$}clc*l`=yd(rk3FFFNOPNPOOQQPOOPOPPPOSSSWWXVXVWXXXVWXVXXXW[[[^`_`_^`_```_cccgghfhggiihgghghhhgkkkoopoqoopppoopoqtttwwxwxwwxxxvwxwxxxw|||~,:=J$>)?'A(B)BEPHQHR\ilsg%w/v0zuLVN^Vc\`WaYhaic-=+5FLJÁܔʡ.̫5߸)׶0,>.-HֿFԹ[ϿѵgDEH<-0+9>o~DUWBSudHXĈܑڼᖑ㘓ňΑÿͿƉՌܚݟ H*\ȰÇ#JHŋ3j8CArIɓ(S\b=|ѣn޲9nQ6˘38/$E&E'P|lglL,c{PN_B*gSby+ٯmӾ5ԭWa[W]}w_hx-bx2{&͙  G^Ճ瑞i|n:6PG/_ʘIK=\8ow'ο??=wcѡ_Ιzvw>ҫ獜rr*YoRr'[|a[h!N 6F(VhfvaܒP0a6P|,0(4:(4N"_ :Zx^|:5F)TVi% q, pdih{:2 6H,$Ӡ1[0Z)蠄Z&17 e;gN6=79y9駠*s JBv )I`|d*E뮡sK;>0 :0r s *nN/fFqđ *HYE\pŒYtkl0@CC> #P{8a g;n;%2خkk2l+K 38ä0\A vD)/'Qc:St褓;VR'f9@묵6 PoʎP#e6XkMw}zmwx>vw=ǽ8+8~;>9ߕ}8?ι{妃^z㚯塳N:㯷N螧;3S: :-C +:#wc_씟z_ߣ{޽ӟ? u8`Sހ:SO~Z,z GH(L W0=a Ca؍R ء9"HL&:$Lrt@S]Lr8H2hLc1%Ё"npB-VppHBL$!Tn@jRNz$؋Z*`0rY3.`A!̥.w"8qaE#@"$.PU`1̦6۰ 8޸rL:vπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[׶`gxc62N\(E}pY9jBNN4-0p|X0RJP<<Jn朇9KV0`}4GgJa[PUw?qv1b`hЋl3f78YdnsAy˃Oy1Bc:WzeG@91¼ ʗ^sIb= b\!}|_Y'szu>5fYȢT:,GTћ~O Cr4~@GywjC  3 P} AuQWuhX zgʗ,؂Fh~bF.x8Hj2yԗ>6ti&@XFxHJL؄NPR8THi"WgJ|jzZgYg_8ЅjvgaXjHn07g6f0gfotwphf@ufXgyohfHy(ggx{V'RTu>CLGy[ugPp_WP W,WWtbFf@|A GCw}cf[tw' $8a Gcaf7pWs>sƸH|̘xx{P P0T'4|بbƍ8|XƸqy7g ٰ dȉf s^2pP fI7'xU& sJ{4T-ّUw× ) f8O`n7 tpD CZvYyٕWN)CqJ0;p 9mPYf G~@ s Y fhƚ璪Ct i|)|Ѩ$y@-}IJfNf{ٜ6J@(`X{}؍LZycM빣?z` WG p9 WYP*WGO`z `rp؋xua r&ʊfEw<A`t&&ꊰ8sHtps 7r8x0u(jƍ(  ɸޗxfеX0dƷ׊fZyr xeu=` l.nzݞHzlr>q,Ej۪x$%hm8KOvk 7pZ& " ]as0iI7!sC}B}Gz/|&}vkvs}w{w~x7xW~ywy裗~z꫷z~{{|)(J§!J1 X B͝3|Pln ZVdI)9#Sq B@P U -0>Pneq{JR~2ŒP;%Ѭ>Hp4JY`HSb" HMKȌ)EPdgE4QS\4_H$xA6$"bHQ?1ڲG@p|֋}AݠK!fcl 7d%-yIuu{[IPR-:7JTR*]JXRe-myK\Re/}K`fC1bb f3Yа4,+ m(3F#R"8yNm,8 B)Bpt570WV|P?c?Mr=ɟ+}@G`_0aDgI[gR6d6¦:8@17\0%M~T"uJA^0'DBN̆ $@<0AT'3Uf 4i[UTsP(Sd_@E䴵Ske#2ӦNAOUrĮ) ]CҰV`rBJ* &f\iBM1$F29]H Z #"m E@ͥ8P1Kݟ<*s*R^{Z()[ڂlAaegȹE_,x#so݅,nQ!Sdfzw Z7g浒σ&t }hg ыft`@ |؃@^Ѐ<ћ4LP<y'1X((:|:ԣtgc.S rHa!(GR@ hA "1{ŶuGMPA&C 1$  ~xGptD v˷؍yEYcm N B4eOC̀p{#ϝ>oT\,bA֎*TYwjhdiR\[\ѧ>.h8м0dCGJ {C=Bm@]T'ys֤ H!֮^ЩP9[t7XX)x#\UW' VLŠݣ @5p"@@\@ذGM G{#Ǽ9yЛ]kۛ+x8-"S%-пI. bQ@ۈ2R[Q ?,JkR*0/ڿ+ +,;~./zAb[@8J(JHBXBıߘ6a!1ƒ ëL0 P 0 i9 ;:33r[H@G C030C8?A?<@BBK/ X G..(S `8 bp28D2s$#|Y2X?+T(5pCpabp곓X%˵\!nԩԚ[ŀo`m @cY4|@ͿL o Hߌ". ή^x~>AP^p/<6`4ܔ*1&0>cqIc(Cn>3#;ç0=̈愣7aHqJ>pNfx^z]1_L1F1|FfE-f0jnrdFf'˔nhh5O* OOrr"si8ui3os7s8s9s:s;ss?s@tAtB/tC?tDOtEH%*GG*HIFEtMtNtOtPuQuR/uS?uTOuUsIɸVɸU'%̫z-l_?E[%!T5 n| >:o$*EkP&M-wYj꜖Jpxw<\tt^Orl].^xxxxxxxxxyy %My_yw/o5`?VzyrWO&WO?zHz(Pxǀ   cőO{_{o{{{{{{ƱrR ޽w{!g{N|{|R&|g C|||}}O)u|__|GÏ]|'Pտm}O}}P~?~O~_~o~~|}L b뇿Uծ \bG:_DZK$h@ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJE*骦O{Zj*֬Zr+ذbǒ-k,ڴjײm-ܸrҭk.޼z/.l0Ċ3n1` ̚7s|oȒ5@ YWngT \5ܺwo@L!N 98@)(ʄ!^ (n<o;Y> loIV?R@>D)A'^J8ak'u DAd!8"bDBr AqEȂx#9}" {`y:*$ga@L{ 1)R=TTi ՗^vTdn$iQ@-9'uy'y'}' :(z(*doBDeT{M iL.)Vi9*Ss+[F bO)ЊӰ-ٺlYJQrS.N_2tmGq,!r%S; Ut dܸrn:zSrttWL#7",%O8 G(ZOlcJ 4Di\;3ϥ Auk2Y801K*OFm6q4ټь5R*5AlR64Mے\6F2Ļ6JKR/}[.ݓi&TB]P4YP^ ^\,-gܯ;; ?<<+k*_?/'%O0}[#,=.% fl%k]C(&!(!F<"%2N|"()RVlt#^"ѳE/vQaa<#o nlfD#_6zqk6vx#klh$"s:dT)I@`F1)Ir/X% 6@?@?WSXT]XZUc^d`?@@D. G1 F4W: Y=@??@?@VH@@?WF&gKhPjM(iU&u\$}clc*l`=yd(rk3BBBGGHGHGGHHHGGHGHJJJNOPNPOPOOPOPPPOSSSWWXVXVWXXXVWXVXXXW[[[^`_`_^`_```_cccgghfhggiihgghghhhgkkkoopopppoopoqwwx~\ilsg%w/v0zuL-=+5FLJÁܔʡ.̫5߸)׶0)HֿFԹ[ϿѵgD<'+9>o~DUWBSudHXˉΑϋՌܚݟ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8ޣǓ=;{lМH*]ʴӧP:5z*OTjP`Êuy/_Brf%#7۷p%vuk¹;*;nܿWXʎBwLǐs-j'=++&9sȠC/ly mVo cѰc5Pkn;g 2svLuʎ9\V}o~p|g/!kW,:jcs3g`oQ^ 24 j!1GCOc4k D:"RIhPc+(\4 v- sVu%sH&R^}vY୦䕑QC#3v:՘@sElrU{iEcxe~hcYf>56O9y6hCY}PWMfԞ8@T7]~9NYߢ(j꫔Y9P@yõ뮼+k&6F+Vk?fv+k覫+kk.,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.nMS O LoJbq+|Wo?<ĀN~*b\>{|k |Cֽz0T#á$ X <FA L`g?gHC} <;}` r81`qp{` '{5̢[s``C)L##b@-$lQ"(p kA(G9 gChHc-Qr<QIb %AE/3t%I `@A{hJQE; s8d5"H&b@nafLθ1wFg:ɴBt;?v Ҟ̧>Jb6r ޗ0 MBІ:D'JъZfã. dXHè6sH'Fzі.zE>0bdZItc;p0K![:JubU՘Le`Yn 0>As U 0ps|`0Yj01l+Q VFO9nQ*BnY0`tի L ըF6؀[q :Fvlm%Kv`m nFuhl%QZvjU;~ekj*|!e r z!U u Pv-'^/_̗+qjha\w@|z|(х4[3Ă6F?VV ƷGPd8?^{'N1|d'QA9@-nPW< ^o~|б~tX\ 0z0g_5LNc*" &zoюTr@z+zE9'ecG2HӾh$=DU AOX;lO5'`mh;fiVak#۫}fW!v ['Q:w Mp}v ,0*:`[];7`1@'?3c 0H=kb S*0خ571*_ၘ@u-p{prhN]c^ܨN|fTrXtf&Am^k~s"nN<.h   :~7 sŷtϑ&yv06e )P&%dP:??>-Ϩ]Ҋ <>;=v_Vjnbӣ>y(!BxxV(+9 g;W0C{bF's>$ldrP?CZ)x ϧ{46z#h\ReUG6GG}OxI 088GU0.?b,0jm7~NHD`t p %yDgWE`$NT0 U UX6rޤ~YX0]`f7zm!CNsy$0g1&j,4{G%爴nMZLlgbUEOhy|h( [ՉLJO~SO>(011XJdkX1P?x0mg0ňqUH01%p׌t1xXy?H}H{C j;C0(9Yy 0?Ɨ8WzW~X%3X#{5MXكV٘V0YuYYt^m b@ ZCZ]EY)^u 0&U 0\ŅVǩtm]l:BMV NtyA0x)0VVPacS?)B0 s sg Oa@4A>F`i `$$_"d `_D0Yz%@pb&Ob&(bf1v 3Vc7cr0+dE6%dAd$Ze#fdPƢPve+EZQV\FwII:T4HC)KǰJWIjpj YiG4 EHFI@di~AK=[ziqVI~Z $jwuygjr(m6mFt%gpk;1xt&6tɶljZlzjVz6:|zmJgoY:tT2?oy 09jWrD>t ZzGÕbEa֟cTF qRqcnqq '%#{Zt r Zz)tNr fw(s4v9W;|gt qFtthuuVu7uZgtc NpG:i 0Z 3Omj0m J0M1ϸyu1Uxpiť9|`\0],0 0<;%0ų<#u|fEY;@ Z3}s Ix|ȈȊȌȎȐɤ#Qnpv0K>`C1g40! ,#PrcP\0p Pe#$#Is0# t #kOPF0KzQ C{ ꦫ+:0ҙ0Nt ?QWIDAzςE3\ sI4s #@e^腗IyWzZR& R8EP\IxYXl՗| LDMF댎Z`V%P`9`4=p <`6 лaUjUg3l$fclO^sFRw y6D1p_psPyF<B;wyi`D/G$HjH$0ִ Xq! Vn },hf>zUaR?q0a%pD]XYD2Ѧp0 y=US OȠk@؅hAgg :Mi0P pZ0~(f! lAcc`Q9"ܺ0^&vI 3YE E-_TPPG <P]uP =݃ĴDK=gBMWtb z8JͧuOy絬GlhAW001F0I@[ 0y C CU^Wc,1 LOd[I' 0@dID0hHIye6l(|RXzUBm&D1зD[x[zTn͝@&W\곙Pn#f^pE$t# I@oHGoz469 F0u]Fyd\)3}im?3K0Hq*p3&ٷr?3 p 0a]`x֊6IpCc8+s t @z% $E?iCSAdנ,$FPw&p_@#Y<-7@Nsp ¾?xE 88 Рg .dC%NXE5nG!E$YI)Ud,myYM9uOA5FI.eSQNZUYnWaŎ%[Yiծe[qΥ[]μ`$1b ,aĉ/ZBK|x-`fgС 1 gEf5\ -7nk6np-psn7| 9U fb7^H>9& <ʍzv1xp@3C[ʪpCl С %j,@B rU`a pjq'cJ5{j( eH( & kQ$2&@4T`AЗB9cZ9FBԓDrtCD U;ADHnC-6t3HSFהuVZ;a `PQxWbNa[%4T)tB nfH%9V5&Zl6S9 Zw_p1$T#@X=g L&bWEwS|2y*|1|UhGvqe)M_:+x>efi!Z87ӠjRJ |qfpS^hˆ(Sa3 'J]V{zpwꌀ%әj|Nr9Aц`|8$h~=@L!"SxF4~%2YD,7Z 7d@ P؀6Kth>2$[Dm*"N`r=`" &`=Eot#8CFYZVRp8:uzSpvNx4Őb+wIg=h{ R Q{ӕ)wSeA A)1ЄF8Zюz vJ FƂ-{0)&uIQR8qI_JT&I hD` 'a!+8TO:Ԣ5jWAAQj uGE!ZU8L`yO9ka"PJ]*SUf a# LGeB@V" HbXVke'iPQx׵n} œ0l (%k'r.khיZyɶ^B*rEbH 2V HtAцW죘3Hd Z<d> -T;2?<1"ЃAzT |piW[ uMl#T2A+E"}n|- 8?['x ~p'\ gxpG\x-~qg\̲ϣMt>b}ȉg5?9`yJ -8`@Ps9}nz!Lr4XX4Q0etL8tʐ˸ZS ~|}JIOY}mzDj ~`#XeJ fbU [!5p"\V]ǍWle/ ;;t><]q5_&`I7\2#߲#zuG#d9oHnq L-,tS `l ѿ:Qb)t@}K̘`;84 +,A~;A\AlA|AAAA|8P8ۈ{2{A)@:P˰Ȍ$ '" $Aps76ڈ05"?8(á`, 3 g83 Mb >}tTᐩ9Opue/9y?;2&'7Vr C辪>aW}RFL>id=RrUX)PX\m[Vɹ?Ncy :3,>L?V_s 8ਜ!5ږ3ӔH#J?Pô=s@q+tm挻οNVqY(,MSA5TEՁmJ5KL}/8 >e5@A@c3VLeiVqdoJQӋ=X3Tf>zM2W1ek?qfj恨X^.g?aZǑfHZ]}y~@nR?I[4Z%@Mh5gͅӵ@e]ehnh h~Պ=i~iiiiiiiiijj.j>jNj^jnj.j7jgjꪞ|jkk.k>kNk^knk~kkk'p99k#k.aa*:Ğ;j;kS;5Osc^S7Q6j٨GfHs;\F*0UpK1h\N\~>~Q}Yy=?qvpVku!>Zn@ntn@o.o>oNo^ono~ooooooP3o'o[nj `gЀwg pMp~D' `pqOq!r"/r#?r$Or%_r&or'r(r`5rS//308.+r5_j.o0X:g;s>s?s@tAtB/rC'j,Ot~sFj9G1FsKEtvtNHttQ9ՅL&FbR%uA,P8LOTmdK^/@YxgAQa߾Ka?n^nzejx0:0w * .w\EڄZx!j!z!!8"%x")"-"18#5x#9h`B8~8+8;8K>9[~9k9{9衋>:+9`P ^ 7~; ;Ӑ5 < o;<+|O};Cw_ӣo}s~WO?O@π $՗@N`1@ O=A~~%MBƏ w;nvcr:U:C̡XD#q;\"D(щJ\bx&r["0qXX+ъ_$ǘE1Rlc(;QrF$QLzrLe"5YJR2<s]B!}E%= 1Da*Ol0e&sΔyMdӚ&5oF&3Yq$&9NxӉT8N{Ӝg>OS 9PԠ(B)ЅFThBщnCo2 ;pipx-0.12.3.1/setup.py000077500000000000000000000040561343501662400144420ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys if sys.version_info < (3, 6, 0): print("Python 3.6+ is required") exit(1) import io # noqa E402 import os # noqa E402 from setuptools import find_packages, setup # noqa E402 from pathlib import Path # noqa E402 from typing import List # noqa E402 import ast # noqa E402 import re # noqa E402 CURDIR = Path(__file__).parent EXCLUDE_FROM_PACKAGES = ["tests"] REQUIRED: List[str] = [] with io.open(os.path.join(CURDIR, "README.md"), "r", encoding="utf-8") as f: README = f.read() def get_version() -> str: main_file = CURDIR / "pipx" / "main.py" _version_re = re.compile(r"__version__\s+=\s+(?P.*)") with open(main_file, "r", encoding="utf8") as f: match = _version_re.search(f.read()) version = match.group("version") if match is not None else '"unknown"' return str(ast.literal_eval(version)) setup( name="pipx", version=get_version(), author="Chad Smith", author_email="grassfedcode@gmail.com", description="execute binaries from Python packages in isolated environments", long_description=README, long_description_content_type="text/markdown", url="https://github.com/pipxproject/pipx", license="License :: OSI Approved :: MIT License", packages=find_packages(exclude=EXCLUDE_FROM_PACKAGES), include_package_data=True, keywords=["pip", "install", "cli", "workflow", "Virtual Environment"], scripts=[], entry_points={"console_scripts": ["pipx = pipx.main:cli"]}, extras_require={"dev": ["black", "flake8", "mypy", "jinja2"]}, zip_safe=False, python_requires=">=3.6", install_requires=REQUIRED, test_suite="tests.test_pipx", classifiers=[ "Operating System :: OS Independent", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3 :: Only", ], ) pipx-0.12.3.1/templates/000077500000000000000000000000001343501662400147165ustar00rootroot00000000000000pipx-0.12.3.1/templates/readme.md000066400000000000000000000336431343501662400165060ustar00rootroot00000000000000

# pipx: execute binaries from Python packages in isolated environments

Code style: black

*For comparison to pipsi, see [how does this compare to pipsi?](#how-does-this-compare-to-pipsi) and [migrating to pipx from pipsi](#migrating-to-pipx-from-pipsi).* *pipx uses the word "binary" to describe a CLI application that can be run directly from the command line. These files are located in the `bin` directory of a Python installation, alongside other executables. Despite the name, they do not necessarily contain binary data.* ## Overview * Safely install packages to isolated virtual environments, while globally exposing their CLI applications so you can run them from anywhere * Easily list, upgrade, and uninstall packages that were installed with pipx * Run the latest version of a CLI application from a package in a temporary virtual environment, leaving your system untouched after it finishes * Run binaries from the `__pypackages__` directory per PEP 582 as companion tool to [pythonloc](https://github.com/cs01/pythonloc) * Runs with regular user permissions, never calling `sudo pip install ...` (you aren't doing that, are you? 😄). pipx combines the features of JavaScript's [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) - which ships with npm - and Python's [pipsi](https://github.com/mitsuhiko/pipsi). pipx does not ship with pip but it is an important part of bootstrapping your system. ### Safely installing to isolated environments You can globally install a CLI application by running ``` pipx install PACKAGE ``` This automatically creates a virtual environment, installs the package, and adds the package's CLI entry points to a location on your `PATH`. For example, `pipx install cowsay` makes the `cowsay` command available globally, but sandboxes the cowsay package in its own virtual environment. **pipx never needs to run as sudo to do this.** Example: ``` >> pipx install cowsay installed package cowsay 2.0, Python 3.6.7 These binaries are now globally available - cowsay done! ✨ 🌟 ✨ >> pipx list venvs are in /home/user/.local/pipx/venvs binaries are exposed on your $PATH at /home/user/.local/bin package cowsay 2.0, Python 3.6.7 - cowsay >> cowsay moooo _____ < moooo > ===== \ \ ^__^ (oo)\_______ (__)\ )\/ ||----w | || || ``` ### Running in temporary, sandboxed environments pipx makes running the latest version of a program in a temporary environment as easy as ``` pipx run BINARY [ARGS...] ``` This will install the package in an isolated, temporary directory and invoke the binary. Try it! ``` pipx run cowsay moo ``` Notice that you **don't need to execute any install commands to run the binary**. Re-running the same binary is quick because pipx caches Virtual Environments on a per-binary basis. These caches last two days. You can run .py files directly, too. ``` pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py pipx is working! ``` ## Testimonials "Thanks for improving the workflow that pipsi has covered in the past. Nicely done!" — [Jannis Leidel](https://twitter.com/jezdez) PSF fellow and former pip maintainer "Just the “pipx upgrade-all” command is already a huge win over pipsi" — [Stefane Fermigier](https://twitter.com/sfermigier/status/1093073303521116160) "This tool filled in the gap that was missing with pipenv and Virtual Environmentwrapper." — [Mason Egger](https://medium.com/homeaway-tech-blog/simplify-your-python-developer-environment-aba90f32dddb) ### System Requirements python 3.6+ is required to install pipx. pipx can run binaries from packages with Python 3.3+. Don't have Python 3.6 or later? See [Python 3 Installation & Setup Guide](https://realpython.com/installing-python/). pipx works on macOS, linux, and Windows. ## Install pipx ``` pip install --user pipx pipx ensurepath ``` to be sure you are using python3 you can run ``` python3 -m pip install --user pipx pipx ensurepath ``` ## Usage {{ usage }} ### pipx install {{ install }} #### `pipx install` examples ``` pipx install cowsay pipx install --python python3.6 cowsay pipx install --python python3.7 cowsay pipx install --spec git+https://github.com/ambv/black black pipx --spec git+https://github.com/ambv/black.git@branch-name black pipx --spec git+https://github.com/ambv/black.git@git-hash black pipx install --spec https://github.com/ambv/black/archive/18.9b0.zip black pipx install --spec black[d] black pipx install --include-deps jupyter ``` ### pipx run {{run}} #### `pipx run` examples pipx enables you to test various combinations of Python versions and package versions in ephemeral environments: ``` pipx run BINARY # latest version of binary is run with python3 pipx --spec PACKAGE==2.0.0 run BINARY # specific version of package is run pipx --python 3.4 run BINARY # Installed and invoked with specific Python version pipx --python 3.7 --spec PACKAGE=1.7.3 run BINARY pipx --spec git+https://url.git run BINARY # latest version on master is run pipx --spec git+https://url.git@branch run BINARY pipx --spec git+https://url.git@hash run BINARY pipx run cowsay moo pipx --version # prints pipx version pipx run cowsay --version # prints cowsay version pipx --python pythonX cowsay pipx --spec cowsay==2.0 cowsay --version pipx --spec git+https://github.com/ambv/black.git black pipx --spec git+https://github.com/ambv/black.git@branch-name black pipx --spec git+https://github.com/ambv/black.git@git-hash black pipx --spec https://github.com/ambv/black/archive/18.9b0.zip black --help pipx https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py ``` ### pipx upgrade {{upgrade}} ### pipx upgrade-all {{upgradeall}} ### pipx inject {{inject}} #### `pipx inject` example One use of the inject command is setting up a REPL with some useful extra packages. ``` pipx install ptpython pipx inject ptpython requests pendulum ``` After running the above commands, you will be able to import and use the `requests` and `pendulum` packages inside a `ptpython` repl. ### pipx uninstall {{uninstall}} ### pipx uninstall-all {{uninstallall}} ### pipx reinstall-all {{reinstallall}} ### pipx list {{list}} #### `pipx list` example ``` > pipx list venvs are in /Users/user/.local/pipx/venvs binaries are exposed on your $PATH at /Users/user/.local/bin package black 18.9b0, Python 3.7.0 - black - blackd package pipx 0.10.0, Python 3.7.0 - pipx ``` ### pipx ensurepath {{ensurepath}} #### `pipx ensurepath` example ``` > pipx ensurepath Added /home/user/.local/bin to the PATH environment variable in /home/user/.bashrc Open a new terminal to use pipx ✨ 🌟 ✨ ``` ``` > pipx ensurepath Your PATH looks like it already is set up for pipx. Pass `--force` to modify the PATH. ``` ## Programs to try with pipx Here are some programs you can try out. If you've never used the program before, make sure you add the `--help` flag so it doesn't do something you don't expect. If you decide you want to install, you can run `pipx install PACKAGE` instead. ``` pipx install ansible # IT automation pipx run asciinema # Record and share your terminal sessions, the right way. pipx run black # uncompromising Python code formatter pipx --spec babel run pybabel # internationalizing and localizing Python applications pipx --spec chardet run chardetect # detect file encoding pipx run cookiecutter # creates projects from project templates pipx run create-python-package # easily create and publish new Python packages pipx run flake8 # tool for style guide enforcement pipx run gdbgui # browser-based gdb debugger pipx run hexsticker # create hexagon stickers automatically pipx run ipython # powerful interactive Python shell pipx run jupyter # web-based notebook environment for interactive computing pipx run pipenv # python dependency/environment management pipx run poetry # python dependency/environment/packaging management pipx run pylint # source code analyzer pipx run pyinstaller # bundles a Python application and all its dependencies into a single package pipx run pyxtermjs # fully functional terminal in the browser   pipx install shell-functools # Functional programming tools for the shell ``` ## How it Works When installing a package and its binaries (`pipx install package`) pipx will * create directory ~/.local/pipx/venvs/PACKAGE * create a Virtual Environment in ~/.local/pipx/venvs/PACKAGE * update the Virtual Environment's pip to the latest version * install the desired package in the Virtual Environment * exposes binaries at `~/.local/bin` that point to new binaries in `~/.local/pipx/venvs/PACKAGE/bin` (such as `~/.local/bin/black` -> `~/.local/pipx/venvs/black/bin/black`) * As long as `~/.local/bin/` is on your PATH, you can now invoke the new binaries globally When running a binary (`pipx run BINARY`), pipx will * Create a temporary directory (or reuse a cached virtual environment for this package) with a name based on a hash of the attributes that make the run reproducible. This includes things like the package name, spec, python version, and pip arguments. * create a Virtual Environment inside it with `python -m venv` * update pip to the latest version * install the desired package in the Virtual Environment * invoke the binary These are all things you can do yourself, but pipx automates them for you. If you are curious as to what pipx is doing behind the scenes, you can always pass the `--verbose` flag to see every single command and argument being run. ## Contributing To develop `pipx` first clone the repository, then create and activate a virtual environment. ``` python3 -m venv venv source venv/bin/activate ``` Next install pipx in "editable mode". ``` pip install -e . ``` Now make your changes and run `pipx` as you normally would. Your changes will be used as soon as they are saved. Make sure your changes pass tests by installing development dependencies ``` pip install -e .[dev] ``` then running tests ``` python setup.py test ``` If you added or modified any command line argument parsers, be sure to regenerate the README.md. ``` make docs ``` When finished, you can exit the virtual environment by running `deactivate` and remove the virtual environment with `rm -r venv`. ## How does this compare to pipsi? * pipx is under active development. pipsi is no longer maintained. * pipx and pipsi both install packages in a similar way * pipx always makes sure you're using the latest version of pip * pipx has the ability to run a binary in one line, leaving your system unchanged after it finishes (`pipx run BINARY`) where pipsi does not * pipx has the ability to recursively install binaries from dependent packagages * pipx adds more useful information to its output * pipx has more CLI options such as upgrade-all, reinstall-all, uninstall-all * pipx is more modern. It uses Python 3.6+, and the `venv` package in the Python3 standard library instead of the python 2 package `virtualenv`. * pipx works with Python homebrew installations while pipsi does not (at least on my machine) * pipx defaults to less verbose output * pipx allows you to see each command it runs by passing the --verbose flag * pipx prints emojies 😀 ## Migrating to pipx from pipsi Although `pipx` does not provide an automatic migration command, it is pretty easy to do it from the command-line: ```bash # install pipx with the recommended method pip install --user pipx pipx ensurepath # you may have to open a new terminal here for pipx to be on your PATH # migrate from pipsi to pipx pipsi list | grep 'Package ' | cut -d\" -f2 | \ while read -r p; do pipsi uninstall --yes "$p" # reinstall everything with python 3.6 pipx install --python python3.6 "$p" done # clean up rm -rf ~/.local/pipsi rm ~/.local/bin/pipsi ``` If you want to do this manually, you will have to remove pipsi's directory completely then reinstall everything with pipx. First remove pipsi's directory (this is its default) ``` rm -r ~/.local/pipsi ``` There will still be files in `~/.local/bin` that point to `~/.local/pipsi/venvs`. If you reinstall the same packages with `pipx`, the files will be overwritten with valid files that point to the new pipx directory in `~/.local/pipx/venvs`. You may also want to remove files in `~/.local/bin`, but be sure the files you delete there were created by pipsi. ## How does this compare with `pip-run`? [run with this](https://github.com/jaraco/pip-run) is focused on running **arbitrary Python code in ephemeral environments** while pipx is focused on running **Python binaries in ephemeral and non-ephemeral environments**. For example these two commands both install poetry to an ephemeral environment and invoke poetry with `--help`. ``` pipx run poetry --help pip-run poetry -- -m poetry --help ``` ## [Changelog](https://github.com/pipxproject/pipx/blob/master/CHANGELOG.md) ## Credits pipx was inspired by [pipsi](https://github.com/mitsuhiko/pipsi) and [npx](https://github.com/zkat/npx). ## Authors pipx was created and is maintained by [Chad Smith](https://github.com/cs01/). Contributions and feedback from * [Bjorn Neergaard](https://github.com/neersighted) * [Diego Fernandez](https://github.com/aiguofer) * [Shawn Hensley](https://github.com/sahensley) * [tkossak](https://github.com/tkossak) pipx-0.12.3.1/tests/000077500000000000000000000000001343501662400140625ustar00rootroot00000000000000pipx-0.12.3.1/tests/__init__.py000066400000000000000000000000001343501662400161610ustar00rootroot00000000000000pipx-0.12.3.1/tests/__main__.py000066400000000000000000000000521343501662400161510ustar00rootroot00000000000000from .test_pipx import main exit(main()) pipx-0.12.3.1/tests/test_pipx.py000066400000000000000000000176261343501662400164670ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import subprocess import sys import tempfile import unittest from distutils.spawn import find_executable from pathlib import Path from pipx.main import split_run_argv from pipx.util import WINDOWS PIPX_PATH = CURDIR = Path(__file__).parent.parent class PipxStaticTests(unittest.TestCase): def run_cmd(self, cmd): print(f"Running {' '.join(cmd)!r}") rc = subprocess.run(cmd).returncode if rc: print(f"test failed; exiting with code {rc}") exit(rc) def test_static(self): files = ["pipx", "tests"] self.run_cmd(["black", "--check"] + files) self.run_cmd(["flake8"] + files) self.run_cmd(["mypy"] + files) class TestPipxArgParsing(unittest.TestCase): def test_split_run_argv(self): args_to_parse, binary_args = split_run_argv(["pipx"]) self.assertEqual(args_to_parse, []) self.assertEqual(binary_args, []) args_to_parse, binary_args = split_run_argv(["pipx", "list"]) self.assertEqual(args_to_parse, ["list"]) self.assertEqual(binary_args, []) args_to_parse, binary_args = split_run_argv(["pipx", "list", "--help"]) self.assertEqual(args_to_parse, ["list", "--help"]) self.assertEqual(binary_args, []) args_to_parse, binary_args = split_run_argv( ["pipx", "run", "cowsay", "moo", "--help"] ) self.assertEqual(args_to_parse, ["run", "cowsay"]) self.assertEqual(binary_args, ["moo", "--help"]) args_to_parse, binary_args = split_run_argv( ["pipx", "upgrade", "cowsay", "moo", "--help"] ) self.assertEqual(args_to_parse, ["upgrade", "cowsay", "moo", "--help"]) self.assertEqual(binary_args, []) class TestPipxCommands(unittest.TestCase): def setUp(self): """install pipx to temporary directory and save pipx binary path""" temp_dir = tempfile.TemporaryDirectory(prefix="pipx_tests_") env = os.environ home_dir = Path(temp_dir.name) / "subdir" / "pipxhome" bin_dir = Path(temp_dir.name) / "otherdir" / "pipxbindir" env["PIPX_HOME"] = str(home_dir) env["PIPX_BIN_DIR"] = str(bin_dir) if WINDOWS: pipx_bin = "pipx.exe" else: pipx_bin = "pipx" subprocess.run( [sys.executable, "-m", "pip", "install", ".", "--quiet", "--upgrade"], check=True, ) self.assertTrue(find_executable(pipx_bin)) self.pipx_bin = pipx_bin self.temp_dir = temp_dir print() # blank line to unit tests doesn't get overwritten by pipx output def tearDown(self): self.temp_dir.cleanup() def test_basic_commands(self): subprocess.run([self.pipx_bin, "--version"], check=True) subprocess.run([self.pipx_bin, "list"], check=True) def test_pipx_help_contains_text(self): ret = subprocess.run( [self.pipx_bin, "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, ) self.assertTrue("pipx" in ret.stdout.decode().lower()) def test_arg_forwarding(self): # passing --help to cowsay should NOT contain the word pipx ret = subprocess.run( [self.pipx_bin, "run", "cowsay", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) self.assertTrue("pipx" not in ret.stdout.decode().lower()) self.assertTrue("pipx" not in ret.stderr.decode().lower()) def test_pipx_venv_cache(self): subprocess.run( [self.pipx_bin, "run", "--verbose", "cowsay", "cowsay args"], check=True ) ret = subprocess.run( [ self.pipx_bin, "run", "--verbose", "cowsay", "different args should re-use cache", ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, ) self.assertTrue("Reusing cached venv" in ret.stderr.decode()) ret = subprocess.run( [ self.pipx_bin, "run", "--verbose", "--no-cache", "cowsay", "no cache should remove cache", ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, ) self.assertTrue("Removing cached venv" in ret.stderr.decode()) def test_install(self): easy_packages = ["cowsay", "black"] tricky_packages = ["awscli", "ansible", "shell-functools"] all_packages = easy_packages + tricky_packages for package in all_packages: subprocess.run([self.pipx_bin, "install", package], check=True) ret = subprocess.run( [self.pipx_bin, "list"], check=True, stdout=subprocess.PIPE ) for package in all_packages: self.assertTrue(package in ret.stdout.decode()) def test_editable_install(self): subprocess.run( [self.pipx_bin, "install", "-e", "pipx", "--spec", PIPX_PATH], check=True ) def test_include_deps_install(self): self.assertNotEqual( subprocess.run( [self.pipx_bin, "install", "jupyter", "--spec", "jupyter==1.0.0"] ).returncode, 0, ) self.assertEqual( subprocess.run( [ self.pipx_bin, "install", "--include-deps", "jupyter", "--spec", "jupyter==1.0.0", ] ).returncode, 0, ) def test_inject(self): subprocess.run([self.pipx_bin, "install", "cowsay"], check=True) ret = subprocess.run( [self.pipx_bin, "inject", "cowsay", "black"], stdout=subprocess.PIPE, check=True, ) self.assertTrue("black" not in ret.stdout.decode()) self.assertNotEqual( subprocess.run( [self.pipx_bin, "inject", "cowsay", "black", "--include-deps"] ).returncode, 0, ) ret = subprocess.run( [ self.pipx_bin, "inject", "cowsay", "black", "--include-binaries", "--include-deps", ], stdout=subprocess.PIPE, ) self.assertEqual(ret.returncode, 0) self.assertTrue("black" in ret.stdout.decode()) def test_uninstall(self): subprocess.run([self.pipx_bin, "install", "cowsay"], check=True) subprocess.run([self.pipx_bin, "uninstall", "cowsay"], check=True) subprocess.run([self.pipx_bin, "uninstall-all"], check=True) def test_upgrade(self): self.assertNotEqual( subprocess.run([self.pipx_bin, "upgrade", "cowsay"]).returncode, 0 ) subprocess.run([self.pipx_bin, "install", "cowsay"], check=True) subprocess.run([self.pipx_bin, "upgrade", "cowsay"], check=True) def test_run_downloads_from_internet(self): subprocess.run( [ self.pipx_bin, "run", "https://gist.githubusercontent.com/cs01/" "fa721a17a326e551ede048c5088f9e0f/raw/" "6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py", ], check=True, ) def main(): loader = unittest.TestLoader() suite = unittest.TestSuite() suite.addTests( loader.loadTestsFromTestCase( PipxStaticTests, TestPipxArgParsing, TestPipxCommands ) ) runner = unittest.TextTestRunner(verbosity=1) result = runner.run(suite) num_failures = len(result.errors) + len(result.failures) return num_failures if __name__ == "__main__": exit(main())