pax_global_header00006660000000000000000000000064146270165140014520gustar00rootroot0000000000000052 comment=273c558fb5f183e16f396dbeeba2a951cfce678a pipx-1.6.0/000077500000000000000000000000001462701651400125045ustar00rootroot00000000000000pipx-1.6.0/.deepsource.toml000066400000000000000000000002701462701651400156140ustar00rootroot00000000000000version = 1 test_patterns = ["tests/**"] [[analyzers]] name = "python" enabled = true [analyzers.meta] runtime_version = "3.x.x" [[transformers]] name = "black" enabled = true pipx-1.6.0/.github/000077500000000000000000000000001462701651400140445ustar00rootroot00000000000000pipx-1.6.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001462701651400162275ustar00rootroot00000000000000pipx-1.6.0/.github/ISSUE_TEMPLATE/bug.md000066400000000000000000000010231462701651400173220ustar00rootroot00000000000000--- name: Bug about: Report a bug or unexpected behavior. --- **Describe the bug** **How to reproduce** **Expected behavior** pipx-1.6.0/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000006511462701651400217560ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea or new feature for this project --- **How would this feature be useful?** **Describe the solution you'd like** **Describe alternatives you've considered** pipx-1.6.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000005241462701651400176460ustar00rootroot00000000000000 - [ ] I have added a news fragment under `changelog.d/` (if the patch affects the end users) ## Summary of changes ## Test plan Tested by running ``` # command(s) to exercise these changes ``` pipx-1.6.0/.github/dependabot.yml000066400000000000000000000002621462701651400166740ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" groups: actions: patterns: - "*" pipx-1.6.0/.github/workflows/000077500000000000000000000000001462701651400161015ustar00rootroot00000000000000pipx-1.6.0/.github/workflows/bump-changelog.yml000066400000000000000000000034041462701651400215150ustar00rootroot00000000000000name: Bump changelog before release on: workflow_dispatch: inputs: version: description: 'Version to be released' required: true type: string concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: default-python: "3.12" minimum-supported-python: "3.8" jobs: bump-changelog: name: Bump changelog runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: Checkout ${{ github.ref }} uses: actions/checkout@v4 - name: Set up Python ${{ env.default-python }} uses: actions/setup-python@v5 with: python-version: ${{ env.default-python }} cache: "pip" - name: Get release version and construct PR branch run: | echo "RELEASE_VERSION=${{ inputs.version }}" >> $GITHUB_ENV echo "PR_BRANCH=bump-changelog-for-${{ inputs.version }}" >> $GITHUB_ENV - name: Create pull request branch run: git switch -c $PR_BRANCH - name: Install nox run: python -m pip install nox - name: Update changelog run: nox --error-on-missing-interpreters --non-interactive --session build_changelog -- $RELEASE_VERSION - name: Commit and push change run: | git config --global user.name 'github-actions[bot]' git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' git commit -am "$RELEASE_VERSION: Bump changelog" git fetch origin git push origin $PR_BRANCH - name: Create pull request run: | git fetch origin gh pr create --base main --fill --label release-version env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} pipx-1.6.0/.github/workflows/create_tests_package_lists.yml000066400000000000000000000022411462701651400242010ustar00rootroot00000000000000name: Create tests package lists for offline tests on: workflow_dispatch: concurrency: group: create-tests-package-lists-${{ github.ref }} cancel-in-progress: true jobs: create_package_lists: name: Create package lists runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest] python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] include: - os: macos-latest python-version: "3.12" - os: windows-latest python-version: "3.12" steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: "pip" - name: Install nox run: python -m pip install nox - name: Create lists run: nox --non-interactive --session create_test_package_list-${{ matrix.python-version }} -- ./new_tests_packages - name: Store reports as artifacts uses: actions/upload-artifact@v4 with: name: lists-${{ matrix.os }}-${{ matrix.python-version }} path: ./new_tests_packages pipx-1.6.0/.github/workflows/exhaustive_package_test.yml000066400000000000000000000044411462701651400235260ustar00rootroot00000000000000name: Exhaustive Package Test (slow) on: workflow_dispatch: concurrency: group: exhaustive-package-test-${{ github.ref }} cancel-in-progress: true jobs: test_all_packages: name: Exhaustive Package Test continue-on-error: true runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: "pip" - name: Install nox run: python -m pip install nox - name: Execute Tests continue-on-error: true run: nox --non-interactive --session test_all_packages-${{ matrix.python-version }} - name: Store reports as artifacts uses: actions/upload-artifact@v4 with: name: reports-raw-${{ matrix.os }}-${{ matrix.python-version }} path: reports report_all_packages: name: Collate test reports needs: test_all_packages runs-on: ubuntu-latest steps: - name: Get report artifacts uses: actions/download-artifact@v4 with: pattern: reports-raw-* merge-multiple: true - name: Collate reports run: | ls # DEBUG mkdir reports cat all_packages_report_legend.txt > all_nodeps_reports_lf.txt cat all_packages_nodeps_report_* >> all_nodeps_reports_lf.txt tr -d '\r' < all_nodeps_reports_lf.txt > reports/all_nodeps_reports.txt cat all_packages_nodeps_errors_* > all_nodeps_errors_lf.txt tr -d '\r' < all_nodeps_errors_lf.txt > reports/all_nodeps_errors.txt cat all_packages_report_legend.txt > all_deps_reports_lf.txt cat all_packages_deps_report_* >> all_deps_reports_lf.txt tr -d '\r' < all_deps_reports_lf.txt > reports/all_deps_reports.txt cat all_packages_deps_errors_* > all_deps_errors_lf.txt tr -d '\r' < all_deps_errors_lf.txt > reports/all_deps_errors.txt - name: Store collated and raw reports as artifacts uses: actions/upload-artifact@v4 with: name: reports-final path: reports pipx-1.6.0/.github/workflows/release.yml000066400000000000000000000061551462701651400202530ustar00rootroot00000000000000name: Release on: workflow_dispatch: inputs: version: description: "Version to release" required: true type: string pull_request_target: types: - closed concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: default-python: "3.12" jobs: create-tag: name: Create the Git tag if: >- github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release-version') runs-on: ubuntu-latest outputs: release-tag: ${{ steps.get-version.outputs.version }} permissions: contents: write steps: - uses: actions/checkout@v4 - name: Extract version to be released id: get-version run: | if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT" else TITLE=${{ github.event.pull_request.title }} echo "version=${TITLE/: [[:alnum:]]*}" >> "$GITHUB_OUTPUT" fi - name: Bump version and push tag uses: mathieudutour/github-tag-action@v6.2 with: custom_tag: "${{ steps.get-version.outputs.version }}" github_token: ${{ secrets.GITHUB_TOKEN }} tag_prefix: "" pypi-publish: name: Publish pipx to PyPI needs: create-tag runs-on: ubuntu-latest environment: name: release url: https://pypi.org/p/pipx permissions: id-token: write steps: - name: Checkout ${{ needs.create-tag.outputs.release-tag }} uses: actions/checkout@v4 with: ref: "${{ needs.create-tag.outputs.release-tag }}" - name: Set up Python ${{ env.default-python }} uses: actions/setup-python@v5 with: python-version: ${{ env.default-python }} cache: "pip" - name: Install nox run: pip install nox - name: Build sdist and wheel run: nox --error-on-missing-interpreters --non-interactive --session build - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@v1.8.14 create-release: name: Create a release on GitHub's UI needs: [pypi-publish, create-tag] runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@v4 - name: Create release uses: softprops/action-gh-release@v2 with: generate_release_notes: true tag_name: "${{ needs.create-tag.outputs.release-tag }}" upload-zipapp: name: Upload zipapp to GitHub Release needs: create-release runs-on: ubuntu-latest permissions: contents: write steps: - uses: dawidd6/action-download-artifact@v3 with: name: pipx.pyz workflow: tests.yml workflow_conclusion: success pr: ${{ github.event.pull_request.number }} - name: Upload to release uses: softprops/action-gh-release@v2 with: files: pipx.pyz tag_name: "${{ needs.create-release.outputs.release-tag }}" pipx-1.6.0/.github/workflows/tests.yml000066400000000000000000000050161462701651400177700ustar00rootroot00000000000000name: tests on: workflow_dispatch: push: branches: - "main" pull_request: schedule: - cron: "0 8 * * *" concurrency: group: tests-${{ github.ref }} cancel-in-progress: true env: default-python: "3.12" minimum-supported-python: "3.8" jobs: tests: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest] python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"] include: - os: windows-latest python-version: "3.12" - os: macos-latest python-version: "3.12" steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: "pip" - name: Persistent .pipx_tests/package_cache uses: actions/cache@v4 with: path: ${{ github.workspace }}/.pipx_tests/package_cache/${{ matrix.python-version }} key: pipx-tests-package-cache-${{ runner.os }}-${{ matrix.python-version }} - name: Install nox run: python -m pip install nox - name: Execute Tests run: nox --error-on-missing-interpreters --non-interactive --session tests-${{ matrix.python-version }} man: name: Build man page runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python ${{ env.default-python }} uses: actions/setup-python@v5 with: python-version: ${{ env.default-python }} cache: "pip" - name: Install nox run: python -m pip install nox - name: Build man page run: nox --error-on-missing-interpreters --non-interactive --session build_man - name: Show man page run: man -l pipx.1 zipapp: name: Build zipapp runs-on: ubuntu-latest steps: - name: Checkout ${{ github.ref }} uses: actions/checkout@v4 - name: Set up Python ${{ env.minimum-supported-python }} uses: actions/setup-python@v5 with: python-version: ${{ env.minimum-supported-python }} cache: "pip" - name: Install nox run: pip install nox - name: Build zipapp run: nox --error-on-missing-interpreters --non-interactive --session zipapp - name: Test zipapp by installing black run: python ./pipx.pyz install black - uses: actions/upload-artifact@v4 with: name: pipx.pyz path: pipx.pyz retention-days: 3 pipx-1.6.0/.gitignore000066400000000000000000000003241462701651400144730ustar00rootroot00000000000000/.*_cache /build /dist /src/pipx/version.py /noxfile.py /.nox *.py[co] __pycache__ /site /.coverage* /.pipx_tests /testdata/tests_packages/*.txt /pipx.pyz *.egg-info build *.whl /pipx.1 /docs/_draft_changelog.md pipx-1.6.0/.pre-commit-config.yaml000066400000000000000000000021001462701651400167560ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: end-of-file-fixer - id: check-added-large-files - id: trailing-whitespace - id: check-yaml - repo: https://github.com/tox-dev/pyproject-fmt rev: "2.1.3" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.5 hooks: - id: ruff args: [ "--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.10.0 hooks: - id: mypy args: ['--warn-unused-ignores', '--strict-equality','--no-implicit-optional', '--check-untyped-defs'] exclude: 'testdata/test_package_specifier/local_extras/setup.py' additional_dependencies: - "mkdocs-gen-files" - "nox" - "packaging>=20" - "platformdirs>=2.1" - "tomli; python_version < '3.11'" # Configuration for codespell is in pyproject.toml - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: - id: codespell additional_dependencies: - tomli exclude: ^testdata pipx-1.6.0/.pre-commit-hooks.yaml000066400000000000000000000002061462701651400166410ustar00rootroot00000000000000- id: pipx name: pipx entry: pipx run require_serial: true language: python minimum_pre_commit_version: '2.9.2' pipx-1.6.0/.readthedocs.yml000066400000000000000000000002361462701651400155730ustar00rootroot00000000000000version: 2 build: os: ubuntu-22.04 tools: python: "3.12" commands: - pip install nox - nox --session build_docs -- "${READTHEDOCS_OUTPUT}"/html pipx-1.6.0/CHANGELOG.md000066400000000000000000001064741462701651400143310ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). This project uses [*towncrier*](https://towncrier.readthedocs.io/) for keeping the changelog. DO NOT commit any changes to this file. {% include '_draft_changelog.md' ignore missing %} ## [1.6.0](https://github.com/pypa/pipx/tree/1.6.0) - 2024-06-01 ### Features - Add `install-all` command to install packages according to spec metadata file. ([#687](https://github.com/pypa/pipx/issues/687)) - Introduce `pipx pin` and `pipx unpin` commands, which can be used to pin or unpin the version of an installed package, so it will not be upgraded by `pipx upgrade` or `pipx upgrade-all`. ([#891](https://github.com/pypa/pipx/issues/891)) - Add a new option `--pinned` to `pipx list` command for listing pinned packages only. ([#891](https://github.com/pypa/pipx/issues/891)) - Add `pipx interpreter upgrade` command to upgrade local standalone python in micro/patch level ([#1249](https://github.com/pypa/pipx/issues/1249)) - Add `--requirement` option to `inject` command to read list of packages from a text file. ([#1252](https://github.com/pypa/pipx/issues/1252)) - Add `pipx upgrade-shared` command, to create/upgrade shared libraries as a standalone command. ([#1316](https://github.com/pypa/pipx/issues/1316)) - Allow `upgrade` command to accept multiple packages as arguments. ([#1336](https://github.com/pypa/pipx/issues/1336)) - Support Python version for `--python` arg when py launcher is not available ([#1342](https://github.com/pypa/pipx/issues/1342)) - Make `install-all` gather errors in batch ([#1348](https://github.com/pypa/pipx/issues/1348)) ### Bugfixes - Resolve the `DEFAULT_PYTHON` to the actual absolute path ([#965](https://github.com/pypa/pipx/issues/965)) - Fix error log overwrite for "-all" batch operations. ([#1132](https://github.com/pypa/pipx/issues/1132)) - Do not reinstall already injected packages without `--force` being passed. ([#1300](https://github.com/pypa/pipx/issues/1300)) - Only show `--python` and `--force` flag warning if both flags are present ([#1304](https://github.com/pypa/pipx/issues/1304)) - Don't allow paths to be passed into `pipx reinstall`, as this might wreak havoc. ([#1324](https://github.com/pypa/pipx/issues/1324)) - Make the Python `venv` module arguments work with `upgrade --install` ([#1344](https://github.com/pypa/pipx/issues/1344)) - Fix version check for standalone python ([#1349](https://github.com/pypa/pipx/issues/1349)) - Validate package(s) argument should not be path(s). ([#1354](https://github.com/pypa/pipx/issues/1354)) - Validate whether a package is an URL correctly. ([#1355](https://github.com/pypa/pipx/issues/1355)) - Support python3.8 for standalone python builds ([#1375](https://github.com/pypa/pipx/issues/1375)) - Install specified version of `--preinstall` dependency instead of latest version ([#1377](https://github.com/pypa/pipx/issues/1377)) - Move `--global` option into shared parser, such that it can be passed after the subcommand, for example `pipx ensurepath --global`. ([#1397](https://github.com/pypa/pipx/issues/1397)) - Fix discovery of a `pipx run` entry point if a local path was given as package. ([#1422](https://github.com/pypa/pipx/issues/1422)) ### Improved Documentation - Create a dedicated section for manual pages and add an example with `pdm-backend`. ([#1312](https://github.com/pypa/pipx/issues/1312)) - Add example, test and cli help description how to install multiple packages with the --preinstall flag ([#1321](https://github.com/pypa/pipx/issues/1321)) - Refine docs generation script and template. ([#1325](https://github.com/pypa/pipx/issues/1325)) - Add a note about sourcing the shell config file for `ensure_path` ([#1346](https://github.com/pypa/pipx/issues/1346)) ## [1.5.0](https://github.com/pypa/pipx/tree/1.5.0) - 2024-03-29 ### Features - Add `--global` option to `pipx` commands. - This will run the action in a global scope and affect environment for all system users. ([#754](https://github.com/pypa/pipx/issues/754)) - Add a `--fetch-missing-python` flag to all commands that accept a `--python` flag. - When combined, this will automatically download a standalone copy of the requested python version if it's not already available on the user's system. ([#1242](https://github.com/pypa/pipx/issues/1242)) - Add commands to list and prune standalone interpreters ([#1248](https://github.com/pypa/pipx/issues/1248)) - Revert platform-specific directories on MacOS and Windows - They were leading to a lot of issues with Windows sandboxing and spaces in shebangs on MacOS. ([#1257](https://github.com/pypa/pipx/issues/1257)) - Add `--install` option to `pipx upgrade` command. - This will install the package given as argument if it is not already installed. ([#1262](https://github.com/pypa/pipx/issues/1262)) ### Bugfixes - Correctly resolve home directory in pipx directory environment variables. ([#94](https://github.com/pypa/pipx/issues/94)) - Pass through `pip` arguments when upgrading shared libraries. ([#964](https://github.com/pypa/pipx/issues/964)) - Fix installation issues when files in the working directory interfere with venv creation process. ([#1091](https://github.com/pypa/pipx/issues/1091)) - Report correct filename in tracebacks with `pipx run ` ([#1191](https://github.com/pypa/pipx/issues/1191)) - Let self-managed pipx uninstall itself on windows again. ([#1203](https://github.com/pypa/pipx/issues/1203)) - Fix path resolution for python executables looked up in PATH on windows. ([#1205](https://github.com/pypa/pipx/issues/1205)) - Display help message when `pipx install` is run without arguments. ([#1266](https://github.com/pypa/pipx/issues/1266)) - Fix crashes due to superfluous `-q ` flags by discarding exceeding values ([#1283](https://github.com/pypa/pipx/issues/1283)) ### Improved Documentation - Update the completion instructions for zipapp users. ([#1072](https://github.com/pypa/pipx/issues/1072)) - Update the example for running scripts with dependencies. ([#1227](https://github.com/pypa/pipx/issues/1227)) - Update the docs for package developers on the use of configuration using pyproject.toml ([#1229](https://github.com/pypa/pipx/issues/1229)) - Add installation instructions for Fedora ([#1239](https://github.com/pypa/pipx/issues/1239)) - Update the examples for installation from local dir ([#1277](https://github.com/pypa/pipx/issues/1277)) - Fix inconsistent wording in `pipx install` command description. ([#1307](https://github.com/pypa/pipx/issues/1307)) ### Deprecations and Removals - Deprecate `--skip-maintenance` flag of `pipx list`; maintenance is now never executed there ([#1256](https://github.com/pypa/pipx/issues/1256)) ### Misc - [#1296](https://github.com/pypa/pipx/issues/1296) ## [1.4.3](https://github.com/pypa/pipx/tree/1.4.3) - 2024-01-16 ### Bugfixes - Autofix python version for pylauncher, when version is provided prefixed with `python` ([#1150](https://github.com/pypa/pipx/issues/1150)) - Support building pipx wheels with setuptools-scm<7, such as on FreeBSD. ([#1208](https://github.com/pypa/pipx/issues/1208)) ### Improved Documentation - Provide useful error messages when unresolvable python version is passed ([#1150](https://github.com/pypa/pipx/issues/1150)) - Introduce towncrier for managing the changelog ([#1161](https://github.com/pypa/pipx/issues/1161)) - Add workaround for using pipx applications in shebang under macOS ([#1198](https://github.com/pypa/pipx/issues/1198)) ## [1.4.2](https://github.com/pypa/pipx/tree/1.4.2) ### Features - Allow skipping maintenance tasks during list command - Raise more user friendly error when provided `--python` version is not found - Update `pipx run` on scripts using `/// script` and no `run` table following the updated version of PEP 723 (#1180) ### Bugfixes - Include `tomli` into `pipx.pyz` (zipapp) so that it can be executed with Python 3.10 or earlier (#1142) - Fix resolving the python executable path on linux - `pipx run`: Verify whether the script name provided is a file before running it - Avoid repeated exception logging in a few rare cases (#1192) ## [1.4.1](https://github.com/pypa/pipx/tree/1.4.1) ### Bugfixes - Set default logging level to WARNING, so debug log messages won't be shown without passing additional flags such as `--verbose` ## [1.4.0](https://github.com/pypa/pipx/tree/1.4.0) ### Features - Add `--quiet` and `--verbose` options for the `pipx` subcommands - Add ability to install multiple packages at once - Delete directories directly instead of spawning rmdir on Windows ### Improved Documentation - Add Scoop installation instructions ### Bugfixes - "Failed to delete" error when using Microsoft Store Python - "No pyvenv.cfg file" error when using Microsoft Store Python (#1164) ## [1.3.3](https://github.com/pypa/pipx/tree/1.3.3) ### Improved Documentation - Make the logo more visible in dark mode ## [1.3.2](https://github.com/pypa/pipx/tree/1.3.2) ### Features - The project version number is now dynamic and generated from the VCS at build time ### Improved Documentation - Add additional example for --pip-args option, to docs/examples.md ## [1.3.1](https://github.com/pypa/pipx/tree/1.3.1) ### Bugfixes - Fix combining of --editable and --force flag ## [1.3.0](https://github.com/pypa/pipx/tree/1.3.0) ### Features - Allow running `pip` with `pipx run` - Add `--with-suffix` for `pipx inject` command - `pipx install`: emit a warning when `--force` and `--python` were passed at the same time - Add explicit 3.12 support - Make usage message in `pipx run` show `package_or_url`, so extra will be printed out as well - Use the py launcher, if available, to select Python version with the `--python` option - add pre-commit hook support - Add `pipx install --preinstall` to support preinstalling build requirements - Return an error message when directory can't be added to PATH successfully - Expose manual pages included in an application installed with `pipx install` - Check whether pip module exists in shared lib before performing any actions, such as `reinstall-all`. - Drop `setuptools` and `wheel` from the shared libraries. This results in less time consumption when the libraries are automatically upgraded. - Support [inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) in `pipx run`. - Imply `--include-apps` when running `pipx inject --include-deps` - Add `--force-reinstall` to pip arguments when `--force` was passed - Support including requirements in scripts run using `pipx run` (#916) - Pass `pip_args` to `shared_libs.upgrade()` - Fallback to user's log path if the default log path (`$PIPX_HOME/logs`) is not writable to aid with pipx being used for multi-user (e.g. system-wide) installs of applications - Don't show escaped backslashes for paths in console output - Move `pipx` paths to ensure compatibility with the platform-specific user directories - Pass `--no-input` to pip when output is not piped to parent stdout - Print all environment variables in `pipx environment` ### Improved Documentation - Add more examples for `pipx run` - Add subsection to make README easier to read ### Deprecations and Removals - Drop support for Python 3.7 ### Bugfixes - Fix wrong interpreter usage when injecting local pip-installable dependencies into venvs - Fix program name in generated manual page ## [1.2.1](https://github.com/pypa/pipx/tree/1.2.1) ### Bugfixes - Fix compatibility to packaging 23.2+ by removing reliance on packaging's requirement validation logic and detecting a URL-based requirement in pipx. (#1070) ## [1.2.0](https://github.com/pypa/pipx/tree/1.2.0) ### Features - Add `pipx uninject` command (#820) - Ship a [zipapp](https://docs.python.org/3/library/zipapp.html) of pipx - Match pip's behaviour when package name ends with archive extension (treat it as a path) - Change the program name to `path/to/python -m pipx` when running as `python -m pipx` - Improve the detection logic for MSYS2 to avoid entering infinite loop (#908) (#938) - Remove extra trailing quote from exception message - Fix EncodingWarning in `pipx_metadata_file`. ### Improved Documentation - Add an example for installation from source with extras - Fix `pipx run` examples and update Python versions used by `pipx install` examples ### Bugfixes - Add test for pip module in `pipx reinstall` to fix an issue with `pipx reinstall-all` (#935) ## [1.1.0](https://github.com/pypa/pipx/tree/1.1.0) ### Features - Add `pipx environment` command (#793) - Add `list --short` option to list only package names (#804) - Improve the behaviour of `shlex.split` on Windows, so paths on Windows can be handled properly when they are passed in `--pip-args`. (#794) - [dev] Change github action job names - Add additional examples for installation from git repos - [packaging] Switch to [PEP 621](https://www.python.org/dev/peps/pep-0621/) - Add a CACHEDIR.TAG to the cache directory to prevent it from being included in archives and backups. For more information about cache directory tags, see https://bford.info/cachedir ### Bugfixes - Fix encoding issue on Windows when pip fails to install a package ### Improved Documentation - Add more examples - Fix the command for [installing development version](https://pipx.pypa.io/stable/installation/#install-pipx-development-versions). (#801) - Fix test status badge in readme file ## [1.0.0](https://github.com/pypa/pipx/tree/1.0.0) ### Features - Support [argcomplete 2.0.0](https://pypi.org/project/argcomplete/2.0.0) (#790) - Include machinery to build a manpage for pipx with [argparse-manpage](https://pypi.org/project/argparse-manpage/). - Add better handling for 'app not found' when a single app is present in the project, and an improved error message (#733) ### Bugfixes - Fixed animations sending output to stdout, which can break JSON output. (#769) - Fix typo in `pipx upgrade-all` output ## [0.17.0](https://github.com/pypa/pipx/tree/0.17.0) - Support `pipx run` with version constraints and extras. (#697) ## [0.16.5](https://github.com/pypa/pipx/tree/0.16.5) - Fixed `pipx list` output phrasing to convey that python version displayed is the one with which package was installed. - Fixed `pipx install` to provide return code 0 if venv already exists, similar to pip’s behavior. (#736) - [docs] Update ansible's install command in [Programs to Try document](https://pipx.pypa.io/stable/programs-to-try/#ansible) to work with Ansible 2.10+ (#742) ## [0.16.4](https://github.com/pypa/pipx/tree/0.16.4) - Fix to `pipx ensurepath` to fix behavior in user locales other than UTF-8, to fix #644. The internal change is to use userpath v1.6.0 or greater. (#700) - Fix virtual environment inspection for Python releases that uses an int for its release serial number. (#706) - Fix PermissionError in windows when pipx manages itself. (#718) ## [0.16.3](https://github.com/pypa/pipx/tree/0.16.3) - Organization: pipx is extremely pleased to now be a project of the Python Packaging Authority (PyPA)! Note that our github URL has changed to [pypa/pipx](https://github.com/pypa/pipx) - Fixed `pipx list --json` to return valid json with no venvs installed. Previously would return an empty string to stdout. (#681) - Changed `pipx ensurepath` bash behavior so that only one of {`~/.profile`, `~/.bash\_profile`} is modified with the extra pipx paths, not both. Previously, if a `.bash_profile` file was created where one didn't exist, it could cause problems, e.g. #456. The internal change is to use userpath v1.5.0 or greater. (#684) - Changed default nox tests, Github Workflow tests, and pytest behavior to use local pypi server with fixed lists of available packages. This allows greater test isolation (no network pypi access needed) and determinism (fixed available dependencies.) It also allows running the tests offline with some extra preparation beforehand (See [Running Unit Tests Offline](https://pipx.pypa.io/stable/contributing/#running-unit-tests-offline)). The old style tests that use the internet to access pypi.org are still available using `nox -s tests_internet` or `pytest --net-pypiserver tests`. (#686) * Colorama is now only installed on Windows. (#691) ## [0.16.2.1](https://github.com/pypa/pipx/tree/0.16.2.1) - Changed non-venv-info warnings and notices from `pipx list` to print to stderr. This especially prevents `pipx list --json` from printing invalid json to stdout. (#680) - Fixed bug that could cause uninstall on Windows with injected packages to uninstall too many apps from the local binary directory. (#679) ## [0.16.2.0](https://github.com/pypa/pipx/tree/0.16.2.0) - Fixed bug #670 where uninstalling a venv could erroneously uninstall other apps from the local binary directory. (#672) - Added `--json` switch to `pipx list` to output rich json-metadata for all venvs. - Ensured log files are utf-8 encoded to prevent Unicode encoding errors from occurring with emojis. (#646) - Fixed issue which made pipx incorrectly list apps as part of a venv when they were not installed by pipx. (#650) - Fixed old regression that would prevent pipx uninstall from cleaning up linked binaries if the venv was old and did not have pipx metadata. (#651) - Fixed bugs with suffixed-venvs on Windows. Now properly summarizes install, and actually uninstalls associated binaries for suffixed-venvs. (#653) - Changed venv minimum python version to 3.6, removing python 3.5 which is End of Life. (#666) ## [0.16.1.0](https://github.com/pypa/pipx/tree/0.16.1.0) - Introduce the `pipx.run` entry point group as an alternative way to declare an application for `pipx run`. - Fix cursor show/hide to work with older versions of Windows. (#610) - Support text colors on Windows. (#612) - Better platform unicode detection to avoid errors and allow showing emojis when possible. (#614) - Don't emit show cursor or hide cursor codes if STDERR is not a tty. (#620) - Sped up `pipx list` (#624). - pip errors no longer stream to the shell when pip fails during a pipx install. pip's output is now saved to a log file. In the shell, pipx will tell you the location of the log file and attempt to summarize why pip failed. (#625) - For `reinstall-all`, fixed bug where missing python executable would cause error. (#634) - Fix regression which prevented pipx from working with pythonloc (and `__pypackages__` folder). (#636) ## [0.16.0.0](https://github.com/pypa/pipx/tree/0.16.0.0) - New venv inspection! The code that pipx uses to examine and determine metadata in an installed venv has been made faster, better, and more reliable. It now uses modern python libraries like `packaging` and `importlib.metadata` to examine installed venvs. It also now properly handles installed package extras. In addition, some problems pipx has had with certain characters (like periods) in package names should be remedied. - Added reinstall command for reinstalling a single venv. - Changed `pipx run` on non-Windows systems to actually replace pipx process with the app process instead of running it as a subprocess. (Now using python's `os.exec*`) - [bugfix] Fixed bug with reinstall-all command when package have been installed using a specifier. Now the initial specifier is used. - [bugfix] Override display of `PIPX_DEFAULT_PYTHON` value when generating web documentation for `pipx install` #523 - [bugfix] Wrap help documentation for environment variables. - [bugfix] Fixed uninstall crash that could happen on Windows for certain packages - [feature] Venv package name arguments now do not have to match exactly as pipx has them stored, but can be specified in any python-package-name-equivalent way. (i.e. case does not matter, and `.`, `-`, `_` characters are interchangeable.) - [change] Venvs with a suffix: A suffix can contain any characters, but for purposes of uniqueness, python package name rules apply--upper- and lower-case letters are equivalent, and any number of `.`, `-`, or `_` characters in a row are equivalent. (e.g. if you have a suffixed venv `pylint_1.0A` you could not add another suffixed venv called `pylint--1-0a`, as it would not be a unique name.) - [implementation detail] Pipx shared libraries (providing pip, setuptools, wheel to pipx) are no longer installed using pip arguments taken from the last regular pipx install. If you need to apply pip arguments to pipx's use of pip for its internal shared libraries, use PIP\_\* environment variables. - [feature] Autocomplete for venv names is no longer restricted to an exact match to the literal venv name, but will autocomplete any logically-similar python package name (i.e. case does not matter, and `.`, `-`, `_` characters are all equivalent.) - pipx now reinstall its internal shared libraries when the user executes `reinstall-all`. - Made sure shell exit codes from every pipx command are correct. In the past some (like from `pipx upgrade`) were wrong. The exit code from `pipx runpip` is now the exit code from the `pip` command run. The exit code from `pipx list` will be 1 if one or more venvs have problems that need to be addressed. - pipx now writes a log file for each pipx command executed to `$PIPX_HOME/logs`, typically `~/.local/pipx/logs`. pipx keeps the most recent 10 logs and deletes others. - `pipx upgrade` and `pipx upgrade-all` now have a `--upgrade-injected` option which directs pipx to also upgrade injected packages. - `pipx list` now detects, identifies, and suggests a remedy for venvs with old-internal data (internal venv names) that need to be updated. - Added a "Troubleshooting" page to the pipx web documentation for common problems pipx users may encounter. - pipx error, warning, and other messages now word-wrap so words are not split across lines. Their appearance is also now more consistent. ## [0.15.6.0](https://github.com/pypa/pipx/tree/0.15.6.0) - [docs] Update license - [docs] Display a more idiomatic command for registering completions on fish. - [bugfix] Fixed regression in list, inject, upgrade, reinstall-all commands when suffixed packages are used. - [bugfix] Do not reset package url during upgrade when main package is `pipx` - Updated help text to show description for `ensurepath` and `completions` help - Added support for user-defined default python interpreter via new `PIPX_DEFAULT_PYTHON`. Helpful for use with pyenv among other uses. - [bugfix] Fixed bug where extras were ignored with a PEP 508 package specification with a URL. ## [0.15.5.1](https://github.com/pypa/pipx/tree/0.15.5.1) - [bugfix] Fixed regression of 0.15.5.0 which erroneously made installing from a local path with package extras not possible. ## [0.15.5.0](https://github.com/pypa/pipx/tree/0.15.5.0) - pipx now parses package specification before install. It removes (with warning) the `--editable` install option for any package specification that is not a local path. It also removes (with warning) any environment markers. - Disabled animation when we cannot determine terminal size or if the number of columns is too small. (Fixes #444) - [feature] Version of each injected package is now listed after name for `pipx list --include-injected` - Change metadata recorded from version-specified install to allow upgrades in future. Adds pipx dependency on `packaging` package. - [bugfix] Prevent python error in case where package has no pipx metadata and advise user how to fix. - [feature] `ensurepath` now also ensures that pip user binary path containing pipx itself is in user's PATH if pipx was installed using `pip install --user`. - [bugfix] For `pipx install`, fixed failure to install if user has `PIP_USER=1` or `user=true` in pip.conf. (#110) - [bugfix] Requiring userpath v1.4.1 or later so ensure Windows bug is fixed for `ensurepath` (#437) - [feature] log pipx version (#423) - [feature] `--suffix` option for `install` to allow multiple versions of same tool to be installed (#445) - [feature] pipx can now be used with the Windows embeddable Python distribution ## [0.15.4.0](https://github.com/pypa/pipx/tree/0.15.4.0) - [feature] `list` now has a new option `--include-injected` to show the injected packages in the main apps - [bugfix] Fixed bug that can cause crash when installing an app ## [0.15.3.1](https://github.com/pypa/pipx/tree/0.15.3.1) - [bugfix] Workaround multiprocessing issues on certain platforms (#229) ## [0.15.3.0](https://github.com/pypa/pipx/tree/0.15.3.0) - [feature] Use symlinks on Windows when symlinks are available ## [0.15.2.0](https://github.com/pypa/pipx/tree/0.15.2.0) - [bugfix] Improved error reporting during venv metadata inspection. - [bugfix] Fixed incompatibility with pypy as venv interpreter (#372). - [bugfix] Replaced implicit dependency on setuptools with an explicit dependency on packaging (#339). - [bugfix] Continue reinstalling packages after failure - [bugfix] Hide cursor while pipx runs - [feature] Add environment variable `USE_EMOJI` to allow enabling/disabling emojis (#376) - [refactor] Moved all commands to separate files within the commands module (#255). - [bugfix] Ignore system shared libraries when installing shared libraries pip, wheel, and setuptools. This also fixes an incompatibility with Debian/Ubuntu's version of pip (#386). ## [0.15.1.3](https://github.com/pypa/pipx/tree/0.15.1.3) - [bugfix] On Windows, pipx now lists correct Windows apps (#217) - [bugfix] Fixed a `pipx install` bug causing incorrect python binary to be used when using the optional --python argument in certain situations, such as running pipx from a Framework python on macOS and specifying a non-Framework python. ## [0.15.1.2](https://github.com/pypa/pipx/tree/0.15.1.2) - [bugfix] Fix recursive search of dependencies' apps so no apps are missed. - `upgrade-all` now skips editable packages, because pip disallows upgrading editable packages. ## [0.15.1.1](https://github.com/pypa/pipx/tree/0.15.1.1) - [bugfix] fix regression that caused installing with --editable flag to fail package name determination. ## [0.15.1.0](https://github.com/pypa/pipx/tree/0.15.1.0) - Add Python 3.8 to PyPI classifier and travis test matrix - [feature] auto-upgrade shared libraries, including pip, if older than one month. Hide all pip warnings that a new version is available. (#264) - [bugfix] pass pip arguments to pip when determining package name (#320) ## [0.15.0.0](https://github.com/pypa/pipx/tree/0.15.0.0) Upgrade instructions: When upgrading to 0.15.0.0 or above from a pre-0.15.0.0 version, you must re-install all packages to take advantage of the new persistent pipx metadata files introduced in this release. These metadata files store pip specification values, injected packages, any custom pip arguments, and more in each main package's venv. You can do this by running `pipx reinstall-all` or `pipx uninstall-all`, then reinstalling manually. - `install` now has no `--spec` option. You may specify any valid pip specification for `install`'s main argument. - `inject` will now accept pip specifications for dependency arguments - Metadata is now stored for each application installed, including install options like `--spec`, and injected packages. This information allows upgrade, upgrade-all and reinstall-all to work properly even with non-pypi installed packages. (#222) - `upgrade` options `--spec` and `--include-deps` were removed. Pipx now uses the original options used to install each application instead. (#222) - `upgrade-all` options `--include-deps`, `--system-site-packages`, `--index-url`, `--editable`, and `--pip-args` were removed. Pipx now uses the original options used to install each application instead. (#222) - `reinstall-all` options `--include-deps`, `--system-site-packages`, `--index-url`, `--editable`, and `--pip-args` were removed. Pipx now uses the original options used to install each application instead. (#222) - Handle missing interpreters more gracefully (#146) - Change `reinstall-all` to use system python by default for apps. Now use `--python` option to specify a different python version. - Remove the PYTHONPATH environment variable when executing any command to prevent conflicts between pipx dependencies and package dependencies when pipx is installed via homebrew. Homebrew can use PYTHONPATH manipulation instead of virtual environments. (#233) - Add printed summary after successful call to `pipx inject` - Support associating apps with Python 3.5 - Improvements to animation status text - Make `--python` argument in `reinstall-all` command optional - Use threads on OS's without support for semaphores - Stricter parsing when passing `--` argument as delimiter ## [0.14.0.0](https://github.com/pypa/pipx/tree/0.14.0.0) - Speed up operations by using shared venv for `pip`, `setuptools`, and `wheel`. You can see more detail in the 'how pipx works' section of the documentation. (#164, @pfmoore) - Breaking change: for the `inject` command, change `--include-binaries` to `--include-apps` - Change all terminology from `binary` to `app` or `application` - Improve argument parsing for `pipx run` and `pipx runpip` - If `--force` is passed, remove existing files in PIPX_BIN_DIR - Move animation to start of line, hide cursor when animating ## [0.13.2.3](https://github.com/pypa/pipx/tree/0.13.2.3) - Fix regression when installing a package that doesn't have any entry points ## [0.13.2.2](https://github.com/pypa/pipx/tree/0.13.2.2) - Remove unnecessary and sometimes incorrect check after `pipx inject` (#195) - Make status text/animation reliably disappear before continuing - Update animation symbols ## [0.13.2.1](https://github.com/pypa/pipx/tree/0.13.2.1) - Remove virtual environment if installation did not complete. For example, if it was interrupted by ctrl+c or if an exception occurred for any reason. (#193) ## [0.13.2.0](https://github.com/pypa/pipx/tree/0.13.2.0) - Add shell autocompletion. Also add `pipx completions` command to print instructions on how to add pipx completions to your shell. - Un-deprecate `ensurepath`. Use `userpath` internally instead of instructing users to run the `userpath` cli command. - Improve detection of PIPX_BIN_DIR not being on PATH - Improve error message when an existing symlink exists in PIPX_BIN_DIR and points to the wrong location - Improve handling of unexpected files in PIPX_HOME (@uranusjr) - swap out of order logic in order to correctly recommend --include-deps (@joshuarli) - [dev] Migrate from tox to nox ## [0.13.1.1](https://github.com/pypa/pipx/tree/0.13.1.1) - Do not raise bare exception if no binaries found (#150) - Update pipsi migration script ## [0.13.1.0](https://github.com/pypa/pipx/tree/0.13.1.0) - Deprecate `ensurepath` command. Use `userpath append ~/.local/bin` - Support redirects and proxies when downloading python files (i.e. `pipx run http://url/file.py`) - Use tox for document generation and CI testing (CI tests are now functional rather than static tests on style and formatting!) - Use mkdocs for documentation - Change default cache duration for `pipx run` from 2 to 14 days ## [0.13.0.1](https://github.com/pypa/pipx/tree/0.13.0.1) - Fix upgrade-all and reinstall-all regression ## [0.13.0.0](https://github.com/pypa/pipx/tree/0.13.0.0) - Add `runpip` command to run arbitrary pip commands in pipx-managed virtual environments - Do not raise error when running `pipx install PACKAGE` and the package has already been installed by pipx (#125). This is the cause of the major version change from 0.12 to 0.13. - Add `--skip` argument to `upgrade-all` and `reinstall-all` commands, to let the user skip particular packages ## [0.12.3.3](https://github.com/pypa/pipx/tree/0.12.3.3) - Update logic in determining a package's binaries during installation. This removes spurious binaries from the installation. (#104) - Improve compatibility with Debian distributions by using `shutil.which` instead of `distutils.spawn.find_executable` (#102) ## [0.12.3.2](https://github.com/pypa/pipx/tree/0.12.3.2) - Fix infinite recursion error when installing package such as `cloudtoken==0.1.84` (#103) - Fix windows type errors (#96, #98) ## [0.12.3.1](https://github.com/pypa/pipx/tree/0.12.3.1) - Fix "WindowsPath is not iterable" bug ## [0.12.3.0](https://github.com/pypa/pipx/tree/0.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 autoformatting, linting, unit testing ## [0.12.2.0](https://github.com/pypa/pipx/tree/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](https://github.com/pypa/pipx/tree/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](https://github.com/pypa/pipx/tree/0.12.0.4) - Fix parsing bug in pipx run ## [0.12.0.3](https://github.com/pypa/pipx/tree/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](https://github.com/pypa/pipx/tree/0.12.0.2) - forward arguments to run command correctly #90 ## [0.12.0.1](https://github.com/pypa/pipx/tree/0.12.0.1) - stop using unverified context #89 ## [0.12.0.0](https://github.com/pypa/pipx/tree/0.12.0.0) - Change installation instructions to use `pipx` PyPI name - Add `ensurepath` command ## [0.11.0.2](https://github.com/pypa/pipx/tree/0.11.0.2) - add version argument parsing back in (fixes regression) ## [0.11.0.1](https://github.com/pypa/pipx/tree/0.11.0.1) - add version check, command check, fix printed version update installation instructions ## [0.11.0.0](https://github.com/pypa/pipx/tree/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](https://github.com/pypa/pipx/tree/0.10.4.1) - Fix version printed when `pipx --version` is run ## [0.10.4.0](https://github.com/pypa/pipx/tree/0.10.4.0) - Add --index-url, --editable, and --pip-args flags - Updated README with pipsi migration instructions ## [0.10.3.0](https://github.com/pypa/pipx/tree/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-1.6.0/CONTRIBUTING.md000066400000000000000000000176221462701651400147450ustar00rootroot00000000000000Thanks for your interest in contributing to pipx! Everyone who interacts with the pipx project via codebase, issue tracker, chat rooms, or otherwise is expected to follow the [PSF Code of Conduct](https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md). ## Submitting changes 1. Fork [the GitHub repository](https://github.com/pypa/pipx). 2. Make a branch off of `main` and commit your changes to it. 3. Add a changelog entry. 4. Submit a pull request to the `main` branch on GitHub, referencing an open issue. ### Changelog entries The `CHANGELOG.md` file is built by [towncrier](https://pypi.org/project/towncrier/) from news fragments in the `changelog.d/` directory. To add an entry, create a news fragment in that directory named `{number}.{type}.md`, where `{number}` is the issue number, and `{type}` is one of `feature`, `bugfix`, `doc`, `removal`, or `misc`. For example, if your issue number is 1234 and it's fixing a bug, then you would create `changelog.d/1234.bugfix.md`. PRs can span multiple categories by creating multiple files: if you added a feature and deprecated/removed an old feature for issue #5678, you would create `changelog.d/5678.feature.md` and `changelog.d/5678.removal.md`. A changelog entry is meant for end users and should only contain details relevant to them. In order to maintain a consistent style, please keep the entry to the point, in sentence case, shorter than 80 characters, and in an imperative tone. An entry should complete the sentence "This change will ...". If one line is not enough, use a summary line in an imperative tone, followed by a description of the change in one or more paragraphs, each wrapped at 80 characters and separated by blank lines. You don't need to reference the pull request or issue number in a changelog entry, since towncrier will add a link using the number in the file name. Similarly, you don't need to add your name to the entry, since that will be associated with the pull request. ## Running pipx For Development To develop `pipx`, either create a [developer environment](#creating-a-developer-environment), or perform an editable install: ``` python -m pip install -e . python -m pipx --version ``` ## Running Tests ### Setup pipx uses an automation tool called [nox](https://pypi.org/project/nox/) for development, continuous integration testing, and various tasks. `nox` defines tasks or "sessions" in `noxfile.py` which can be run with `nox -s SESSION_NAME`. Session names can be listed with `nox -l`. Install nox for pipx development: ``` python -m pip install --user nox ``` Tests are defined as `nox` sessions. You can see all nox sessions with ``` nox -l ``` At the time of this writing, the output looks like this ``` - refresh_packages_cache-3.12 -> Populate .pipx_tests/package_cache - refresh_packages_cache-3.11 -> Populate .pipx_tests/package_cache - refresh_packages_cache-3.10 -> Populate .pipx_tests/package_cache - refresh_packages_cache-3.9 -> Populate .pipx_tests/package_cache - refresh_packages_cache-3.8 -> Populate .pipx_tests/package_cache - tests_internet-3.12 -> Tests using internet pypi only - tests_internet-3.11 -> Tests using internet pypi only - tests_internet-3.10 -> Tests using internet pypi only - tests_internet-3.9 -> Tests using internet pypi only - tests_internet-3.8 -> Tests using internet pypi only * tests-3.12 -> Tests using local pypiserver only * tests-3.11 -> Tests using local pypiserver only * tests-3.10 -> Tests using local pypiserver only * tests-3.9 -> Tests using local pypiserver only * tests-3.8 -> Tests using local pypiserver only - test_all_packages-3.12 - test_all_packages-3.11 - test_all_packages-3.10 - test_all_packages-3.9 - test_all_packages-3.8 - cover -> Coverage analysis * lint - develop-3.12 - develop-3.11 - develop-3.10 - develop-3.9 - develop-3.8 - build - publish * build_docs - watch_docs * build_man - create_test_package_list-3.12 - create_test_package_list-3.11 - create_test_package_list-3.10 - create_test_package_list-3.9 - create_test_package_list-3.8 ``` ### Creating a developer environment For developing the tool (and to attach to your IDE) we recommend creating a Python environment via `nox -s develop-3.12`, afterwards use the Python interpreter available under `.nox/develop-3.12/bin/python`. ### Unit Tests To run unit tests in Python3.12, you can run ``` nox -s tests-3.12 ``` > [!TIP] > > You can run a specific unit test by passing arguments to pytest, the test runner pipx uses: > > ``` > nox -s tests-3.8 -- -k EXPRESSION > ``` > > `EXPRESSION` can be a test name, such as > > ``` > nox -s tests-3.8 -- -k test_uninstall > ``` > > Coverage errors can usually be ignored when only running a subset of tests. ### Running Unit Tests Offline Running the unit tests requires a directory `.pipx_tests/package_cache` to be populated from a fixed list of package distribution files (wheels or source files). If you have network access, `nox -s tests` automatically makes sure this directory is populated (including downloading files if necessary) as a first step. Thus, if you are running the tests with network access, you can ignore the rest of this section. If, however, you wish to run tests offline without the need for network access, you can populate `.pipx_tests/package_cache` yourself manually beforehand when you do have network access. ### Populating the cache directory using nox To populate `.pipx_tests/package_cache` manually using nox, execute: ``` nox -s refresh_packages_cache ``` This will sequence through available python executable versions to populate the cache directory for each version of python on your platform. ### Lint Tests Linting is done via `pre-commit`, setting it up and running it can be done via `nox` by typing: ``` nox -s lint ``` ### Installing or injecting new packages in tests If the tests are modified such that a new package / version combination is `pipx install`ed or `pipx inject`ed that wasn't used in other tests, then one must make sure it's added properly to the packages lists in `testdata/tests_packages`. To accomplish this: - Edit `testdata/tests_packages/primary_packages.txt` to add the new package(s) that you wish to `pipx install` or `pipx inject` in the tests. Then using Github workflows to generate all platforms in the Github CI: - Manually activate the Github workflow: Create tests package lists for offline tests - Download the artifact `lists` and put the files from it into `testdata/tests_packages/` Or to locally generate these lists from `testdata/tests_packages/primary_packages.txt`, on the target platform execute: - `nox -s create_test_package_list` Finally, check-in the new or modified list files in the directory `testdata/tests_packages` ## Testing pipx on Continuous Integration builds Upon opening pull requests GitHub Actions will automatically trigger. ## Building Documentation `pipx` autogenerate API documentation, and also uses templates. When updating pipx docs, make sure you are modifying the `docs` directory. You can generate the documentation with ``` nox -s build_docs ``` This will capture CLI documentation for any pipx argument modifications, as well as generate templates to the docs directory. To preview changes, including live reloading, open another terminal and run ``` nox -s watch_docs ``` ## Releasing New `pipx` Versions To release a new version, manually run the `bump-changelog` action under the *"Actions"* tab, passing it the version to be released. This will create a pull request updating the changelog for the upcoming version, with the `release-version` label. Merging this PR will automatically trigger the release workflows. Attaching this label to any pull request of which the title follows the format `: Description` and merging it will trigger the release workflows as well. The release workflow consists of publishing: - the pipx version to PyPI, - the documentation to ReadTheDocs, - a GitHub release, - the `zipapp` to the GitHub release created. No need for any other pre or post publish steps. pipx-1.6.0/LICENSE000066400000000000000000000020741462701651400135140ustar00rootroot00000000000000MIT License Copyright (c) 2018 Chad Smith and contributors 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. pipx-1.6.0/README.md000066400000000000000000000412371462701651400137720ustar00rootroot00000000000000

# pipx — Install and Run Python Applications in Isolated Environments

image PyPI version

**Documentation**: **Source Code**: _For comparison to other tools including pipsi, see [Comparison to Other Tools](https://pipx.pypa.io/stable/comparisons/)._ ## Install pipx > [!WARNING] > > It is not recommended to install `pipx` via `pipx`. If you'd like to do this anyway, take a look at the > [`pipx-in-pipx`](https://github.com/mattsb42-meta/pipx-in-pipx) project and read about the limitations there. ### On macOS ``` brew install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions with --global argument ``` Upgrade pipx with `brew update && brew upgrade pipx`. ### On Linux - Ubuntu 23.04 or above ``` sudo apt update sudo apt install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions with --global argument ``` - Fedora: ``` sudo dnf install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions with --global argument ``` - Arch: ``` sudo pacman -S python-pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions with --global argument ``` - Using `pip` on other distributions: ``` python3 -m pip install --user pipx python3 -m pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions with --global argument ``` Upgrade pipx with `python3 -m pip install --user --upgrade pipx`. ### On Windows - install via [Scoop](https://scoop.sh/) ``` scoop install pipx pipx ensurepath ``` Upgrade pipx with `scoop update pipx`. - install via pip (requires pip 19.0 or later) ``` # If you installed python using Microsoft Store, replace `py` with `python3` in the next line. py -m pip install --user pipx ``` It is possible (even most likely) the above finishes with a WARNING looking similar to this: ``` WARNING: The script pipx.exe is installed in `\AppData\Roaming\Python\Python3x\Scripts` which is not on PATH ``` If so, go to the mentioned folder, allowing you to run the pipx executable directly. Enter the following line (even if you did not get the warning): ``` .\pipx.exe ensurepath ``` This will add both the above mentioned path and the `%USERPROFILE%\.local\bin` folder to your search path. Restart your terminal session and verify `pipx` does run. Upgrade pipx with `py -m pip install --user --upgrade pipx`. ### Using pipx without installing (via zipapp) You can also use pipx without installing it. The zipapp can be downloaded from [Github releases](https://github.com/pypa/pipx/releases) and you can invoke it with a Python 3.8+ interpreter: ``` python pipx.pyz ensurepath ``` ### Use with pre-commit pipx [has pre-commit support](installation.md#pre-commit). ### Shell completions Shell completions are available by following the instructions printed with this command: ``` pipx completions ``` For more details, see the [installation instructions](https://pipx.pypa.io/stable/installation/). ## Overview: What is `pipx`? pipx is a tool to help you install and run end-user applications written in Python. It's roughly similar to macOS's `brew`, JavaScript's [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b), and Linux's `apt`. It's closely related to pip. In fact, it uses pip, but is focused on installing and managing Python packages that can be run from the command line directly as applications. ### How is it Different from pip? pip is a general-purpose package installer for both libraries and apps with no environment isolation. pipx is made specifically for application installation, as it adds isolation yet still makes the apps available in your shell: pipx creates an isolated environment for each application and its associated packages. pipx does not ship with pip, but installing it is often an important part of bootstrapping your system. ### Where Does `pipx` Install Apps From? By default, pipx uses the same package index as pip, [PyPI](https://pypi.org/). pipx can also install from all other sources pip can, such as a local directory, wheel, git url, etc. Python and PyPI allow developers to distribute code with "console script entry points". These entry points let users call into Python code from the command line, effectively acting like standalone applications. pipx is a tool to install and run any of these thousands of application-containing packages in a safe, convenient, and reliable way. **In a way, it turns Python Package Index (PyPI) into a big app store for Python applications.** Not all Python packages have entry points, but many do. If you would like to make your package compatible with pipx, all you need to do is add a [console scripts](https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html#the-console-scripts-entry-point) entry point. If you're a poetry user, use [these instructions](https://python-poetry.org/docs/pyproject/#scripts). Or, if you're using hatch, [try this](https://hatch.pypa.io/latest/config/metadata/#cli). ## Features `pipx` enables you to - Expose CLI entrypoints of packages ("apps") installed to isolated environments with the `install` command. This guarantees no dependency conflicts and clean uninstalls! - Easily list, upgrade, and uninstall packages that were installed with pipx - Run the latest version of a Python application in a temporary environment with the `run` command Best of all, pipx runs with regular user permissions, never calling `sudo pip install` (you aren't doing that, are you? đź„). ### Walkthrough: Installing a Package and its Applications With `pipx` You can globally install an application by running ``` pipx install PACKAGE ``` This automatically creates a virtual environment, installs the package, and adds the package's associated applications (entry points) to a location on your `PATH`. For example, `pipx install pycowsay` makes the `pycowsay` command available globally, but sandboxes the pycowsay package in its own virtual environment. **pipx never needs to run as sudo to do this.** Example: ``` >> pipx install pycowsay installed package pycowsay 2.0.3, Python 3.10.3 These apps are now globally available - pycowsay done! ✨ 🌟 ✨ >> pipx list venvs are in /home/user/.local/share/pipx/venvs apps are exposed on your $PATH at /home/user/.local/bin package pycowsay 2.0.3, Python 3.10.3 - pycowsay # Now you can run pycowsay from anywhere >> pycowsay mooo ____ < mooo > ==== \ \ ^__^ (oo)\_______ (__)\ )\/\ ||----w | || || ``` ### Installing from Source Control You can also install from a git repository. Here, `black` is used as an example. ``` pipx install git+https://github.com/psf/black.git pipx install git+https://github.com/psf/black.git@branch # branch of your choice pipx install git+https://github.com/psf/black.git@ce14fa8b497bae2b50ec48b3bd7022573a59cdb1 # git hash pipx install https://github.com/psf/black/archive/18.9b0.zip # install a release ``` The pip syntax with `egg` must be used when installing extras: ``` pipx install "git+https://github.com/psf/black.git#egg=black[jupyter]" ``` ### Inject a package If an application installed by pipx requires additional packages, you can add them with pipx inject. For example, if you have ```ipython``` installed and want to add the ```matplotlib``` package to it, you would use: ``` pipx inject ipython matplotlib ``` You can inject multiple packages by specifying them all on the command line, or by listing them in a text file, with one package per line, or a combination. For example: ``` pipx inject ipython matplotlib pandas # or: pipx inject ipython -r useful-packages.txt ``` ### Walkthrough: Running an Application in a Temporary Virtual Environment This is an alternative to `pipx install`. `pipx run` downloads and runs the above mentioned Python "apps" in a one-time, temporary environment, leaving your system untouched afterwards. This can be handy when you need to run the latest version of an app, but don't necessarily want it installed on your computer. You may want to do this when you are initializing a new project and want to set up the right directory structure, when you want to view the help text of an application, or if you simply want to run an app in a one-off case and leave your system untouched afterwards. For example, the blog post [How to set up a perfect Python project](https://sourcery.ai/blog/python-best-practices/) uses `pipx run` to kickstart a new project with [cookiecutter](https://github.com/cookiecutter/cookiecutter), a tool that creates projects from project templates. A nice side benefit is that you don't have to remember to upgrade the app since `pipx run` will automatically run a recent version for you. Okay, let's see what this looks like in practice! ``` pipx run APP [ARGS...] ``` This will install the package in an isolated, temporary directory and invoke the app. Give it a try: ``` > pipx run pycowsay moo --- < moo > --- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ``` Notice that you **don't need to execute any install commands to run the app**. Any arguments after the application name will be passed directly to the application: ``` > pipx run pycowsay these arguments are all passed to pycowsay! ------------------------------------------- < these arguments are all passed to pycowsay! > ------------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ``` ### Ambiguous arguments Sometimes pipx can consume arguments provided for the application: ``` > pipx run pycowsay --py usage: pipx run [-h] [--no-cache] [--pypackages] [--spec SPEC] [--verbose] [--python PYTHON] [--system-site-packages] [--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS] app ... pipx run: error: ambiguous option: --py could match --pypackages, --python ``` To prevent this put double dash `--` before APP. It will make pipx to forward the arguments to the right verbatim to the application: ``` > pipx run -- pycowsay --py ---- < --py > ---- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ``` Re-running the same app is quick because pipx caches Virtual Environments on a per-app basis. The caches only last a few days, and when they expire, pipx will again use the latest version of the package. This way you can be sure you're always running a new version of the package without having to manually upgrade. ### Package with multiple apps, or the app name doesn't match the package name If the app name does not match the package name, you can use the `--spec` argument to specify the `PACKAGE` name, and provide the `APP` to run separately: ``` pipx run --spec PACKAGE APP ``` For example, the [esptool](https://github.com/espressif/esptool) package doesn't provide an executable with the same name: ``` >> pipx run esptool 'esptool' executable script not found in package 'esptool'. Available executable scripts: esp_rfc2217_server.py - usage: 'pipx run --spec esptool esp_rfc2217_server.py [arguments?]' espefuse.py - usage: 'pipx run --spec esptool espefuse.py [arguments?]' espsecure.py - usage: 'pipx run --spec esptool espsecure.py [arguments?]' esptool.py - usage: 'pipx run --spec esptool esptool.py [arguments?]' ``` You can instead run the executables that this package provides by using `--spec`: ``` pipx run --spec esptool esp_rfc2217_server.py pipx run --spec esptool espefuse.py pipx run --spec esptool espsecure.py pipx run --spec esptool esptool.py ``` Note that the `.py` extension is not something you append to the executable name. It is part of the executable name, as provided by the package. This can be anything. For example, when working with the [pymodbus](https://github.com/pymodbus-dev/pymodbus) package: ``` >> pipx run pymodbus[repl] 'pymodbus' executable script not found in package 'pymodbus'. Available executable scripts: pymodbus.console - usage: 'pipx run --spec pymodbus pymodbus.console [arguments?]' pymodbus.server - usage: 'pipx run --spec pymodbus pymodbus.server [arguments?]' pymodbus.simulator - usage: 'pipx run --spec pymodbus pymodbus.simulator [arguments?]' ``` You can run the executables like this: ``` pipx run --spec pymodbus[repl] pymodbus.console pipx run --spec pymodbus[repl] pymodbus.server pipx run --spec pymodbus[repl] pymodbus.simulator ``` ### Running a specific version of a package The `PACKAGE` argument above is actually a [requirement specifier](https://packaging.python.org/en/latest/glossary/#term-Requirement-Specifier). Therefore, you can also specify specific versions, version ranges, or extras. For example: ``` pipx run mpremote==1.20.0 pipx run --spec esptool==4.6.2 esptool.py pipx run --spec 'esptool>=4.5' esptool.py pipx run --spec 'esptool >= 4.5' esptool.py ``` Notice that some requirement specifiers have to be enclosed in quotes or escaped. ### Running from Source Control You can also run from a git repository. Here, `black` is used as an example. ``` pipx run --spec git+https://github.com/psf/black.git black pipx run --spec git+https://github.com/psf/black.git@branch black # branch of your choice pipx run --spec git+https://github.com/psf/black.git@ce14fa8b497bae2b50ec48b3bd7022573a59cdb1 black # git hash pipx run --spec https://github.com/psf/black/archive/18.9b0.zip black # install a release ``` ### Running from URL You can run .py files directly, too. ``` pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py pipx is working! ``` ### Summary That's it! Those are the most important commands `pipx` offers. To see all of pipx's documentation, run `pipx --help` or see the [docs](https://pipx.pypa.io/stable/docs/). ## Testimonials
"Thanks for improving the workflow that pipsi has covered in the past. Nicely done!"
—Jannis Leidel, PSF fellow, former pip and Django core developer, and founder of the Python Packaging Authority (PyPA)

"My setup pieces together pyenv, poetry, and pipx. [...] For the things I need, it’s perfect."
—Jacob Kaplan-Moss, co-creator of Django in blog post My Python Development Environment, 2020 Edition

"I'm a big fan of pipx. I think pipx is super cool."
—Michael Kennedy, co-host of PythonBytes podcast in episode 139

## Credits pipx was inspired by [pipsi](https://github.com/mitsuhiko/pipsi) and [npx](https://github.com/npm/npx). It was created by [Chad Smith](https://github.com/cs01/) and has had lots of help from [contributors](https://github.com/pypa/pipx/graphs/contributors). The logo was created by [@IrishMorales](https://github.com/IrishMorales). pipx is maintained by a team of volunteers (in alphabetical order) - [Bernát Gábor](https://github.com/gaborbernat) - [Chad Smith](https://github.com/cs01) - co-lead maintainer - [Chrysle](https://github.com/chrysle) - [Jason Lam](https://github.com/dukecat0) - [Matthew Clapp](https://github.com/itsayellow) - co-lead maintainer - [Robert Offner](https://github.com/gitznik) - [Tzu-ping Chung](https://github.com/uranusjr) ## Contributing Issues and Pull Requests are definitely welcome! Check out [Contributing](https://pipx.pypa.io/stable/contributing/) to get started. Everyone who interacts with the pipx project via codebase, issue tracker, chat rooms, or otherwise is expected to follow the [PSF Code of Conduct](https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md). pipx-1.6.0/changelog.d/000077500000000000000000000000001462701651400146555ustar00rootroot00000000000000pipx-1.6.0/changelog.d/.gitignore000066400000000000000000000000141462701651400166400ustar00rootroot00000000000000!.gitignore pipx-1.6.0/docs/000077500000000000000000000000001462701651400134345ustar00rootroot00000000000000pipx-1.6.0/docs/changelog.md000077700000000000000000000000001462701651400177242../CHANGELOG.mdustar00rootroot00000000000000pipx-1.6.0/docs/comparisons.md000066400000000000000000000152101462701651400163120ustar00rootroot00000000000000## pipx vs pip - pip is a general Python package installer. It can be used to install libraries or cli applications with entrypoints. - pipx is a specialized package installer. It can only be used to install packages with cli entrypoints. - pipx and pip both install packages from PyPI (or locally) - pipx relies on pip (and venv) - pipx replaces a subset of pip's functionality; it lets you install cli applications but NOT libraries that you import in your code. - you can install pipx with pip Example interaction: Install pipx with pip: `pip install --user pipx` ## pipx vs poetry and pipenv - pipx is used solely for application consumption: you install cli apps with it - pipenv and poetry are cli apps used to develop applications and libraries - all three tools wrap pip and virtual environments for more convenient workflows Example interaction: Install pipenv and poetry with pipx: `pipx install poetry` Run pipenv or poetry with pipx: `pipx run poetry --help` ## pipx vs venv - venv is part of Python's standard library in Python 3.2 and above - venv creates "virtual environments" which are sandboxed python installations - pipx heavily relies on the venv package Example interaction: pipx installs packages to environments created with venv. `pipx install black --verbose` ## pipx vs pyenv - pyenv manages python versions on your system. It helps you install versions like Python 3.6, 3.7, etc. - pipx installs packages in virtual environments and exposes their entrypoints on your PATH Example interaction: Install a Python interpreter with pyenv, then install a package using pipx and that new interpreter: `pipx install black --python=python3.11` where python3.11 was installed on the system with pyenv ## pipx vs pipsi - pipx and pipsi both install packages in a similar way - pipx is under active development. pipsi is no longer maintained. - pipx always makes sure you're using the latest version of pip - pipx has the ability to run an app in one line, leaving your system unchanged after it finishes (`pipx run APP`) where pipsi does not - pipx has the ability to recursively install binaries from dependent packages - 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 emojis 🀠Example interaction: None. Either one or the other should be used. These tools compete for a similar workflow. ### Migrating to pipx from pipsi After you have installed pipx, run [migrate_pipsi_to_pipx.py](https://raw.githubusercontent.com/pypa/pipx/main/scripts/migrate_pipsi_to_pipx.py). Why not do this with your new pipx installation? ``` pipx run https://raw.githubusercontent.com/pypa/pipx/main/scripts/migrate_pipsi_to_pipx.py ``` ## pipx vs brew - Both brew and pipx install cli tools - They install them from different sources. brew uses a curated repository specifically for brew, and pipx generally uses PyPI. Example interaction: brew can be used to install pipx, but they generally don't interact much. ## pipx vs npx - Both can run cli tools (npx will search for them in node_modules, and if not found run in a temporary environment. `pipx run` will search in `__pypackages__` and if not found run in a temporary environment) - npx works with JavaScript and pipx works with Python - Both tools attempt to make running executables written in a dynamic language (JS/Python) as easy as possible - pipx can also install tools globally; npx cannot Example interaction: None. These tools work for different languages. ## pipx vs pip-run [pip-run](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 ``` Example interaction: None. ## pipx vs fades [fades](https://github.com/PyAr/fades) is a tool to run **individual** Python scripts inside automatically provisioned virtualenvs with their dependencies installed. - Both [fades](https://github.com/PyAr/fades#how-to-mark-the-dependencies-to-be-installed) and [pipx run](examples.md#pipx-run-examples) allow specifying a script's dependencies in specially formatted comments, but the exact syntax differs. (pipx's syntax is standardized by a [provisional specification](https://packaging.python.org/en/latest/specifications/inline-script-metadata/), fades's syntax is not standardized.) - Both tools automatically set up reusable virtualenvs containing the necessary dependencies. - Both can download Python scripts/packages to execute from remote resources. - fades can only run individual script files while pipx can also run packages. Example interaction: None. ## pipx vs pae/pactivate _pae_ is a Bash command-line function distributed with [pactivate](https://github.com/cynic-net/pactivate) that uses pactivate to create non-ephemeral environments focused on general use, rather than just running command-line applications. There is [a very detailed comparison here](https://github.com/cynic-net/pactivate/blob/main/doc/vs-pipx.md), but to briefly summarize: Similarities: - Both create isolated environments without having to specify (and remember) a directory in which to store them. - Both allow you to use any Python interpreter available on your system (subject to version restrictions below). pae advantages: - Supports all versions of Python from 2.7 upward. pipx requires ≥3.8. - Fewer dependencies. (See the detailed comparison for more information.) - Easier to have multiple versions of a single program and/or use different Python versions for a single program. - Somewhat more convenient for running arbitrary command-line programs in virtual environments, installing multiple packages in a single environment, and activating virtual environments. - Integrates well with source code repos using [pactivate](https://github.com/cynic-net/pactivate). pae disadvantages: - Usable with Bash shell only. - Slightly less quick and convenient for installing/running command-line programs from single Python packages. - Can be slower than pipx at creating virtual environments. Example interaction: None. Either one or the other should be used. These tools compete for a similar workflow. pipx-1.6.0/docs/contributing.md000077700000000000000000000000001462701651400211242../CONTRIBUTING.mdustar00rootroot00000000000000pipx-1.6.0/docs/examples.md000066400000000000000000000145611462701651400156030ustar00rootroot00000000000000## `pipx install` examples ``` pipx install pycowsay pipx install --python python3.10 pycowsay pipx install --python 3.12 pycowsay pipx install --fetch-missing-python --python 3.12 pycowsay pipx install git+https://github.com/psf/black pipx install git+https://github.com/psf/black.git@branch-name pipx install git+https://github.com/psf/black.git@git-hash pipx install git+ssh://@/ pipx install https://github.com/psf/black/archive/18.9b0.zip pipx install black[d] pipx install --preinstall ansible-lint --preinstall mitogen ansible-core pipx install 'black[d] @ git+https://github.com/psf/black.git@branch-name' pipx install --suffix @branch-name 'black[d] @ git+https://github.com/psf/black.git@branch-name' pipx install --include-deps jupyter pipx install --pip-args='--pre' poetry pipx install --pip-args='--index-url=: --trusted-host=:' private-repo-package pipx install --index-url https://test.pypi.org/simple/ --pip-args='--extra-index-url https://pypi.org/simple/' some-package pipx --global install pycowsay pipx install . pipx install path/to/some-project ``` ## `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 run --spec PACKAGE==2.0.0 BINARY # specific version of package is run pipx run --python python3.10 BINARY # Installed and invoked with specific Python version pipx run --python python3.9 --spec PACKAGE=1.7.3 BINARY pipx run --spec git+https://url.git BINARY # latest version on default branch is run pipx run --spec git+https://url.git@branch BINARY pipx run --spec git+https://url.git@hash BINARY pipx run pycowsay moo pipx --version # prints pipx version pipx run pycowsay --version # prints pycowsay version pipx run --python pythonX pycowsay pipx run pycowsay==2.0 --version pipx run pycowsay[dev] --version pipx run --spec git+https://github.com/psf/black.git black pipx run --spec git+https://github.com/psf/black.git@branch-name black pipx run --spec git+https://github.com/psf/black.git@git-hash black pipx run --spec https://github.com/psf/black/archive/18.9b0.zip black --help pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py ``` You can run local files, or scripts hosted on the internet, and you can run them with arguments: ``` pipx run test.py pipx run test.py 1 2 3 pipx run https://example.com/test.py pipx run https://example.com/test.py 1 2 3 ``` A simple filename is ambiguous - it could be a file, or a package on PyPI. It will be treated as a filename if the file exists, or as a package if not. To force interpretation as a local path, use `--path`, and to force interpretation as a package name, use `--spec` (with the PyPI name of the package). ``` pipx run myscript.py # Local file, if myscript.py exists pipx run doesnotexist.py # Package, because doesnotexist.py is not a local file pipx run --path test.py # Always a local file pipx run --spec test-py test.py # Always a package on PyPI ``` You can also run scripts that have dependencies: If you have a script `test.py` that needs 3rd party libraries, you can add [inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) in the style of PEP 723. ``` # test.py # /// script # dependencies = ["requests"] # /// import sys import requests project = sys.argv[1] pipx_data = requests.get(f"https://pypi.org/pypi/{project}/json").json() print(pipx_data["info"]["version"]) ``` Then you can run it as follows: ``` > pipx run test.py pipx 1.1.0 ``` ## `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. Equivalently, the extra packages can be listed in a text file (e.g. `useful-packages.txt`). Each line is a separate package specifier with the same syntax as the command line. Comments are supported with a `#` prefix. Hence, the syntax is a strict subset of the pip [requirements file format][pip-requirements] syntax. [pip-requirements]: https://pip.pypa.io/en/stable/reference/requirements-file-format/ ``` # Additional packages requests pendulum # for easier datetimes ``` This file can then be given to `pipx inject` on the command line: ```shell > pipx inject ptpython --requirement useful-packages.txt # or: > pipx inject ptpython -r useful-packages.txt ``` Note that these options can be repeated and used together, e.g. ``` > pipx inject ptpython package-1 -r extra-packages-1.txt -r extra-packages-2.txt package-2 ``` If you require full pip functionality, then use the `runpip` command instead; however, the installed packages won't be recognised as "injected". ## `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.10.0 - black - blackd package pipx 0.10.0, Python 3.10.0 - pipx > pipx list --short black 18.9b0 pipx 0.10.0 ``` ## `pipx install-all` example ```shell > pipx list --json > pipx.json > pipx instal-all pipx.json 'black' already seems to be installed. Not modifying existing installation in '/usr/local/pipx/venvs/black'. Pass '--force' to force installation. 'pipx' already seems to be installed. Not modifying existing installation in '/usr/local/pipx/venvs/black'. Pass '--force' to force installation. > pipx install-all pipx.json --force Installing to existing venv 'black' installed package black 24.3.0, installed using Python 3.10.12 These apps are now globally available - black - blackd done! ✨ 🌟 ✨ Installing to existing venv 'pipx' installed package pipx 1.4.3, installed using Python 3.10.12 These apps are now globally available - pipx done! ✨ 🌟 ✨ ``` ## `pipx upgrade-shared` examples One use of the upgrade-shared command is to force a `pip` upgrade. ```shell > pipx upgrade-shared ``` This example pins `pip` (temporarily, until the next automatic upgrade, if that is not explicitly turned off) to a specific version. ```shell > pipx upgrade-shared --pip-args=pip==24.0 ``` pipx-1.6.0/docs/getting-started.md000066400000000000000000000005261462701651400170660ustar00rootroot00000000000000Now that you have pipx installed, you can install a program: ``` pipx install PACKAGE ``` for example ``` pipx install pycowsay ``` You can list programs installed: ``` pipx list ``` Or you can run a program without installing it: ``` pipx run pycowsay moooo! ``` You can view documentation for all commands by running `pipx --help`. pipx-1.6.0/docs/how-pipx-works.md000066400000000000000000000121141462701651400166730ustar00rootroot00000000000000## How it Works When installing a package and its binaries on linux (`pipx install package`) pipx will - create directory `~/.local/share/pipx/venvs/PACKAGE` - create or reuse a shared virtual environment that contains shared packaging library `pip` in `~/.local/share/pipx/shared/` - ensure the library is updated to its latest version - create a Virtual Environment in `~/.local/share/pipx/venvs/PACKAGE` that uses the shared pip mentioned above but otherwise is isolated (pipx uses a [.pth file](https://docs.python.org/3/library/site.html) to do this) - install the desired package in the Virtual Environment - expose binaries at `~/.local/bin` that point to new binaries in `~/.local/share/pipx/venvs/PACKAGE/bin` (such as `~/.local/bin/black` -> `~/.local/share/pipx/venvs/black/bin/black`) - expose manual pages at `~/.local/share/man/man[1-9]` that point to new manual pages in `~/.local/pipx/venvs/PACKAGE/share/man/man[1-9]` - as long as `~/.local/bin/` is on your PATH, you can now invoke the new binaries globally - on operating systems which have the `man` command, as long as `~/.local/share/man` is a recognized search path of man, you can now view the new manual pages globally - adding `--global` flag to any `pipx` command will execute the action in global scope which will expose app to all users - [reference](installation.md#global-installation). Note that this is not available on Windows. When running a binary (`pipx run BINARY`), pipx will - create or reuse a shared virtual environment that contains the shared packaging library `pip` - ensure the library is updated to its latest version - 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` - 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. ## Developing for pipx If you are a developer and want to be able to run ``` pipx install MY_PACKAGE ``` make sure you include `scripts` and, optionally for Windows GUI applications `gui-scripts`, sections under your main table[^1] in `pyproject.toml` or their legacy equivalents for `setup.cfg` and `setup.py`. [^1]: This is often the `[project]` table, but might also be differently named. Read more in the [PyPUG](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#writing-your-pyproject-toml). === "pyproject.toml" ```ini [project.scripts] foo = "my_package.some_module:main_func" bar = "other_module:some_func" [project.gui-scripts] baz = "my_package_gui:start_func" ``` === "setup.cfg" ```ini [options.entry_points] console_scripts = foo = my_package.some_module:main_func bar = other_module:some_func gui_scripts = baz = my_package_gui:start_func ``` === "setup.py" ```python setup( # other arguments here... entry_points={ 'console_scripts': [ 'foo = my_package.some_module:main_func', 'bar = other_module:some_func', ], 'gui_scripts': [ 'baz = my_package_gui:start_func', ] }, ) ``` In this case `foo` and `bar` (and `baz` on Windows) would be available as "applications" to pipx after installing the above example package, invoking their corresponding entry point functions. ### Manual pages If you wish to provide documentation via `man` pages on UNIX-like systems then these can be added as data files: === "setuptools" ```toml title="pyproject.toml" [tool.setuptools.data-files] "share/man/man1" = [ "manpage.1", ] ``` ```ini title="setup.cfg" [options.data_files] share/man/man1 = manpage.1 ``` ```python title="setup.py" setup( # other arguments here... data_files=[('share/man/man1', ['manpage.1'])] ) ``` > [!WARNING] > > The `data-files` keyword is "discouraged" in the [setuptools documentation](https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#setuptools-specific-configuration) but there is no alternative if `man` pages are a requirement. === "pdm-backend" ```toml title="pyproject.toml" [tool.pdm.build] source-includes = ["share"] [tool.pdm.build.wheel-data] data = [ {path = "share/man/man1/*", relative-to = "."}, ] ``` In this case the manual page `manpage.1` could be accessed by the user after installing the above example package. For a real-world example, see [pycowsay](https://github.com/cs01/pycowsay/blob/master/setup.py)'s `setup.py` source code. You can read more about entry points [here](https://setuptools.pypa.io/en/latest/userguide/quickstart.html#entry-points-and-automatic-script-creation). pipx-1.6.0/docs/index.md000077700000000000000000000000001462701651400165522../README.mdustar00rootroot00000000000000pipx-1.6.0/docs/installation.md000066400000000000000000000201361462701651400164610ustar00rootroot00000000000000## System Requirements python 3.8+ is required to install pipx. pipx can run binaries from packages with Python 3.3+. Don't have Python 3.8 or later? See [Python 3 Installation & Setup Guide](https://realpython.com/installing-python/). You also need to have `pip` installed on your machine for `python3`. Installing it varies from system to system. Consult [pip's installation instructions](https://pip.pypa.io/en/stable/installing/). Installing on Linux works best with a [Linux Package Manager](https://packaging.python.org/guides/installing-using-linux-tools/#installing-pip-setuptools-wheel-with-linux-package-managers). pipx works on macOS, linux, and Windows. [![Packaging status](https://repology.org/badge/vertical-allrepos/pipx.svg?columns=3&exclude_unsupported=1)](https://repology.org/metapackage/pipx/versions) ## Installing pipx ### On macOS: ``` brew install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions in global scope. See "Global installation" section below. ``` ### On Linux: - Ubuntu 23.04 or above ``` sudo apt update sudo apt install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions in global scope. See "Global installation" section below. ``` - Fedora: ``` sudo dnf install pipx pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions in global scope. See "Global installation" section below. ``` - Using `pip` on other distributions: ``` python3 -m pip install --user pipx python3 -m pipx ensurepath sudo pipx ensurepath --global # optional to allow pipx actions in global scope. See "Global installation" section below. ``` ### On Windows: - Install via [Scoop](https://scoop.sh/): ``` scoop install pipx pipx ensurepath ``` - Install via pip (requires pip 19.0 or later) ``` # If you installed python using Microsoft Store, replace `py` with `python3` in the next line. py -m pip install --user pipx ``` It is possible (even most likely) the above finishes with a WARNING looking similar to this: ``` WARNING: The script pipx.exe is installed in `\AppData\Roaming\Python\Python3x\Scripts` which is not on PATH ``` If so, go to the mentioned folder, allowing you to run the pipx executable directly. Enter the following line (even if you did not get the warning): ``` .\pipx.exe ensurepath ``` This will add both the above mentioned path and the `%USERPROFILE%\.local\bin` folder to your search path. Restart your terminal session and verify `pipx` does run. > [!WARNING] > > It is not recommended to install `pipx` via `pipx`. If you'd like to do this anyway, take a look at the > [`pipx-in-pipx`](https://github.com/mattsb42-meta/pipx-in-pipx) project and read about the limitations there. ### Using pipx without installing (via zipapp) The zipapp can be downloaded from [Github releases](https://github.com/pypa/pipx/releases) and you can invoke it with a Python 3.8+ interpreter: ``` python pipx.pyz ensurepath ``` ### Using pipx with pre-commit Pipx has [pre-commit](https://pre-commit.com/) support. This lets you run applications: - That can be run using `pipx run` but don't have native pre-commit support. - Using its prebuilt wheel from pypi.org instead of building it from source. - Using pipx's `--spec` and `--index-url` flags. Example configuration for use of the code linter [yapf](https://github.com/google/yapf/). This is to be added to your `.pre-commit-config.yaml`. ```yaml - repo: https://github.com/pypa/pipx rev: 1.5.0 hooks: - id: pipx alias: yapf name: yapf args: ["yapf", "-i"] types: ["python"] ``` ## Installation Options The default binary location for pipx-installed apps is `~/.local/bin`. This can be overridden with the environment variable `PIPX_BIN_DIR`. The default manual page location for pipx-installed apps is `~/.local/share/man`. This can be overridden with the environment variable `PIPX_MAN_DIR`. pipx's default virtual environment location is typically `~/.local/share/pipx` on Linux/Unix, `~/.local/pipx` on MacOS and `~\pipx` on Windows. For compatibility reasons, if `~/.local/pipx` on Linux, `%USERPROFILE%\AppData\Local\pipx` or `~\.local\pipx` on Windows or `~/Library/Application Support/pipx` on MacOS exists, it will be used as the default location instead. This can be overridden with the `PIPX_HOME` environment variable. In case one of these fallback locations exist, we recommend either manually moving the pipx files to the new default location (see the `Troubleshooting` section of the docs), or setting the `PIPX_HOME` environment variable (discarding files existing in the fallback location). As an example, you can install global apps accessible by all users on your system with the following command (on MacOS, Linux, and Windows WSL): ``` sudo PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin PIPX_MAN_DIR=/usr/local/share/man pipx install PACKAGE # Example: $ sudo PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin PIPX_MAN_DIR=/usr/local/share/man pipx install cowsay ``` > [!NOTE] > > After version 1.2.0, the default pipx paths have been moved from `~/.local/pipx` to specific user data directories on > each platform using [platformdirs](https://pypi.org/project/platformdirs/) library > > | Old Path | New Path | > | ---------------------- | ------------------------------------------ | > | `~/.local/pipx/.trash` | `platformdirs.user_data_dir()/pipx/trash` | > | `~/.local/pipx/shared` | `platformdirs.user_data_dir()/pipx/shared` | > | `~/.local/pipx/venvs` | `platformdirs.user_data_dir()/pipx/venv` | > | `~/.local/pipx/.cache` | `platformdirs.user_cache_dir()/pipx` | > | `~/.local/pipx/logs` | `platformdirs.user_log_dir()/pipx/log` | > > `user_data_dir()`, `user_cache_dir()` and `user_log_dir()` resolve to appropriate platform-specific user data, cache and log directories. > See the [platformdirs documentation](https://platformdirs.readthedocs.io/en/latest/api.html#platforms) for details. > > This was reverted in 1.5.0 for Windows and MacOS. We heavily recommend not using these locations on Windows and MacOS anymore, due to > multiple incompatibilities discovered with these locations, documented [here](https://github.com/pypa/pipx/discussions/1247#discussion-6188916). ### Global installation Pipx also comes with a `--global` argument which helps to execute actions in global scope which exposes the app to all system users. By default the global binary location is set to `/usr/local/bin` and can be overridden with the environment variable `PIPX_GLOBAL_BIN_DIR`. Default global manual page location is `/usr/local/share/man`. This can be overridden with environment variable `PIPX_GLOBAL_MAN_DIR`. Finally, default global virtual environment location is `/opt/pipx`, can be overridden with environment variable `PIPX_GLOBAL_HOME`. Make sure to run `sudo pipx ensurepath --global` if you intend to use this feature. Note that the `--global` argument is not supported on Windows. ## Upgrade pipx On macOS: ``` brew update && brew upgrade pipx ``` On Ubuntu Linux: ``` sudo apt upgrade pipx ``` On Fedora Linux: ``` sudo dnf update pipx ``` On Windows: ``` scoop update pipx ``` Otherwise, upgrade via pip: ``` python3 -m pip install --user -U pipx ``` ### Note: Upgrading pipx from a pre-0.15.0.0 version to 0.15.0.0 or later After upgrading to pipx 0.15.0.0 or above from a pre-0.15.0.0 version, you must re-install all packages to take advantage of the new persistent pipx metadata files introduced in the 0.15.0.0 release. These metadata files store pip specification values, injected packages, any custom pip arguments, and more in each main package's venv. If you have no packages installed using the `--spec` option, and no venvs with injected packages, you can do this by running `pipx reinstall-all`. If you have any packages installed using the `--spec` option or venvs with injected packages, you should reinstall packages manually using `pipx uninstall-all`, followed by `pipx install` and possibly `pipx inject`. ## Shell Completion You can easily get your shell's tab completions working by following instructions printed with this command: ``` pipx completions ``` pipx-1.6.0/docs/programs-to-try.md000066400000000000000000000037651462701651400170570ustar00rootroot00000000000000## Programs 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. ### ansible IT automation ``` pipx install --include-deps ansible ``` ### asciinema Record and share your terminal sessions, the right way. ``` pipx run asciinema ``` ### black uncompromising Python code formatter ``` pipx run black ``` ### pybabel internationalizing and localizing Python applications ``` pipx run --spec=babel pybabel --help ``` ### chardetect detect file encoding ``` pipx run --spec=chardet chardetect --help ``` ### cookiecutter creates projects from project templates ``` pipx run cookiecutter ``` ### create-python-package easily create and publish new Python packages ``` pipx run create-python-package ``` ### flake8 tool for style guide enforcement ``` pipx run flake8 ``` ### gdbgui browser-based gdb debugger ``` pipx run gdbgui ``` ### hatch Python project manager that lets you build & publish packages, run tasks in environments and more ``` pipx run hatch ``` ### hexsticker create hexagon stickers automatically ``` pipx run hexsticker ``` ### ipython powerful interactive Python shell ``` pipx run ipython ``` ### jupyter web-based notebook environment for interactive computing ``` pipx run jupyter ``` ### pipenv python dependency/environment management ``` pipx run pipenv ``` ### poetry python dependency/environment/packaging management ``` pipx run poetry ``` ### pylint source code analyzer ``` pipx run pylint ``` ### pyinstaller bundles a Python application and all its dependencies into a single package ``` pipx run pyinstaller ``` ### pyxtermjs fully functional terminal in the browser ``` pipx run pyxtermjs ``` ### ruff An extremely fast Python linter ``` pipx run ruff ``` ### shell-functools Functional programming tools for the shell ``` pipx install shell-functools ``` pipx-1.6.0/docs/troubleshooting.md000066400000000000000000000126261462701651400172140ustar00rootroot00000000000000## `reinstall-all` fixes most issues The following command should fix many problems you may encounter as a pipx user: ``` pipx reinstall-all ``` This is a good fix for the following problems: - System python was upgraded and the python used with a pipx-installed package is no longer available - pipx upgrade causes issues with old pipx-installed packages pipx has been upgraded a lot over the years. If you are a long-standing pipx user (thanks, by the way!) then you may have old pipx-installed packages that have internal data that is different than what pipx currently expects. By executing `pipx reinstall-all`, pipx will re-write its internal data and this should fix many of issues you may encounter. **Note:** If your pipx-installed package was installed using a pipx version before 0.15.0.0 and you want to specify particular options, then you may want to uninstall and install it manually: ``` pipx uninstall pipx install ``` ## Diagnosing problems using `list` ``` pipx list ``` will not only list all of your pipx-installed packages, but can also diagnose some problems with them, as well as suggest solutions. ## Specifying pipx options The most reliable method to specify command-line options that require an argument is to use an `=`-sign. An example: ``` pipx install pycowsay --pip-args="--no-cache-dir" ``` Another example for ignoring ssl/tls errors: ``` pipx install termpair --pip-args '--trusted-host files.pythonhosted.org --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host github.com'" ``` ## Check for `PIP_*` environment variables pipx uses `pip` to install and manage packages. If you see pipx exhibiting strange behavior on install or upgrade, check that you don't have special environment variables that affect `pip`'s behavior in your environment. To check for `pip` environment variables, execute the following depending on your system: ### Unix or macOS ``` env | grep '^PIP_' ``` ### Windows PowerShell ``` ls env:PIP_* ``` ### Windows `cmd` ``` set PIP_ ``` Reference: [pip Environment Variables](https://pip.pypa.io/en/stable/user_guide/#environment-variables) ## `pipx` log files Pipx records a verbose log file for every `pipx` command invocation. The logs for the last 10 `pipx` commands can be found in `$XDG_STATE_HOME/pipx/logs` or user's log path if the former is not writable by the user. For most users this location is `~/.local/state/pipx/logs`, where `~` is your home directory. ## Debian, Ubuntu issues If you have issues using pipx on Debian, Ubuntu, or other Debian-based linux distributions, make sure you have the following packages installed on your system. (Debian systems do not install these by default with their python installations.) ``` sudo apt install python3-venv python3-pip ``` Reference: [Python Packaging User Guide: Installing pip/setuptools/wheel with Linux Package Managers](https://packaging.python.org/guides/installing-using-linux-tools) ## macOS issues If you want to use a Pipx-installed package in a shebang (a common example is the AWS CLI), you will likely not be able to, because the binary will be stored under `~/Library/Application Support/pipx/`. The space in the path is not supported in a shebang. A simple solution is symlinking `~/Library/Application Support/pipx` to `~/Library/ApplicationSupport/pipx`, and using that as the path in the shebang instead. ``` mkdir $HOME/Library/ApplicationSupport ln -s $HOME/Library/Application\ Support/pipx $HOME/Library/ApplicationSupport/pipx ``` ## Does it work to install your package with `pip`? This is a tip for advanced users. An easy way to check if pipx is the problem or a package you're trying to install is the problem, is to try installing it using `pip`. For example: ### Unix or macOS ``` python3 -m venv test_venv test_venv/bin/python3 -m pip install ``` ### Windows ``` python -m venv test_venv test_venv/Scripts/python -m pip install ``` If installation into this "virtual environment" using pip fails, then it's likely that the problem is with the package or your host system. To clean up after this experiment: ``` rm -rf test_venv ``` ## Pipx files not in expected locations according to documentation Pipx versions after 1.2.0 adopt the XDG base directory specification for the location of `PIPX_HOME` and the data, cache, and log directories. Version 1.2.0 and earlier use `~/.local/pipx` as the default `PIPX_HOME` and install the data, cache, and log directories under it. To maintain compatibility with older versions, pipx will automatically use this old `PIPX_HOME` path if it exists. For a map of old and new paths, see [Installation](installation.md#installation-options). In Pipx version 1.5.0, this was reverted for Windows and MacOS. It defaults again to `~/.local/pipx` on MacOS and to `~\pipx` on Windows. If you have a `pipx` version later than 1.2.0 and want to migrate from the old path to the new paths, you can move the `~/.local/pipx` directory to the new location (after removing cache, log, and trash directories which will get recreated automatically) and then reinstall all packages. For example, on Linux systems, `PIPX_HOME` moves from `~/.local/pipx` to `~/.local/share/pipx` so you can do this: ``` rm -rf ~/.local/pipx/{.cache,logs,trash} mkdir -p ~/.local/share && mv ~/.local/pipx ~/.local/share/ pipx reinstall-all ``` For moving the paths back after 1.5.0, you can perform the same steps, switching the paths around. pipx-1.6.0/get-pipx.py000077500000000000000000000005271462701651400146220ustar00rootroot00000000000000#!/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/pypa/pipx for current installation " "instructions." ) if __name__ == "__main__": main() pipx-1.6.0/installation.md000077700000000000000000000000001462701651400214752docs/installation.mdustar00rootroot00000000000000pipx-1.6.0/logo.svg000066400000000000000000002003701462701651400141670ustar00rootroot00000000000000 pipx-1.6.0/mkdocs.yml000066400000000000000000000023751462701651400145160ustar00rootroot00000000000000site_name: pipx site_description: execute binaries from Python packages in isolated environments theme: name: "material" palette: - media: "(prefers-color-scheme: light)" scheme: default toggle: icon: material/brightness-7 name: Switch to dark mode - media: "(prefers-color-scheme: dark)" scheme: slate toggle: icon: material/brightness-4 name: Switch to light mode repo_name: pypa/pipx repo_url: https://github.com/pypa/pipx edit_uri: edit/main/docs/ extra: analytics: provider: 'google' property: 'UA-90243909-2' nav: - Home: "index.md" - Installation: "installation.md" - Getting Started: "getting-started.md" - Docs: "docs.md" - Troubleshooting: "troubleshooting.md" - Examples: "examples.md" - Comparison to Other Tools: "comparisons.md" - How pipx works: "how-pipx-works.md" - Programs to Try: "programs-to-try.md" - Contributing: "contributing.md" - Changelog: "changelog.md" markdown_extensions: - markdown_gfm_admonition # GitHub's admonition (alert) syntax - footnotes - pymdownx.superfences - pymdownx.tabbed: alternate_style: true plugins: - search: lang: en - gen-files: scripts: - scripts/gen_doc_pages.py - macros pipx-1.6.0/noxfile.py000066400000000000000000000172761462701651400145370ustar00rootroot00000000000000import shutil import subprocess import sys from pathlib import Path import nox PYTHON_ALL_VERSIONS = ["3.12", "3.11", "3.10", "3.9", "3.8"] PYTHON_DEFAULT_VERSION = "3.12" DOC_DEPENDENCIES = [ "jinja2", "mkdocs", "mkdocs-material", "mkdocs-gen-files", "mkdocs-macros-plugin", "towncrier", "markdown-gfm-admonition", ] MAN_DEPENDENCIES = ["argparse-manpage[setuptools]"] TEST_DEPENDENCIES = ["pytest", "pypiserver[passlib]", 'setuptools; python_version>="3.12"', "pytest-cov"] # Packages whose dependencies need an intact system PATH to compile # pytest setup clears PATH. So pre-build some wheels to the pip cache. PREBUILD_PACKAGES = {"all": ["jupyter==1.0.0"], "macos": [], "unix": [], "win": []} PIPX_TESTS_CACHE_DIR = Path("./.pipx_tests/package_cache") PIPX_TESTS_PACKAGE_LIST_DIR = Path("testdata/tests_packages") # Platform logic PLATFORM = {"darwin": "macos", "win32": "win"}.get(sys.platform, "unix") nox.options.sessions = ["tests", "lint", "build_docs", "zipapp"] if PLATFORM != "win": # build_docs fail on Windows, even if `chcp.com 65001` is used nox.options.sessions.append("build_man") nox.options.reuse_existing_virtualenvs = True def prebuild_wheels(session: nox.Session, prebuild_dict) -> None: prebuild_list = prebuild_dict.get("all", []) + prebuild_dict.get(PLATFORM, []) session.install("wheel") wheel_dir = Path(session.virtualenv.location) / "prebuild_wheels" wheel_dir.mkdir(exist_ok=True) for prebuild in prebuild_list: session.run("pip", "wheel", f"--wheel-dir={wheel_dir}", prebuild, silent=True) def on_main_no_changes(session: nox.Session) -> None: if len(subprocess.check_output(["git", "status", "--porcelain"], text=True).strip()) > 0: # has changes session.error("All changes must be committed or removed before publishing") branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], text=True).strip() if branch != "main": session.error(f"Must be on 'main' branch. Currently on {branch!r} branch") def tests_with_options(session: nox.Session, *, net_pypiserver: bool) -> None: prebuild_wheels(session, PREBUILD_PACKAGES) session.install("-e", ".", *TEST_DEPENDENCIES) test_dir = session.posargs or ["tests"] if net_pypiserver: pypiserver_option = ["--net-pypiserver"] else: refresh_packages_cache(session) pypiserver_option = [] session.run("pytest", *pypiserver_option, "--cov=pipx", "--cov-report=", *test_dir) session.notify("cover") def create_upcoming_changelog(session: nox.Session) -> Path: draft_changelog_content = session.run("towncrier", "build", "--version", "Upcoming", "--draft", silent=True) draft_changelog = Path("docs", "_draft_changelog.md") if draft_changelog_content and "No significant changes" not in draft_changelog_content: lines_to_keep = draft_changelog_content.split("\n") changelog_start = 0 for i, line in enumerate(lines_to_keep): if line.startswith("##"): changelog_start = i break lines_to_keep[changelog_start] = "## Planned for next release" clean_changelog_content = "\n".join(lines_to_keep[changelog_start:]) draft_changelog.write_text(clean_changelog_content) return draft_changelog @nox.session(python=PYTHON_ALL_VERSIONS) def tests(session: nox.Session) -> None: """Tests using local pypiserver only""" tests_with_options(session, net_pypiserver=False) @nox.session def cover(session: nox.Session) -> None: """Coverage analysis""" session.install("coverage") session.run("coverage", "report", "--show-missing", "--fail-under=70") session.run("coverage", "erase") @nox.session def zipapp(session: nox.Session) -> None: """Build a zipapp with shiv""" session.install("shiv") session.run("shiv", "-c", "pipx", "-o", "./pipx.pyz", ".") session.run("./pipx.pyz", "--version", external=True) @nox.session(python=PYTHON_DEFAULT_VERSION) def lint(session): session.run("python", "-m", "pip", "install", "pre-commit") session.run("pre-commit", "run", "--all-files") @nox.session(python=PYTHON_ALL_VERSIONS) def develop(session: nox.Session) -> None: """Create a develop environment.""" session.run("python", "-m", "pip", "install", "--upgrade", "pip") session.install(*DOC_DEPENDENCIES, *TEST_DEPENDENCIES, *MAN_DEPENDENCIES, "-e", ".", "nox") @nox.session(python=PYTHON_DEFAULT_VERSION) def build(session: nox.Session) -> None: """Build the wheel and source distribution for the project.""" session.install("build") session.run("rm", "-rf", "dist", "build", external=True) session.run("python", "-m", "build") @nox.session(python=PYTHON_DEFAULT_VERSION) def publish(session: nox.Session) -> None: """Publish the package to PyPI.""" on_main_no_changes(session) session.install("twine") build(session) session.run("python", "-m", "twine", "upload", "dist/*") @nox.session(python=PYTHON_DEFAULT_VERSION) def build_docs(session: nox.Session) -> None: site_dir = session.posargs or ["site/"] session.install(*DOC_DEPENDENCIES, ".") session.env["PIPX__DOC_DEFAULT_PYTHON"] = "typically the python used to execute pipx" upcoming_changelog = create_upcoming_changelog(session) session.run("mkdocs", "build", "--strict", "--site-dir", *site_dir) upcoming_changelog.unlink(missing_ok=True) for site in site_dir: draft_changelog_dir = Path(site, "_draft_changelog") if draft_changelog_dir.exists(): shutil.rmtree(draft_changelog_dir) @nox.session(python=PYTHON_DEFAULT_VERSION) def watch_docs(session: nox.Session) -> None: session.install(*DOC_DEPENDENCIES, ".") upcoming_changelog = create_upcoming_changelog(session) session.run("mkdocs", "serve", "--strict") upcoming_changelog.unlink(missing_ok=True) @nox.session(python=PYTHON_DEFAULT_VERSION) def build_changelog(session: nox.Session) -> None: session.install(*DOC_DEPENDENCIES, ".") session.run("towncrier", "build", "--version", session.posargs[0], "--yes") @nox.session(python=PYTHON_DEFAULT_VERSION) def build_man(session: nox.Session) -> None: session.install(*MAN_DEPENDENCIES, ".") session.env["PIPX__DOC_DEFAULT_PYTHON"] = "typically the python used to execute pipx" session.run("python", "scripts/generate_man.py") @nox.session(python=PYTHON_ALL_VERSIONS) def refresh_packages_cache(session: nox.Session) -> None: """Populate .pipx_tests/package_cache""" print("Updating local tests package spec file cache...") PIPX_TESTS_CACHE_DIR.mkdir(exist_ok=True, parents=True) script = "scripts/update_package_cache.py" session.run("python", script, str(PIPX_TESTS_PACKAGE_LIST_DIR), str(PIPX_TESTS_CACHE_DIR)) @nox.session(python=PYTHON_ALL_VERSIONS) def create_test_package_list(session: nox.Session) -> None: """Update the list of packages needed for running the test suite.""" session.run("python", "-m", "pip", "install", "--upgrade", "pip") output_dir = session.posargs[0] if session.posargs else str(PIPX_TESTS_PACKAGE_LIST_DIR) primary = str(PIPX_TESTS_PACKAGE_LIST_DIR / "primary_packages.txt") session.run("python", "scripts/list_test_packages.py", primary, output_dir) @nox.session(python=PYTHON_ALL_VERSIONS) def tests_internet(session: nox.Session) -> None: """Tests using internet pypi only""" tests_with_options(session, net_pypiserver=True) @nox.session(python=PYTHON_ALL_VERSIONS) def test_all_packages(session: nox.Session) -> None: """A more in depth but slower test suite.""" session.install("-e", ".", *TEST_DEPENDENCIES) test_dir = session.posargs or ["tests"] session.run("pytest", "-v", "--tb=no", "--show-capture=no", "--net-pypiserver", "--all-packages", *test_dir) pipx-1.6.0/pipx_demo.gif000066400000000000000000010075171462701651400151720ustar00rootroot00000000000000GIF89a$Ś÷1˙ H IN EEP=#E 6(7 7 1*T $"0_# $8$ ('.'%/)#) ) * +(+#,, &,B,:g- - - 1.1#H33>3O44 4,U5)8 8C`99:E;,_;Ar<3D=Pu>>5h>;R??F}A;BC&QFG.GVdH0EH1;JJ+#K(NWsOOH~OR‰P3P0ZQT*"T.7T4JT7VTBnV+WBYY*[fŽ]1^YŤ_52`Gs`V_actd7CdQvep hDUi3&mSEn:nJ`n˘pW`s:1sR to‰uK.uL2uM6w~µx‡‘zJUzTf{^u{`V|SA}SX}…~bgq}qťŚą€†ťACpŠODŚQŽ| Ź^e’es’j]“ŹŽ“˘Ă”\U—i@—‹˛—ž¨s„™s]™Ź~™¤¶šxtš€iš…@šŹˇšŹ˝›¦Ůś‹qž¨ÄŁtŁŻä¦˛ç§łć¨i^«€„­ ą®wg®ŚdŻ¦Í°˝ďł“łżŮ´t´›´ąĂµŹ ¶s¶ŚŽ¶–ť·ĄĄ¸­Ď¸°«ąš@ą´­Ľnľą´ľÎřżÓÜĂ•oĆ`<ĆĎýČľĹČŮůĚ–„ÍČíηĄĎÂŮĐŞŹĐßűѰĂŃĽ«ŇŐ×ÓĄźÔ›ŹÔ¬±Ô±§ÔżŐ˝«ÖĄfÖş·ÖăýŘÔóÚȶŰÂĹÜ×ÜÜíůÜí˙ÝąžŢź8á˛áÔÂ並欖ć»8ćÚđćâ÷ćđüćűý篡çŇÜçĺäé¬.ęÎĐëĆ ëĘTëÚÝëóŘěťěÄÄíÎiíÝĆőÂłöË9öěý÷Ú,řä ůË/ůřüúÚ9úçńűŃ·űŢ0űř˙üŇÂüŘŃüďňýŰĹýáČýöîţŕßţĺÚţćÎţîÓţďŢţđýţú˙!˙ NETSCAPE2.0!ů ,$Ś˙-H° Á*\ȰˇĂ‡#JśH±˘Ĺ‹3jÜȱŁÇŹ CŠI˛¤É“(SŞ\ɲĄË—0cĘśIł¦Í›8sęÜÉł§Ďź@ J´¨ŃŁH“*]Ę´©Ó§PŁJťJµŞŐ«XłjÝʵ«×Ż`ĂŠK¶¬ŮłhÓĄˇ¶­Ű·păĘE9ȶsóęÝË·Ż[u…řL¸°áĂIiŘE̸±ăÇGşoäË3k†L‡–7‹Mş´Z8L«^Íşµë×°cËžM»¶í۸sëŢÍ»·ďßŔ NĽ¸ńăČ“+_ÎĽąóçĐŁKźN˝şőëŘłkßν»÷ďŕĂ‹˙OľĽůóčÓ«_Ďľ˝ű÷đăËźOżľýűřóëßĎżż˙˙(ŕ€hŕ&¨ŕ‚ 6čŕF(á„Vhá…f¨á†včᇠ†(â$–hâ‰(¦¨âŠ,¶čâ‹0Ć(ăŚ4ÖhăŤ8ć¨ăŽ<öčăŹ@)äDiä‘H&©ä’L6éä“PF)ĺ”TViĺ•Xf©ĺ–\véĺ—`†)ćd–ić™h¦©ćšl¶éć›pĆ)çśtÖiçťxć©çž|öé矀*č „jčˇ&Şč˘Ś6ęčŁF*餔VjéĄfŞé¦śvęé§ †*ꨤ–jꩨ¦Şęެ¶ęę«°Ć˙*무Öjë­¸ćŞë®ĽöęëŻŔ+ě°Äkě±Č&«ě˛Ě6ëěłĐF+í´ÔVkíµŘf«í¶Üvëí·ŕ†+î¸ä–kîąč¦«îşě¶ëî»đĆ+ďĽôÖkď˝řć«ďľüöëďż,đŔlđÁ'¬đ 7ěđĂG,ńÄWlńĹg¬ńĆwěńÇ ‡,ňČ$—lňÉ(§¬ňĘ,·ěňË0Ç,óĚ4×lóÍ8ç¬óÎ<÷ěóĎ@çěÉčZĐ’ńJ2¨t„XÂ!ľäR´;<ý` h€K.ľ$‹Ö"€Ă(°DcL“- d/@ ‡Ŕ"LMÓq7˙š@D"vßî6á: ·*N#Ţ áş8î`ŕŃ0~Ş ¶Şâ7N*ćDh®Şác_ž9«Ów©B„.zŞŠWîůç­żŽ*ä¨fnű©±[njí»›Jşł‹šyńĽëů宣.8+ȇŞ;ę‹ç^{«Q˙`=ć’7čzđÝ:řá8}ů Ź~ú§Żŕřîżß~üŞOý×ßoţüúh˙ţôżöç|<`óxŔü1p?|`~ (ÁűŻ‚úˇ éÁ rp¬üB(Bţ‘0><ˇ{.¨Bů¤°…ëé Ůó¢g„6lŹ sxCňP=,ü!˙}(Äóě°ă©!ÁĂ%–çNüŽŁČť RQš°‘|t#$˙¸ĆIÚQ’–,ä#3‰HLrr‘üdr )ĘŢ$˛”ą$*éÉUú†”®ÄÍ)cIFŇň•›ĽĄ)[©KYV˛—ż™%0]ËaÂFĆ\Ť-“i›b2“5Č|&iT)ÍÚDłš›q&6§ÉËmB3”ŢśŤ6Ă©™k’2Ô*Ó„f´¦ ])N߂ҝć%¦>íŠK U+4=Ş[†ŞTˇę´©eé)TŐbÔ©R…©VĹJUł•¤r•,XýęUź*Vˇúł¬0%+Z‘zÓµU­n˝ŠWăĘ•°Ň•)[˝«Q¤Ş×­äµŻC±+`Źň×Áe®†˝j[k•Â2–'|}ěT+Ůś¶˛?ˇ,fm‚ŘÍâu±žuŠfC+“Č’v)Ł=íK.«Ú›¤¶µ,é,l‰ÂÚŮxÎäµ¶E‰isX¸ň˛ ý­Pp+ܑȶ¸Ŕµ(r•BÜĺ~d·ÎÝIsŁË‘ÚR÷$Ó˝nFŽ«]šX·»Ćő-xW{Öńú$»ćťČwÓëô˛"Ü}ol+_¸·ľ .~c+Ţý–d˝ţµČ}|ř$>°D€!ů ,#‹!ů ,$Ś˙5H°ŕŔ&„`°ˇĂ‡#JśH±˘Ĺ‹3jÜȱŁÇŹ CŠI˛¤É“(SŞ\ɲĺH…0şśIł¦Í›8sęÜÉł§Ďź@ž„©P¦ĐŁH“*]Ę´©Ó§PŁ%şPŞŐ«XłjÝʵ«W«TýJ¶¬ŮłhÓŞ]ű3ěż±lăĘťK·®Ý»:)P0A‚˘[¸x L¸°aµŕ<1aâßĂ#KžLąňĚ üŃ*#"EŠĆ[Mş´éÓ“4 ń(¸LE@7Ťş¶í۸scŐ{ÍľrELp°îăČ“+_^’B<ÍĘ5baăqŞĆ™kßν{ňWŚŐ˙3ö‡‰i{_Ďľ˝{Čnť˘"ĹyęßëßĎżż×Č&Q~ţhŕöÄÁpŕF(aMNhá…fxQ…včá‡b â‚hâ‰(¦¨âŠ,¶čâ‹0Ć(ăŚ4ÖhăŤ8ć¨ăŽ<öčăŹ@)äDiä‘H&©ä’L6éä“PF)ĺ”TViĺ•Xf©ĺ–\véĺ—`†)ćd–ić™h¦©ćšl¶éć›pĆ)çśtÖiçťxć©çž|öé矀*č „jčˇ&Şč˘Ś6ęčŁF*餔VjéĄfŞé¦śvęé§ †*ꨤ–jꩨ¦Şęެ¶ęę«°Ć˙*무Öjë­¸ćŞë®ĽöęëŻŔ+ě°Äkě±Č&«ě˛Ě6ëěłĐF+í´ÔVkíµŘf«í¶Üvëí·ŕ†+î¸ä–kîąč¦«îşě¶ëî»đĆ+ďĽôÖkď˝řć«ďľüöëďż,đŔlđÁ'¬đ 7ěđĂG,ńÄWlńĹg¬ńĆwěńÇ ‡,ňČ$—lňÉ(§¬ňĘ,·ěňË0Ç,óĚ4×lóÍ8ç¬óÎ<÷ěóĎ@-ôĐDmôŃH'­ôŇL7íôÓPG-őÔTWmőŐXg­őÖ\wíő×`‡-öŘd—möŮh§­öÚl·íöŰpÇ-÷Üt×m÷Ýxç­÷Ţ|÷˙í÷߀.řŕ„nřá'®řâŚ7îřăG.ůä”Wnůĺg®ůćśwîůç ‡.ú褗nú騧®úꬷîúë°Ç.űě´×n;‹˛ä.Ëípb űyÁďÁżI|ńmŹüšĘ/źfóÎź }ôeNOýÖ_föÚÉ}÷]~ţ–⏟eůć_‰~úU®Ďţ”îżeüň?IýMŢŹ˙’úďźd˙ţ;X¤pH<`¨Ŕ1°=z w$Á 樂Ľ3XŁ rpFü`ŚB(‘°„-:! W¤Â¦¨….< c˘ŇĐC6Ľˇ†r¨C ń°‡ú!˙%$Ä!B¨FL“x %2±@N|b˘(ĹýP±Šďą"ŰŁĹ-®§‹^ěøť1’‘9f<ŁrҨFä°±Ťşy#q#Ç9Ú¦ŽvD óhš=ň‘4~üŁe)Hʲ’9$"!ŁČE¦‘Ž$ $#)IR/–Ľ¤]2©Işp˛“rů$(Ů"ĘQŞĄ”¦D *Si–U˛’,®|ĄWb)K®Đ˛–Zą%.±˘Ë]ZĄ—ľŚ 0ů”ał)Ć<ćR’©Ě¤0ł™Gy&4"Íiţ¤šÖě 6łą“mr3'ŢüćMÂ)Κłś39':[˘Îu®¤ťîL <ăy’yŇł$öĽçHň©˙Ďđłźů'@;"Đn¤ ÍBz‘…2´"}čD"*ŃP´˘ą(F˘ŃŤ¤ŁHCŞ‘†Ô¤EéFUŠQ–VÔĄ…éCeĘPš&Ô¦Ĺé@u PžöÓ§úę=…JO˘ĆÓ¨îDę:•ŠN¦–Ó©â„ę7ĄĘMŞfÓŞÖÄę4µ M®6Ó«Ęë1ĹJL˛Ó¬ľDë.ŐŠK¶ÖŇ­˛„ë+ĺĘJş¦Ň®¦Äë(ő JľvŇŻšě%KIÂFҰŽDě"‹HĆұ‚„ě%ËGĘćѲvÄě5 GζѳjíEKF҆Ѵ^DíU‹EÖVѵR„íeËDÚ&ѶFÄíu DŢöđw!ů ,#‹!ů ,#‹!ů ,#‹!ů ,ˇ5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ14há„ )L€|(ŇĎ2ő”ąQ‰1ŁKçÔdéÔ/ĚJ.M{ÁŕC/b?ŢśĆăÂ…6Ě’ÚÚô)3 ňjbšíE¸zIý·ő’˝D] ő‹3¶,˝yőŔJŃ6¨0$¤ [“lP¦ëR Ü×ă@1(^Śq@!ů ,¶hH°ŕżBX°a‡ :|¨ˇÄ+$ Ă'!0füQ+ýt™qa… `iˇˇKŠ.cX€O›F’ÂCŹ'®\…täB!6ŚPĄ”©Đ…ElHĄşô&DY·Vőš1$8x † $® ‚:׹yשE %:˝{w*…Ü‚ @€ Â°ß‚&¶´xQ.Ę`ŘĚĂe!ů ,#‹!ů ,#‹!ů ,"µĐ@° A˙*TA A.l8đáA‰ZÔă?Š9zLrcGŚ4€đ@B†&NJLég™żzĘÜÄůQ KçÔdéÔ/ŚĚŚ\šö‚Á‡^ÄŽ2ôiiŹ Ú0“JŇçŇ«Y™I7’˘Ňl/0ŔŐ‹kϤ—ě%ę©_·LÁPJo^=p€RŕMˇB©0$¤ĚÓěW ńzµ ůbYŤŔŔą3Ĺ€!ů ,#‹!ů ,#‹!ů ,#‹!ů ,+şhH°ŕżBX°a‡ :|¨ˇÄ+^$ń`ÄŤ:ţ[Xˇ‚ $B$H B…H’1şˇb˘Ä-[)^čBG3F)DEŰaB§‡Čä;ĄK:‹Ř0a¶R>0„ě¸Pꄵ°ť;‚‘+1š@òl‘Ť:C„ČsŚJ -×ţŘĐŮ`Iľ:!4,č4oÎ DŕĐ!A–:^ ¨µlĆŹu°X†Ď 1l!ů ,6\5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1t°ňˇÇ†3ZÔP˛"É”˙Nl©p%ÍŚ!^¦Ä “%L tv´ů“čNŁC%XĘł)ĎĄ!ů ,>˙5HP€@řǰaC #&D¸ĐˇC NS°lĐąPđ @Á?†82ú?!«ßĽ~0ăČ„‹· !ů ,#‹!ů ,#‹!ů ,P­5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ 6h‚&L€„řÁP5ý”)QÉÂ… yýáň +/x8T‹J H„X©áŠ[ţ4…iA‚&F hŃÔĎŘĚ•8Svć­ĐŕÁš1:LLŃëĆŽHĆ@ą2C!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,m%ŃH° Á*\ȰáA #JÔఢŋ1NܱŁÇŹ7NI˛¤I‘MŞ\yeD–0c"t Q¦M›hŢÜÉňBN”<–ě S¨ŃŽ4)]˛(Ó§ “Bťšđ'PŞX Z™µ+€­˝b•*–*ٲP“ţ[Ë–-´AąhK÷-\¨tŰÚ˝Ë4Ż[ľOý®Ý بŕ„ =śXńNĆŽ nY&äĘÎP˘DŠĄ4Xd0H† 0gJĺIµŞŐ«Xqv`‘¦5rîĐ}CG,”:Řč PˇÔ©=bŔŕó&…)R` y7oÖżű¦H)x/ŕ‚>™bĎ]cwđ s´Š›;H&lŔđ–f\pě„qłDzIV€Č„áð ŽŘ3Ç5JÓ¨_ÇŢJŠ\ăxŤ©±ą”l9rť˘ đ±łL…ŚPÉ!°ÂV®FôXcW)#X˙šž¤ři>rĐaŹŇŁOgXšĽä÷Naí>\Ŕ׳Iyqç‚0đACĽv­×Ţ{#ńPcŔ=5ÔtčŽ;¤ ˇÂ^ÎŤ ÖčaĂ^Öa§Ý@U 0é‰$Ŕ%ä•´c~8pE?ş`X‹.ęvĐ2ŕ zM0 8ŕ‚ 6TŕŐxcŽ1°D>aô#… I¤‘!1QL‡pşs\śŢč!ÂG 4ÁHWLyB *ĐA ŕpÍ" Â#Ś2Ęzhŕ0D{yÔ€‚jč(jĄ†"´Ł0"ôé ˙ęčhP`j¨…&´j«~@<đ@ŁŁyŞ€«)‹kŞqd*-0(ź˝ (`‚ $ ¨ŤŞŕS¬ĚÂ\gľćÁuŮÁg,˛Öę ÁĚŘÁAŠ GĐm¦›Â¸A.讻›дd‚ Î*­´zňé0Äô‰e·„Ţ{P} ăŘ${řcŽřŔÁŻ~h“N=ÝĽ‘ w€ăĎ8nř´2íôŚO=żX7Ę5ďÜřü#Ď/*„=öć‘Ô€Ëp­ŚSŽŹĺ~=ă—ß *,„PÂ-¶řz”|Ź:¤¸ó )ęh I¤ÇĂĎ9䀄Tč  ę1 â|ŕ‚`„k AؤXá‹7ŚaŘC6Oôz$Ă@Á 3ä xŘÇ&˛p…}4‚YŮ<˙ř€„NěĂ VAľ<`#8´!žđ8Ŕ@!;˛G"ş‰~ÄÁ:vx"¸@†f`‚`—ŕ}4˘p…/dHCvŹFčÁ\q;(8fü Ud 6h„f|0„$€™čÄ ’&v/¬Îl7Ł4®±ŤŤ@&XA'(KIă9|°L ÷H‚Đ®l= D‚ „‘FDâ˘@5dˇýCň¸Ç>óÉ šÁ";0AB:Đżýťáŕ 9ľůÍo°/ČŹ^@€Ü#“ۆ :@‚€"*»€ šˇ˙‡„€Bs…ŕf`ÂiŔdy¬ăŠQx=cŽQŠLŕ÷řá0Ői‰l°Óť‰đ  ě˘7Ä<¤ŕŕnÄĽ„G0\ă1؆2`‚ Â>pŔ1Á 4@ĆÁúТ w Ŕ&ťÉŁŹľÓp‡¨ô‚—r@źüĚ |Ň‘–ô¤9¸—B )NÂG¨D5*ROĐmĐ!$@€x°Ń\aLŘB:–…y •]yâđŠ<ĐŇŕAo‰,Ć"Yť®îŚ0‹ßJGyĘ-wąő‹ĺÔç2k)ŕ0ĚöVÇ9ÓéÇ2[Xń„Kí) śëÍÚÍ@Ů…çT7ćxKď:G ›°čĘŃËţŮßŔ5ó2ÁS:7€.˙e€ ě! ¤Ý7´ 1FÓC¨@/ŘÖD?ń‚ą¸t„svxB 6 XŔŔ.ôżG#¬ą€ŕ)ĆÂ%N‘ ÜÁB@%¤AuCn´`ŇI0ŃPôĽ«Í© `gł#8,@Ś&Ô¶H+ń®‡`70ŘCIĄ‹•1ť)lŞČŻ}ě;R<ăC`Oc`a‹°Áń˛b°ăóě™m1[u°ĂôěH§ú­äW`‚¸F/A<ŘrĂ”*ŁŠgť űH„î)NgD‚[4„€xuŹ÷ßqgĹ2ŢŔ…î¸w€ř î|?›ÉçXC˙†L€ř8ĹĆ`'ô” ú°EĆ!ČY‘tVČ8@Ů»á $`x°v°_đ^`Fĺq{z {f&}Ôg}ĺCűsđŁBHŘo0$Fý` 2T0tĐ™đU€qĎV݇B`=F|Â÷ĆgÉ C(€ăöqZÄE^„%Ŕţ×—„]Ł‘ǰUZp 1S6vĎŔŢ€…Ô@ /N?…`(b𱩠-<Ý  ßc3ă0_Ó]>ů` ëâ Ľŕ€ ™ ¤A1  ţp‡,GĽŔ|}ř‡osé˙ąĐŤ€%a†h¨†™đ%Đ EóÚđ)Đw  ňŕŕ 0°Qó9ěC>†8‚3\`ąła7ĂŔÁŔ t±€¨°‰ď𦖆'°†Ťł[Ł6™?÷B‡v‡IÉ/ó‰ľ"©wŘ66V©07¦Ť86\Ť{ŔŠÝ0öS_µŽEĐ@łX¦ŔŕF°5ÄŘlj—6y3|ă7ŚśHŚ0°#ô€}ŠcR¤±ť0`/an ÜŔ â@ }đ"N ’Ü 0ó(#>q-* .·/ ˙ ,Ť˛@˛¦ĎC`*;ą}˛2A™D©'Kq0Vń’“3)/ČbT”˘0Á0<ĺ+Ż·'Čâ·R)<‰-±”Ů•ň’*@•1ąL €)ĺb“.§•Ăb—ע0Śf”v/ˇ’_U–ú,•ń Űň)&`Ń” @,!° ®ň– @(UŮ'‡7¬‚×â– Ó+Ѝ‡Ňú‚„B â›Ďđ ŽŔ µ›"ů G0#1áPVśˇ)±–.ye0Z0 öĐÍGś 1!ť 9t SĎIť6F…(Aś Éťž˙‘ťŕ™.÷óq@˛ŐŮ!ŕ0›±™’ńY ˛0—•"© `ďĐé0 f m±1 zćÉj ”b@ ńů âĐ>ŕRŃUYŞX ÚˇŞ]µ-T`|Ŕ…`J?řˇ,Ú˘.ú˘1„ň</€t0šŁ:şŁ<şť=úŁ@¤B:¤DZ¤Fz¤Hš¤JúچŁKú¤PĄO`RzĄX*¤ ţ@ e y!žY:¦dzBʧh7eÚ¦nJ Śvh°ĺP&°2oš§zJĐxĐ Ç6ŕť{Z¨†:pĆPĆ.𩴷‡©’Jp § 7'•“ş©śJ!ŔbÚ©˘:Şđ§¤zިz!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,$ 1˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|ˇ¤I R!ů ,$˙5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(€{ś8„H(ň_Ç‹®ôÓĄ’ĄH @x !C *(P€Ą€67âôłĚ_=en€Ć°öź0HC¶„ ŔŇ95Y:ő ÂCŹ'®\…X©ő¦€KÓ^0řĐ‹‹F¨R˶ĄË®Óx\¸Đ†Yy÷®MZńmŕÁ…'ćËăŰl/0Ŕe—“`Á0A‚„_®—ě%ę©_!8p s ‘›7¦·ľĄ7Ż8@)ŔP˘Ó»w¦`ś~+L„ )‚Ě B ËáňŔđĐ ‰Ůs/ňôE1¨_˙Ý`@!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,$$¨5(Âż HĐ`„třđ`D‰(VĽ(QăCŽ =BlĐ R‰C?ËüŐSćfeĹ–,ťS“ĄSż0nZpiÚ zĂ ô†śÓx\¸Đ†ŮBź•J•Y‘vY‰f{Ń€®ĄMµÚKÔRż8AĂ^˘7Ż8@)X˝$L„ )ň¦%•Ł^§„yN‹€c #cp!ů ,,$·5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ T¨ A‰ ¨PRdŚn¨X„(qËVŠ–BčhĆ(…¨h;L´ô"™|§ôaé@˘e&LÂVʆ‹!€ÚٶsG>r„ ó(cX–-˛Ń˘eyŽQIˇĺÚ-,ÉW'„†ťć i9ˇ:$h°˛ĄŔ ŻŠÍęëD­"ŔŔą3 !ů ,#‹!ů ,6$Ę1\Ŕ€ˇC 5XČpῇ!BHH1aÆ3N¬Hń"ĂŚ7rDčŃ!ȇ"GĐaʇ&O¦äHŕJ?]/c‚„pc… `i NŤ#5Taí>aŚ8‰2é=ž¸rćTŞ3^ŕ@a„*®^©ţ KqY´GC&Ečöl׸CĚ˝:  $H¨…€a/:׹y#ě…ą0”čôîť)ç*Đ )Td†ůâč¤%żĘ™š!Á×!ů ,#‹!ů ,H$˙5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(dH‘˙:^4‰2eH"…Ŕ— HaÂDK ühKWŻŰ›>ŞćŻź2%>QB`éś$©ôÁŔ!ł?\ľŔaAâ§€KÓ^Xq/‡jQI‰f-Mă1áC4E8¬¸ĺOS$˘ŠśŠ–!B$X ES?cPÍ6î 9ÄuAkĹCó^Ί"ŰŮó剗fJK]*X‹ 'şeňŕa2ţčebWj‚*Tl¨03„ rŠů§Ŕ×ë–¬+Ń:I–RWš4X·/Hpb™ ŐjŤ®SaŁj @A"ŇŇ´(÷_D‰uďŔ·Ąß–|!ů ,#‹!ů ,t$ź5HđźÁ!\¨ˇC… :D1bÉ!La >\BÄqÂ8pá"!ň"FF°r˘%É7xPEÓ&IFđ¬9ň§Ŕ B{}y4)Q—s:őÉ´“h±0A‚ÄM…6pČ Đ›9^z‰ˇD*ďLĄřú´ATĚ5jęĂľ~)†Ă1 !ů ,#‹!ů ,#‹!ů ,~$Ă5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(dH‘˙:^4‰2%I 

!ů ,Ź$˙hH° €ţ[Č!#&LذâĂ'*¬č"Ć7rüwń#Č#–4@J’8lP@‚„)$Pˇâ`… DĽ|čÁĂťjő”ÍÉiČX‹*ś Wf(€xômʢ©_lÎůX@cBŹ{i¬F8VęE‚˝¸2ďČ–tK˘Ě#2TCŤfzxpŕІYŚ(ů ¶g Ľ#Vk\ |áBá=čĹyu˘l>Ô˛}Á`.b#NÜŚJ-P¶xXĹŞ•«×˙Q±!Ů)n0j­^77&ďŮV$D”t\lXÝp¦Mś4@P`„î&¬Ä€!cÂ.{üŘR<Ć–ÉË'Ź0 !ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,˘$Ł5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1PŘ @*T€|ÁÉGÖü˝Wd%Äxězň ›  š'ĺÂ$€f¬ĐăV:TZZäPúO$FPÍBC HȰ'IĆĄ{}ąqg_˘® öTóç\¦źg«VhpR‚„)şZÔ Řba†cXĚCâ€!ů ,Ş$§5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ &h‚!B€„€C‰\éüŃűăA%G#ş|‚+[bx Á®V9VnŘ€ŕ¶wȰµzÓ‡NÇębmęĘ '– "Ab@-Ż7'Śpĺ«—G©b„X˘S5ő´ýI±R`’$HHÁ÷¦Ç‹sŻ "ˇ!ů ,#‹!ů ,#‹!ů ,#‹!ů ,ł$ÁhHp „&Ä ° Á 2tř0˘Ä†!Zü7‘˘Ť;fÜa‚*Tp¸By$–°fJ%‡GÚXä @¤s>&|H& dD†Şě3AĆľ8F/NN+ű¤D]`BAŃ DšćckɆ5š•ц)‡Yž€ÚŚŰť á§ëB‡·yeŘKá#^nhˇőKEĂ1DaVOÓ…3Ľ ł@ĎB‹fčą3éҨK!ů ,#‹!ů ,Ľ$ #5H° Á*\¸đ‚B !"ěŔ°˘Ĺ‹3ppc@!ů ,#‹!ů ,6­˙/\xĐ E *\ȰˇĂ‡#JśH±˘Ĺ‹) śň(S„CŠI˛¤ÉŚ˝`ŰgĄĂÉ—0cĘś ĺĘ–4sęÜÉ3!†źÖŘUŠI  qB k˙đáę"a kňţMăÁ”€{ś8TíIV¦Ŕ*Ř€ů8ş$_‰&ĐŔ ‰± dŕ5m­BWúé[¶đCˇJ1)€D‘¨"6&HÇ6P‚ :l  €łg*pˇ/LçĎ©KK`ˇ‡¬\…űSŔĄ­c+ŔŇ"t ˙Čó j1ä’N=Ú’BBx Šnc%$@%}…÷TTÂHxśÚśŘÍ+ĐŔÚ\¨ĚA>TÁ©¤ăO>¤ŕwTSĎ‘)$`1-TUÁ ô”á…bř%č=xÂU¦¨ŔŹhS5€F:ů8ŃŔőôiž yžlnľŚ1(Ě‘CxŘCČ_ŔČpĹ>„˘yPĆQ@ÂĎtPÁ/î˙¶ĐŚŠ*ŘĂ®Ŕ(Ł%çČD*ű˝*Č5™|QE3›ĺPjF`cĚSŔńE ”ęłIšôFlśăĂ4LĐĂ=iPj)¦š&4B_@6|đ@$ŢNđA2˘pZÓ (đYÝI`‚ D«˛Żş2Š8Ŕ &ň2Ź‘@BMܰĎ?QuÁHŔ ĺ4˛Ű†±ĆŔÁ ]Ŕ°ęşňo/°Â=‰TĂ6‚ ŚŔ1É*9‚/ Ŕ Âh)Á1ĄĽŔ˝cŔó±E:KD1HLń˙„Á !°K+“V±ȰO %Řďg 4ŔÁ± Ŕ«ą…˙@µ´ÂC=Ü’*Z´€ ̰ńB  đ8éTĂŹ$'Ç,«Bzł¨ůXX˛•˝Ń(B#4ĐĘ6ĀۉPµP ÍčÁĂśm0Ců16{ŚĎ„ޏâl€Ŕ!ÚĽ 6‚;ŽéźJáRž{ćhĽŁŹ&¨Ě9Ťă#ŕ‚W@š¨`8„„?®P©€SZĚ ! ,łŚä[˙6ç›Ńť t§Ű‡˛ş Śn ®—\ĂvÉ] z@Ź8Ľâ´@D6|@őµoďó@'ŽQ‡ ÁŃ«€ ˘a€HÔ¨eP‰>¬@€;ü‡ jČĽ˙Ěń‹ńí|ăA(`±×Ůs!Ŕ ZĂ0¤`Dyé$€pŔ“  L6 Ň(âĹ:p0Âd$Ay@:EkаŘĎČ Á-HAŔƴ0`¸ ĆNp P µ…-”ČD8Q8Á2a1ô)‹veĐ&r Ő`ź`ÂéD!*Ř€) ö‘1Ľá»ń$ö/Üŕ´&@˛d8ę »Ä<ř°„,”CTŮň€ @Ľa3#@5‡7„Ćet¸"Ü€Ě9Ö1.¨Ř"Ć€‡kđ‘!ŘŔśő‡/t›ŐşV¶Â0˙‚ üî*X618^ú‰Ŕ\á‹:pa(‚“(¶0r!bŮŤ@:FA†P šx’)X°Wđ˘‹@F&T0=TĂţG&` L2E t¦ ŐŁč€KĐ”ŠśéŁMʇ)Ü4uâď0 Š`ěôÝČĂ>‰wÔăîäřR,đ˘L¦HA‹î`ŤźşaPŘĂ6Š‚(¤ p)LeJS” /EŃ‚t:~č˘U ń XŔ)ŲŔ8ˇ€J#$o6xzš r€śÎ`§esPCšt¦*Şs^sTŇ( ˛›ë,R ‚ďČ­łéd»ft¬ ˇŽ–C›Ł]€;ŘI0°Ň ¬ëů¬˘KÂĘŔi€ĄMX˙„Ă 6č¨D$ń†– ąžn1Ľ-la ZŔ=ŔG¨¤!@‰y)r€h#ęčv­P˙(Ľ†I°+`fČă®Ŕ đ¦ŕDőĐÄe´ €)řE ŔbűT¸Âům*zOŚ_ \@lčČ(‚ ¨¨yYĚăOdĹ ŮŻŹ‡LdŠ!ů ,6 8PČ!„ ¦ 1!D0TÜńÂ…J1)pPT‘8xi§ /ú!ĽMş|NěiČÁc*T4HĐPFŽ !ů ,#‹!ů ,6ź[˙¨ˇ Á*\ȰˇĂ‡#JśH±˘Ĺ‹3jÜȱŁÇŹ <˛¤É“(SŞ\ɲĄË”#IľtąaC† :¤ĽpA†:g J4#O ?]łŕR•F * ÄN…°ú´«×§<Ŕ±łő+L Đš˝ŘTá„ĺ$Pj˛ÂV®Ę®őĘłAT¨ëĐ/„"TeŘW`"ôR4 A‚„) 0B%‡@»x%ä™ŕo`!č"¬°AcŔ§&Hű4×˝Ű&ś€"îĎ” óŢĆ]”çŤNďŢ)sł¸á?ŐüŤűCxaŘ-·üIźăa¸Ä†Ţý˙«×  Ő ]XÓc€ŕ˘=^Ô;ézć3´»LŢżţŃ3„{ -‹<ţÉgMéFÜC5PÁEÂ('”ÓP j`Řd‚ î%`‰mŐ—iEZ $ Xdf5 ‰&¦ĐŘŽ)ȄЋ,Z8bbpŕ &č4›`#–xb•—Ą ˇePN© UĂ6íTóN;ŘÁwźM6ďŚ 6|đŔPTť¤“K5hęagETbSÜŃŹ"5e Â\Ą V×|!“#Ś2ʱuФ†D6öŘ`č Ä“~ŚŃ(ĚtĆÁBxđS@˙a„5Ŕ´×ĐŻ”ĆO°@BZ!ů C˘‘‹?ô0Ň]TŹXăO.ü|ŘA ř±Ś?ő,‡"%ä’˛tÇÁQ¤r_>ŚŚp—+U©gŠ bz[Ź6€)âÚ ÜBz€Ć-ő€H{j)ÄSąçžâëĐI. ٤ŁD”lá#6|`HtĘqaBY,“ÎĽ3°>ýLĽ‚5ů4ˇ_ˇĹŚŇN)k.4A Ě0Ă…U´“ŤlŔ“ PĐ,í`’C¨PÉ4H§ Ř%q c@•žvą ( şFÄçî$8!°‹?Ŕ 1Uĺ,çťmĂ$ AAÁ{ řˇiĄîÓxA {AŚî`ŕĐvŃŠ`Ň@óś*X/p0 ô¦bÚ†  €?ňŔÇ*ĐQĂW ą$>áE‰`QŔ3°‚-`cL ýNńŽ@xě6@ €–x€ňŔ[Ś őłEp׊?9„h‡/Ç\ˇˇh6ş‹}Hˇh!@üÓ˙ŹdPÁ‘ˇhQl [¸lf‚ărA3ôČĄÍ€s3śćÇRĽ  `¤ş\1 `@ŁN;ˇ¬Ń}„!Ź)€ |P†D`ćŁÇ~3ą`ѱ!@‚ů´Ł°Ő`pžéŤ$ y‘¨ŽjĘQ„řd͸‡ E/ôĂľ‚ĺ>̰?zňCtŔlŕ…vücŠ f „hXöüĐE. lŚcŁ€f N€Bó RÚy~˙|‚BŔ•=ń9 @Aš?“D¤†|`ëCX7Á„*Á󑨟tź  ĺ¬ÁD!Ę©*ŞČ ®[N‡„%YD3ÔdŢ €€ý[D(°ÜŐ)-`mĐOÔ~ÔB Aš ‚ŁęA JeŞZśŠHDuŞ6čÄ1ę X«źkÚ`á }đ« H8ę€)Ř#pUCAčŠ=íÖÁ &B`6a•‚R űA„€ŤüC °!ÂăÖ ęfpj Ě )€5ę!-"´zĂU=±Ťunp!č„ôuC1hßűş&槢(A-úń‰˘ß˘Ë E3ÚQNsă#ť¸ÁC@0ŁüHěöóŔcţÂĽ8EÜă~đUäx˙ür§“îߎŐŘSüî €,¬` ^¦@QíĚ ĄŔp `ć cđę2#Šw›ĐUĂ“h”v'`p0L”;q8e /3=°Ť€Ăý Ŕ7p¦ŇDěwj#av Ń `,ŘŇ Ó*{€ ÚŃ6¨w—@ó0ő˛*%€ţđÚ@“ ŕů` ŔŘg ôPš` @°á°ĚŐ*˙’\pBG0Eh J@đŃŃ Đ đ:a°†€„P,ŕČpÝ ,@#Sŕ-3 iĸCAĽĺ@Ö˙đňŕňD Đ ú żĎóĐ…\q‰™řĐšŔ1Ćŕ6AÁw€2N`Q‡ÁĐŞ1.CöCňŐ~]p-Mč#€}@ńČ *7w0eĘđ6đ„ÁŔ s!ŚÄX4Qá‡Ú‘ŠzÁ†qpŤQa@€ŤÚč"q xŐ6ĂŃ‚M傪6‡a5ˇ0†Ä DŇ#+a/ `“’(Ŕŕ%~Ł- t±đĹ]®ń)íEú%”![á%ĄÁ$ň±´tr•’ŕ@ŇôP*ĺEŻA‘P#“ŇKbŹđ’ “˙’‚Q­Ĺ ^& µČ~ä'«Ń26!VR*pś$5Q•9Ž7yŮ# `’b™gĆk&É °©”#,.č ö–€k÷G,s)•#čˇg65±[0Z  ű01! Đ‚陡rfśĺ ËĐŇPo™“9™A“é+ gÔˇ„Z@ şĐsF1Ł›“i—{ÉŽA9xɵYP†Đ ňđ¸ŕ1&€j{Qdí  RŔdD. \đqT 0Bé C€uşéd˙"áÉÓ—D!›©ś{‘HÁ•ġt˛i:‘żYž›řąź‘›üůźzţG‘z *ˇ4<‚ ˇ 0Ä W1~ˇš€°-Şšˇ÷ąˇ1µˇŹ!i[ńf úź%` ţ‘—ńT4+Ú˘ľ©y1đř€ Ó÷ öŔ Ŕ3ú.Ú0zv7ú9şŁ)ĘFŕ˙ (Łë‚KMşˇ 8 ÓŁ/Ú` YşĄ]*#G8€ ¸@ĽĺđNş¤1¦\ęĄF ¦2Griş¦m ˘ŔOlpkđAPt–Ň–C’%=˙b P˛¨ ş,Ů)T™)Ub"ŰBŹĘJ Q,‚!@,9Ş@!!Ki!Śq ’ ˛)š%^ň (µą©‡˝ & *¸–Źű˘ -HŃ«á‹3’•C©ă4ź8âDÂCą(Äú¬ŐŞDŇ­XĐŐ‘¬xꬣşÁŞŹŚ Ě*˘âŞŢş®JŕN»u!•˛6Ű‘ań/30îˇ1ŃŃĘ01ý 0óeŞňB/)Đ*y€ő0n‚Őr-ŮâŰ"°ţ@°ăÝň-:Őňąp.ڰ1x,É›Öáw“WmŁ7Ć87Ę˙Ŕ/ `ĆĐVá@ôPąŠ/Exł0dvÚwŇÁ€kô0@C! ..k´7áĄ+j ĐĘŹ  E‹a°#ă° Đď ó‘wĐ2ńR¶ő˛RJ* zV;S;˛!ŕ´P őŇ•µ\q°˙ްW`O«’DKÔDO4zŰÓ=ßs!Ěđ\đpŕ+Ë=Ţ>Óy$#°<ÍĂkľ€E“08< :¬ă:°ł–‹ąškĄ A;¶c_<Ŕ7 ˘°&ž@5OHşÎ=đ®ŕ®qż1żşŰľďżv‘żp§=ž;ąˇ ˇ«¸‡6 ®°k´Q9» K´dK,Ŕ‰C)0n?KłTK·4ÂďJJ¦ä!Ă3• Ňŕx©HŔHݱµ`Ă8 5Hń1I•Ô|ű°I©d`{Ä a$eR(ĹARŚdW0G°é°Q0D@iG‚Đŕmă ŚÇ@E<4¸¦k4äkMU˙LI\dÁ]9L>ű Y\›GQJ§d˘ŕ }…c5•@|JGCLÁä;5ć4Ĺ‹\I…Ľk€ČřęÁ°çh.c4 c4Ć  UĆËÜ /c36h$b$fbśŕsهL8ÍÍ ĺÔýŐ(afaĺ„ĹíL ýő_B4PfÔŠh?÷ˬű`1ĐôŻp´€C3™)ćÓ ÝĐÝ`Íť° g}a-Ó‚yĘz=6d‘P¦ b#Vb'6>4ľ€Ŕ&ŕŮYÚšbŮĂaÁpcÖ&Ů_­Ó¬-GMŐ4Ö§ü9Ô«RÔ”nâ¶Ĺ$ŕ@!HÇŔUÇnăćĂńÖöŃ€(•2 & Č—@AŻĚk˛lÜ˙€ÜĺĄ3' ly¤hjs©t*T|Ý“éŰĘíQLMt'p   TP  ` Č+sÚ¦yÄÇ"5Ňđś4&‚GE|ÄIĚÔÄđkă˝J$€Ć6ŕ•Pŕ0Ő­2 ´ ĘěÚUÚŕ4Ý/pmrŃÓ[ v``ŕÔÝŃ !:$hyänŕ$0^Ţ”Öŕ đŕ7îá$ kÁMn)ĘŰĽ,Hz¦‡zBp4v°_đ^pĽŁWz§—zĽ…k”gy'#ĚľDÔş— w|·Wžĺ[: áă€'x„—ÎëĽÖf:i·vmçâ¬jt}€R”€ 8˙đ? ‹Ŕ?<*#wáŕy ×ÇĎsđ#'=hÎľ«ł]`‡TçWxqé™>Mň&€đs > ŰOôĄc~yŠPp+° ×Hä{ ·Žy˛Ă7tp ŕűX‡ęšţwWę7ý须¬îęzÄ#E`ޤ €¶M°¸€}UŤĐę/Ů!\°o7¨ô !@†ç>gx9Xř-čóQ1 Ű  é@7··=ř~ű°°îČâîR<„ďP¶żÜ+/)äá1(î!@îĆŚĘx4{€Ň!é°Pđ‰% ÷†ĚĄW éĐ‹0čÚ˙°©Ú0k9ˇđEx„0Ôň/o °‰% Eh 0Tˇ…šűQďEŘ  8.Ź‘çW…3Ř…:!ôČń¦pp.ó ĎđZbóÚB BOô\źűV†čŽ˘˙Ůx=‰Ń`«˘•jI§Ń*’$[1. aŞ#ŐŤ)pÔ´— ¬Y}o¬rBžš%44)ŕ9ď(Ż QvO¬ •SY•1 PâP50hůPV‘ 0)*[Ź©±©&C“ż °/ű\‘‘G/ö÷Iř°Zj©Áň§ĘaŮ~¦‘gÉűąŻ%$·ŹľřĹ˙Ą1źź>g·ĺŠŕOź ¦‘ţ”ŮY‡I€.¶áţq7 ´đ ˇ˘‚ 0đ  ;…UęTŞUj\Ző#Ă ŻjVěX˛eÍž%›íZ¶mÝľ…Wî\şuíŢĹ›Wď^ľ}ýţXđ`Â… †{áB ¨˘cÇ*Tpŕŕx%Á T¤  A‚&*TP @‚„)Ng‘0AË˙mßĆýVq”Tďüĺc´˛ÁpţĆąéŔá‘2,|°6ÇĆCŐüőS¦ÄtŚ\éęiä:8Q:$€4oH×ÜíÝż©ŕĂŚ’đ#çË›/&Ş‘1ą†č€ĺ„šPÁfô°!fţŕâ 8X aĘ" HřYc4exŕc±E b…Xđ "Š EšHŕ‘„ bŘF%¶¨&8ňÁÂ…c¨°adšH!B¸€ $`…rq‹k¸°!‚fáÁĆ×ds0Ĺđh§|ÜČaŁŠĚÄdĹ‚@b5 € {Žpˇ™ 4Ń'˙-–Ńn…[ŇŃ$Ś€J „GŔI§~B!Č]6áAL%l°łMSOĺë‚VbŠ0†HAMđÔ“ >ýTP&8Ž\>‘†ZX0!´Đ¤c´+ pęŔa {$YI€AÎ9bZ`0Á9Tż—®‰0(Ő"…yˇ2ŔŕÇ ‡EPtfšf1ç“8xŔ+Ži…v)ĺ… >†Z&Â8˘ dłp'¦ŘŻ®čGýĘxc‚˙®@„źBDB8ÁŽ=ľx‹fňti>–ȢE:F±Ć)T­¸hŁíÚ-•z~3ĺˇüĐƸ9Jŕ˙z†` Š|¸Ŕ=ńÇz2a! bĐ$Ţéćž9¸ lTäŕh»ďvkŁ@„ČB 2Éfł¬ ăŔpĚď•(@MĘT`_"8FŹZńćĽsŔľ*( RČg´ F—ćą6Ř Ěs‹şVńĽ‰ q¨źE^Šg!”řĆ7¤ŕ?R@C ř; ř"°˙zúaY60D”ˇrdA1~ŕd@¨hüň‚4<đ4ľAJdŔ Ü  Hđô©….„ˇ C¸Ä±¬’HHSG9‘Ľŕ ë DW†X”ăè ÔB:páXP‡;Ü 8á‚’ˇG¬E-’€‹^Ł™¸Ç&zIM°&•k~?E<Ľ!ŃeŕĂĆDS‘4‡-hÁ ˇFwP -€ <@»@J‘ŠdäşÉIňŃ•RŮG|Éi|«Ídó€Ő´†3xŔçśxaVřß~pĹu4Ó”řÁ $;H@‰˙9C1  oPĂiTŁ:Ľá nlóśp E”ÉLgBSšÔ´ć_9Ď™ŚđÖđG.řѧÇ8Č™ ÔĽÓŤ7¤ ! @C.ÄĆŐ Çô~U|Ł™ÍTÇ:bá"!  Z8ŕGP“śŚ‡ѱRtPixB$JQ‹^4ŁíčGCJOžĹZôŘD>Ô˙(dâ,q9 !úĂIěP@p 3ÓÓC­ŕ-‹Ŕ )j +&”B¸&Ů4 'u;âÁv´ôC«WÁ*Öf’Ő¬0@«<{:XŹ`n/đŮ=1 B]D2’˙K¦ń¬ŕ‰¨@¶a‡ 0‡XR/ÜC \ĺ˙~@Šuxă"€€¸ íYä!/4ŢŞvÄ•®ě %Ž ÁŞ–µ®…­li‹AÂ67$5¸†r0?Ţj Ô ” “EC|ę>Â6őŘ* ö`BÝ@ňU!|C’e!†'ĎÔ·ľśčm~ëę >Ř7"0äBŔę^ÇÄwľÎEđsŁËę~)}ú“CuÉ2řŢoh A!Ŕ ~á‘dÔřZ†P0#GE,V!‚Bxż­+4¤ŔA>‰Q¬â °ŘĹ F2G0˙Šé~ŕ‰î $Ż wWî:ÄgpŇ$Ŕ j @€/©ń hŠ`w2}.1„ŕ·®t˝1;ś×]`ą)ó™Ó|†5·ůÍIF´A€}”" WŘÇb+  ©UF"F0:´ăsś řjçç!Ďř†;ľŃ4Ś™"/đAšPŚßr“®Ü83®ýWJ‰°ÚŐ°–5­mťhf‹čkţ¨Ç8¦€§EMÚY@*‚Ń‚ ś ™PUŕp hw ¤f€!ňáÁV„ ó}Á'"™öXä*}ř5¨± &€ÁÔ@G1V˙ŠĽ›!ńžw˝™ÝěĹHî1”.#sϨ'«q0yÉ€´‰ÍH00„ůŠŔ Žx-Ögôá`xÁ(ÁŤbśa§[!9CLŽr•/ÜçQH>”2«•!,@ ± B‚: $`ž^7ŁÎHŃ˝‚t(ýç_ŹËCÂÜn0˝>ŕČ1‡ŔF 6ź‰Řc vD˙Ăîwż»Šë²{#CH„bCĎ„ďtO4ŢŻwşÄQ$@ł~ĚÇ#>ÁŠÇ;ăo3ž[ŢóÁ|Ţ??ú‰…Ţîš'}ęŮdú ^őŻgë]{ÚçFöµÇ˝{nź{ŢŰ;f÷˝>a~|â˙eřĹGľ^Žź|ć×eů͇>\ž}ęŻeúŐÇ>Y®ź}îkeűÝTĽ2ţđ—,!ů ,#‹!ů ,~˛5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(dH‘˙:^4‰2% &H@d‰‚8OL`xHS$„ üŃ*#"EŠť=7BHЀƣ|ŕ2A ˛ĄĹ—Đě+WćŞ5Rč§YąF,l\ëóŔcőŚýaA˘ĂÇŚVÜ:%DEŠş%Ů* ÁaçLÁ9pđ´"É»­>nĚqĄI2kĆp0 !ů ,#‹!ů ,~ 5H° Á*\ȰˇĂ‡#J„ b@!ů ,#‹!ů ,~Ł(Âżb HĐ`„ |QâDŠ#JtQ#CŽ14há„ )L€|(ŇĎ2ő”ąQ‰1ŁKçÔdéÔ/Ś„š˙0¸4í˝a*ÔŇ4.´a6Ä_MˇDˇJeV¤ÝŐˇŮ^4`€K)ÓˇöuÔ/ÎĎŻ—čÍ«PŠ•‡ !ABŠ»głjÄ«pčÓÁL-ÄŔ¸qÄ€!ů ,~˙5HP€@řǰaC #&D¸ĐˇC Nô"F÷cxő¦ČvŹ Ú0+üÄy÷2öű823 ňÂb`A‚‡I°` A˘o¶ ŕęE‰8Đą†Č͛֗ě%ę©_śÚ1”čôîť)}éÍ«P äŤB€BE_a"$HHq=le‚ 7;¶ĚŃ|ú}×St0ăČ„ňëg!ů ,#‹!ů ,+~şhH°ŕżBX°a‡ :|¨ˇÄ+^$ń`ÄŤ:ţ[Xˇ‚ $B$H B…H’1şˇb˘Ä-[)^čBG3F)DEŰaB§‡Čä;ĄK:‹Ř0a¶R>0„ě¸Pꄵ°ť;‚‘+1š@òl‘Ť:C„ČsŚJ -×ţŘĐŮ`Iľ:!4,č4oÎ DŕĐ!A–:^ ¨µlĆŹu°X†Ď 1l!ů ,#‹!ů ,#‹!ů ,6~\5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1t°ňˇÇ†3ZÔP˛"É”˙Nl©p%ÍŚ!^¦Ä “%L tv´ů“čNŁC%XĘł)ĎĄ!ů ,>~ 5ČŔ&„0p`‡*dذ˘Ä‰-^DaB kđáę"âĆŽhŕŔ…‹DI 9 ô0‚•«/cţُÁŞ›9cR¬0â'N“yŠT˘RŁAO ܰô(Lˇ9xD‹… tňä 7oÂbˇD*ďLĄ۰ARĚ]›Qş}›N / c !ů ,#‹!ů ,F~şĐ@° A˙*T(°á@.\čP ÄbŔ0ĐâE 3ţăčđÂ…»Jń8(2!Ɇ&«`ćeË—$€€cH [ެXš@a9.˝YŃCž¦­\*'“*IµYµ"Á¬[©f´úUëÔc’ ’ą$H ťřr ‚ŘěK4ćÍ\Ť^5PˇÉ_>SľTń‚ DHěŇáG®i-¤™ň­Ń–•'cF  3ÄĎ;!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,b~ '5H° Á*\Aá…†;,śHń D„-VÜX€!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,b~ :!üH  L¨!Ă BtČ0âC‹%Hś¸cBŹ ;Rü82¤DKË—X!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,~m%ŃH° Á*\ȰáA #JÔఢŋ1NܱŁÇŹ7NI˛¤I‘MŞ\yeD–0c"t Q¦M›hŢÜÉňBN”<–ě S¨ŃŽ4)]˛(Ó§ “Bťšđ'PŞX Z™µ+€­˝b•*–*ٲP“ţ[Ë–-´AąhK÷-\¨tŰÚ˝Ë4Ż[ľOý®Ý بŕ„ =śXńNĆŽ nY&äĘJ W?aŘČb„ ŞĐÁ P¨`†‹µ¸`‹p34sŹUQĐŔ5ŽÂ‡!ލ„ J€& ʬá# 0@ř"ä’MVxăAF"i‘uĐ2„ł™ ±Ů€“‰¦jjiŁŁJúžA_†9ć´‰evâ©'P¨Ş˙ĘeŽ$6Ŕ€@‚A‰&i'‰¤ŞŚZ2č §†rhl´Š«Bň÷U鸡ěaM’# ‘‹?ô0âÁ~h“N=ÝĽ‘]äăPÖĺÓÄ'Ś8¸@ąŕf‚š—°±[oT0E*éŕ{ Ô;s=ă`Ń@ßćĽÍ;¨Đ…<íüŁĎ@±ŰN;řŕc±Ľr­ÜňË•|˛ ]@@¤“V:‚Ö ˙ű‡ @)Í´Ó0TĹ23˛¨ÝxŹJ´ŃĽ}wH5Mw[€-6ŮHNą?–;E;ô41AřtŁÄ®Č­ ʆ´ó‹ ŚŕK;sذ÷Ěôý !ćú 04`H=Ůu°@Ăs\ µ?TcÁ´]9°K,9Lđ.¸ŚP\sAF3đ €%çČD*ú€á/8‚Ŕ‚žŔöňÄpŔŕĐ#(â ~¬áA3lˇ‡)ŚÁ $ě‘%řAŤ¸ëâ € ~±©+|1†1€‚fČÁČŕóŠä\KÚG-ÚaŔ 0`íxG7°ŃŽMäŔ-ľHG?˙’qŤm(‡ŔF>xq l Ć ř,đAśH7ýČG.´ń‹`řŘ/´‘'H°ă`6f)D! ŔĆ=ŔĽ±ý؇+xqŠ"Äp†tPcZX6¤hĄ €HŕCČb#B°,j‘‹)°c.”q‹kđŁ!H¤¨ E)R1{'€6ş1Žv`cF*ÇFÄ|ŁíŔžT6@ŞHŔ‡/†`0Í _ ăËČę%%‘8Ç©Ź8T ۰CL€AøÄ4^@˙€Ü#µCE4ř˘@áÔsR( QęöB 0ĺd›Á‡Śi8F xPÂ,Ř`BĘ"€JP&i#pĹ(<€0Ł|ŃA3ěÁ j“ŕG,l0 )Ř6ľé-<"kHâžfp5¸Ć<ŽPžb#E°â jŤL´@B0˘_?$A´ g C§ ‰{€á Ŕ5h™©$€ řĐ. ›ć4ă2Li*1„0n”‚ő$P~Řc,ŕŞWÁšÉ @ŔČ?l7E"ÄŞXEĄ*Ý 4 őZA3öAGŘr´Ą=->ŔŠv˙0Ł­@š`gZSGn˘Á®áT¨J• „JŔ túřz°Ń#V˛šőPć´ `@  Űí>üA^Ěců„‹ö˘ˇ` ŘĐCě°Ť"ŕť·H*´Đ‚Ś5$%x8ŇQ ~Hb1h†~ŐzÔĽř(GÉ’žT„® P‹Vg!'ÂĂnxŔǨA‚üĐ…ĽŔg„4Łű[şŕ‡}¤!Řęˇ6‹‰­ şßfEF€ –1ŹşĂŮ–ˇ&äĹrpKac t Ás<P¬ hĹÄ\vPGĽÂF‰rRÔń6˛á‡†˙P€Â‘µS€$t#l˙H±HpćQ]@ȶŮkăËďĂ Ŕ–™`AëˇĐ«CY"° |D›30H €űő#Ó¤ Ľ6y`ćl#—7ŕ›ľ‡lŔ%·ÉN.lvŤňĐd|bšŘ o„@b7Aéĺ-Ů»bcľß}AdTäk(R*ŔQLÁˇĐÁŘĄͨť ś±pGŔŠ ‡€Ă6Ń-Ë]bUł!ĹđB?ś!?ëńCĆŘč"ö±ëřŃ(&®‡0&ÔrpT‘{>áŕŔG>ä Á}D™Z˙¨±0 h1µÖ \ĆŔ—ýťâ)U`ßś®ŰÝFY5ły(đ6ľ°Ž$ÇŔ‡ ¶p“6oÁ¸Ł]Q¤Çĺ‹®ĺľs`u0`Ŕ,Í@ysUňɬÂ5î9j|,Câow ]„€ Ŕ†6怏dŔŔ¶úxČG>˝];ĺKd8Fú1ö Ä`‡A ľn dŻ·˝(Şa{x˝®$Ȥěqŕ2-/XŻ$´“ŕrŰéźxË}tšă>Á°đýáńč€÷HRcp˝L §ĚpBtCTlTô…8ţš8(h/|żé¨ś`]}˙°dŕ†HqÉöˇĆ9 »Bz?°@!”Ż˝Ŕ@` wâ \ŽRÜuöEŤ d 4= F\ - 2ĹMpŤőX; Yâ÷$&ö0 ĐXşˇÔ€Řđ€- e±}­5h¤eCŐZňGŕ}°ßÔOŃĐ“Đćptö{ÁG7ť3qTř€ ´Ôg}€}ÜÁeŕÇŃŰđI"C~ú‡~5Wf†W .…Ş`)P@řp s0vŕ&`yŔl!ĐOŰp űÄ"{_pw°‰ v óŔKĺ Ž2nÂa˙¤¶PcQr‰0o {÷Öa˝—0ý (3|tÁe 08¤C®Knńhe!b_Ŕ‹€ +8Ś`Q"öDISşńH[4Cp Ó žŕIśPrrđ÷ł+‡ôFÝĐ ^řÚ@D…˙€™Š˘h ÔF„ÚGůĐ ô€^ŽÔČ@CŤ€*˝¨żP –Ö Ŕ€ˇô討CđŠN–ăŔC±ŔÓóŚűŤ;pK‰!}kÁ‚×đ "%pY*b") Á”"µ p2!s˙r©RČ“‡(3p$I"#Z « śr)Â"`+w" a` 2’#m€ ż€+"ĐŞaPÁ\B*`ŇÇÉr ”eQ,R@"Ç–Ľ·°*Ë.7‘¬(„˘Ä}ňɡünÉŞ˘-ś4˙0ĂČ=ăđ.ä’’ő  nŔµ`3ÓĘ | QC5sÁő’ ¨É3Çb”áX Q”ßňÎ!PČĐEţ˘ §ŕ3ÍTó.*ěwP Ů<)@ÝüÍá Ž Ó0s•ÝĽ ţĐI8ĎwăYZ.ç’.صc ×ÂŹ  EŔ pŃí( łss<#2s0ď˙0©1´0 (S;?&•" e%Ă 0kp–±dŇEĆpn Ç ]Îçś˙p6ř€<‚ČPăůáâ ßÁ7~s X/Ľ°5Đß±3Ó•Ĺ{®cąđFë| !•Đř˘ Iy3ő3;Ăěb1řŔ“ [ŕ®”6[­)Ö=ŁeńŐŃr´l133ăpÎe×u©×!6 .€ŔŚŮŚ–uť2ř0} CPŘ˙pŘIÂ?i.C<Ś@D@$B$4“p Źv>ç YĐ Lâ yŔ ŔüŁ® 1]đP bĺĆ7 ˘˙ @cđ'bő€âC>¸‹†ä ĹăS>ÇO°çŔ#@oĂ]ܵڛšĐÜ!đÜŃ=Ý4AtAŤ0 ĺ="K儆 Žc0×PnČ­>ěău‹NçÖ Á5>án>ž°i@W’`e Ä@A©á“Đ q y1Ňi&ĺŔ‚P,` `ŞpsWŕÔÓł]ú"’y@Ő aÝح݇Fp „A°ËQ4EUTwć|ćăH$Ipi´FéĐFőTô ÖĐź Ę€YL[VâĄCÝđ µ#bú ęś”@$DD˙´ Nđ© ŁÔ°4\Eżŕ ¨°źŞ”Ž®TnĄ$ćPÚ‹E¨C;ÔC<|Ž~ţ :· ąŔC ę,äBľuŘůeç°4Žž70MřPM4$LťŠQńHo®ŕA. ř¤O/E˝@ 㲵@“‡^Vf,÷»Đ 9p7űÚž{Ź'OôdO>PNŽO>QO÷¤Ţř°ÖBĆě ŔfHW /ФÓÎÖŽíłµQőQ'Ot$€·»Bď.@AÎféĹOţđ†ę1–Hĺ>ŹGńżď>p(Q«7QĎwQ1ř8Ä˙+2`R<đ]˘ŕ .p `p° ?ŽäJŢ:7PjY-“ęŻ<ýíá.šŕÍ _ÖŐ`ŢSˇĺ‚đ­< × ‹upj… lĺVaBX°@Ŕĺ ÎUSěŠ`~¬j„ŘŔâ6`EuTIu‚&Ŕ+đč3ŇdĐş 6čŞ[?ŚZYe­´nU?T1H÷v/€Ň ŕ;PʛƴŽqoSx `G˛@řŹłŔ$ƅݬ`V`’Pßőć ÷3UçeŃĚP6°Ó© aĐ|š€‡  ď€ Řŕap&W®Ű˙˝ĺe^CŔÔřýçŐ«ŤÔy_Ęüx0UčöhźoüČŻüéŔüÎo ö`ţa(€±/ ŽmâŃŔB† Ů·€lě`iŹ ˘)ę˘aĂ 1Ŕ)"peź”%R´Ń0Ž(Ę5şĐ!B3BíĽčÇBp`~Ä(Ď5†*l)ă÷xHâŹŃĄó@5¨ ‡ „¸@üôKŁ2úY0„v)ĺ…Ž>Âr”QL á€KĚńÁĂl^h€\a!˙„Ŕ Ž (–„¨Gyś·9D…é´G޶KĹŕLHŕ©oŘĹ–Š>:éĄ}ŕ X`ęŞ)Ŕz]®yHü“„{mA`HÁ „¬ű8†mÂNišţ#Źńs/4ËĐ“ŕD'ýÓ}Xʡ?¸éŕť(µtݶ0€`ˇ<1‡‡Ą íŃ!ě‘㉠n„iíb ëž—*ŇőĎŔ›ě`×m†Ź2 áŕµB¬rî0ƢCsź&¨‚źr°l …üÚĎjú`0H_KřqŹ"IXŹ"H `*4°(pÔ(Ě˙|Ŕ€o€Ó‘qAĄŔCŚH@,hÖż˘ ´ď} aŔÁ Lp%>Çč\8‚(`NČŔÜÇěŠŔ@(8(lcEAgŕ1 Q{S xł~„ˇů+GI –ę@iHPĎ<4>,! ĺP–XÁ DŚa×艇ě‘.@b€˛Ăľđ/4هŢcĹ2ŢŔ…ě˘.¸ÁŽš7 ЧĂěŕ=žĄ(II?ĐHÂ>ř0 ńŃŹ€Tô±‰.¨( T$#©<6čĂe „0С™řBšń9Żę}˙ü#Ąô¤ş>(Ĺ6Ŕ‘ôâš·¤ÔvôQŠ,tAŤ3zâM^yp€#ŻTÂP !€ěÁ ÷°‚H`µYer ÚÉŐ®~BHN˛’]ű™9ä0†7f}8Ť-¸?čč‚>úŚvđُÚQúü"”ŞÚč#DR€AôC0ăvúŹwtŁĘŘ r‘ŽeТí¨KbĚÇĘŹ0ŁŔF>şAŹ!°ý°G4¶Ń"$,1& BęC0ŕ×h‡®Ŕb OŕFŤÁŃŽ˘¶*QŤŞ  ŔíčĆ/<şÚµŕh`˙zúÓ1ćó¨E;úŃ˝u«Zĺę^Á5€;ş Č4‘őEۆ6ŇAŹ@dČCôG=ŔÄfČP=2Q5Đ1%čÄ;ŇQmü!čÁAhÜ !OéJ ”T÷şőČn ŢęÜŘhbIĹ6–ázü€Ń¬QeĽÁTřmp‡‚Ř áŞŇ€=T»sHÁ^.Đ?hĂăòŠ`´ 'čF&<ş—‡(('!°!’©äÁŔŽpVŽ9Ř`n/Ň«5ÚŃz”˘j čD…‡c«­ůDÖĐ…w4,TĚGŔ˙’€VáĹ 9nr—ŰÜ ]Xo>LázâаřpCŔra_Č_wÇ/lŕEol¸mBş €Ř>‚«şh Ę{É Ć˝¨Ix3•Ék€†+Ľ…`€¸7@ÇĘ ‘žą )<ôpˇ˝Y‹đ¨‡|8†vX żč‡~¸…–’KŔH®nłÄU (ř2h†şŘľxó8Šp}ĘÓ7~›É¸K»îŞľdŠ+ëŁ+đ{p—˝đ€'(‚$°‡ęđžd„˛p‚(Č•TM@ô€<®z7`H8kľ)HÖĘZܦ ‚|а˙(Ąň3.‹Ż×ŚÍđ.öb.Ă8Üd­w8đ€đůę†?0 ˇ&@’!«FŘ€630ŘÄ`7ö„ďptčNčÚ|x@ (#ř°~(…¬ ËcĐ,Ŕźî . X€˘€…~(ŔË P…Q`¬s8‚°SPB{mHŞşüŚ4SŃ}čǰ;‡sea0Ů*QśŁ±i‰łDJ>,H€‡ŕ«;ʍĚ!Ô\Í!µCńó…1Iř¸€()Hŕ‡5( #Ŕcř)€/H}{)ŘV\č‚/€‚ÓH'<؇˙MČ•hô°z.đËG2Ą čŚ~ȇ\І_čŇ”ŇdH‡Íâ)}°‚¨‚€•,|Ř^І|p‚`Ŕ[Č…\`•ž@–Ë€%Iă" đ~H„7<Äöˇ…: ‡0đ…p(«+´¸„2ˆ#`5÷şů㲠=‚„sđŽHQđ•éQ‚đxŕ$č„}°@„zŔ¦kĐ&K89@‚TĐ0ŕϽؾ„s`‚[ĺpkřŰ j±I"ĄWJ<±ťÓˇ* €Č¸‰ń„Zŕś  € }#k°p1ˇ€@KĘđš˙ޏ‡F(‰m°±‘,¦±ş KĂLhŠs¸~ŔČ{pCŘ304@}P¨«F€śh%SŘ6č ÉŇ@µä¸|µÂ -Cľ¸ĽSŘwpX'°« ‘Î sž ?`$8‘ €*á؇8ŚY‰ˇµ„§!€¸‡DĐś(ťÇГۺÝÉK±Đv¸ŕ€X°#yWhUÄŇN!­×ČŤÂ'Ô€”â–r)UĆT(_0A8€[(*O8YNčŹĂJ¬Ĺ˘ˇÄi|0JŮ ËŠ†`p…`@ëp+¸’+ŠŔ»"ë·lŽ·Â<[ ÝÓą4KÁk¨0tm\E §m 82›H$}˘¶čŹ(§sʦ“‚čnZ Ř7ęNŕ î€ yç˙üŰ ;]¶ŘíަI8ŘŇ.č„~ŕ‘šfnnôZŻöz/ M°ěúe©€,ŕ…ë~Vś°`P9phäR.ćr. 8CH‡tČ…ÍbQëÂ.íÚ  ČQH40†"¸0„7‹ł©Đ33Cř‡?Pë\/ІL N0¶th‡d«2~00ă…°Py  ŞąWS¶ř»NćŞYkµQH‡_Np°z0ű"h iĺZQ^pΑ谞IˇĂ3ŕúîo Ă0 ł2?HŃë€$ż° ۰X4łÇ7 FŘđ€G`×V€(05eŘđr˙çR;?XŻ,oćvóÉ}îQ¨·ďűE§;QěÂ~Sđ9Ă= »†#XXƸ‡8xŻŚłľg Ť–ÉźŰ=B9=x¸šK9 Pľą3€ô-ŕ^ăG‚łą+a7Ţ3H™=Ýk7·9…«7pÜň€JđbáůsŚÎ{0:ľŕ€H<›SÂ:ˇLĄ=c: d+‹La¬őJoEN÷90ŹFŮŁľ«G0óoGŔ ™?Ś^–IFD„ż¸‚'Ő‚Q°‡&hä%ĚÁ‡ŮżlI‚WX|0‡w´żOfAőc€x}@ó @üĹ…˙˝řż÷żz_@[´x\pçxĘýĂ0„wh‡t…˝Ţř?DżÄV0’™~DX‚SŔ†R*´B,™ű˝ç{É ‘`ó#î:UŃŕ€GP†˙kh±0ëehÚś2Ţp:H¨ÝéęűĎýR<÷ˇďTbŘRÚ.'kE' X8xĐ Čfř.ř8ř˙{Ň(ťRŃXř;Ѣ‰Đ7ţăÇD°MŞ* d‘†›Ěˇť‰…ÇŘ‚j8Č,pc0ŽE@†&¨Ĺ†.> ŕWmŮ‚k™ťč —Gţř—˙( <10x řm¶:d<#.šѤ/‘–eJL¬¸•NS$L$(ń\şjüBŕ`×&[®)±qˇ#Ę”*W˛léň%Ě2gҬió&Îś:wňěéó'Đ BY^č°Č”0CRtpˇ&) ٧¦c6ö88'×'ith± ¸@‹¦~ĆH®Ž)ö$…!`Đą#‹hÁ0b(ŕŔ‚.lř0â˙ÄŠkbčá$Lł„˝č@"† 1¶ "Aâ(i>Ľr6-Â,sźBpx€á5c­xŘUęĹ„ŃčĹśhę..nü8ňäĘ—3GŕJ?ipľ”y3a‚ kĆ şĆ‡G€Hü ¤Ź‡vö|yâ*—ćńY’Ąś˘!|eÍžE57 x ‚ ötÁQ¤RŹ?ůŇA řˇŤ?ăĚAawĐ3QäĂěŚ?ţĐ“ !P&éřóN7čÇÁ5` (ř#A 9$‘@ť´@@ ‚u5$*4ŮA ¨ B HÉ $ $“ĺuQP (y%¬qÁ1zHU$śqĘ9'ťu˛ôÚKMŔZŁ‹Ů9(ˇ…zč€!Z“Ž(C '˘‘J:)Ąüs)¦BP©JM…ĐAcśŠ:*©Bfzę¦ĄŞş*«­*wj¦©ş:+­µÚş¬šŢş+Ż˝öšëĄ˛ú:,±ĹR ě?»,łÍ‰¬˛ÎJ;-µËA[-¶Ůj{صŰzű-¸:u.ąĺš›Ň¸çŞ»n¶é˛ű.ĽĆş/˝őÖ:Ż˝ůę;*ľűúűݎý<0Áp \0 #x°Â ;śÜkăů0Ĺ3!ů ,#‹!ů ,Ř t5HÁ "¨paB‡.@‚ x€óĆ>€ňG«Ś)>HЀƣ|ŕ2Q)°â4űĘ1Áˇf<ÍĘ5baăÂ+ĆęűĂ‚D‡„nť˘"…Ó!8|ĚȡçD!Jd l@!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,Ř 1˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|ˇ¤I R!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,Ř 5H° Á*\ȰˇĂ‡#J„ b@!ů ,#‹!ů ,Ř 1˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|ˇ¤I R!ů ,Ř•5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1\¸Đ *D€|(ňB”Tďüĺc´b$üÁůňćKM…fI{A˘(‰ź#4ĂÄŁ!ƤK›DúCPa/:Č€*†WúIŰYćŤ×‘/ëÉ4uVĂ“DČđ´ŞE ^ďć• /†ż€1ô !ů ,Ř˙5HP€@řǰaC #&D¸ĐˇC N<‚Bp¬Ô‹ z;c› $€’–CmŤfzxpŕІŠ,űÖ$ Ŕćžż×_¸Přđ>5‹Ůě{ěrmŰ ŕ"6˘® y÷öíŚUk—®_'%k–Ďj•DďXCú&E¦FŁÎÁ€Aí† 2%d°‰S'O!€vH\z>% Ă'Š˙Ö˝+Q/_‚ N ·łçĎ C‹]Ńż¨ĺáë§d+W,H´MÉíZ¶q“¦ą@P—+_ L±÷ďŕ&ĐŔ  ĹN \é§ ˛@ăŔű '.0ůňćĎw‹˙OľĽyńo'v`ń›{kžÁbÔ(­*Tč°ÂY 4 •"`B H ÁIÔ&P(Đŕ)$¤@ć§ABđ€¤`‚@!B€ ‚%` W*đDA… h%‚ 5PÁ O1ź~lŔÁ†~„U~Vxâ%¦°ĂQ†â‹Lv€Ą0]a(‹6Ć•Yâĺkb)ćb~\ U Dˇ…I¦Ŕ@*0&ź*ÜyáG‚bŃÂ~ˇÉdÂČÓ—aB¸ćk@Ŕ`žçeŞé¦śvŞ‘nQpAWě#OŚ0Ę5ďř3Î!đ˙ç·"6` Á†TăO?Ę(±ŕ¬·Ôsk®ęVA ą¤SŹ6€¤Ŕy ăO=ă¸A ř±ĚµĘ¸aÔ®˝ţ쉕Ь?ôüáAśđH.­ćĂO  ‘ »ŚĽ¤~ëęéÁŐÔŁĚ)$`1-ôTÁ ô”eA ܡŤ?ď, TŠw€ăŞ aIĎ8ĆF+şé°ë®b!Ź Ŕ„U©\¦¨ŔŹhS-ŰěłŃ6ĐĹ;r\Ŕčů4a´łĐ¦°¬fÂLPÍÚ˝Ľn»ďŞĚ28.ßśs›áD«±¸^ěéŰpÇ-÷gµŮöĐY”*¤˙ĘŠ/oŚ1 6`äö$˛„ú4âtĚüÁĹpÄvxâ‹7~lş]0BSD ?kTŕš/c~Ť<čuŽYtŇOĐ bĽkfDăsr…<@ ŘE+r@ě#i$Ac° ;dŔ„9|‚Σ𮽣/HŔ i€+Ěă[HǢ0"Ŕmن :c~™!‚9Lđ1ĽD6^Đ€ ŕ‚,8Ó#ÉI:D™IŐ€*ě °$&7¨:Ú±¦…/Š4<Ř@;ëx˙ÇźQŕ1L¦ýämv3Xšf5Ż™MqĆpŤmŁ‹¨ÄŠZô˘u ňDSE‘M±@-ZÁ`Łőđ‡?đQ„`·đ‡&ÂĐ ×@©JYJĎč&%x8ŇQ ~Hb AđpKËđ !m`FlS™ŇÔ¦1ˇŤw $ťŔ ö!‡…„HXŤJU:Ź!LŹR$)IkĐ Öý,Ş1B>0lěa đ8ÂCĐşŹ5eǤź2 kXr"î€|ę˘:U,˘«_%©@íB‡V „ŠŽ©y  •¨Fí‰Iő;lŁ& @P‡ZTI˙   •Ú,ý´ĘUŻ‚‡vŞTmPłů 8ŐéJËŃÓŚ:÷ąĐ="ËâD äÍŁ0ĄB ×’6ŁN @:1`Zđž1„EWđŠ—Ľtňiz pÔSpŚvŰt¸y0!˛ÂťŞ,ÓŰŹő˘Ë 8ëÄ1ę X¤•$«Y€Ö~ÔB š§­/©ÝĹ)ë„Đ#Ż8-M·Q űP@‹ĚúqöĹ1âcő‡ë‡-Rgs;Łüűŕ˙Kě¦Q,­ |Ă™+xˇ|™đ±T:.xŔ{°»2‘ÍiŃŠţ\ŔHuł,š3ďĐ °iŰ  é°@—@óĐ2Ň‚úGü+%Đ ď@5ć3@ę“(ů˛/őĐ \wťĺëçRď8sÖ 0o`?łŻQ\`V QĐ*°óă©ů` Ó-ó*9⾢0âÂĐ­ňÚ‚±„Mř„ţ©Ŕ1¦đ1hĹşp·>1P€€‰'Ź_€,K¨ Öp-tččď` 0 „Lč„P¸…‚)Đ-W˙.ňfh%p†÷÷®€â·‰śŘ‰źB]ąˇ ŔŇ7ŕ |#K*Đa°!C2-®Č?qb!CBµ1#¶ů!EٰM*đ!’'8‹>2‘"yRM>„2"‚)±§(DŁŠ9 OHR%N   ˘ o8 ň"+Ŕ řÔ@rŚÜÂ%?RŽŃřIŁŚbëŘŽł¸%řˇ†2`iŕbˇ‹5‹ú‘p­¨ˇ„4˘-€#Ś”") řČŽ ŕŽöřSB"&đ1üȋҒ·č‰$Y’& ‚‹‘’bV 6ÁHr·5ibă˙(G+q“‘“á´[°S Ş@oG4Á“)q7 ´đ 8r㨔űŃS©T$+I~'Ů•^é•,y7éA3)C5é\P†Đ ňđ˝€XUQŔ ő  C)]\ů•|Ů—~ů—2q“%X ˇ ‘—ć1]Š ŚŮŽůq硋 ™–y™JG5–(1–'é™/Á™)G™•‰™¦yšž˘™Kš´Ášž(š*›RAš|†š¶y›¤‘Ş©š­ŮDf±—«éš!ś¸(!*§QŔ9»9–Ä9ś˛ą´yś¸9ťÔ9š¶±śÍ ťÉŮ™Ů9~Ď)ĎGŇ˙©śŰŘů’ÝIžé‰ŃY7ŐůžđŮ›şaśíYuźýŃń#"pÂs"_ ·¦ź±"&@!Š!ň$űń&ÁčžÉRźĆ)–oA]*Gˇő9â)ˇµą•mA™ÚžćI›rjˇú’ń٢.Šśóą˘&Ş ©P/÷Â-%s24Ęđ.gńÖ06Ŕ+ŐŔ",S4Vŕ ZĐV ѡ2*śęˇWŞ›\iĄô)ˇ Ş"ş˘+ť(J˘*Şˇ/ş¦lš¦[J™ q ˇü@ pđođřĂ<űCyt '0M W¤6`;“S9$˙€B*D:8Ł °06€eŔŔoj¦ŐĺĄo:˘¸á™śŞ©aJšká©&ĘQhަnЦmÚŞmš©îY,Ŕ;ŔŁ0 Ňš„mś¤mĎä[P 1ů€.p T`‹€ M H GsÄOxä[p ?÷Äd«:Şvă­\zť]Ł)ş©±:®çŠ®¤jŞíŠŞ2ęŞňú˘íŞ®ö9] íĐřŕ6]Ń“„%cŽeGŕÍš ‰ Ë ,0•3US&`Z´ĹˇP° ós­J„â:žŕz¦šjŻćŠž){źśY™ Z®$k˛"ꮥ Żd˙:Ż8űžő®ŠŻ°@0a0)Đ­uŁ­‹«cöŔkąđ Ň@ďv±čĄ^ÂňeTf[$4çp‹@ '_#+›ˇşł!Z›/‹˛śjłéÚDk ¦ŕ견şŞ˘šłx{›eëžş˘p¤™«Â°$mšÄG~„eÎ0 0 ćđ ´ř‡ŮhApů k1Q` p H¶{[ž4«¦çúĄ°Ę®oK®ë:·{k·w›·˛{™ŞşˇĄ[7yÓҧeđxí#y<Ä…“ „XÇsĐ#u˝7{‰1HŁ` ö n8şf›ş·ŞŰŰş޶Ú˙«şŁ »§:»ć ™|–Ą$şlQŁ©ROX…S8 ‘w@CŔzĹ`ţM{Ř€ř.'&u©DòŢZ˘™Ú˝l{ŻfłŰ ÁĺëşßkşXzłçŰÁŽY»ěŰłé‹€»`#łčźńŘź(BŠ"‹ îH·H‹ŕJ¬#łi ¤kÁcšŞZж˘)Á+{Ąv[ś[ęŔŢëÁLÜ—ę›0Á˘: Ĺ+‰˘…‹p|V)„Z@ şp\Ĺ©’w›eĹ·RśĆąaĆŞÄk̢, Škě¶ÜÄxśÇĚ”$ ,0xúk é Cp|ŃÇz˙ě©0ZDZċÉçGX%Mq,ęŃšt/° ri’ áR ™PɆɚ,É›yÇ®ËMŚ%r´OĐʱNĐĘR0 ±`Ë0 YąµŚ€Ëş,Ë2QłĚüĚŕGŤZ(śĽ #'ĂX¶/ Ďp A ßđ R0ͤ J°Ě»LŘ Ç/ ˇńg°”Y\±P÷˙0 u.f•\đX îŕĐ N°Î±RĘŕĘŇ. Ó$ Ó4mÓ8-ŇR=ŐŹ9v$ ‘Ş™{p¬Î8đ±Ţ Yś?0 Ăp*ň!đ.,Đ-đŤÔî@ †0ŕ<ŽlÖc]ÖgťÖkÝÖT}Řm’/w”#\B$ ˘:Â#î7^°V`˘>ň-˝˘í ”đ/ q`°qtĹ Đŕ Ôŕ @Ôęŕ ŢŔ °ý ś Îuó١=ÚĄ}Ú©˝ÚŻÝ;ĹśŘĚÝÜ5‘*ŹĐ‡ąŔŤ#;š-H̀Рo0 ˙˘/ü¤ÖµŮť-˘a«đ ˘-Úę°±ŕäđKÂ>ŕÔ`×vAŤţŤÔ ii¸qŢé˝ŢëĐŢďßó}Üń:ľÎá.0ôŔ=ŁOíă§ü<!H ú¦ł<€ŕ<>§Ůś-şî'B@ ęíŢV "z-¬]7 Ńi0 č ßîŔńŔěŕź`˝Läâ0.㢠5.7ž•ŘÁß:áV~ĺ#áJ› HpŤŔLś¬a{÷ŕlžJ˘DJP^p§2ł1Í?@ ëŕ ? ŕ\ ™¬ ńR ?®ěäD˙ÎÔ@ G OL®tnçx®ç|îçěĽÇSÎłďŠĺśŢé!b9`Ő%ÍXGq9‚5ZHĐř°VţĐVgAIĐ´|Sĺ†ăßŔÖĐ0P–¬/ěÁÎ ‡^ěEî | ě) €;®/.ąî˝nÉnŠÄ™ľÜžžíÚ.bd‡@ckęq™Va&^AP¨dA3đ >ŕĚ‘0@ ?a r9ÎDG ±° "PŢ€‰^äĐ |đď_ Í®é÷>ďő~ďůžÍâkí×ţťÚžńWrˇţ%Ť¸ŰćGa©Nk¶†k  g‘€/p«ÎŚ˙Ŕ / ,M ßPÚ"p|:ţşCđÄ^äDNđěĘ}  X^*ó4oóg€ó:ŹČńÜ«ńXźńuW YP*_ľdŔŰáôCňú¦#0tĐk×vow řşr.GŽ DĎđ îđ Ť0_/ŕ6˙Ĺč±MäÜ@ó?ÍF»Ăgu÷yż÷}Ż5®kőŹŢĂYżůĚŤ3ůw-TŘź~0ż ±© -01Ý nŘpS)¸‚gÁ†Ú‚şk̶üź°ÖPĄÓĹÚ}đ Ô@ ›Ŕ`` ԀŠÎűޞşďÉ˝żź—™>Ĺ2ËůÚĺú˙ä5¬Â±˛$*–’#;2"”=ű|"›.GC`É"`Žđ O™ ăĎĐ//đA‰[±3$0h@! 5`"V˝¸ áFŽ ~tč$H†#K*ěRĺJ–-]ľ„SćLš5mŢÄ™SçNž=}ţTčP˘EŤĘDŘ!éDŽ›˘lşŃéJ 0eGD©'§j Á˘#'$^¬2ó"…›b…2̬zubÖ­1vĽËręL’GýţXđ`Â… FśX1ŕ/ëěĐË 0ĂöńA‚rs^d!Ą ÎČ“+/~úőjÖ­]ż†[ölÚµ˙9˛8 “)Ă!‰Ü¸J‚«NÜ®űÚFž\ůrćÍť?‡Î2˛M /DPqÁçôŘ{Ł^üxňĺÍÇäšQuĐŹçÝűl˙^ţ|úőíFéhüűýő®÷/@$đ?¨"@{8á Ç¬é‚ jŘĄ”†`:Ŕ*rXHżźř+Đ«<”ę8ĽF"±%“\‚ ÄžP$FW ±FoT D®čG—ĚË& «Ŕ™\°F ’= ”ŃŔ„.ĚĹš¬śqJyŇČı¬rKÇ$< (0„h€$Č *¨@°hA®4`‚7ă4! $ !„`H˙)/9:†ČˇŁ €@L0áP®ů »,Ű1TQťuJ)KUTä1µEE“ĹPERµCU©LiÖ\ŁdÂ2–9ŕx„ÜZjŔŹeü©G7ćŚÁšđĆE“]¶Ůg+ˇTXˇ„[lIˇŐ”JöarĐŽˇ ©€~”Q„i'ßzđůĄÝ^ó«őVZG=5ŕ6V1uý2aY†ŕ^ţ×׆-6cŤaűh)C„R8¶#,9GŤ,:é'Ś<čá W\ !„NNyĺ–;A‡fIA”hv0׎<O8’0fţŕ 8X ˙i#š!Ś v(tĄżŽŘk°Ç~ŐUS/Žőŕ&a"»mŚ^{×·Ćuc»ďF-hx$p2)˘dޏdšř bŔÝ`Uh¶Y G\qB€Ś|NŃ H0ši7şŔCjˇ‚d 4ăŕšŃ#ᆫT·żűö±<í'áN±`˛Ő¸vŢë–űwĽ—g°3@cźrŠ0•Nž† Ű`¦Ľć›-É~űîm`‚I°)ŇĘBgń‚n@“0Z ˇh ^ׇsGŮLE°U%ŹTş3ßĆ0ĆíS©" ‡'Ľŕ• mÍĂ`˙Bŕˇ˙ĺh l0şŤLN{ŕž÷Ŕą›î„)D_jŤsx[ MôĂőB`çż.5°xÄ»áKeŔŻ đľŁ`ďţuĄľXI‚»‹˘^heĺiĐ‹_¬É®`ŚzăTŁ]J—Ť4€¸X 8ŕIŔi"ÁŰřĆĹŕ 0–±´ r#rI$̱pŕŽŃ ˙a@|xfRäD'>“µ2"ŔVJ ‚Č$źtŕ¬âcĘ‚Ń•Żś nq !¨ Âi áě‘.@˘q(T#ép D¸á yĽÄ.{ůËšĺá©ÓÂ5ţ°$0­„ ˙HÄĐH;ěá OđB30AÄěÂzĂ<ETBŚťí¬¦Ż(*â­¨”ľ˛ç'Cy—ǰRKń„e@Ę‘p@p,!=ćQp˘\Á@ :ńŽw ](Ú€%äŁ6[@'ć1őXp#šđCX°= #Ąôȸ”Ň€.,ů0Ĺ:÷YOx:,‰=M›*ç©Ä%ěPü))źĄU⳨…*T9 C™Bú¨ ŞŔŮČpt@o*ŕ©KtĘl@‚Ŕuj¦” ¸é`uńČÓ.éΓ@h‰NŮTŰn§ş `[ÔĄb‰°MZb˙đ˘:YĘ2Ä„%ÓHÉ.Űy4yg‘27¶ĺhź˙-i%ë!ďřT±¦ÍUIbË—.ĘVž’}Nľ"VÖ·żÝěK‚›śÚ~(°Ć1ibňCĹ´ýֹυnxň"Ĺî5ÖU‘H˘»]îv×»ßoxĹË\ęÖçLš­x(€Ţ1awĽď…/~Š{ LBČ«{ę ü¶×˝ńp€qŇĘÖHBĄŕÁN6P2`#{?Ňߡd®GŕęÉ8ŕfآ# `‚á@XÂŢČ‚ś=’ŕ ňW8¨`4ęÄĹňřG?dLăŽXX੬†9ěáă)VĹN°€•˙Ľä‡1°Ŕ 0| ŕx„ŕ‰'l”x˘…řO6pH`GđWîŔ/”8Â[NI㬌ĺř`Ł E?ř1ăźŘĎzćsGşüĺ™ĚfFs“›9_9ÉL†twß:˛\@ ŔT*đHą† Oo’ŔČĐ!gUÁ(`'J©­ÄŁ“ťRňéV§ umşmC€Gĺŕ €¬]­§Ů™ű¨„[†Ő‡`R QW€A=˛Ô$v¶›:­” p`͸‡lF<@€€-U}éV«€MŹ”@U¬€(ŹXC¤Ŕ$  řE»•†˙]Ů&PJ"Ă„cÇ YwŤr›ݶü4GŢđ+¤Űß÷6ŔV‹ főľwľ!îVaőP®văUÓ„׫ޮ®Ë1>©»šÜÓš°<ÂţxÇ8ŠŻöÍÓ!hłG.źů@m‘! ÇÝ8?Xě0–xď{ŕĂY°)Cpô«ßż˝ÜkśC¨†ßë@¨™-ľé«>Ŕx€t(hh‚ Č|č% ?]¸#Ch‡_P _h‡9°˝¬‹)O3Żó‡†‚0„zř…6[Č› >ăĂëaş!ěŘ…XČ ř\Ŕ…¨;h>. qâś‘$H}nA€OČŔ „'€‘ ˙2‚(€~X6"[Đ)˛6ŘĄ%đ}h„ čŔŹ@Ąa1ůVđ…1P`3Č{Šx…/» P¶}¨…vĂ `€Eh‡wčlh‡MČó…tč‡d¸†mP8lČ^¸l°"BXŔBČ:!’~ȇ\І_H|Ř^І|p‚=ě‡q`l°;{‚(HPŔ†{`iłĆZč‡}p^8…"ČÄM”CJ´Ä0ż6›˙k|ĐdPĹF řĹ`Ćh€(Če¸…k€B¸€xG‡›1…ČĹ]L€lč†qhlŘ˙°FlÔF®”HŠ€MŘkW~P‘PGÄ@4c+‡XĚch†v@B|sT@|đ…!°o›&0FdTFfD1"tJ÷€H¨ˇwÔ‡8¨€Ř;Č€A0ś €¸‡D`Tp",ëĘy A/‘ @"±KbA$8†@ŕ hQ0Ş €J8Dt…Qđ pf§Aź±&8[€Iŕ‡X`€(ŔfŔ‚Řl8ĘÓ‚ľYXü¦t`. ‚¸†y8›ůLl‡"čšLh?±Ą˙0ěI €hpĆ0Ĺ)Đ„{h€¸†ŤrK2Ŕ]€€ ÍäĚXX§Ęl†Ëd’vě?…´†Đkŕ,P€*ŕ{ŘčÍß|Ś«đČ~°„H?ôdHĐĚ͇ŚČß@Ó<6Yf؇m€ŽyŔ±ŕľ7ŰŐ đ€?µ(_˙7°TUUVőµĺŘň°ËdřťDÂ"­! “mŻrˇŽtRŁD`_đÂ9Y5#@…¸@‘Hp¨{=fŕČŻh†:p“±0Cú:%"dČŃS>­’ đČŁT‡eC-/gřB#ä‡Gņ.@„}X?˝Ô†2Đ‚şŐPŠ‚•ČUM~‚C|Č9ŘC€UfĐI5‰p×=Ń€]Ĺ€t[C宍HŻ= Ľ8Ďd˝€emÖ @_Ŕ†/XjÝ8|„-8„ĚëÜpE˝ŤŚxĺP]Gu\pPŰĹÝ˙cĐÝ i=ă‚˙Ó®X¬‚křĘŇe [»m-+2č‘‚lІ9Ŕ‡d€pŁŔÜÂÂŽ5ßďč628†:č‡âť€؆C ¸LaŇhYkej°{ 7Ȇł‡3M8‡(' iRIhł4=ÚüRÝO M •¨4‡L"«ĹÚZ(6ŕ‡{"  ^/č‘ Mfp‚ ’ÓĆ۽ÄJý.¨Ĺ9G‚h)=JîŘlČ„h·XČ€0C˝Ľ}PĄ ×4PŐí,”;"ěě ČŢ7ۉŚŇ{ žŚ`„]Â˙í€F.źá‡&8ř”ĎčM ľOř6{‚€O]@Ç5nă7ÎŽ 1ÍmÔ€xý #Hd®€b)–€€ uäŁËhč‡Ihs8=)aŹhl,|Ŕ„‹Ť‚®á¸a-ŰŐđ€.k‡mŕ‡B°!Ćb#¶\I<ß_NíL|PH :Ŕ‡S1°'0űmŮËm¸ĂAŘ@ř‚¸}H=ˇÓK>X‚,(EŚ˘Ĺ˛üÚC}°…2ű’ZŘCpN' ®™¬ýŹ„~…;ňŐĘŐ…PĹŠĽČë ůÓ/`EŔ˙Î[†t`„˝üÓ[Ü˝ ¨‚yÔa‡!8ČëO`ON¸g90O݇ĆĹ€0DĆnč†" f$0RpĐz X[]řâh c˘~ž@Y䎹©n ‡!€HŔ‡~Ŕ~h‘#zip€ZČ×N¸C…׎‘E¦&© Čh"Š×|RŚ°Ţ™ŢJ–ŵĆI(€NŔ‡FPŕN`hÖUK‚‰Ö×$üĉ¦‡eąčî市v‡3CÇ@Q4éżĆ6`öěĺŔ€0„|pëÁ€¸:fé.°—T†ŕÚnČkiťGH‡/ &mÖ†”ú˙5DnŃ„»EÓ[tPÁÜ(ťÁ.8` €@)śZ©pÔ€řdĽ¦, =EÉ„ĂěwŘj!1ľ‹—n„ËŮvp[Ă€<‡â=Ŕ:Č»±]|pŕj€,…w@Rc(¬hüÎ@Ő~8; `Chßʨ€ ȆP…ziś)·J 5’A ¨«”0čŞü6ßé+  ¸´ëąAůoRva‰Ă>ł„8URSCąŽČ`H:›aô 6LóÇrű“‘!€.J˘dWŤ8“Kcx‹“xą­Đs5 Ç5†Č S€I‘W{ąW«şPőOž’ÓN€XW ©·ŤP°´s‹ô6+ösĂś+7A“¸Jş_v[dŹtĐ095aJxř×3t6LůöŹ6W›Ž˙Óću8Tu{_7p5y·^'™?yç­á`×cŮŤD™Ř’D_n—ÍíťőP@f‰ľĹ¨đ• ˇĘ ť“€§‡X šě:-Üň¬»y[\S†HŻ))Üş ŰzŠÁ‰„ÎôVx=×$óĺĘ×ţAů§ŁŻyĽ` ž ˛ďĄů´(ę-—xßâzŔŘj Ă%›€ź›x{y͉䪉ąOîđ]_ćŔwű€ű¤WűÄWüźĆ `ăŽk"Ćo|´˙+ ĐĎ2ű±ß|•¨|Ë_üĐ}řrúŃ7ýÓr™Ž•GÂĐoŽÖ€×7“ő2ÔÇ}ç¨ď˙90Ž-ť)xćň;Źßţđ¨/zÎýäOL<†‹<6fL›H_}äFŹ6zKJˇ”«Z°Rc@·‰ Ů™đ±¸ú˘8˛1ô‰đ‚}ř„;˛s/”ĺČőW ›rŃ*ŘţýŰǤ€„ 2lŘđ "\¸ˇlÓx Ĺ/M†ĽěűÇ*W˛léň%Ě2gҬió&Îś:wňěéógĎÇ6ńjôć?ĚÚő3ćÄCďţŐ놠:ĄË¤ˇ˙ÉĂ×/”|aR&đCo†š.¬é±ćOý M8 ›ž˘Glá !˙Á< DęW®‰ ći÷+GÜľůä¨Č0ď^!BśqiT;Š=KźN}aáÉ;~­±cČ’óîíű7đŕÂUV¨ @ )R@T@*thĐ Rk "L`™ŕ:*B„ `\ABő+J ”aśř…p˘vÜY]}*Đ ŕ IäµXcŘü"‚xř%¨z˘&tź~Ja[C`‚źL,tbˇUx{ $´!‹ě=Ę2¤)§žvÔO>¦Ŕ@«ŻĆZ%¤¦8»íşű.Ľ?UC.éÔŁ )pŕAČřSĎ8ntŮ€Ëü«ŚÝđ!ŐřÓŹ2ž˛TB˝ţĐó‡íťđH.ˇŃ1=Śdě_ű5đ1!g\2˙ż¤0Ż2§xŕţ,°ÜQM=ĘĚÁÜ ?qd qK=ŕ bWĐŰřsË5!®ÔŔŕřpŐůˇŤ˝ÝĽ1áJ%Xc ‹<˘MPm5Ö,Ë/*蚏Č|Ŕq:ţĽă•J…Ń2ĘIőüBK± 0>šĎ;!łWÖTőGŚ]ä˘7/ŰĽH …íá08™`ĄĐăýčrR‹Q¤ňŽ?ůśÂ ;üŽ2\ĐŇďđb Ý tA>üxšŇţ´ >őףĮ˙¸ë>šě´űĐ"¬…$ĹaăŔX b=ěioIQ@öčˇ$„p€ ‰ŢôLĐ|ŚŁď8ĹÔÇ>÷™! 0×’çĹ«….|! ßu”a Q€?ÖP°ÂcĂ$®XâjČB'ŔĹž<0ă\ř¸W˛)`]řđ€ >đ€7Ї(j8†' vHČĐ LŔ?ţ©ŔěP@@ŤŕÁ˘° ;`ç`ÂxčC ^3ŔĂ>6‘M(1Lt"ąÇ&{$b ~ĐG#&PAÔcĐ"QĄ8rŇ“($x9 !úô˙  ç°Ý’!ŠL ”c8%ŕ `ŕĺD,‘e =La N Aß<0‰fÄAËII ç 0@ĺhÜ@ń¨âäYS㤠Aá‚@ň0ş•X‹Zä ‚`„k AŘAÖX€Ŕ„ČÁíş1ż`Fú@F:úŃÜĚŔF˝ě!… ˘ôČ…5úń Y`ŻŘËhY…~ŕăÝčĆ/v¨E}H#ď_F|Ńd\cNřB*rŽpPÁŕŔRQ lĐă®@E ň§Đ- f =čnV"Ŕl%„XD;\ŠŤv%+méKÁL˙áąČĹX“­jk!&E)6ČŹ[DôHŞP‰ję`řG-ÚÁ5„@–1|,d#+Ů—@`€1QV¸b§4| €KLăí12¶ZPáR AcŰčĆY .!ŘE+rpĄ}ÄS ±CLŔQsČŤú™@ öH w›qÄÇ"¬a†ěłž g6|c”â Xj—´ÚÖ ¶8F xPÂ'čÁ6č `(<%r·!»˘%í °‚{$B@*1ë>Ŕ0đvÉÝoA‘ÝĽsĆ”uĹ,7š ¨Żâds#˙čB8DÁ 9€Ă2‡NÍ­óő“‡ęä1O‡ë¶Ĺmöĺ‚fč!!€¦c»l„ŁÝ•2°lŘ‚:¸†>° €*đèhŤ)hâ`č=°° 𣀚a&ÄĄ°řP„r$‚‚Śxxl`‚ŚháůXĹÇ€ µ¨Úˇ d #€˛”©|_0`ÉMîLKčŞdl0 )Ř6ćÁ;ăYĎP›<°Z!˘fHśç—Ô\ 0§v°E7Ú¨%ť¸0~Ä"c“}6´Ł-Ů”ŕŕHG5ř!‰@r–=‡ś˙Ǹ´E°Á náM„ˇ$0qőó Bď@6ZGĎÉÁX 1‹?îŹy !Ţ`'K>đ‚c@ŤáŚŞë oăÜ5 2^]îs§;ěv· jpŤzÔ#ŕř( °Ź4ĚR(Rk;?—I†Ű™Ŕ˘ˇR!ȇ"Ψśrˇc=Â=Ěb–Łč€ĺęc±  ©řÇ2\śÍúý „Cj(< 0#03V'ŘyŹ@<á 3¸űĆzŰßúNČ“d…\ŕü°ĹŚÎ ŘČ.fĂ1ć;đCÉÂ#V.ú±J°Aq˙´Xkô)[žŮŇuEÁ)ČHü°ň<`cş .6BžžbvIđ< |QúއżŹŘ%· ?śÁ˝ó&¸óŻIŤâv¨n#sµ ň+ ůMÓ& V<lŔ;!Őg?tÁsi“żüćNRŽ:ŕ` öŕ„Ä˝ÍUŹvÜظ ľ«FĂS×J'CXľíVżůV?Ô AĐ@äŔÄÂ1 Đ@4ÁWh@Ô?śĂŔfM\°‰Ş‰\`›ąĺßě_SxĘĹŐ\ AĚ©÷Ů—,Ýŕš ]¸‘ť€Î±‡Jh’ DDÂ4ř˙]ŇQÓ!€3pQĎ9D,@Á5Cd“1`d@ ¤@aôYŔŤU)F¤SŤéĺ`Ŕăěll…  ˛čÝKVăeŤíÍž^vYŘ60ĂěAă‘3hę™@€Ch„A°ćí uŔ±‹g‹¦Â6ÔC?¸ÁéaC ÂçhQ‘]I÷MĆ"u˘˙$„ĘA@…šŤD?8 „€ě?ńyĆĽ\” ”Á!´ĂFÄĹ­!ź&RźG¨!†ŘŔë –÷yDHĎřťź8Ž#9ćÄěBwáśÎĆ(Ś‚ ô×%ĂeĂ °˙ .Ă’ÔG2ĂÝń‡l%D_, ,Ż % ~(Ä!üČhŔ;b@ĽU lĂ!”ˇŕG|Ŕ=ŢŔ.Ř °Ł;ÂŁđ·ńç/ůç!éĂ&t#…Ah‚.(›č-”Á‚LŔĐA;dÂTA3Ľ˙\nŇ5ôg0ˇ: Ą{&„€Â6€‹‘R“ľ(Ť„>”Bt&%&Ć”&„V @A‚FM*iÓB€ĚYJ@Ü„DŇXÚyčŽ[6„B¨„R¨÷í‚9ČÁĽAďaáhQ•¤mŢ6čB*5T? b5ÂăX(4ŇĘ9śY€6ô#„D B?ÂIH/˘U7(ð@˝,-4C;č›iŮŁĆ“Ť6äC7Ľ…nö=DĂ6ô@üĹŕU*„€@*zŃ5´›¤„÷yBűĽT ŚXąÔü”•°”KĹ*  €/´LFvćŶ‚dpÔŞ¶˙ę±VbIyŕ° ë[Ôb€„_ŁĘ'Á¬8΋&äŤKý;n×ĐC °ÇhŃĂ<¨ľxŔř‹ĹdÂ’8”@'Ľ˝häŔô@c¦Ô~ÄĘT…řś‰´l7pA ÜŔ5”ěľhÂ2Ěę(lÁ\ äĚřŽ2|ŤVdlŔŃÇ"ѨŰŐpB4ŔňüK7üĚJdČÖ\ÍdͤB0´€®tC& ¬C°Sř=Ý,I­m­ˇl@8ŚÖfÍ ¤Ă0 KFt­=”Â’0@'|­mř-ŕ–Qä Ä’úĽC¤D©[¸\¨ÄdžěČ–,…tÁä)8›C`˙–/ŕYť€/Č)Ţ<ü‚ xŔĆřľ´Ő”b\DE>pÁĚěÓ^ uđZăASBĽÚéŤ1ĚjÍśŘrĎ´)rj¶Ă5¦ÔË;ĂdˇTĂ?ĽC˙ťŔ2¤Ă馮öˇ+čŠ.š˛€&\C&¤€mTŔäS Ż ÜŤĂtC ,Iő\ŹđADA˝ČĂ˝¤/ňµo;äC/„ x ř.,$\[UB @óFo:LďÉT”0ä˘Á~0O–{‡ŹČÍ´cʍuŚ–0ŕŠ„\€8µJ’UĄ4ŔÜǾъ,‡ÁéGq8Š„8ÇŹ´˙xl  pzŕ‡\€‚lsÄđ´41{´ GÇt¤ €X K×t\Drxpنe`Jâř?†€G ĚH(@ ¬GURŠAuľ@´0€tx«ü1hŇ}Pą”«0ń«„ §ČzŐGµ`!t>řÂ\„@Ŕr0˛g)üHř± „‹€ J'kqB$6Сł„ {<@+«JcÇr$„.—ĐÔHx,‡wÄI°Ŕ@§#Wň%g2'˘)+/‡16€-ßyś.'¨PKwš€ ‡$SłXsŔ2ŞË.+0KČŠÔ´ě]Ç˙ł<żË|đ .ÄOúVB|ĺM$™>O]B.„qˇé¨ ´BđsB˙ódH.CÓDEpâCcĺ h-Ä <»DF/LÁ5ĽYBČ’ËDgŐp8ły€“4můKŰMY¤ K'™IĎRM„„żŐ´Ă…C,HCÄRđóDs4Iő>łôÄ´¦-ÄFĎ3TGuůűäspřăNĚ(Ůs~`µCx5´E3Ô& f ‡ NyČgf~„ór-•ŮMV[§AĐJV\J5_÷µ_ó†VóBŻÄlö~ČXőa·Ń?Ʊ¤ÔK˙µOHRĹQW6Ľ@u<˙µ»\¶d6h‡6Mh5b'vC6ɶK¶j?f‹6lǶlĎ6mĹ@·‹usiôl±DÇLÜvo×vNP@č6q'·r/7s÷Fj» ÁŘ÷m«ÄoWwKP÷p7wL4 ÂĄp·xŹ7y—÷i¶ißDk;ÄO–Ěu¶BĽ7Ěf·|§÷NڰTw”4{ńÔ ĘDg:ËDsL‹xřĘJ TD.•ÚÜ^÷D$ç÷v¬µJ3x¤G7÷ —đk›·‡8+özăÄvł7îöo[w}—řyË7oT$,řĚ…cáĽmUĽ 9„w×KĎü třŻx€!¤˙<řC70Â’Ô¨>ź¸Q4@Đ‚˝ LŤ7Äř A”Ľ*0lŚ€űD=ÂM‡¸™ź9ݏ`\/ 4Hq‡·-[ĘO&NŽh@śµ¬‡ˇ$Č-ĎHâH˛¨ü6ť#Gt!˘( ;ŰČ›k4€zxŔ†k1Dđą﹣ĂQrś“CśW=äĂ1¤F„cCR?ôĂ-(–°‡ž¸MČvĂ,:M†*Đ|éŰŠ 1 ɸ€;•0 »p:ËČŽ`‡;r*ŽÁx‚F%™<Á@A$=žcőE2BŰ9Á9šŹ;ąĂ¶š˙6 ÷ËżL\Ě‹Źă˙ ŘT@RĺM>€÷ONŔäĂ؆ĹäŤéŠÎŘ ÖŚĘÇXŚČ„ŔoË{*(ě)Ŕ€Ś@ďüŽ tm>4ÁŞO=0ÂlŚĂ TYŚ’€ ¤CĹźě6Xޕ߆ÜI8ńC)Ä’JśW–fđu¬C,Ŕ@çŔÂ^xŔL ‰*Ś pGťĂ ŮĽÚŮĚę¬S^ęŞŔhé>ä8¤KŐ\Ťd Á¤×€Ť#SŔrÝĘ%™ĺK@<ü€haÎŐAyyąĎ=Ý'÷ąqBôĐ‘L ŮéP6ĂL|A °đ LÁ6H·~ÔSQ¨*Rć4É˙ё؀hD?äC.hËęCEÔD ‚>Ŕ TA ŔÁ^p>ě/hC>8µ´Ő[ĹÜbŠŢĽ—'ôŻ\ŔhńC"ÜőCč%-Ô=„/4™ \á«ŐŔ%”n6¶ĆÄEtĆýÔŇ-áś.yČ@ćÄA™(AŚ<đtÂ>Xv—¦R±’+ÁŇŢťG L@ścÂ@AlŕŕâÚś€b›R¤¸‘cGŹA†9’dI“'Q¦Tą’eK—/aĆ”©RCM›7qćÄ `+W.% ‡ $0@Q®Ń†°hÁHqB . #dÍ˙N‹‡0<¨‰`W«Ž•z1áĂ˝FbT$A"Ŕ s>Bč¬p˘¶L- ÂĘVîáH:9¦Ž €°†I'ˇ”’Jú©!h˘ :ĐéË0Ǩ3ó›hf¦Č"FšŮeTŕ9‚€8|ň‘.f°¤ŚČ eŕZđAĂšž!Ťh"ÁFšB`•# jh&bKg›"l¨! ¸‚źdjŤÎI` BDk‚ ‰Ć€Hň+¨Ľd v‚Ś­r5 Z¶YĂWä5Ź(Ř€€’eÝŽ`– 2Aş€ 0GnéM]őŐYoÝő×[ĘWö{Geî»ä.vQ«XIö‚”¦ş`®ý|€¤>Ö:aAć˙ &#hf“µ>` ®m!>,L0qľľ2yTA‡fřiâĹʉˇ‡śé©›]˛‰q…‹0„]pllc)Pގ¨B†âĂ9PŰA–ŐŹh°€Čîزf`‚¸@ގ,ĽŹÎđ@2¸Á`+°ŕđŔŹa°: H€ Tŕ‘«Q‡ [ş `7ĐG<€¤Ŕp0Ö|¶˝ű E?—–%'®‚P€öqZ2tT`.Čź2OĂ"ŁŃ.’_Ĺx`—G=}ôcLf7»}1cÄ5Á¬ĚKČ˙B9± lĆřĂş0‡«\blŔĂcÇŠeĽ 5(‹"#AŹDtÁúhD&@|śbc°§— (úČ…6ĆDü@F;řńʧ`Eđ6´s€[ĽŁž0 '&â ýÂŘ@ŕŹŃ|Z,ČfŹhĂÁhfxŤvôŚ «)ć1ů!‡×ńŘ '”Ź\()ź$€¬ ĎČf:-—@±ŤmP‘R2Ć0†7lňŠOś€ ®QČCňA‘V$'· ěá ě?Ô5ĆŔB D]ő8xŃÔ¦r„\Ú90ěŹE5ęQ˙‘šÔyĄEÔŔŠF±Ťe€ A(MXĂő¨Pn*^pő¦HÁR x€هLP‚NĽ#őĐĆR@"éČE?‘› !]ír©4 ŁxG–ŚQ„ °ŔÖ°+ Z IMČĂ &0Ä?ţ ‚řaYŇF&`ŕD!éh‡]3ˇ ‚ć`×d y0Çřx\7ŔM\#¶ąš,«Ť:¤ŕ8ÁE:Š €tB]5Ćd+ş3ŃÉś ń€*xqÂTéÔrŮ.`dř٬-@«B÷ŇŤLx`±~‡?Ć1‡ÜĽ·ńťď Ň˙CT÷ĘxĂ…ŠâG4D¶‰B:ÜH•jÁx 0iŮkŕ(•Ăöđ‡A|5Ő©P Ŕ†P€Î×”ɱ x€0˘‚ÜP’< LĐ€śÇˇŠ@Ü#WőÓnŚ‘Ř‹‹/Ć1%ee)ĺĹé˛ 0(y*P@,ĺ‚U…ŕ@¦ľfĂóťO1tş,a—y@Ë1.^<2 ů°`  ”T‚j˛ŮŔůRz„Ů# ]PdŘËŔ±`‡Śľw€Ó=ö´6!F@tą.gů† vY¬ŕçĹ˙6ʇ¶ula{ŘŔ—ľF@ťH$7©ę Rµšř&HŔĘ0-ŚÂMSE‘iź(6`Ůą ”$Ľbř0G ş[˘‚…aćV´BÔŹ0`ŹĐ‡…Or€hż"HtÓt{$á ÷Ă?ńč›Ř·řĹ1îÇ}9tC;Y€!ŢŃŽtŚ‚ś 7JvB’‘ˇř`ź,/,á8đ ĹCfÔCCČÎ3tˇťčEďđ´ŕA°8Ű H§6‰Yâô’`骣·ÂQ–ŁHÜč]÷ú×ÁöI}$'r ŮĹžvµŻťímwű‡Śmě·Ďť˙îu·űÝńžw˝ďťď}÷űëĚ~vĹRí©ößźxĹ/ŢďŹÝŕď‘”3žň•·üĺűxxEÇvŞ€˛jQĂFô8ä ť `ZĐńSźSŕ§ €L h1ź{Ýďž÷3™ĽäOţůš% ©xěÍ^Ó€;Üwn(Ó#”qš|ŔshYDćÓÚËĆ>ŕH .Ą÷ĺ7˙ůѦ>ř ż@MrcŻ$ÄjKa)zô$Ą,N`NĆA®!‚+ۢřa fC`al`^Á4Ňď10oý6âóŽÍ:v€ĆĂ^ `¤áćb.˙ HŠđö bň \ŕÄdˇ "¨)”‚)fc ® l z)ć40 •p ŐŽŐďä€đÜŔAF §x@ŇE jÂqŽŔš!4AA –® "BFhÄFř! ÂvAH„P lß0őpÎ › ;`€`  €RĆě°P § =-ŕ >Ač€n‹#f` Ć$á5`nc˘ÂâŤI±MńŹüđ …jÂd§…áě#0`çB(¤Á(Ц!fÁ>:(Žw|lj6‘˘Ŕŕ aŮNńˇ1]gÄ˙:Bř¬QÚ¦¤¨Ęŕ &ŕŁBĘúď4" !&A@8b‘鑦ž>`¬Á¤ŕPőqůŃCîE$¨‘đŔ­Ú. řęÁňÁËŞ+żr#€˘¸@čKĄ´*Řë«BŔ(j 4*ŞI˛$MŇ÷ä Ďó®qřX(ÔT,ůB-}`Ăöp¨ ‡ #­ĹĹ` }rč#9„ô Oň(‘2)5ä÷š!2%SRDtĂip@ AÄK)µr+ą˛$’ýţqu(ŇŇA†ŕŞş2-Őr-‡-6`čŘ2.ĺr.é˛.íň.“đ+CL/ń˛/˙ý2÷řňĂó/ ł0+.ňDĚ^81Q.đĚN/S Ă2ę’% O2W"2 s3ůP3ËN1;n0Ib%«Mî “/+“232W˛15Ź3a“ʏw)ôfrÔJON/őj‚őR@ô$@Ŕ‡#dO4€ÔT@|xíĆ2B!Ό̦-9¦SÍví|pč8©±%+<Á3_$“<˙đ4ňĆ3*׳OÂŕŕ LvĎř’’oůđËů8ú¤O¨Ďú>ŔŞÁúAĐĐőşďűÂoüX'` KNˇŔaR`6î ęA<E”˙ ÂůĽ+DGÔCäD4ţF,>‘.=iôD®ń<'Ó)mGŰSGs´%áóFKsvčóHEâ@Áhˇ D #*T'ćŻţîď H˙řŹŕ˙p Đň€ţ€ ľ((¸¬Ć P)Đ4L¤@ä °ÄďVC6! 4!]F°Fę4đ@OůÔOGKĹ‘¤týŐH…T «±G•=ĺ3G‡´R9I9µ#lŹ!Ŕ!Š Js˘‰"3…>nňăcpkđs0Ŕ ä(M…ŤpH¤Y¤šˇ˛ŔAH-`zN€>죏ő˙’uY›5ŠžŐU}€4u'¶•©"u0Ő3>áS…Ôɵ[Ť´SŐ5"j‚‹ öˇŠŔ´5'pŠÚ‡ ±‘Yľ0 ǰ ĎĐVŕŇA €l#Bˇ&äp ďP' xEX‰Ő¬ lŠňôÚ€P ΛEc+Š:öcCv_›]=0îÄuH35Ďő^8ĎeOÎ=7Ő\1“eAs]}¶]{š)X bíµ0_·Pd™Ŕ!Q)Ń’U úÔ!61:ńCQőp‚’ŕŔb‹U 8†€âdAV_˝0$7öÔvUöxÖfťFÔ4=pR˙Ásf{g!Uř`¶nSÓg9ő®ŔęÁ’(čue±‚j‘U§(w±ńŠâč ŽI `#ňb’q›ŃkżX¤JčA ˘•a(}ŕucwvk—ŠP—pĹ•[·5oyp×[Ű3\}÷5 IŕNAăŞě%·ń şńA*KÉŃŃQ9 ě`ľŕ ĽiŤRtť†íMdbyEp(V ňtş OĂ`>j˙UY uOíuP“·F¸oÇ•x 7fÇMSřw˙vyŹô#MŐnqb?2!cŁżô‹Ô"r"Ł ¸`'÷`˝˙ü2†(€#>ňBŇ4ÂDŔf€ (2šD-ËŔkőB”©E‡˝Şłí‡Ňq“·Éłx ř)S®€Ť7ŠŐo•X>!X]Oď5Mäý&W,JoÔ@9Á,'E TÎŚÎľŘ#NŹ(ŤR†oO'q2}$i:]mĘVď6a˝˛S×Âř8÷đľµ\‹ôxwyß]q¶Š—G Ů[óŠ!8*ťŇóžPý.‚*­+{„’'Nß@ů Î37Ż’ˇŇR•î6ď+GYňĽň3ů‰;PR;Ź]#ů#.“ý`Y’}9uƲ,Ď2;Ä”I4ŰĹÝ…Rwfo•˙9š‡Î-±®^ y)]vŻY^⎗Uň•qyGĄyśÉąśÍůś3n›Ą1—S™ő™ŃyśáŮÝů¨ę9Źć9ž}9źQ±ýř;Ĺů›Áąeö%îą•˙yŻy5 7%üĐ<…WźŁYť“*}t‰),›Ů‘ŮŮ ůˇ™f“ˇ;:1#˘ťY˘•ŞeĄXťoô™űÖQýY3/Ú3YZ<:‰źŽoo– Xxˇ4KÚń‚—Ł´¤Ušu´É™śÉ!ÜÉY˛DZ¸Ýá-^â ˝'žáˇýžĎíÚş˝ýâ}YÝŰ="lÇ ¬;;`Ő®ÓÚT Ĺ€ň8Ą3ÓÔ,Ef“X»™cűQľĆýĽä·o%µĽ+>č=^ßM^’Eç ŕ ę nÁ®4ˇčaH@Ł­@´€D]f±´ů&†EIt*RÄ>ńs‚žăZčOĽĆ˝rxÇś±˙ ýľ‰ľéյʠhˇ~Áđ!„••öaBPŢ´t~ő~U•ňí÷5LDI™ÔIˇ´ yĽĎŻÜ´ é…~Ż/;Ę){ďůľS•쬡„Ӝȶu€”@ hß> " Z§•YťuŠňř••hŻ1ŕSCuTKŐ˝íŢČá:ő˙ĽăMŠó;˝AzŘQ˙ő}šÂ@*Ş™#ČÖ…Ő‘"H–c=6 ` P¤m›acM–˘  ¤@áš}ĺŠŕ`° €‰'FÔ€`Ć‹;züh°˘ČŽ"+‚ÄXŇ"Ç”,7žŚ˙čĄĘŹ3A¶Ś)ńćĹ–WŢü 4¨ĐˇD‹=Š4©ŇĄL›:} 5ŞÔ©F ŕŃW.S @šőČBOŠ ŻYî­ŃŔŢ‘Řôđŕpˇ 3Yö©Á€ŤZ¶náĘř‘B<Í4baăÉ’;qľ| ™§Ď”'%7 9gHŠ•/fů™rO “©š>Ť:µęŐ¬[»~ Űh'Đäj÷+LRvĄbŁ€®J”TDb"(i"›Č`.b#blCNâŔrÎK˝>ťEŽ®«gě <‚Î ?~NŃň{Ö<ź~ţš=ëGÖßśÁtZ±`‚ .Č`ކ˙ (ŕ‚.¬ÇŇoÁ × ,ROE|ŔU›dˇI?aŚ0Ś1Č5|đP˘>'¦¨Űx!pË)B¨{4č_‘ĄŤ”Y$ I ‘ŚídäKďý“IP†ö`–ZnÉe—^~yT\€ÁMS¤Ł„ MaŤ60pG5Ś3G!lŕÁÔÓŤ&`Ô@śţĐi'žwXçźtd'‹Ú7e”ńń'‘L.IŕbGZą§ý%9©Ą]†Ó€›a fŞŞ®Ęj«®Ş¦€&¨‰ ĚZA Eô–€¤ @ "„ĐÁŻ ;l±q•˘Jj“c–E¦˙)L4mję~ĄRŠm§H®tY“ÚŢ÷j»îľ oĽ®bP&EevĐž¸Đ[é€#Ń”{Ső‹äF˘yŞ.eśúŰ/Áś E*Qŕ26i“ćđ{Fe,oÇ rȧEŚšŔ^b4ń‚)ëD˛Č.ż sĚ2Ϭ`Ë'«t˛ą'LsĎ>˙ tĐGé,tŃFŤtŇJ/­ĎL? uÔROM5«NWŤuÖZoÍu×;čuŘbŹMvŮAmvÚjŻÍvۢť`‘äÂ7®ŰvߍwŢÂŤ ÜJú­wŕ‚NřĆâ•@Č"+‚T°řâ*¨xäŤ?9˛“Wľxăł–KwᢏNzá|·ä˙B:˙ü#Ď?ř€łĂŞŻŢ:=C¤N»ë°Ëľ:ë˙ŘŽ»ďŻA街Ž|ňĘ“}zJ°đDôŇáôŇG„ #\Ź}őÜ?‘ýöÜ‚ŽsűmňňęŻĎţÓͧ„ň{€ŻĚ?? łQ€ý÷ăďýy€óĂłĐbĽµo lŕĚŢW’Ěnuř(G x×»ß A‚¬ŕ'¸:Űq°w,BůT9p…,lá« X ŔAß° „ś€8°a¬Đ‚Ü †=ÄN°ĂÖđ‡AâŠ(<… tˇŻĹ,Á°$ôÂş€t(Ó3ŕĹ2˙b@Ś],#ÎčĹ|JRY¬Łď›-ŠdŚł×íőĆ@ĆđŹYż¨č-›áq‘Śl$Rô¸Ç>F’(’Ś Ř(Ć.Gjr“śü >ɤ©°“¤,%ů€‰T* e—,ĘL ËXâŤx{Ą,o‰Ë\¶Ë–şěĄ/é ^sÄ$f qÔË’é+¦3ź‰Ëč`i Š0ˇ‰ÍlŠ †č3RÝÎĹ‘ śŔ‚0Á)U tfK›ělgÇ®ÎPQńIyś |aÂ|ýíJ‰Ą;˙ Đ/5aLҵŇ0Ă-Ud@ Q 4\ 5h<92€WŘ‚…dD? Ň’©Đ˙\§2ŢůJŕGx~ ©Ęt¦®™(I_ÚQ‡ť„30‹řźŇt¨DefĘrŠ®‰őł -PA‚?u´¨T­ęRüąO¤®JŽi*–AĽśZu¬dĹL+·%7lˇŐ3ËŚXiů”u®t-IJjŇ••ô"x0B‰W Z´®„-lkÎú°L&E`Ă<°LÉl˘†­¬e_Uˇŕ÷T®yŮĐŠvd.‰Jd™˛˛ŃŞvµ¬m­k_ ŰŘĘv¶´­íÇ.ŔCŔb6°­oűĄ1uE68-pŹ‹Ü`Ąlrź Ý×”Ą´Ś®uŻkDAa˙Hvż ŢĄ\€HĆ'‚đŞw˝BąŔŻň° Ţ ‡˝ô­oEĆä‚k׾üµ/2şŃţ ˝y™ÇŚ`đ2ŕüĐÍ| áäNŕÄ á űvLd`r á۶7.`!rĐ«8¶KńŠ_ ăËxĆ4®±ŤoŚăźŤ)VÄÂpQĐeů8ÇDÖĺýŃŽ97) 0D=ędÜ"K–<}‡6ŕńúeŔÁ5–±Ś!€xĘdŽe.Á !ŘŁěŮňF €#c.łť7ů8-\ )đ3ŔPçˇŕ ÷Ăî@"ŘéÎŚfdbŕ‹CŘ đ˙0-”ĺĆ" °.<ŢF‹şŽ8 Đ Lá 0ňON°%$çP€¨GŤë+Ę$(*@¬(· Ŕ¬zăĹňĺzŮu#łź íhK{ÚÔ®¶µŻť´ T V™űb·“%|a{ÜëŰŔrŃ»ÖÉç@·şYWS›ÜôFŢjř˝ŕ›{;c˝˙=ş1ŤéŹ÷* Ľ đ„çmŕ• Ăç­đ›í~€€‚°‚[8|®–¸Çł6¦íkܲŃŚ• ·şĺíÇ_.µŢTá„xł¶Ě b`p›AÜ‹Ă|č@#Ŕ ě ôNdx–°˙5‘č*Y˝N„Ć9ŠIOdąÍ%ş×‘F€;ÜC ݎŞQeĚ!˝ 8ĺ†yW€zćBoI´Ň#T÷ë|˙™,í\ĽŰE*Á\#9÷ż»Ř`µË]„÷}ň2@ăyđŕîĽ  č1N`At ; Č†ö.€KüULä5ŻŇ)ű—9`ČÁkô·p@.tŮÇ&’µT$‘F(9`?řĘ7öĚ™ĺ1yŠÔ@ż<ďë˘ŕëĺŔ€%€áôâWżwoľůăőwđWDóŕˇNč®i„cB@-Jaű‰üWŁ?ż˙]d`Rj‚· ]€˙#,‚x12#>w¸g0âDNćäc0˝`a “ĺyga7ve§sWww7]z×. ö„O=9Ŕ`qŕ”ů䓌–~+I˙’–çxб]ÝŐ.pĺ B™P µ’yL@iéYÉh^}L‘z«7^ĺu^Č*6É P5_¶’‚Y„)—v6{µwAA|ĆČwĘ·!­‚'¨ŕ ,¨R,µLăç9°w™ŮR‡YfĎW—Ká}ŕ'~_űĺ*x ŞŔ‚<ĺSŃ’ů`˛ą‹)š1–~0)^`ř7_ű`®ŇiĺĐ0ŘTOUĐQ^˘`N±śPĄ&»Yd8€|ůŚŘ 8ŽU«Ň €ú€wčU`ĺ]äąaqM9_E<ÖYd¸ş™)¸‚|é‚¶*\†Ąç›öâVˇT˙Žy·wšr\Iź3F6´ŘCX„|‰„†ź ‚'„h%ŃW•’¶Qöˇ Ú 2愆…°h,j(9"P…WŹŘa¶*Ǥ| e"ŃXŹ%\äe? Y'šcsX‡pnéĆ:’řnňo°zȇ>ö‡'VŤ^RU  6d›ŐY[µŔ[CĘYže¤9¶‰÷vŠ±ČŠÂá‰×b«R& :l»¨?!ˇiúb¸Ś4dǧJ¨…j¨‡zER÷ŕ–^˘¨ę‘ |Ťú¨]B©’Ú|@€ Ŕ±¨–ş@691Y śČ©žŞ©ć—©Śę¨ˇj˙ĆĐé%NôP¨Ú ŞşŞĚ—©JůŞ´™bď9&1oĂFf¬ř’É´40=pi@&7‘©»Jy© Ź®z©ôÇÝÚ­ËÔ­;Ŕ=zŢú­®ăÚpʵé°Q0DĐkÔÚ©5j­}ת J `­Ór@Kc‚íĐřĐ™ŔňŻ˙°{{°ťIH@N°ذcŔR\‘«řšŻ_׫ü: °S0k0+×+SCЇ$k˛(«˛,ë˛0Ë2@qđ y@ <€«şú±úzŻźú«>FËT/PŤÄ(H‚ä´Ź)NŻ Â@µ˙ "ŠŽŘZ´×Ú±H»­§ń8€ ĐK&JŐúµD˛I‹˝±Ű`B@©ť%á¶o s^KÚş˝ń˛b¶bŹ{+€ë·^·Żr›Ću}۸·c«%”[ą×p¬Ňą› şˇ+şŁKşĄŹ‹ą±!¸‹¶¦«p—Ë ľŠąšëş×Ƹ°ş ’»m{´µ p¨Ë »;´ë»Ô» "»|ŰşĹKo·+ĽňĽ·ËĽŘĽ ˝Ë;˝Ô‹˝É‹Ľ"۶؛˝ÖćĽŢ‹ ŃŰ»ák»ŘűĽŞKľB´čkĽŰŰľ±Á˝AĽđ›kă ąĐ۾ҋżŃV˝şŰżŕű˙żĐvĽ Rżßűľülź«*ĚŔ,ÁLÁlÁŚÁ¬ÁĚÁěÁ Â!,Â#LÂ%lÂ'ŚÂ)¬Â+ĚÂ-ěÂ/ Ă1,Ă3LĂ5lĂ7ŚĂ9¬Ă;ĚĂ=ěĂ? ÄA,ÄCLÄElÄGŚÄI¬ÄKĚÄMěÄO3$Ĺ»ĹÔ&ĹDĹU,mWÜ;Y¬ĹĐĆĹ«ăĹ_ĚlaücLĆąfĆhśĆ36Ť’wkÜĆ8ćpđr<Ç6ö ŕ´P"l-ˇÇ{Lc@FŹsVWȆLcˇ áv:Ź É2&„ś‘Ą—ĆlśÉ"Vç‘ë‡<Ę*Ć#>$$mFȡĽĘ1&Š{ Ş<ËF-DËąLd˝ěË8ĚÁ<`!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z˙5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(€{ś8„H(ň_Ç‹®ôÓĄ’ĄH @x !C *(P€Ą€67âôłĚ_=en€Ć°öź0HC¶„ ŔŇ95Y:ő ÂCŹ'®\…X©ő¦€KÓ^0řĐ‹‹F¨R˶ĄË®Óx\¸Đ†Yy÷®MZńmŕÁ…'ćËăŰl/0Ŕe—“`Á0A‚„_®—ě%ę©_!8p s ‘›7¦·ľĄ7Ż8@)ŔP˘Ó»w§Rś~+L„ )‚Ě ‚ ĺşáňŔđĐ ‰Ëµs/ňt@!ů ,#‹!ů ,#‹!ů ,"z¬Đ@° A˙*TA A.l8đáA‰ZÔă?Š9zLrcGŚ4€đ@B†&NJLég™żzĘÜÄůQ KçÔdéÔ/ŚĚŚ\šö‚Á‡^ÄŽ2ôiiŹ Ú0“JŇçŇ«Y™I7’˘Ňl/0ŔŐ‹kϤ—ě%ę©_·LÁPJo^=p€RŕMˇB©0$¤ĚÓěW ńzµ ůbŮ€!ů ,#‹!ů ,+zŻhH°ŕżBX°a‡ :|¨ˇÄ+^$ń`ÄŤ:ţ[Xˇ‚ $B$H B…H’1şˇb˘Ä-[)^čBG3F)DEŰaB§‡Čä;ĄK:‹Ř0a¶R>0„ě¸Pꄵ°ť;‚‘+1š@òl‘Ť:C„ČsŚJ -×ţŘĐŮ`Iľ:!4,č4oÎ DŕĐ!A–:^ ¨µlĆŹ_!ů ,#‹!ů ,#‹!ů ,#‹!ů ,6zT5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1t°ňˇÇ†3ZÔP˛"É”˙Nl©p%ÍŚ!^¦Ä “%L tv´ů“čNŁ!ů ,>zť5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ lŘ AB‡ ¨PRäc¨Svć­ĐŕÁš1:LLŃëF !ů ,tzŁ5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ tč "T„Â…%rĄóG!Đ0˘Ë(x°ńáŃr$†ěj•Łĺi{‡ [+˘97xčt¬N Ö®¶śpb™ $Ô›“,«eo¸ÔXŠ#0;˝KWOŰź-W60 A‚„€szĽhwqË€!ů ,~z‹5(Âżb HĐ`„ |QâDŠ1”°&Ŕ4 bİ@PÓ|\‰€KCbĚ(P@Ą”+)bˇÁćÇś1tčy“ĐŠDj©łfŃŁ ¨$í LJĹł/Đś7Y‘R‘*]>SaŁj @A"ŇŇ´(÷_D‰u1!ů ,#‹!ů ,†zĽ5HP€@řǰaC #&D¸ĐˇC NÔ˛}Á`.b#NÜŚJ-P¶xXĹŞ•«×˙Q±!Ů)n0j­^77&ďŮV$D”t\lXÝp¦Mś4@P`„î&¬Ä€!cÂ.{üŘrh@!ů ,#‹!ů ,´zš5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1PŘ @*T€|ÁÉGÖü˝Wd%Äxězň ›  š'ĺÂ$€f¬ĐăV:TZZäPúO$FPÍBC HȰ'IĆĄ{}ąqg_˘® öTóç\¦źg«VhpR‚„)şZÔ Řb×€!ů ,#‹!ů ,#‹!ů ,Ľzž5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ &h‚!B€„€C‰\éüŃűăA%G#ş|‚+[bx Á®V9VnŘ€ŕ¶wȰµzÓ‡NÇębmęĘ '– "Ab@-Ż7'Śpĺ«—G©b„X˘S5ő´ýI±R`’$HHÁ÷¦Ç‹sŻ !ů ,#‹!ů ,#‹!ů ,#‹!ů ,Ćz¤5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1$h B‡ RbĚXš)“iůC€Hç|LřLMŞě3AĆľ8?NN+ű¤`XůĂ„ ‚˘4ÍGŇŚk4+Ł SŽŻU µ łT#@ÂO×…hĺʰ—faŢ7´ĐúĄ˘†ĽQŐÓ4$‡ß¸!ů ,#‹!ů ,$Ś˙H° Á*t;÷ďŕĂ‹˙˙}‡r’,"śÍ^4Á T¨xůâĚ:J2(«Ü˝auŔ°A]/`ˇŽ;î@#‚“…P`EőÝ—ß~ýýŕ€Ůµ·{yŘŢgh±'‡ Ŕäµčâ‹0Ć(Ó( ‡]ŤhbA ě‘´„Á±ÄăŤúeđĂ0Ăś…ŕA,´Đ Ť0č5X´ °pŃBCyd’K6ů¤x;¦¨bB;˛X˘wm ˘ś2ć©çž|˘¶ $@Á ĺ4rQ @|! ÁHB x5PÁ B!ŕ€űXAŰŠ:jú}ë¤ę %?Ľ AvH˙đĐg 4ŢPăÍ‚ ŞăŤ7ÜÜú '‰yg*ŞŞ˛ę*¬˛b #Š9Šřě¨Ţ4íťŰéxⵣ’ęŢ´Ö‚ë-·´‘-ąÔŇ mźě¶ëî»7±ö5ţäÂŹˇ4p8ţŚăơ~h“N=ÝĽAiľhä=ŚLé)¨˘–;â¬ňMŞ©ŞłN,ŽADhÔ>8BŤ–ZĆĂ :,ŁC 4i|´ĹcĽŽĆ{ ˛Č讇®´zůgĐŰ’[´şÝŽ›.žq«tĎ©řóŃK× ďŐXgťµĐłIÜ[Á‚ÔČ\ĂXrŽH¤˘`G=€pAF3đ˙đp¨ťNËÁd )olĹ“_ 1k{7vĆ0č ě;ń°ĂŽËźHq‡~xâ±,.AăŹCíĎ×®Žâ·¬+u¶Ú »ÓQýtěTW«őďŔ˙bÇlňÜÓČ1l#F€’Ť\2Í ¬pO"ô°ŤŔ ćřĐi^Ü#EŕÜÎő)ëxóxŔ…={Ń R@Są:츜ćŘA JA΂–űŕ'?úٸ]¸nW;‚<ëh˝›šŇĆeA¤Y­l]îş4 fPwÂKˇ WHš\C9 z€„}¬"`=ŽĐ¶iđŔ<ŃP ˙űŃó^{0?Ý7ś/Â! Ń ¶¸ENđ‹›ó¸|îMR¤˘±84¦0„oˇÄŞFµÝAmv°[WÓXǤ屏'D! IČBĹ…zřaŤ€ŞA 9Üaő|8qu h„&¨  Ŕ ~áŘeÔřŞ«¤®=GE,V!‚BxÜ4¤Ŕ‡Y~Agä)S  d •~iŁiB×aĐ„ă3{wB7™u»{#35(.Czó›ŕÄ ńBĂóH˘ÍDF˘' ęYď‡"šw¤ŕ0 đ’˙€`á%ş0NĽ@őˇĆ7X%t6x.1Ž —ôHt…ú."=hB:?‡ţQ/‚´c3]§Ě>ľŽv|üčŻ 4ÖÔĄF §NwĘS–ú(E®°ŹĺU@×8[ÚÖ6Ixq C;N1‡1ŘÁ űÔŔRŹ@pŠup„‡g|ĂßhDŞE ôĹ ®pÉ ľŔsyhŇ”"V˛š­jek +8Sś’¨°-5ě`ES»ľQ„T¬{JŮĘötŘ2üQŹqĚa$ Xż>ۤ"-¨Ŕ ş‘‰ ä ·ŕl7¸U˙"nČâϸ€Ĺ|˘I ÜłfŐ‡oP›`lA t#1ŻŚ#xűßW¸ŘŇŁUŞşÇŇT˛'Eib­i´ ĆÜu¬e×Ë^nŕ P€˘G-jSH@äł DęP—‚”¤(ĄÄG·ĂŔ°(+8âAâ÷Ś>Ľ /ř%¸QŚ3đL» f°!lµeÖŃi„ő.cŃ+§{đ°¶[ńw_^ŢÉń‚íͱŽ×k—`Ç%{=A €Ü°`08ŠÚŃH`G8/X…^7ŁN ˛Ald$ŻN9Ѳí”bŮŔř&ÚMQ´śŮ4ś9˙G;Žłśç ”‹ü“Codr|&c/Č€¤ŕa™Řů*¨Áq[ŇLçF;úŃ,džň›!$ "(˛Ck"éöÍga4¤GMęRłkL/‰¨¦€‰TCúĚ¦Žµ¬g-Ľ‘‰Ö¸Îµ®wÍë^űú×Ŕn4t`Np 68až5ţ\tٸ@ vQ ¬äF B‚Íín{›×¸B?tqěśL`4Ŕ.pAh_  ؆VâkčÁ“ţ¶ľ÷Ío¬Q€&€I© ¤Ŕ¨€Đ%ő€ŕ08Âý˛čW>zťŤFŔ W|Uú…†,"Dż8˙¸¦EđIn°ß0ŹąĚĂă8<Áů.Hh—ÁYe¸á1X6>„ĐFůçőđ9Đ» „ ·°G„YUxÄK´Ry#4`ÂÚmb¶›ţô¨ç |hđ|€#E¨»őŽ÷^Ă鬙<˛'I{ŰO)dČÇ)ôŚ<+÷W×üP‰Ěkŕ8D-¨@ ÎÍ€ˇC/RćÔ{˙űŕwÉ˙ż€†}”Ł&ŕŔAzČh·E°ň9%xKřĐýđ·Áą'ŤRř"ł3ěŁĚç|Ď'ţ°GŘ—HU#Sá÷€@=€ÍP(,`·VM…ń'€‚÷N¨=P ŘpG0M¤"€žQ€~“R¤Ů÷‚Ý$6x¦wW` ő` Ŕ›†Ő“ /Đ € ·g}0 °GCX„Gx{!=Ć€˰6Đ8°„´ŔOč, ćđˇ~đ9‚28Fˇ8X‡vřmp § ö„Bx ö] ýíĆ@Iĺo…€˙(„ś’Ç@) ×đř¦#Ŕy€ €đs@žÂűcđ †Ń2»`zŠ‚Ą^wX‹¶Čk!Ŕ9gŐCóPŕ) %Đ ďđ¦˝ř‹Á °ůP±±ťDÜ…% ţ€ŚF1  h ,°J Đ<—¦0‹Ňu‹îřޞ†-Q= ‘2)a_) ôhŹ6  )uňńĎb_ö„űp™äx T €)š´Ź™‘˝ÖT“Ć!Y¸‹:‘X ¦‘&y’¦ö‘ˇ’0kÚˇ;Ą'd(9“4‰zßB*!˙"csd%M8Y“@”Á–].YX'F‡lMBą”L©'Y-ő!ÝE^Uóo!’.b•Ń”\Y‹Śµ7U”Ű䀤“0€ ČÖ'g™–kŮ•p)_éfHchwcymÓVmOů4ýEŘŕC0 üoÉŔ7nN/ŕĚ` <° Ŕ#!1…yń—imQW ˙Đá@6d4š˘Iš¦‰š‰© ‹yťč‰• Á™>—şé}ifu‰Xw‰—Ęoňö”íÁž€ „Ŕi@1žĐ…Pn6ń^‘€ đpwPvלšé#˙śË‰0Ł@ ýŔ¦™癞ëŮžťŇIťaťŘ©ť4śĘé™»ůźd(“ҰpúV‘á ¦rńˇ˛pó5 ‘p wŹFpó•_zB!7r%÷|đ%_‹2vń,çÉű &0{˘—(™ňIő•‘‚)*!§ ¶Ć3Đ ę0‘ ‹’Š˘ň("+Š2)  8đkPr Ę Đř *Ł 3`Ѣ/j¨)Á2Ąi› ( @ŁGúIş¤7`kÚ¦oJ ¤D*qAˇ÷Ĺ)UzĄY ꤛ˙bqűĄFhŹ'f ŁU*° gO?Ú¨yJĄ‰_'‹Zˇş›]n P´ÖŁ#0 Ó0 Ę]€[ÎÂťůĐpó˛Ťă{ą00Ú ŚxńŹP¬Ű ¬ęhp Ŕ›8"Y÷[×uĎç~ ­ŁUtÓBl0nN8ř@Óš#ń~P ýňŐŇúĽ` ůŔś˛˘E™›ŃĆń6o:©Űx `â«îÚYXpŽą°ŤĽ° ď€*ĐňĐ˙ C¶*vř€Řş«ćŠ®ŕ€ę:âJ®&@|*ź¬áÖ@0€s˙[° Ë`¬Ś€¦-ű˛p:˙°¬qŐ`°Ýś˛›±+žH«´LQĐôĐřĐ J p)« Nhíđ *yľĐs`#Đ®ţŔŻN׆ 0ţŚ0 ·őđ ±Ň: °ś5XŔЧƕ° ±PNë6`ď0]{ ŕ 0€yđSö@Ođp q#PSał®%¶ S0OI‰°~ Ťp¤Ř•wyÎy¬ŕ c0 Ŕ fs8đ Ň$2şµĐü°Ŕ‹ĐďĐ ŘĐ›€é éĐÉ˙p Ű ,pŘĽp Ř™<°€„ oýą  ż\űŔ ÚNCý0Ě€ ĹjR© ŘpLZ \ ý°®Ŕ §PÍűĽŃKĽË›s0B+x‘€ú€ ßŰ!°ôkżřëŚQ Ęp ×Ŕ…p! Ân*źíűďż• ŘĐ ăĐذ < Ŕ ěŔ#ÄC\ÄGĚúÚ®uü kéÁ7Ś:ź-Z;0ć›ĆĐ í¸0 ř0¬ €řŕ C`C:L°żýűżN° … ”e‚"¬qP=`7á3>ć #˙€ Ńŕt2¸śă3ž»[‰цŔ‹$!oŘu”ěÇ< ‘˘` @8"Ńć‚xy®0 €Ŕ }Łb€xNä,bş“Ŕ±ŔQ€ Ě€)°Ř`Ç€©­·ćűOĚŔDŕBóp±áËŘE ż'`‚™ĐŹbO™Ű’@Đ) Ŕa`ľS  ÷Đp L< d€ş0)ąĽË±0%aËL°‹A»ĂC«5Ś Pü`;ŔÜěÍŔ©P?ü` á˛MÖŚÍ1tBŚihPĚG€(+Đ űđŔŕÄ$mŇđ¬ĐĚ˙Đ­ °Ý ·ŚÍ™˛˘0Kp ĎÍ×`ÇbšŔËđľ€÷°Îă\ÎĂŘÇ]ICŃ›CđŔADG„DC—`!€5€ 0dŰ€~„| é€ ZĐ]— PŹéP ü źGŕBőPF„ç÷qíˇĘŕ»GP ­ŕźT“pxo<J©9Äş`^Ŕ΄ Ľ`]ŕűźp@vŘŠ­úĐúSPp=Ŕw vË M›-€™ŹÚ7â׬›­ ív™„©ŮlŔŮśBŮ–ť¦˘Ăo$^€ Ó˙ŁÉဠPąmÝ€±˙ŔŮ@ÚÍĂ@۶PNśH~*>¦Ü\ÝŇ"ŤÖýŕ —{¸üPÚŘĐ`C•ÍÚ˙ e x®-0.qŰ= Ŕ@pŕ€ů˙ 9´ÄÍ Z€ÚfđúŤ#ÍŤČÖśÍýlbŽ d>ş˝ÝĐÝÓC#ľ€ _°.Ä‚°‡@®ݧŃçáÄ|ÄCÚ’N¤,më¸~ ş.mͰž\0´›Ţé_\×P>ŽËpçyŢÍYd0nąŘ  s€É6`„…~č‰N¸'”JÇPýPě ‡0wO+{RlP v``ŕ,GJŔ¦öŔ×ŘÝÁÔö@$ rč×PžÄó ~‘éU†g]_.ŮGS:Ŕ÷Łx1í^0nđËĚ đfĚśŢuđ‰_Ŕę;"€)˙58gmÇ1'° Ř /Pˇ °`ś-®ű #AŰiÄÓX)NH÷Ü …Ňžáh® QHŔńč· ¨O®5=PŔĽŐ"€xüĐŔĐ˝ÜÜó­CjC ­ °aöh/-LŇVĚ˝Ţßf„?M˙ô€ó#-oÇŮ ý0 í`)ŘĎń0ş™#ŔŔĺ€ âQđň1˙…éÓ­őťí° 6P?_8CĎŮ®Vî@ů9±ŚŞ`)06t€TeUX%!=Űp ×S){_pwpŠÇ‹—0|°YPŠpN˙ľśě“Cú` e0nÉ]‹ŽŠoPń?A0ý Nřńfľú 0Ő{˝FŚÄ€™HŃVŮń…Ĺ"lřč-KÇ(Ç… x°Ůâ@… U ęËĄmÜ·ęuótŤ§löÉ!!ž}f0`ŕ ßľnÝŠ„ €¤>pÚč0‹_š’ütučP`P?Q0L\Dł~ĺŠ8á(lůşŃ" ľ~ČÚńk´aE|5ÂpP _´N·Śvˇ•«W° BĚzV×qŘÚĹâÁ@Ě™5w&lqNř 52DĄLťJÜ@!IÁhCrL`@Đŕ2 -ŕĺn‡W˙ÚÉw@ČŢÉ)D‡¨ĹŤGž\ůrćÍť?‡]útęŐ­_Çž]űvîÝťkŔ°ŔPľ0!8€€&€Ź\°"÷€Ă…GéľŘŔ ˇÁmţüˆĺ*A“tüůí¤VHgü4€đиſq¸ 5„°C ô'SXŘŔ^vű™LT9¨…5:č°·wä``|„îGŞń§›@<aŹvÜH ň‡ FŘ#˙´$Pđ7rP Čb”wü3¦ü@ČmdŕŽ~ÜŔ 釋8+"—tňQE 6!k§<Âń˙Ž%‚‘”Śű }2Á Ă 0ŔˇÂw‚)‚‚±¦*SL1ý©§Ě¦ĐŐn2!ˇK3EÓ+łÜR± ë&ź|Daa8(X‚–tú &^}6„.ä٨%ŢyÇ  qĆâ0čFĚ“J)Ő¬rßÝ‘*!—I©3YS3@ďîĹ7_}÷ĺ·_˙8ŕâ L TŘP &ŕ $H!…ĺR@il  x8â8“Ł ‚Š!€ŕ` BHŔb7¤X’6®C™)đ bDPëaĹX@……Žëp´Ü:ě€UH ›‘Ęře¨8b‰*6!˙…Śp8 č_†°ˇŹ)  â‡n€¬%Đ:…¤U¸8řÎl„?9P Ž~é–@hݶm@é¸-˝ e§=¸Ŕl%î€lł18¸Ť]–îárĽd¸ölâvĚŤ n‰BĆ»ČTg=„@»‡M0Áđă?)/ŻÎ:â‚W|¸Đ*>¸EâŮöX`é§§ľzëŻÇ>űë>–îĄâ2¬Ž¸„5 ±Ă¨ JNfő×ý枀 ĚźÎ}‰âßű¨Ä '\—÷”ł0ůEÄ8tŽýśŔĺ…±đQ‡ =|ŰŔ+(‘ Fĺ˙%|źŁż2ÚCa U¸B¶Đ…-TßwÖ7C Hg1¨y@?~Ĺe(±já s¸Aú0 ÂË dřg‚Kl˘q„¨ĂVŃŠWÄbµ¸Eémč9^äĐřjŘ˝—xŚűbŘÂ2’…P1ˇ—âś2–°Ž\Äcő¸G>ö…g„ű¶H?҇Dd"ąHFú±†c¤ µFV˛8 ÁďćXHL>@“†$ RbIR–Ň”§Ä”ć`‚M˘rŹš‚¬eIXĘň=…¤Ŕ!„ąŇ—żÄŁ 9C‰“92›pŚMP‘3† Ţ5Ťc“˙ ßT&·Śd"Ŕ*7‰OŐ9€¨č€ ýĐĹ CÄ|‰“ ؆3ł/ěăNQ čJĐśnžúŚŠ;á¬ă0Ä"˙řÇ>Ĺę8•hí‰OĽ& ˝Lh?˙i‚.Ó¤'­ž1łCĂbĆP†< Ř2›ŮČříč‡1¬5§wüă#€q6ŕN¤cEÄ1‚? úy%P ĎÎü–V&ÇÖĐ~ 3OôŁDhwĺ l"¬Ö)@$Şr¨0$ířEâôD&"‡«^ĺHĎw\bíČ(wŇ׿¶8c-kG…ňQă¤u­OAi˙d%; ‘) c) X$ :5&'?Ö”5M@C‚ů "`Q`ç˛Ó´ ¨ÖjG̨Äö"ŘŤó2W‡™Gšĺl6Ŕ7Íb -CîvY‰XóĚh&EŹkZ˝Öo3nrĚ9’…ŔÖ¬nŕ(˛:56mc%‹rÔB‡k‚ ş V*a0LÁMŠ0Nd  Aă ž6Üc OÂf@Ź5H¤$ąYNÁľ™Ú‚áŕ_¸™k'Ć4ăR`R€ZĽ,Ow“{H± l o—ĺ^fŔŹ}ři>Ö¬ťyˇ÷]ÝAkpK›p ‰0đn>Ik6~˙NČn0a@­6#‘ pŘĂRĐë10•{0ˇ8ć%q”kÚwó´RÁK¸ěĺĆθĆ&J?Âđ2+1@ČDćťó®ËÜÉöů—Ň“¨ŞÄ䨜˛ěA |Ŕ@ę‡2üDZ ” Uôř‘<ő\Ś)ß AÔăz0‚H´=®zPj"•żH”q xŔ‡®G˘+5Ô;TŁĘfŕhHKú)ň8ˇUGoĂ·¸Ft•Ó€;€Ă‰fš´‘ŽŹĽAbĘ)5LˇpŕÚ(¨mmlw`ąř… d÷itŔG­zÇŠ’(ZŚÂ)đdP‰˙i䶢 L@6đÂóXCś(p\aXîn°ŹŕÁ‡KŽĄ„i"ęíh>ęń‹Î*‡!lŔ0|0Á|ĽŁÔ›”BŐŤ?|· Rz/¶ńD´P{€‚†Ă B*<}Š˙AĘpO<tk|š]€(>řaclÁí(>T®ČÔüć˝|yĚ}Ŕ DŔĂl–HM4ŽL‹ęRŐCß, NÝď~ś¦ëÂ)AÁÇ8ęńŽS áëa» #žm×€XşźEoĘ Ś  S$ř±v±ÂcĂ$®AĎă„ Ěřľ‡˙Q˙z]řÂ0ŕúĹéÇđŠŘˇŕš‰ştaΤOý Dav8Ŕ"ÎÁ„ŚŔő°—ýW˛ŹMdArŢĚísżű˙•ĉX‚ôŃ T@χh¦E› ř?DA¸âK89@‚TĐ0¨: €H8‡™ű€d…0@T@ô`ŕ @r„J™ [Đ)' ăŞIh†8QŚ 8¨„rP¸…?°U8Ţq0‹“ĹČ }3H€<€0ĺř˝ŕ>v #¸B Ř5BřXŔB8Ť¶ë´cŔ±Đ˙d8–F(EfŔ=±)€A¨zČkč‡O02€WđŞK €*؉ßč†_`‡Đič4÷¸'_8–d¸†mp‚/H…\‡p ‚°á€)H…˘‡_pTP–Áđ 54 1$C3T ă°».“źvř Ăh¦CLÄšřu™‚[Č…\0 ł’YÄ»¨ÄBT¦Y»[8–OđQäDO´52gś‡Z8 5–ŃÇFb €+)‡´0?WŘ€ Bi;ř€E¨*H— á ˇ—xA€]h… ؇8ŔQ"ůľ 0<4—şˇď%†äÁ °˙|Xk0h=udGPČ€c(…ŕ™^ †`‘Gz´Çp€cĐQ0†čm  `&˘„ ! I¸„ixX{H„ÝHŽCÜ0ŚmʡIŕ*4ATŁ©X"†Ą}ó‹qŞzÓÁ|ú€.QŘ 80Č8X…K‹cÂP;y89ÜąăĐG‰čÇ$4h=ČÖiąä`€(Ŕ†p(‚3Lť ( ¸}Ŕ¨~°P”08lM¸0č0zŔ‚~(?‘h{`‚8ÉF|PXť&®`„˙ 0{Ň‚Gȇ5(M÷`€čÄO”•Ś!vĐČ€ ŮÁĚ"ŽČśĚĘ”®c\<9‘LfŔ‚Řl&ČÍÝěÍr»Ř$#Aâ@Ćă MŰŚ‘30Ű hÎç Aś9K€Ax " ÇU¤(G‡t¨~„ňcWŘŚ•‡Á<ލMĐ.8mxdŔ†V(ÁŤ“ýÉ ˛đ˙‡!h)/ʉť€˝Q/‹~čČ Ĺ­ĹL hf(ŃtQ5¸†z¨˙Ŕ‡r@$؇4đ™ňIäČ Ž‹ű;‚Ě'˙­EŔ‹ä¸!pPPÂđŇó86°‡4Á<ÁF¸€°;clŽ—`.H…X»ÔAµC•ĘS‹6`"Ş ľ€ś¸‡@x‚'AčĐ}ăUQuQ‰PĚ O*[ ~°…z«{*8/Ŕ†Ľ’p0Í;p”{Ę‚GřR¶Ŕ‡°Ă%°Špú€ë2đ!42HEU"¨š{ę?řŇ<Ŕ†ŤśJ%Ž@˝'°Yĺ¨öyŐXmU¸OŹ“ gřź—ŚJfť¨Úš#‹v8ą|OZ¬­ HÖ1ő(ÔU0°e”Ĺ*ŠŁ @uŘ<*€T‡:Ŕ˙)°N(Ň(‰őڰĐ‚÷3†I›ˇˇę„c¨ kpŃ€< Ő‰: !h‚źA¦M}ŮĄ (űŚ‘sŘ?IÇ eő´Ň b&}RžůŘśň“$­' "(S5`”žŚ˘«u0=MÓŁ,ÁhÓ)CŽţ„h0€HŕÚ<ÝÓ®ôSŚ`âkXă`h ¸`Č4,‚ h®đĂ(ĘÔ%ÜÔă‹8 `¸)”A˘2Y”UYš VuŽlt¤ W™łŐ4Ám`†)Ř^e-ŔV3°p-Đ‚08V%ňÉ-»2đ©2;„˙m¨‡7IkEŽsĆ H„mź ׹ë€Đ}GĎ•0LŽuĺ§~ppÉ]ŕ1Wđ!:„28„vȧ8YW‰p2l >âx 5(Ýpp’nµĆ„…Ťwb؇Ő_>€](I6U@…Q0ˇĽ„†TŽŔ<Ąˇ]YA%YYŚŃŹAČCPŘÇ[Zź @m8„Â8ŢI€Ŕb¸]°…`6ŕ†É’d€Há`ˇ€Płć‘ü„˙*ČĽJA€Ó(BH ÖJw4Ę5ý€±˝[HŇ2ĐL8Ť!Ąvôô/­8G5˛;»eŽáR1‰8O0˙hKQ°9@°ö8%dB$0°3eĘ•˘ŕ ®…TŐÝ%Ęס(†¨őśW Ę[ͧ$݇&8€Ď,Ń\=âxŐ4č°~Ŕ€×±S~¸¶€¸ĐM`śŮ°  €Ň$Á{Ë%ŮÖÓ@:ä(Üö±Ubh‡ayjdŽBdE1\f ľâÉ~Ŕ‚‡ňt‚ HĎő4€]ĐM ȶéľm؆"‹ĐWu=hŢĺR†¬8  ä«0A]će#VX6¸‹(Ţß}v!Łś>X‚,(‡6?f@@$ÔÚ;Ř/x/ľę[ź˙]a…ex.¨|Ń–ý :Ŕ‡S1°Ąí…i‘&ik!€©"‚H‚}ŕ 5čÜB5Ć}Ř„.xżň†vh¦ľ’Đ[(1ŘĄ :h‡Lř‚*his"˙»†^@hâ|bE ŰäŔŚm»\A¨j›&>~҇RČ‚.Ř?‰ [łŇçˇB8€‚‡Ž6¬ŢÁâ /°MCL‚{°‚iܾ丮ĺăâ h‹ĆhŤf”]097¨·äđ‹ ŚÁ¨ {Ҭ‹˛8‹F`¸“pťőK± ‹žč‡o€Îh Čş^|PDeŘĐ“e …fhĄe.i˙ :ĂQ芯‚cî{†mč"ŔlĐlř g2ľkh‡Ü()®»šX\LClŘE/čĹnPŔ’vXD˛*gěć‡n‡«ČCĎhgmäĆ~hŢŃ ŕć‹!D‰ Łl~p,"AžŕmŘ6z„®6BŰC#µL–ňY (NxnÓ†?H čNľ5)iŹ÷ˇ×RµöH¸'4MX†Ů…m` L‹^ e𶡊p˙  7dł 9.¤s•`sąжk›¤X€T†ťW đäČ ŁÔáAňqxňP‹<'_ŃŞ˙唌D9z(…`a€Nrzó8źČ@¨”Ż{‡&Đ•(*H€©‚8Âp çpo®.` aĐ0Ä-á’‰8_$ąyřđ€O *ij{“8™“|ŕ‚ZŰ !µ?PŁFy‰(·¨“w0†Ůľ5˙x•˙1$Q’·r’YŃ“Mî X?¨†u¶CKÇô‚}ô\‰Š `M¸†L •ÚZ‚\Ŕ©Y7! –ů€u)“ÁÓyjWßko‡|č… ĹG‰Á€„ ý@h†Přő`ŕsi“ˇŢřZ-§a—ŢÔzLĽ­3« _˙ĐB± ¸Z먠!ŠX›Éů­ ć.€v„?3ĺ‰Íj ů­oBłůÎ:.Űâłä/)ë€Ŕ§‡ x˝vă4ŕŘz›®»!™8§›W™¸v1‚p~ÍH›ŕ‰Š¨/¨ Ş€›Q# ›sŠy…tÜázš7->ÓŮB3ä¸Ňůš°Áqrăűuü­łqş‰›Ż‡(Ö‚™ÂÁ>3–ߌŕ{›Źšo‹Íkśnšś8Á± °·{µ7ťŹYžÉßÍą™jş.Ďń;“ŢYůk˘¤˛W€Îß™ú=Ë®Żçă9š¤aťtřŰÇž ÉX˙č` —Ňřßç 娪"$őUĐPtŁű1ˇXd~íȱ٤¸- …xłýĺČţű™‚kͨ˘ ş#´§‚ ¬Łń—ŁáO ¬#éR ö7Žńžřç˙‰A˘^ ,HB„H(đB… ‹°ŮâQ°ĂŚ7rěčń#Č"G’,iň$Ę”*MVÁĘU'5ФąňfÁ–/câěI2 łzš†äčsŁ‚&LmĘŃA-~i:`tZpBŚZŘôX´ŠŞTU˝’ÄŞ•+Ů´jײmëö-ܸrçÄpÁ!ÝĽ'/4tëШޅřR ĚđŻá˙ÄŠ3něř1ä€#S®lů2ćĚš7sŮ AŠ“+×´ŮŮci G)€}ú5ěزgÓ–ÝŔŹ©šS×^ČŰg8\÷.nü8ňäĘI ¸4­«ĎÔŞQJ˙Ý“B 2dHaĂtÁ´Kzc I3× @ú@ë$€ A„ž i2řfxŞ `És3U§Z <°]w&¶PőA0ˇ,•Ńă)0ˇ *ßr!Š8"‰ś5WŕQ x`x8U…&鼣̶XĐ#äQM=ÝĽĂX —K:ő(ó •ö^|Kt†¤#Ź?Ý0‚LűiŔŔů„aÚ‰˙Đ‘tŕ@ dAK‘ʸacF ăĎ?˙Č8E€áą´g=đŐ¤“% :(ˇĘ±xhuó% jĐA TŢy°¶ Ą)„Ů@@ *Ä´ Ŕˇ tŔéŕSuďip©ŚŞÂę5i„ŽnŮ@©hČę`˘® @~ÚaDĺ-u ÇÔ“Ď1íě3U€G?ýÜŇ?rÄÔt,ĐÉ;Ý̢mV·ÁŞĐĹd4Ó  4Đ!Lá.č«Í ó©A ¬Ú¨ ŹfD& tČWxbŹ«,zđÄPD‘„=¶x€nuśŚ ˙O<áÄŕ*/Í5S\(Î9ëĽo6§eoÖ3Ž„PA DÖŁ ) 8E*éř“ĎpaN0E>™xB DúCĎ[oŔBÝA  ‘Ë׌l]+M@-ő;§ŔŕÁ~XÓă&,J>M\°eő0˛Á ŹTăĎĐX2ď@ ,ŕB:OĐĂ6ř(aŁtń…€ÂO) ,]µú`q@ü8ĺęĄ-°K?…x೪2 0Č9G”`Ť)*pŔÁ#ÚěŔ»řŕ#ç/*4§Ź>˝‘F ÜŽ?gżę‡6ůčt­S@  ±mí©Qp˙@Ďt›ň˘Q„ŔOf¶đ¨ť1°äÉä_Śa “¸†Ł2L! ŕÇ"elăS€Ă4u aĽ` ŰČ MFĐ…/@ŘŕEđ°ŹMdá ű@DěP@pA_ŕŠ*Plô#ąĐĆ/4 |čéčG# 0}XaU(zw<|€ÚȇB€)Ü"ą!x`€Y”«IťĺŞc”Á4‡‰K˘j€ ZÔađE8Š`˙Ąćy5¸„/䑍#px¨€*\±µă%/‘8‡&đdÂăđ„ (#—€Љ˙}XaD=06kŕp@çRˇ0¨NEÎj@ &q&TňP¨rÁ5ţ`Ą ۰ ÚžrS^ü&8ŘÍ߼d0¦“†† 0ĺhâ`A ¤ŕH FkءÓDČh‚€]´")Ĺ DyŹF`ĺšđ;ž9|ŔČť@+™h°+\XP@ěěáCěĂ ‡hĐ 5ŔřhĐ‚T2 đŔÚ`đŕxüĹ·úÁ‰s‘i°aň¨’¨$`ă{x‡`',2QXbśĚ!…‰Ňě’™d ’pŚŠ  űĂd°Ź8ś˙ 7ŘÇ‚|Z"/ Ŕ mC é˛áÝ5݉•1—׎kA2ę(`a î@iEd;şŃ·Ťłł 'hCK"ĎĆÍ%0 Á·ćq„”ŕŕHG5ř!‰´îă°YHsęŃŽMđ€*¨BŔ!´ńd`_ŃC&ŕNI ýŔ‡?˘ëŹy af!Ŕ Â*ŘŕQ•ô6ŰÎp` h€*,  DĐ’whG;–ˇ&ä@„µŔÇžÚń ľ((ô1ő č<ś@ř¨K´…z0ZLµŞâ€fŕ ~آ «ÉĚJCŻI´Ă˙ňčÇ)ě„p(‚W¸ÇV5@€ŔÄV `‹ç·š€ ö8€ž#Ęh(m*şUş Ě4T–EŘ!ŚĆ"ľ€ç+€D? T“6‚˘ý2‘Óeťś¶Çó`BRŽ:ŕ` öd ×Ń4Ǭ¸|ëNŁA‚5Ś‹Áä.—:čGh ˇ *Ŕ“°«]îŇd0ŕ¬r·ÁŚ)d!ŚhĆ.– x Â!ŔŹ|Č+ĚŔ† ĘpŇý~€ř@5H]?Ź ŘĆBđáa ÍČ&P‚plC‘»®É`p~$ĂN z¬&‹ ˇ"€˙ź- DB°LzëŽk&ś€ČÍ݇xěc ;'ŮíV­¬c© `”˘Řňŕă÷<űg`@̡ ľŔ­Ë 3Ä#›1Ź`Ł0`/QěˇCâ `ŠÔóđ;‘ Ń >$ôËüP ă6cĺ;z’c@)Lq¬j˛‚ŤLĽ€C"ĐA3řŃŘńŁ1č¨éQlěb’ XA6`~€7Ŕ6†ŕžçŘ“ Řčś-rPp ô¸Ѱw0.ĘE0ăv‰Ŕ1\€*Ŕ[›{Ýyž¬€;Ŕ?†%š+b®—+X°:‚» ÝŔ„A˙Usy$PˇqĚWčĽ1‘er PŕŻýI†.TW ¸ ôń< ¬nöµżý­Ţ‡×—č!vxÍ$®üĺ_F5žŐ 3tyŤ86g|XBʡ m„řBćp' [:4ĘX±Ś7pˇĺ"AŹDtÁúhDD耏SĚa vpÂĎÁ‡a=Ń8ŔŔL? ąŕ_Ča*/PŔ-´‹'\p‚růtĂ/xL]޵>pUi Ŕ,ŕC4+C†€×]C;Z%} >,`;€ą„ŔÜŔ5`jŔň8q•˙ËťĐXC0ĐaŇinÂ6lđ „;%C˝ÁťÔŰ)BDÂ5H_/‘!Ž©^uPŔĽřu?h¤Ś,ČCÚUD@3Qi´Dîá­Ŕ uA'ôP““ —±óE˘$6FĂŮLKŚÂ6,Ă× IP@ h‚5ßPEd/X?ĽCnüM0¨€°Ŕ(€Ăç”»‰6üA PŔ B:¤C.`‘«¨ Űô t`€™ŚÂ;D—1Á°€!ě Ó´@†h‚<¬‰!üè@Ţh˘?hC&ÜŤD‘´ĂŇdűŔ đ9°Ŕ°ĄĆňČCśř>Ľ˙Ăçl hÂ5 #MĐ‹ŢÔÔA t >ŽB:đ٬@'hăĂ÷T€-±`M•*đÂŰDsń. ŤmŔ2 „)´+¶@ś@7hŤjřůŚĂPĹI¦ä@xĐŃDCÎČ|‡`Ř#Dű¨F¤€OMĄPâ¤h"O¶@űßt8˘ľM˘U^ĺ\|–Ď\â(<©äG'fdž@@ <šĄ4@RPŠ ,@tH†L ŔgLH¦XŠűôŔ=ÄXDJ¬ÔĺMyH¨@Żfḣ„†v¤€ 4Ŕôe{Ü}LŠ6i€lX!pŔ‚DČ„P˙yŔ% Dh  ”h¦­¦ěĘŁ|†Wr‡wTŮ @%čmŔ„čAČ ŘCp@,Šy8K[f”Gř4€Ń…@4Ţ%1ç_ÎĺH@Đćb˛OCЇkBŰl'N*ČČćPZaAÉ$Á+,>C ¨^o¶#&D]¸ŠAđ'„‚¬Ŕ#č.n„1Ŕ h-üeyDUt@„jÄŚÖ¨oĐBLĺo„Ç:_Ź.č_&¨‚NL‘2 |&˙©’6™Ý'Y,€!ĽC;¤Ă(¨ŕhDGU‚_č >°}‰–|YpÉ)ŕ€?]é†~PQ )[\›1…©ćčś.©ťŢ)žJţč'Yd©Hźj„M<ČZ$ŤBĐg!ţ¸é›"iŽ‚z"j¤ć)ĄVŞĄ^*¦fަn*§vDťvęHDeojgř)¨ž*Ş„©¦Ş§®ęÄą*fŔ*«Î*¦Ę*gřŚT˛§~j«jŻ’jOÄ)u¨' ëńŃ©±–$¦çˇ¨j˛Ň*´Â'ŻľFUbłÚ*˛©łŢLŠ`ëGXk±«°.«J«TŠ)°Fk¦â굦kšţĚ|Ć@¨˙@łT «<ĎnfIqÚ,E¤f DЧ<Šż ś&{ jĎpk¶.$6ëĂRe#Nę¶ÚŚŠRěť«ĆrS®©VRěIJ«»Şk’:Ü2¬t F¤CŚś ô(ĂÖ ÄXĂŘŔB5@?(Ăç ŤŇ0ÍŔĆ8D'$P×]€«7™ëĹz“Ęv,Čz–®šĆ´˛kĆvěÍp­ÓJíł†łZm–®'Ôš¬’zít Ć@čçŘ? ÉáÍ Â@ŚÁ.ńĐ,śŔ8š0Ř@0ĂŔŔĺŕ#y•&ŔÂŘŔĽO©­|zěČ:bŐ6˙,®:–®n­ç†-ć’IéŽÓÇN-Çz™m.Í\-ÚŢ)ćXMO[íjMĚ‘4ĽŔřélA5Ää¸Ŕ1p×" C†ç…€=­S;˝“QmÁ5p řa­Ęş®évn7-¬śZ-čJl®î Šîéňh¸®ďë–¬u]íĂÍéčľďŮĆ®{Şí`ŕ|áP‹ř! ¶ĽÉŰŹą@3&čC"hÁ2|Î ÜB:hB´@\˛–kÁ?„M8Ŕ.đ–ő* 4Y—_¶ĘŻŻľkÄ&ĐŻ®gůŢoč‚®¤şŻé ĘÎoŘĆ/Ć®nüćęçš/ţJ«×^@¬L˙Á ĺ0pĽ±ťŹ1AµŔA.|‚4Đ-¸c,€hB?Ăç¤Ůšµ™=HBL¨cň,Â<™E˘® _,úZlÇ1ʱ÷îpýšŞÄÚ* ď0 ż®ńml·îoS»ę×.+qţzm_4ğʱĐ_e`ü®éů@ĺ:Ă4DŔ,Ă'„<@B€Ŕ1đ Çy\™±L@XDC ä›#ß±ĂF­—ĺpĹRĚ/É肯/30r C,±Š,ůš0‡o!łÔ2ň{Ş-0ׄ´ő4 PĽÁ@ ˇöT$đC!Ŕ$č!řŹěÁ<ü!ü]‚őaźöˇ˙MŚ‚5ŘńěÚ2ü’/¬*,úľ0ÖÚq/'kÂz¬ýćqolęrí2×1iAł×ňć˛l*ÔĂÔBa OĚĆdtŢ= DA>pxŔĽÉäd–xbڤ˘fˇMŔO5S ߲ űóř:´ćN­B#t0·o s칳ٳ 'ôçŢäM#/53C4V’ěĂMóŕ,€s~eLČkŁ€ĺÁ6&Đ+†Ń…äG`‡v°Š2ŕW0uĘNó"G­SłĎő‘ý´Nëp]§¬Mk¬üö°3÷čÓşpT2ô_;őŘ2Tźě±ŞđŁÎ„ Š„ŕ¨ATEŕ€.Ô˙,ł>¶ŞiąŠúu‚i¤fîŘFö[Üu§¶˛ú©/«ö|†Ş­Ro«łÎö kkëŠ*o/6Ş“·BFH[C:ÂlŔo·’v¬÷Šě5] r|B7p_wg`t2ęs[79ź[x÷Z ęoÇ…xc7z§jy§7{·÷©žw{Ă·{Ď7}S˘t×÷řâ·~ďwfLë Ŕđ[ç´só´«Z‡›„MŰ5\ó7Cő—H‚ ő‚›ö>źö}ż6éÂ0€78‡ă ëaÜG Ć\n5tÎ%Aŕ+äŰľ¦€ĂLł¬Xf ÁŠ€Áţ‹ăIG‚ôĺ:A@h  }ře‹CŚÄtˇ˛4˙É; ÷NµëÂu o8“—p G¸ř ¸@Ky‡_y‰x<ÁwxE/٧eőřřCŰÎěŰhŔÍćěÎ.ÎĎmŇŘbÓ ÍŃ&m,í4mj4Ŕ°Ť6śB5€ĂđŠÜŹĐH=UĚ›ŹQ:úŕĎKşŔ=4•“¶B'6tĎnRW:Ş“c9¨/Ç€‚?ĐB@h0*ÜĘíĐíŕ"Ŕ €Ţň­ß®ŕ®árÁĐ. 0n}Đ@®äR®ĺţĄüčä6ŔÁŇÁ·čyqŚŔŔ:ŢňROá´g&@µ_{.e;ąőg¸]ő§ă2R¸.?˙«•‡şĽ#‡żĐŔ#ä8dB0Şîň.üÜI ôü D6ďđďń&Ż ,o4ÄóF/;ąH4Cd=ăBmq/Ă Ľ_•ž`‰ü ĽÉŁü_V:ѵŹlĄËńşcz»ëh·°sçüĽ=m°Ţ Á>”C@.Ä»=1 +0;0K0[° `đkĹk€đ50 S3ŔXÇĽ=X±qĹó´3 @Ô˙XŰs!Ŕ˝ÜÓ}ŹýX÷Ry§ŻjĽëüA·Ř*¶€ďv‘ő… ˝ăĂô4Ă;±Ŕ3DÓ˙ÄÓ›ÇLq_qo={1›€ł™›™q ń¨1 °q­$Á=0AÚĽÔńŔ`čýÜ?qßA €Ű_€NˇpÝ6€Gř3Ű<¤˛pČôĄ;Ő:j§?>öÇ\1ÔC YÄ$ż@% ĘŹźéŔ&wň'‡ň(—ň)ËQÇ%Ô*w‹+ò,ÓrjĽŰ=Ë@ ˇ'%±R/,ŔEl€m‚H8JšŹ‚.ăaĉCh9’dI“%¤T©ňdK—/5x™’äJ›2QÚ<‰fO7iúą2'Ď‘A[Uş”iS§OˇF•:•jU«W±fŐş•˙kWŻ_ÁrEpë”)Ht`ŕJ?ipľ”y3a‚ k+ů‰_ˇ“ôâÂΞ/OĽ4ĂÄ#ĺ<>K˛”SÔ!Ł¬Ů“rˇCËHîII´”xômꢩ_uë!3č§Sgaí¶lÚy…ú\|(ń3ŤĆTjňćNăĎ•7'Îň(u”.Ăf׾ť{wďßÁ‡?^{˘^¸%U=ůLučĐŔŹ6ăć¨Mp‡ŢQňáBö@ĆčÉ„…(A“tüy§›?(ăŕ‚°†\b ‹|ŕđż|šŘŔ;¬©G™7R €;Şń?ĘLĽ#ĄnÜ˙0Aů`”1żÎŚCŞşĺ‚ňşś’Jn("kŇéČéžc’9ć¬[RI#‡$OË-ąěŇË/Á “K8ęhD!„PTJ Th€DŕŔXłÍ7)¨@ÖÄSó8(H^bŕNDŇ“Ď 6T‚ RH!Ą8uS­3 JP!ŕ3 §»RJˇ”\rJěvz5ş*Ł.H h-Ş(W“SŘa‰-ÖŘc‘“JS­L  š•)%µ° -ŃŰĚR©gĄzöVépâőVě:×Ęât.Şe§Şµ)ĺĽĺ©§˘Mw\|“í×ßXŕdá˙ĺę?kŇe´şÍ—Řă V6b|'Řâ‹1ÎXăŤ9&V­UŃĂu_‚BöW©*îXĺ•YnŮĺ—aŽYć™i®Ůć›qÎYçťyîŮçźZ衉.Ú裑NZ饙nÚ駡ŽZę©©®Úę«·ŇUV­‹këŻÁ[ě±c-˛l®&[íµŮn»ă­őE[î“Ý®Űî»ń6ĺłçÖ:ďż\đ°Đ5·Ů&űF<ŘÁoÜńÇE®·JféM\8Č1Ď\s·+wĘň ß\ôŃIoűóąKO]őŐ­î›ďVYŹ]öŮ‹†řô™äĄ]÷Ýy˙rC]Sx „/>-~M╇ŕřä•˙Ç“Z”Gf©áޱĎ^űî6!—Ŕ—çyü9ĺ{ńŃŻÇ|đÇżüóŰ—GýďĂwß”ÎĚ.ôíůďß˙ô.„' €OŘ 8Ŕ&PL਄iÇv˙łŕ1xő¨çYŕBĎôT"vĽ‰/ĐÁv€tá aCΆ5´á qCî‡=ôá¸;’Ś \‰ť$ <`N#ŰŃ8 ) tŞYŠęPŞÉ•„0A #÷“+ˇkJA4ăß6’ pŕ pŹRpp‹zhCŐ ÇŠ”+ž¨*šC .pŞ;€ă>nOŤŞeŕ1-ń˙ž`‚ BçułÚ1™ÉbuQ¨-úń €ń&@hF ±>b;`ŢqÜlB7­Á›ŮÔć6¨ˇĺnŢÔ’€Â´(:­Ű]N“Ít&±(ĐGXŁ‚ ‚LŔ- ˛Yˇ%$ŇyAĐ bś€#‚`áD˛aś3ťÄXĐI0`'<"ŕČD”ąĚž<“ íšAŹ0Ŕ č6ĐMÍ2*™ j€G‘© Ě@Aö±‘€ ö8B š±Qt´6ŔN€†}”Ł&ŕP”*©¸´”§= ‹PSŽŇ @¨7˙Ąŕ‚ftók°ÉI±±Ń tôŁűPĂHK U©˛ÔĄI‰&šQŽF°ŔŤÜU«ĽćSµ®µ+!đŔ Đ‹vü" !0AţlbJ*Ř@&¦g"obÎŚ0¤ťˇĐ/|‡I9ŽŻ#-'!‡á·řĹ1žqŤo|s€Ä9| ^ŽŹś§ĐÁ>Ň@r•«­˛¶ęÚ“¨dÉ˝Ą•)8/‘MtŻśçP«XâĘ+9#=ĄČ‚đE«wŢsĄŤâOřĎA<­0ăQK·zÓšNą§ÓĽaŔ+lÁ«ŹiQŻdĐ,F—ď´x€ÇDNvąűĚ˙· O°Â×^=`MMúÜo3µkírË{S*0Z ‚Ö üăwv^Âo˝zfOIâé° 5Cžó‘şşţśBś*PŞm:źúÚ™WWˇźąŢ›"€WhHőµÚáĘĄ/ęq‡lân{áĎŽ7¸‡†źüě_ůÍwţóˇ}éOźúť_ă!`1ľVźű‚SŹ)ő`ćwźül3Ŕ,J!öňŻßn§y{™Ř˙/QŢ·ZůŹ>°fůď<ô'ŞW.Ŕ2’á@›řďżĂ˙ţŻ+.Ŕľň`´ďďpłF5l+ÔĂ®!ü(°)Č/P+0ŕëÂÎMĐ+@đó˙Ľ‚¤ćáNđ»Â9dN8,ď+ŕřˇ®$yp8~ĹW¤e\€0żb>€Dv°™pâĚe÷ŔD=Č€¨ šąÎgÎÄđç 0 }\đ ÷oÍ0 aF Ő° [† Ý09] źB=ĄS–(ě„OöPŐŤßPˇŃˇć@ü®b ˇňcü1ŕ‘eL*řî´^ Đ¨Spŕ–a†Ŕ #±©Ç™˘.„Ŕa¦˘{FhŔźHŃe•˘Č´ŕ¸ Ľ€Ŕࣂ-î €?€2pńŕĘPg&(˙* |ál Ŕ€Áˇâüb!ŕµĹźń!ö–âNŕL(` ŢţN`” …. ŕ`[ĐńťN•bĐ0€ĐŁP’)\Ŕ‹îŞ„ ŔŐ ëĎ)Ţ-"-˛§ń"523r#=r;:ň#Eň+xŃ)~zЇy˘GŢh$-2$—˘{č'~Ţ'~ƧâŁ]Ň ˛ Č hj'Ť˛*6(…HČ„l""Žň)ďP)u(F¨%ˇň*Ń ¦R8.8@'±'R=NcÜ:ѡl=®/ű¶o,Ͱ©ŞŕáVĄ˙9ŕaŔ %ľ/Ą‘.Óp `ě! 0% ż<POň¨łnn˛1%Î/ýS y‘î 482ůČŹ‰2IF ‰Z*€~‘ ¶ĎýŽţ>ó yQ¸Qýh+7vă–bk—PĎY`6Aěî/˙n7[®)Šó8§ÇśĐIťŘé!Ţ âÉ6ŕ4¤đđ1—ł-Ďvr`zPJĄ¨ ¤śJ/˛j%öbĂO.ŕ#p<É‹s1Ôsy@=ÚÓŞR‚¤Lj%Ŕ€Á¸%7p.ő“,Q7t%K!«#$â°ô J!=‰ěx3B_P˙€ 4Ăgi5l©7„SěÔĄĚ€XÔ÷\ĐDypoŞq°±ˇ¶ëDRdEZD5cdF¨Ĺ2 ˛ZpPuôDѰ&` ÚŃľ4…S&ł2E%%4D©eIÔbĆQ¬*6ńŻń ž~Ŕ^ŢaGJ"žš'Ă;g‹¬§\Ř›Ř3>±'$%OäG>¨Kž‚ÎćÓS~¸QÝ;|ŢÉýĺ~ĺA˛9 ˝ćmŢÄÝĂăß{žÁx>LŠ~č‘>é•~é™>ÜţčI˛^„ľé3ëçÁ„릞ę/çÉëé]ëŐ‹ë˝=_˛ěÁ\ěĹĂëˇŢě«í^ężžíËęçî×^î˙׊î˝Díď·ţéűí>đýţě˙ężđOLﻄďßçÝ<˙ń÷űđëžěăžňi<ň9óď^óźéó·DôAżôM˙ôQßô @ěĂKVżő_˙*ŔŞĐ)JŔć>ŃcbŔţpLSꆠ-taöąäřű!ů;*\Ŕ8¶)@p¦ˇ‚éb×p­řY§‹ľ*@ĺ6Ą`‹ěP° ŕ´üĎߊ,‰ Ȥ§ľ6 ‰ä–ÝŠR ýB–:Đ „$¤Hq0!D0‘ ŽknDPѡC…>†€KÓx`8˙ŔĂV®NÂĽ‰“B >ä°AAź)2ŞPq°B… "(U0ńčÁ‘M†y”Ă…‰!L\Ŕ 6¬Ř±dËš=‹6­ÚµlŰş} 7®ÜątëÚ˝‹7ŻŢ˝|Éz€óÄÄKł ü,óWO™bXű‡O #VĚ8F7T,B”¸e bŘ #ڎšüÁZ&…µĄ«×íMŠĆŹ#OŽčÇ5lŮ?ŞćŻź2%& k‡Ľľ_:”ȕν?BPišŹ›<¨Şi˝l…)©˘çC”‡;ŐĎ)jČX ëNĐ+ăáÄ#kţŢŤ+’ŇsŃMW] Ö˘<˘Mô˙a„NHa…^a†nČaZ€â-eđĐ`a `É9jdŃI?a„ŕAO¸Ţu)®Řb„ C3ڤ J4; V#Đ‚  °Ë&< xŽH¤˘Ä8cŤ@)%•Vr3pń,ŕAF4CAě@#tńx`ĂÖa×ŇMF~gÓXJŤ1LÇ)€‡>›dˇ‰‹°qŽ Đ0A÷¤Á¨=„§čEq†e˙d/I.yŚ“Ď°Â=‰\Ŕ#4{K/k.R )¤D ZąĐŚ9RĺaÂ`ˇŘŇËm0S„ ĚjI5VcmĂL‚M)>üŚ“‘H*9@¸O˛ÄĂŞŃ(˛ăÖv-7ݬp‹?š„Ń DŔŻ °˘Í;Č`ÓĘá 7ĚîX đśČŽ7ŐĐ/ ^Ců16{Ś˙ĎôpK:¨hŃBl°xăŹG>A ŕ(BŔűHAŇÂO|ńĆŹüZô€G3ĺ4‚ _M ÷×YŰílő\ťu¦µ`sÎdéŠ*·-.Üś0÷IŘ·ŰŇúí_µ€‘CÜA t~PwťS‡ Á‘»Nv×?‡*, ϡ¤Í]Ăp_‹Ač‡W‚Ȇ”¦# Â?CPĎ˙8@ÜU@Ń0@$´“ĽĘp†4¬ˇ %t€+ن:S𨗍4€¸P–ľ<0 XŔŔůZI‡XÄÎĆŔÂ2aůډJLÜF¬¸}`~ŕ⛨ľ1˙*â$x@J@pŚb`|xAľÖ· Aäkµ( P iŘ1N×$hÁ&’mŮŔ `ФŕeůŇǰ€"Žŕ·E0¨P PŘ‚  @ľ.gIŕQŹ$ŕŁ9Wm`"7¬Ą-o‰Ë\Ę·8…T€±Rωč$ú„@At¸"Üđ¬„ĆDćIňp {iá°#Ç-`Ă_¸3Ň?5ž]Í|f4Ă·“Řa_x‚š‰Ă1ÉzĂÖÇŠeĽ 58Řᵏ@Ěá Ť6ń†9l ,Ř€8 ő….H”QŽ‚”‹F°ŇýA˙‹Ŕ!xP=â 7¸Ă>1¸Âu ¨AŻŠm€ ´ÔĄO Ô  ŐBËü¦XVBŹyÔ€ 0P‚NĽă¦€R•ĘÔ4` ů¨uЉy azaY€€óŽŘ¤`©F ęÓŤLÜŞRĄ* ŘęV¸ĘŐ{@†?¤“‰Î¤]8L>L1™¨ľă5Úřh(ň¶:O-A*úc §r+ ĽŕUSĐť;X6‹QжQ„D!\°ÁöKT*pęŃXŃ üĐEs† Üŕ w¸Ä ‹‚Ô˛a€(7‘R ‚ä.×!)@<‘4@*b˙é@)'" <“GŮ@’şF©Řy%#ˇTE'1HvňŹśÄąĚ ßđ8dщâŠ]@(Dů p@1$é/©{Ú# F-®‡? âç2ŚßD‰qBÖ3đ ÂŕÔŔw|0‡Ô i€g8Ɔn‡ë ‡th‡x¨‡H‰•bŕ Ŕ7]' F ľ0c Ě`9& ŕ }žŠ˘HŠ6ž˙*px ľAJ0zPSŔkĐB“łŠ`ő\@řô$@Ź"ŚBřeü@ ‰ň_P ő€c0×'t '0M Ŕ z`a2&er&ŔżŚĂŘš C`đ šx}ŮgŐ6Z ¤đ†shxB ~Oi0 čđ‡îŔńŔěPźŕ2b Éŕ )9‘–Č’-©K¨‰\Gqä3 €î8KZHŞH“6‰“<°2-CIqŇ@7°k;r€Ŕ]×îŁ@‰Śął v/+c> ˙1›-÷Đ0 ‚”/ůŇŰŔJSäA[P 1cçŮd‹€ Mp/ L@Mů”ĎÓ[p ­lÂQ^pR`eˇj?@ ëŕ ? ŕ\ €¦cđR ©ě ‘ÉÔ@ G Zö‘9™•y™™Il.)›łiK‰›ř<žX­ÔG’s@I1»éJ(Ĺ:®;0Gy €ŹéP ü RY9¤Š»ŐřđW%V50A9 “÷e…™O7±[ű ×Çöpüš ‰ Ë@|“8QĐ)ťü áM‚©˙Ň“śI`L 5h‘Bđ r-… f*öšˇś šę‘ŢPGš"Pv8¦:jˇ+I›-ę˘Ä“¸Ů‰ÁyÉť‡Ł›5Ú›@!4BăPB@Fą7Q©e€Z0ˇ€=8•7ŚÚY4 4잆3žb ć)péąžÔžLŕÇąđ Ň@„ős?Äq¤ŕP80©t0áł´°DÖˇśżpi‘0@ ?ܡplcqˇ « …ŕ č@š RŔ‘ú*P˘`Q¨‡š¨°¨Ťú˘§ŠŞÂćđ×9˙6úG‘ŔŞhIŁ±Ú›ĄtJ2€§!07 z6I)Ŕ$#7·LHä¦sHfI€Űp’40ˇ1ˇ žđ<¬6–ł / -n––k Ňŕé Ół`ź°LnôFqİ Ć:FŐ ÖŃ’€/piŔ / G ß0~"0a/  0/ŔˇŮ‘–ĘwÖş€±)±«° ë°”±©Ş˛+«+iX Yŕ;Żz«˛lđRţ«ĂI*ĹR.•Ŕ2™ ˇMp óŔKĺ@7=čP%Qׇ µPPt€§0˙c`N@ő˛] aůepý ‰R˙ŽÎDŽć”‘Ŕ…“ „Ŕ!0OőtOů´H«´L»#Ç2 Ö`.C řđŻŤŮiŽ DĎđ îđ Ť+n>°°?P ¤ů~É ű> j„·h+ą”ką«ą, »±Ű!@‘žŐ s /®Ŕ ÔöȰÖYš„¦Ŕ »Ľë»*0°őWł´/c~EUošŔ°ńéU—őYY’…XŢ•Ń \5|ĺW8Cx/c„xX!Ńę pô0 :\}őWôX!ĽŃ‘˙VŮ»LPGç90Á†nP€7Áúźwp†‡ö}đ Ô@ ›Ŕ`` ԀŠk,Šś|Á,»/ Ă’8  yP^ `ŁČynćłÓÂĂ9paq”7 ĆŁ–˘ AöX= `ô߸D1; |Ä'_±$`F|7DĂ'/ňUVLĐzÔ¦ c87ÁŰE}lCpˇ"`Žđź*ŔĎĐ//đ”Ŕ Ĺp“hvzś|ěǀÕlÉzÂgAÉpşťF+,JDz¤Ä  S8űT)Á´ÖÉA˙Řć^[gfđ)ŕĹP"{h‰*3«,­|ÉÁ,̲«żÖ˘0)‹!1°÷Ę}ŕůÂä0/ŔRĐČoÁ̉8ĚÝěÍlńá,Î✨Ťg6ÁnÁ*¦íÜÎ)áÎCńTĘüëüÍů¬Ďe1Îý\ÎúĚľ8áÎýÎ ű›Ě˝Ď ťĎý<Î˙ĚĐbAĐmŃŤŃgáĐäśŃa1ŃÝŃ!-Ňh±Ńá Ńh1Ń’Ňo1ĐfńŃđŃ041íÎ#mÓ7Ť%ý'}+­!>Ý M+Ó3MÓ2ŤÓI=Ň:ÍÓqÔ-ŤÔO]Ô`!ŐR ÓNý˙Ň0]Ő[-ÔZÝŇeÁŐBmŐ^ÖS­ÔgŤŃL-Ń\ŤŐa˝ÖeťŐS ×r]Ó0Ôo ×d=×yŤÖ}ÍĐjíŃl­×UŤ×{ÝÎmmŘ5MÓd}w-ЉMŘmŘ~MŮú ŘT-Ř|ŤŮŐś-ÖP]×}ŘcáŮ™ťŘ•ŤÚÝĚÔHýŘ[-ÚcŘśýÚcýŐGŤŘŤÝŐ±Ú’]Ú§ťÚżmÉ«­Ű´-Ř…=ŮĽmŰŚŤÜť=ÚŻMÚ@ÝŰŃ ÜÓ Ă—ÝÚŃíŘËŤÝ/]ÖΝܸ˝Ý¦]ÜÔMŢ*kÝŕŢ»m×éŮn=ŘČmÜě×î]Ţő}Şç˝Ţ>˝×zýÜn]ÚÚýŮ)ť`ŐńÝŰłÍÜ®mß Ţ˘řmŕč˝ßţÔŢÝîM×_ áEMáó­Řß­ŕÎ’ ÎßT}ݬíÔv­QŘŤíŃm˝Ţ´ŇÜ->ÔA-ŕîá5~€ žŰýýâ.ÉÝ4nă?>t!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z q5HÁ "¨paB‡.@‚ x€óĆ>€ňG«Ś)>HЀƣ|ŕ2Q)°â4űĘ1Áˇf<ÍĘ5baăÂ+ĆęűĂ‚D‡„nť˘"…Ó!8|ĚȡçD!!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,zś(Âżb HĐ`„ |QâDŠ#JtQ#CŽ14há„ )L€|(ŇĎ2ő”ąQ‰1ŁKçÔdéÔ/Ś„š˙0¸4í˝a*ÔŇ4.´a6Ä_MˇDˇJeV¤ÝŐˇŮ^4`€K)ÓˇöuÔ/ÎĎŻ—čÍ«PŠ•‡ !ABŠ»głjÄ«pčÓÁL!ů ,zŁ5HđźÁ!\¨ˇC… :D1bÉ!Đaʇ1fHŕJ?]CŠ„Pˇ‚XZhč #ËÖŕććE›!<ôxâĘU?'B`bĂUF‘Šüˇ §PŹÖT ŕęÓ¨[˛ ÁÁĂ$X0L 1‰8Đą†ČͶ+b(ŃéÝ;S0ÚlĐ„*ë]¨ŘbŰ€!ů ,#‹!ů ,#‹!ů ,$zś5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ14há„ )L€|(ŇĎ2ő”ąQ‰1ŁKçÔdéÔ/Ś„š˙0¸4í˝a*ÔŇ4.´a6Ä_MˇDˇJeV¤ÝŐˇŮ^4`€K)ÓˇöuÔ/ÎĎŻ—čÍ«PŠ•‡ !ABŠ»głjÄ«pčÓÁL!ů ,,z­5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ T¨ A‰ ¨PRdŚn¨X„(qËVŠ–BčhĆ(…¨h;L´ô"™|§ôaé@˘e&LÂVʆ‹!€ÚٶsG>r„ ó(cX–-˛Ń˘eyŽQIˇĺÚ-,ÉW'„†ťć i9ˇ:$h°˛ĄŔ ŻŠÍęëD!ů ,#‹!ů ,6z®5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô8!†µřpu‘P俎'L .,Cş„ĐÁŁ#Xą ‘ÓĺKź6xP5´čN¤F0%ÚR$L¤6­şńęìSťZE v«N«!|rđ0‰ $H…€Áçy°z3GîÎ >`(‘Ęß;S)ć"5Ř *? R1ĺŚs!ů ,Hz˙5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ĽpˇĆ®R< ‚©É*Ř€ůP™‘ĺ? @Ŕ1$† @€ A„ 6!”°fPXŽ ?ŞćŻź2%HYBđ„§i)5ĚĂě—/pXHJR@%°/x8T‹J H„H*Đ-ܸ+nůÓ¦‰¬"-ú +0Á-šúĂšôg€Hć^ ÁĂxAkĹŻ†lö%󦳝=_žxi†©´Vbhň—Ď‹ {ůóG/‹˝·5Pđ @6(Đ áyä‰= €W˘iŹ Cj !ů ,#‹!ů ,Yz¤hHp „&Ä ° Á 2tř0˘Ä†!Zü7QĂ#Trܰ٠kzl`Đ Ń"Ă p\s#B„Š–.@Ö®g=|żp^ôÄH3B`‚ě@’# \4Ó“Dˇ JŐĂc$ÉŽ ¦veŮt"†°|^ µdĂ»Ěéó¦-G44č˛Ě_>Svć­ĐŕÁš1:LLŃëF !ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,$Ś˙H° Á*<¨ˇˇ.ŕPbĹ'¬‘âCŤ CŠI˛¤É“(SŞ\ɲĄË—0cĘśIł¦Í›8sÚäŃáDž=fÔČSčGťH“*]Ę´©Ó§PŁJťJőĺĹŁNŻöô©đŞW®?Ą@ Uc’5‹6­Ű·păĘťK·nZŽX›z5:”á×˝DµV¤0vO6Ś8±ăÇ#KžL'^—ECţŐjđë… 5v•âÁąëĹ Č`›ĆcŔ,~iĎ @¦ź.˛Snŕŕ…™-m$`@„H]ĂÎ=µjÖ \‘÷Ż_8*6ł”NÝ:víiŰ˙ĆŤpwďßÁM:_ÍŁ˛ű÷đăËśYĄX›ďô|ˇ 6`>”†WŚŕ 6„´öZl5 ŕI?…pŔÜI\ 6đqÁ@ ÜĎ/h§x`‚ŃÍ0 -ýđťK¨Č˘‹6ä „–g!†ęf ‚íÍ'äDé– ¤B( € &PÁ B Ä@*ĐP\ްNB *(TANJ ’ 5Đ©B \Đ€n*ąŐE $C䀟íigšÚm#?ű(a‚ký„Ńg ÉI§*tB ¸Ie—ÇiZĺ•Çp34sŹQ˙ĐŔ|ž™Âež©‚śTJ€™J& ʬa( 0@ř˛(Ą–ľ‰é@ŹFjxuĐ2„s]ŤŕÚŔĄÉJ«¶šz©¶Üzűâ@«¶úęäJjÂk,ZôÚ‹j h6Ŕ€@‚@ŐJ*,šÔ«Ŕť¦Z‰ĄşŇ‚)q‹ĐŻ‹éńÇ Ă×E:n¨Ŕ{X#éhä=Śx%˛]äăơćÓÄ'C Ĺ@í´>`ëěZÝwç-ĐŰqG‰Đtű­@úaM=ÝüaZ–c®9 d±LŇÚ0r-ńĆż+Đg’Xŕ!ŐdŢ XnŃú뱇;ůćŁBíĐÓÄYŕÓŤĽ.r3D;~ˇ‚ ŚŔí FŔ7Ć9îS†ĐFćŔ4ŔőQpµ9\Ŕsţ8˛šđ„qqŔ.b‘ |¸Aěđp ÍŔ„BbAŔ đÄ4˙<ŘOř`  Ś  S$ř±† tͰ…¦0' l°G"–ŕ}4â$řŠ‚!’Fd…/Ć0P0Ă 9č@~đ mRű¨E;¨8,˘ďč6Ú±‰¨ĆéčG2®± %°ŕŘČ/®Ťßhé°Ŕ!r°&˙ô#ąĐĆ/R €AŕcĽĐF>śĆ~ŚŘ@š=¤…T€÷`rĐËZôc®ŕĹ)ŠHARKÉéc!.@´lM {ŕ@$đˇdD˛!Ř€)Q©Ę3ʸĹ5ř1Í\Ó]ŕúd(G9ŔÝG;°±˙ ôň—ÁDN=ď™Ď}ö3qípE nÁ5ȆŹ~Ä€xô¨rěŕ}™4F3ÚÁBĐmÎT€_ Á­šZůĘXÎrf(Ś©LgZ“DâG¸¦>âPŔ0Aa…ŚŃŔ 4ÔyHá3lIČg0   ŕĽb3ř064’ŔÇ*ĐQiôĘgP Ö4Ä€®…0ŕf`"HŞša& Z ?bÁ€(`XHÁ°ˇRŐháůX&żđ„t0 D¨Á5ćqÄá()OP ld˘tşSű! < )¨e09M˙Ü h@®PČ*dŔ‡. p%V°±™@öÚ×j„{đ\î:± €*đĂ;`AiO›ZsV@@řa‹ßa“ ź m í‰ 7 Ś=‚śVĐŚ}mď{ăK€°˘ĚhG+(7ćú#ž(F°„k\6ł›e´0Á~ŕľŔ‡l ąß¬¶µŻťMGLâł„H "áÁôţ±?ć1\ !Ŕ@ °ˇ‡ŘaE0AOo‘ThˇcKHJđp¤ŁüÄq"ĐŚUDłő¨GŚńQŽ"`é/lu+GŔ W„€¨E+đš×5áá˙?<ĐŁrÔF~čÂ^ŕ‡3Đ Ö}€A5]đĂ>ŇlDőŔŘ^×&‘Ľl#Ŕ ˘‹śmݡvËPDrPg9¨& Ź4:@ĺ`uÖ 3çTcÉÍpĆ–A:đÎomČ ŘȆ¬l@ ”Q’Đ ×ýĂÎ A­˝wGŰ‚můŐ¨Ľ+tĄn1~Ů+mj‹á3Ř>˘qŇĘUŕÍŔ3ńĐŹPx6đÂíäAťčnA©Ţ€Ţl ř"n°.ÝŽLoÚą&N¸ÂŽ^$ăe!ĐŹ:oBšr>cľđˇÉdTm˙HHRŽ:ŕ` ö…®Č >đ ©A3ęŕ„‹'&ŔůWÂüĆ8š9i^sgRöÚ\Îřfť ŕ…~8ă‡*äÇź±ŃDěc o>ô?˘Q-]-@λĺ -IGw ÉÂ!ŔŹ|ČŚűđ43´ h3`Ű®şŻ@RŤVGÝΞjú=źŢÄâÁó3¸ÖőPŕ l|a oHŽAláqîń˛vmĺ—«›÷óßł-P§ç ő`ŔhšŃ".€KńŘ`|E«p sř ŢřXFŮĎŢ‚ 6ş@€ mĚÉ€ &wşŰť„ Ďľöľ*2Łý°ý˙r¤@öPBČq Ŕ†jŘÁ±×€¬HnŮCʲČDóFC3Ge6't°yźđg|q6e/`F‡%IÇfR:Ŕ÷ ) a|U§ `XĚŕŕŤ•{c…ö\ŔIs T2/';¦RÚ2'° ¦ő‹’+ŕp†`gołj€Ź–łyý€n"7\˝€Ĺ· TgÚR)vA¶!É b%V4=€K\ - {ĹMpÖ…];°]:řhŇ*ö0 `]şîT†Řp†- ź1÷•_îeŚu_JČ„`÷˙t‰H+ ý0 í`G lÂS żTř€ ,č‚#’jŕŇŰŔNlĂR„—Űw‹¸ř1dSWř  60t€§0c`N <8’¸ ×0 /'{_pw°‰"!—0|°YPŠ - Ŕ B€`¤¶PcŔ Xx—cđtjF[QТ 7xxş°pH‰dP< Ňöoö,°ŘP7×Ă]őfž$%ŕÜ”Jă0p5Ýŕ ëÄ x'gQDűŕwDŻÔ Ýŕe(öbŕ  ô@©(uş…ű˙ŘŹ&ŕ…€EýĐeÂăBż”Ý@C MřĐČ0HŤ@/© P ăÖ u“îôCY”C ť$ů•ă°H±Ŕ$¤’űŔ’;Ŕ^bI– _{N[˛d[¶–© !ł9«Ą%mk+S ;ęmű¶ř8s›»Ż&h‹qzy´wËcyk¶›¸Š;}±CŤ«7ąqź"€“¶U±!Çą Aą’»ą‹[ş¦{ş+ąô·'ˇş¨űş°»˛ËpѲB«ł;źA%P2¶±»Đ»ď±g‘»Ć{ĽIźsđ<Č ŕS€Ś§)$ϽɋqÍ»˝r! öŢ˙›¶¬kv ýD$rĚ0"%°:¨Ő:©Ě*(f]"‹©#qF@9 ⡠'Ŕm‡Ëë-^°ź 7$T®% q­wO҆ü8ĎŐŘ6ö•ą$ńţáÁ‚שÁ# ěŔĚ˝.Ľá‹_‘Wy!ľăŰ ć{Ŕ•±7ÖĆŚ `ďđĚ0€úÖ é05Čaţ°hň”1žŞ~`”ľ;.` 6¶7RX;&$0 ?Ů…“t,‚k‹_ś#K{3p ŁĐÜź1Çu|Ç1Ć ’ÂQf ”Lű†lkŇ&Ň˙ňH‚.h˘Ťbűšs˘¨ík›&fÂ)X°ąÂ)Ż:%§ňeĘ"Ŕ‡&kâ&Ę×Čş"Ő*Ň’)“,•ś(ÄJ«°zĚĐO™ «ŹÜ»±żyb&@çËŚ˘­kŇŻ!b*vâ;A/tp €Ŕ…P ćSpý AW<Ú Xx,đ Ŕ÷°O0ô°ÇŽ©d“¬ÉřŇ8p _`%ťÂńâ*R_ažNd˘°Jň±ľ,)pő˘ĐçG-3)’’'°*1ź2' kr‚.Ł"3,’P’'ŇŘđ #¸ś‚*ßĂ*˙ S‡E¦6Ó)!(÷Ś* ’ɨrÓg 37•ňĚÉBŇ&tËŃzČ/l4HŁ4LĂČBăp33s(`}ÓĘ QQC- 5˙i8Ó2Ś3X 0š0#3%«d4Ęp `6[ :7ÓúvŐPĘ0­7bíd-)Ďk5wł5Ž˝ ţ NĽś pŕ6n𪊓4Ýđ"v^c &ĂŹ  EŔťýŮ]­- Ôt†Ă6O5ď05ĺ1´0 rÁ Dm• P˘T&đ6Ľ`ó°hA ű+ i_7ĎőŚh˙ť9j-3úµÉĂ9“–ď3X’<ËÓ<M:¦:в}C›G<˙ÁĐKo} hÖ}óĘ`šSS8Ś0;`üpѰţ°O·cŢJŔ–í}8Ť>“ł€—Ó±7}3kýÎś>?‘É8€ŔČ1âÚF˙=7ř0 ~ Cá˙ á’‚ś)AXSA ,Ő˛ëDP$ETGs4“p ¬~yŔ ŔJ„V›1]đPđf6Ç7 ˘Ecđkbő€7”CoÄÁ¨ć€8tW¸ vp‹pL0döäQÎU&ą Y  •‚%U˙~ĺYţEa4FeÔP‚°ćcđfý”%Á8é0p 6'–pr€© ±gµ6u>ŕBɰ` éśîé<Dé6yĺ Ł†EZÄE^T0 Íć‡'DÔV>P ĺŔ&p đ6  ‡~Dt×MB(¦a`& Ý}\îĺ`ŔA`×@`;Đ·Á $JëuODąOźľMÝôMŕ!·”Ké°KCUô ÖĐźpŇQÓ„jUđb‰Ô ż`@o¦Ň ď`šŹI“´ Nđ© đÔp9ĄEżŕ ¨Ąň^lą$î>OĄš٦%˙‰HŠÄH< Ź ˙ m:· ą°H(1_OM»ĂDFđĐŰń”ćQřRäPGŽäŻ;UUuUMIf®P!Î. f)·µ@燫ć˛ńwа ­Ĺłq€öxTCĺ{uým‹çf±÷Ç>v€‹` xdt^ ş¶yĄđ˘Ú Ä€doö `%VdeV'ĐŰ@)@öř÷‚Đ$ŕěşĆŤĐ(‰÷Ť3ó~vMt?xú©Ďř>ŕ µ~U’"XÄUPŐ?%â @•ă`ÄlmĹĐá XâÇ9ËŔěgíR˙€í70oäÝŕ*¶Ä-o÷XíÍĐcg†Ţ‘^˘epł< × Ôő†ŕ!ł… 1EÓ=03šŃòżrJL Ł™=&…O‘‡ "DT Ł Ř0A›–GůÖÂĆĹáÂQ±ŃáBdÚé‘!ð°ąÉ°›-0‚-\‘N!^Ĺ Bł{L BĹĆ KŠ-Řć1Á¨‘ŁG(đ°Ł 6`MµrőšU"E‹jő ŁŔż};6Đ´‰Óé€Y€ âËC¬•-_ĆśYófÎť=ZôhŇĄMźNPâ¸tŐřI1‚•«!˙ŕ™w$óŠ[ţ4…iA„âʼnoŕ€ŕ¶wȰµâ1áĆ>9, €_?ÝýÍŃ8Äěýđđ‘úq aäěÚ·s×h¦‡GŰ6ĚŠŘŕ-ťß‚3ˇ†kę©§;|ĘA‰}ŇXo€c6±«˛ěöYâذç,™&ş˘Q¤Ę,› p!ŕŠ}¤(ŔÁ ذC<©kĘiä‚¶"„άcˇ‹TţYڍ|ü©ç”!6Ř  P<€fô(Ąŕ;$î ä‰'f$·ËSŽ9ç Č…ü*Ěě‚Űř±Ĺ&( ýTš&/°ÉĆP˙›)îŕG•˛xäÁ*°qňźśT† *Ŕ.» ęĘ*8đ€ŚtT„RP© ?Ě3r@†ÄrŔG•ę >Ťú›s˝3OQ1ŰŞ«.˝ŕÇHpŕ} ÂKÔ &0˘|Úů§ťaďRöŞM;­k±YřICÇDÁ°[o˛"ĆĐÝ]L<-_}÷ĺ·_˙8ଠHś:pÂNćŁÍ66ÎĘ,´Đ¤c2θ <čä:‚Âč:ëČC˘ź:h"šČáĆSe–i˘ śŠ ~ÎŮÁ„ dkxĂł Ôď‚ úűObŠ-vż:ś‚˙"¸P y'¤«¬»äĐĂKBä“ÄÚ.› A˘1 ’i|řšĆ°Ŕ1ş%±fřŕáDÍ”^  ®fÉJŚÁB ZHah‘şĂ¦ťR„¤ńË0 ¸Aź 1 € xtłlăŽ?N@óXĚ0j´=ű -TÇm™bŹFÉ`F‹WÍś0´Đ"Ś0XĐ´Oľ;Ŕő{¤ő ámęéÇ V±é ;Ő#’o…Hé]}ŕu`y8"Öĺp}łdó Ŕ‹~ś!váG P™°V A”áŢâE懕 (Ď.óRíÂÁÔŠ|W @†~ÜË˙oaE8B–_ŘE)^0)bhŁ… Hp€K}— Á€€ŕĐÉXqř´ A€~YÉŞsť Ä`‡PA  ‡'c@Á‡Ŕ ř.q]Řâ/Śá kčC… X€Y ě°y?äA?ńë±‰Ű R ! ©",â A! `l"2Ű+ź2h´rb"°H0É+üŹŇ·ľI˛2ČÁ rOLzŰɰ#{Čá A¸Á lŘ%ˉé3ÚĐçĐv"‰Bj^3ř }—QZ Ě@üĘO‚˙đłŹ&  qŁÖŕ”;ĄÁ ý083Fü¸GL 3hK$@G¨D `€0©‹J–y ÄjV: DŔ¸\ Š-€X;l†(šÓ>°f`‚ric?°ŃD…NČ@YÎb€]hČ碰ŤmA“úVHG*/ľ3žóÄ`cÂP€o–CžŤÉBy®4ÔË&„jTĄ:UŞöË‘óŕòPʆĂ ®$Ŕ{řÂĽĐ Ź‘8|bĹ2ŢŔ…ě:Ň1Ůu&0:ŕăsśPĹ ^«Ż ě` ŕzˇIŘ˙bĂŠŻ†u¬ŻÄ>6Ń…Š…ˇ6gMëZ=ş!}آ c„&0:´#_¨B3 ‰"µ]¬bĺ›#ÉÖÂłaF Ř8”t-AŘÖ˛|«ź>J‘….čŁŃ[L™•Ť!PPë5($€JĽÍk^ A„{X2^zŃ妳° E'ë\ëj:šCcxž yN1"Ö –.xĐží ŁühDç¨ăĚŰ<Ŕý‡6úÁĘ`ý €Z?óĽŁÝPĆX‹t,Íhtšđ÷š|6ňŃ z á˘ý°G4¶Ń"¬O%úűѧÜŕíř\ä˙ĺ |đăĂ1Á"Úááv`BƇ‡AŚř˘Ýř…'˛ąä&wň Ŕ…3 TĆŕcµhG?áEĆxĆ5Ŕ+řˇ†0Kú­j =hBKµ‰šH‡?<ü‡nCé G z[RíݡG&ćŘ·j%čÄ;ŇQmü!č: z 4 ą€R7dbĹŚuŔŐą@=dť#›šTšX†G±Ťeř A6vkÔCohś,ŤiM‡€ThčŤ?ĆÁ§4`ŐőR€™ťřAÚžëŠ`´ ÝČ /“{ůh=Ţ÷8Ň*ĺÜčvÝ Ň1˙\3C[„5ÚŃz”bŽ čD»ýq‰ =Č xČ€.ĽŁ a’i>¦0vĎʧC=ęRŹ čB±óaŠÉ\ćPľŔ‡XlńřBÚ»<~aśŕÍÖ ZĐ€;dĎ" 0D>¸ŕigűŘéóKŁś ‘¶D!ďP´1Dě‡KűŢĎÚC;´Ç‚¶‚Ĺ‰ß _`~¨Ć?Ţq1b¦čBoW—sľsl€š¸F&Rŕ· ,!q» >đpw#sl±×Áľ÷"„ $–©HÇ·#˝š|&‡­``Ť®•®4¶Ç=sÂń90˙ŕřFü =|âßř˘ˇ@ “¨@ á <Ó2đ€`ŹÔ†Óťć‰I"š‚4`‘'Ś˙*ťŢ”ÇźíG±Ĺ&1|ô§/‚(űÚĎ'ňĂ>íă>ţł¶˙c>p>h€ ? żĚ?äżH€pľ ¨€ľyŁĄ40¸lľ DŽ·0‰¨> T€Pé *Y> ¨©¨Ť`çÄÁjŞŹH¸Áę{ą \@ĚŔů;¤С €.Ŕ_‚śŔ d>ň3BŘ€˙K€Š˘¸Ap # €ĺk>!L˙lpŻňى(ŔÚx€T \ľ€<4ť¸@€Ŕ° ŘXÁŘÂ(śÂ*džÂKĂD´&TŹđ˘đ{€;¬ Ą!Dž2Ä@\Â:´ÄhĂ7|99l?QĽŠ? Ähç»Ŕî3¤ăłĹ[ÄĹâł †™´Í@9Z#Ž¬Đ€÷»ŠZ„_ôĹ`ÜŚˇQ…†± Y hÄŠô« i$ «`dÄŠ¸- …_ŘÓ0ĆËŔ€)¸‡ŔŠZ<ëĐĆň‘Şö h=v\i¤ÇѸĄđŻj¤Çq¤Ćc Ę8™~lŹp…g©ĆIA0'ŘĎĆ6ŐQ]M 5ŐS-Ë$U ő€<¸´z7č•&*ϤKa¬€)H…DËÄŚĚ ‚|·(3¶?Ś €;xŐX5‘[36FŚŐ€\ÝUE;đ€đfë†?0uˇ&¸úě‚z`„ 0:pU,ČĽÝz„gqtWTŰ|Ŕ·*#řŘ$~(ŞŇcĐ,đ¦fŮ4·Z€x©€…~(XU˙*Q…Q`Hłs8‚°SP¶xm15­ˇSGŇ}€hë¶;ms×éKm€n€¶Nc@ 0˘ŮRˤ¦,H€‡ŕ€ČÔ©>"PUÍU]Ő§ĹPTĄÚŞĺJ¨ŐYŮđ…1I¸=Č•()Hŕ‡5Ř#Ŕcř)€/H@})؆ż$Žč‚/€‚NáŔ}Ř„,p‹›;¨@ŕ‚9m«¸¬€Ié‡|Čmř…¸Ť|ĐdH9ł0}°‚¨‚€‰MłóŕmČ'rĽ…\Ŕ5’÷y,…%·şĄq$~H„ds« &Z¨˙z_ @Ú j‹¸źË†#ŕ€Š­€fśŚŤ=‚„sđJQđ‰[R§¸xŕ$č„}°‚´„z¸­kČ-K89@‚TĐ0 XÁ„Ĺ„s`‚ćťNäpkř‚łL۱DßÄÚÎP«uŕJ~ËŮPšMb¤Ă 8QWX Aş HTB°;h‚łŽ)Ұ«€bˇ{h„Ů;0˘4łˇâ˝L8śĚ„`ż(Ňkŕ,P€o˛0„}0B4Đ5¸|h„:jhŢ€ ą€şHłČđRřč?ťÝNáX˙×ŮÝ6<…=x7€…ppâÝÝ K1)ŕaQŐŔfdH‚c`Ѝ‚i©•}ýZ/ë¶„lxX{HDęE*ÝŠäINŤNŹm‡k0©í´ŤX°)`Ţ/Wä”ŕX.U¦ĺZ>>Y&Ž‘´Ź#HŤŐhŤ×8äNţ Gއv($eKŽĺhŽç śđŃ‘r„ňx’ô©%ʏ•m^Ú1DÁ(@7†Đď±ß[¸ePI[mábíđ…}Hďs«  ¸0xp‚ŮUŐő[đZc:î4R™OŔ“čMš)ĺ˙„vđyč‡S(H‘i‘çAZ ąĚ_mˇ Yâ¨H*‘=¦N  € 0{.×éÄ×íË„J ¸€€ŔPcĘÄĺ¶ĺŁFjB+j]~& A{’ˇä_t$_`…{ŕ׏‘’ŻĄ•»!°™ŞÉ™p¤ĚÉfźľn¶ÜÉ‚|`„fŘ…e@…ĎB 8pŔ‡| : Ń(ZŔ4°†ĎÁg7HŔiřřHN ŔŹlއšĘ ž¶“+ŕ‡dŘčÔ,eX!h0"őe›H(”™€ő2Žç<É•›_˝m˙E¨Ťč¤€ €Čޡî´ÎqÔÍPéa€0]j-ę¨Męę¶nZę€!˘!b)žP`Ą1"ÝňHP¦"¦D:&­j Ąv˘CŘ" ŐaŚ . ”~覢аkz¨lŘ…ĺM€@ŕ0~(2؆!p9‹˘•ČW[¨ ËÜ~†g b!Žň¨ĄlŁ€*gŚď¨Ň€Xˇ8<ŕ‡a#âRËdFW`|ľ Ję†K’íĚ ŔŰGb!A$#˛ŕFbrŢ"ĺâ  ¸dŤJ]ࡠŘČąLş‘|ör˙0s™ćY Đrí­ňüžî6˝î9§sč¬r¨ťŹĘ« ąŞ¬Ú*Ú€˛`Ű/č‚9Ř:Ě€ż5¸’+ş˛«‹zH„.0ç2,ż,Á"¬l\JчČ€ĘĺC°2 T(_¨Č¸ó„kNĐ_0óÖlŁvŔ3čËlłhWU02$c^ ¸Ť&30S_127lvŹ…\çĐ:ŐÄkh7˙Íççm€ß˘)*ŘŘ‘dŕÚ7p¦)wň (®öÍ-x÷í;—é=xBď~× X żé»XÜ\'x™†·í‚Nč‡˙ęŘO|/jЧÎ:ÇřŚ×OU%Uč#¶cM6 M°†\űV€Ď^°EűËu đppP5R35 8CH‡tČ9«ŃW‹µY»óVË‚Q;0†"¸0¤S:*Ń„ź3Cř‡?Pn-6ІLĐVřĽthŃ»U Č0h·ňXy°Č2‡0<ÄSĽăŕÖf€:X< Čżt¨{ XN8·z0†śőiô…iŤńUŕ…iÍ z{Ş čB#@0…pyw;xŁXđŐ7uc7·Ŕ÷0„sËÎ7čL •Gŕ˛Ć(đ»ŔçŘź}˙âčËbkýx8‡óéÖřâ7~$w‹/,íéŁĹĚL@tŠą|ÉńSŔ@.ňÍ8öó«íwzË1ń.ľ˝ŞŃ˙Ĺ ;°ŕU*dŔ,ŇĽ@Bb‚@ dŔŐÄG>˙X¸p 6,‚LRŔ„ŕŔ€€‚r4w[¸lf‚:ń^ÝG7¶ÁĚmÖŁÖÚ°§6Á0ţiž ńv©;Ń qIžŒBîŃS)\ ÚŃ|¸A>…™ &‚'ś}¨á `=Žŕ‚fAúH„–1µÜ"šC H`‚”ŕŕHG5řŠ8`›ŕÁ•` HoW($k ĄÁ–°eĘ›aŢĚ—¶8¦z˛^Ébö<ám„-\Ů丼2’T&Ľ@V„)„aůa3‚¸ "‰LpŔ1ŕ‹OH´`Á MôĂS+@*ŔQ˙LÁ’ŠqŽ#,‚00A¤G-2SŠ™µŠ™<z0brËc9ÇłąK}Łž2˙Ř.W%2nk$8•B¸\¤KĹDź0^Đd 9î(¤áß9c…9><@M 8F+x`€]”âř@4n© DÁpF €ŇÇâńŤ…´!…ő±ÝŚő•G§ąM9vÓx"]ËĽ—M¸Ý-ś.m– =Š\ˇŇ\ŢpA\šă‰`ú B`‡=|á ^Č$p‰yđa Y(‡":|`Ö°‡ 9Q.S¦ËĨȠC–V˙/m=žq‡LiEód|ÔfôVşÖ·˝´Żâ'EăuťŐĂů0rü   ÍÁ5 ¸=†Ŕ€(ä đŔáĐ#,b ‰třăÝřV9p`xp!ďZHžô›z˝ÎG‘·× m!•kĆjTW;Nď¶vť¦Zé×ĺJ†Ç ,Bظ€‰`+!ęŐ•‡©  Đ <ŇX—Sľ4°ODŕzbK}kQj˛-ą(¤žö:W=ÖńŢzŢŻgß·Ž”¸+Ä`6eű·˛2·Á‚jë‚oµGŤfRqJ l¸Š-CG»ÇD§Í´µż˙šám}‡"âbU8J*b)1ăFvµXĹÁ)Ť€ů2żdë‚,äeĄôoŠš¬5Ň!Š!`F‰˘cŚü×g†&™ź˛˛‹±<ä-sKVáĘ‘¦LepÎ)CZÎ2Žůtć.łąÍnF±›ă,ç9ÓyBk®s•îŚç=óąĎj–˛źó¤ç@şĐ†¦Đ•őÍŘ*xÂf…łpÍF«Ő¬‡ľ4¦™čdQÚóÝt1™w×AŮnp-u¦S­j Q€&`dä0íbE)ű‚€DóâŻŔ!ÁŔ v0‰l­ kw S–ČČ8 „Ąç*˝Î® T@%ŽXÁ˙¶J\]gišęBp5m»čfjkŐî~÷f<‡'¤%ÖMĹ; Ë 4Ŕg›=ŃŚL $miM«†?˘65®Y kZăš×Ŕ–±‘M; iŔrámś˘ŕC pw‡jÔC OżÁᏠąFäO3y Řň• í‚|·¤Ëmn[Ť“Ád= ďˇ]3…?hQd$Ěqä$G9Ë ˘Ŕ йυntĄ;]ęţŔ…Ę˝.vł«Ýír·»Ţým@‚>älŔAlGô±‰,°2 #AŐ}ş9>5ď{×üx«˙”đâöŃqŽ,ŰJ~¸¨Î~˙÷Řé˘sľóŠq ‘pd˘NúÔ÷ľ÷ ŰxçEćWżűĺoýű_’C@"P t %HA 6 űšŃ,€µ˝MŔzAڏ^ëŚ_6|ŕü@_úÔýőĺç×–Tš?—™ůw^'Ëg¬Ž?ĺ=/˙ηúhŘG9Š`n'< _‰Ŕ5ŃEŃUŃeŃuŃ…Ńi@ťQ­Ń`Üň)óYA 4Ă{éK0 dÁ>¬A'%QŽ ”ŕ ¦ŕ Ááܧ­Ěĺ=šn5Ú~Ąź©9žI»Íô4±˙Ŕ)†˙ b‡=(‰)™*Aß*µŇ+ĹŇ,ŐŇ-…@.íR/ýŇŔýEÜ$ßňU \Ă{­ ˘ŕ Ŕ^@ 'i€Ö–Îńŕ Â_Vž3!’7ů !ZÔdśˇ$ŞÚ\1Ô1üÁë8` “:±qT¬ĹĐ“=á“>ń“?”@”A!”B1”CAT®ŤE =HÁö1Ŕŕ1ŚĽŢűÄŹ<őâ/Ł(“<ťáŕč`Ű,’Ü| ]ĺ"2I¤eÔćM"7ÜÂ)J4YcĐ”MáÔLŔĺ\`tŽP•Q!•R1•SA˙ŐEP•Ua•Vq•W•Xe pŕA âťŢuAߍŔĺ0ŢŕžŢń]?řÝB çbĐ—ŞFťŕT#€]c6 GůEb7–d íÓéĹĆ˝ÖaąF(cYĹcEÖdU–`–fůCg}VhŤViťVj­Vkńů dA>ÁkŐdś5”ܤ@0ŔČ­\c…€Č]D7¸ ¨Dż!Ü84–ÍQS»ťÝô ZJZ5ý E¶Ąä­Ąň\Ó6š$]ň™ľLFxL—CTżÝ ¨€P8ŚTxx‰×^–×yĄ×zµ×{Á $[^|—ôÄ´ĹDµ}›v@x$€·ÍÚVŚ˙eZˇFžĐ™ćuä»ÖůínE6Z]ĆćŞQ#š0šF†}Ŕ†u؇őVc\cئ™¤Ź ]ŤĺXq<˘Ť­X«€ZŁ=Ę’ RtţXťÜl^gIˇe ™’1ăb–d¤sbx†vž'zúŐ—± ĆJőřÉ igzÎ'}Ö§}Ţ'~ć§~î'ö§ţ'€¨€(¨(‚&¨‚bdZÚl.(„F(źŘGJ¨…^č›˝g!˛ßxb¨‡~čö”%‡"–¨‰†h§q“ĹWüť¨‹ľhެ›"ú×XÁ¨ŤŢčŞhhE“|ᨏţčĚŚčE)‘i§´T|˙©’.)©Xd4–'“F©”nFE|ÄC<\éC¤€X©–f©–>[—˘—–J'Rg‹Íĺ”®)›JĆŚ@.üśĘĂ?Č?śBśŇ©žÖžĘiťÖéťćéźĘźĆ霪)ČG„¨i›6ŞŁ"ĆZÁL*Ą>ÁHjĄNęĄfަbj¦n*§*AJNr>Ş©ž*c¬ĹZ¨ qx†uŔŞŞ 9q˘kÄ*«®ŞćŞ®î*ŻöŞŻţ*°«°+±«±«”ÔśÇb8ŚSěĹ_fJDŰ´Ű‚@LD[·Ť °´Ú«ń ±ćŠ–˛–ëuÖ<” bŕŔ-`Ť&T=Ě˙łbË•ÜÉĺ…ĎMÍąśf†ĽŃ[s8¨sɧą&¬çµš@ĐB?ü‚ŔZb$_Â>đÁ!,řŔ;$†A^Dţ]ŕ5žCŠlÔâN]Ň-]Ó ©ÂĆlIá#XC5›‡ fÁ.3(<Ť“m_÷M_ő…_ömôĂg ĆB4@čŤ^éY‡Ę,Ö!4=„ h„Ĺ)@v Ue`Ôĺ š Ş "Ń´ Ű–`Ř@®Ôßýĺßţ—Y:ZÖ®Ş@Ţ•Cé‰ÉŘ.ß..ŃňÝĂ ĆÜbCÎáÚaäN.3ÜmŢ"ˇ6˙˛‘rý-I .éZxŔ  A.´Ă/¤¬ ĚĎ6C˙Eň íÓôß1”/ă,Ł1jß1\Äî:­3&D%^b&nbnńhé6ďlb4€¸€.Ăë,FňőĎF$°ÔbDJdÉ„ěřZÇ`|c8ŽŁÍ1(q9Żübš’ŔŞ—4ƤĂÔÄX1ŔČVzŔ<ĺVšŔq|eL€SÖĂ[mB¤VŹ”&Źäü^đˇ.`|ÄŔh@\4@°)ưESXk^đÚ_^D¶n&µéŘ]ÚM‚ŐVäa0 s^śxǙȑ¤Ťpöč¶Śn`Ô°(ٱ7˙jF±/17±?1G±O1W±_1g±o1w±ó C\iDLJE?ÄW@«ŔďĄ ĚDZ$ş@:*>€Ă,Ajdѱă±ű)ťöńÓéĹʱ"]°§8r¦ ŚŔ#Gň#Wň#ŻĆ"w2ѵš„2ůt€t„(‡2yś˛k”ň)Łň鮲(»Wx˛-żŰ 챜âC9Ä@ űé?DV.3/ű˛.Ë©03/'߲3€ HޤbŚŔ Đ<5[A ´‡¤n3Á dó6wó7ß@8?5˙˙=3<˙šš@€¬Ú‡šx@«ŞI;A>Ż «âsr0Ç>çp<ôž±ę ł*Ú¶*b ôBŹŞAG4›í„š@-ĎŠm¦•DoôD ©Zr4H÷•GkpH—t mPÝ ôjv¨I·´Kż4LÇ´L]@Â9řDĎ´NăYčŔ>¤ÁNő–p”L ŇF.Żótś€/0´PGu”‘’úślAFÁ‚/03TKµWĆEz´Ą1FÔ€éüßW§µ®°űUžcřŽ- µZĎ5hlI‰îúfbŕDNÓ5`7çGÇ0^«[§Ŕ 8nW6cCâä!uL˝ecś- ‚56fźŰ©‰˙«JŮ cś,"g6iOĘGżćÁÎ ŹÉ^iżv•qvhŞvY†üŽ\ön˙°m!'§„Ěüőn÷¦Ŕ Ü ·sź‹q?·tO7uW·u_7vĂôpŔ!¬]v7˘¬EňťNt·yc ú”Bnź7{ű ŢáÄ;·wc‹ő„L–>„A"Ëw`Ów„\W%Ă'ŔÎę÷\Źô„\ŔçÁ.đÎbřNów_€ Ŕˇ 8ř~C8„`\Ż·…{őH˙vfŃ<A‡_ř ˘SÜ?¤l—xLY‚ĚIq^ČA(°Ŕ‹Ă8LI÷•¬0˙䀏'ů…„‡ 0!(Ş’Gą„pěJą•_9–gą–o9—ź4K[(@Fôxb¦y—ő—‡šş B3qlwwóŽË{¸|†G\!Ľ@-O:Ŕ ě8ÇŚ7Źü<Đ“4¬€=„‚€ß»´•pF\f¦U@/SŹÂ¬_Dzs¸Ôë´•Ŕp $Ý;“̡śż±lTxz]Ä{A|§˝ÚŹ™ŘznŁoB.Eşv9 €ˇµ}ă7ŕ5 ˝uăÓz_ŇÂ˙Sö˝łT¬ţw€—{ä·ô6–&ČPĐ- şm ň˝Ü†PMĂ˙…×(8ŹţLk'ăŃwĽaę!ë«ë'`€%ĹZLřéŕ~ŕüŕ#?` #ďún<%żf^ÔB) >\l¸ó??I€•‡„,BŽěDš¬Ó‡ ‰ś˙p“xřËt»qÍ6ČşF00?Ą2D%@„ĐŕN5ăćtčÄp…Ȱá ~aB,¤¸‘cGŹA†9’dI“'Q¦Tą’eK—/aĆ”9“fM›7qćÔą“gOŽ€ Ya–v€l`°á‚‚2¤HÁ°ATČȰ˙¤}X:Ld8áˇ(}¦U»–m[·oáĆ•;—n]»u ‰a!} Ĺ t䏮ͱŃńÂ2̨ŘP ŕje,WN!brćËž!lîśłgŃ”3«PönkׯaÇ–=›vmŰ25Č›;$¸``]rÆ-ZL¤~€ fläú7]Ţ?yţNIŻľ˝^öéÖ­c×^^wéÔĂ{ßnÝü÷íţLĺ`~›~}ű÷ńç׿6PÝ%/¬%űh°8ŕ 'lđ‰tA%ś0B )¬0C /tP Âř QÄI,ŃÄQĚécÎEĄ† ¬ĆĆŽ˙˘±Fnä(Çk¬R,ŇČ#‘LRÉ%Ä“tTHD (Hn>&±ĚRË-ąě§ <Š'MZŽ/8? Đř"±ĽŚSÎ9é¬Éđ؇áR2lfřŕA©eĹę[@“|ĘHÁ„…ş:Ç2jl…fÉ!ŇIíěÔÓOA ·*®!ä…­Pڀ٠ ˘=’ŞŹDé‡ ” @‡}Ňř¨12ގ"_UŮe™möÓě EüCI (8Á—Ql f)…üxĺŞ@[AL@•˘ &čĹ, Ôő…]wťÍWß}őËk_î¸GŠ :˙¨ö$ * @‹k¸@OxŽŕŕľ’p5Ý ńĄ|Ŕ˘82ŕ Ś5ćß“QNŮ®ÝňJO€áÁ_kÂ`€]6‘Y˘Đ' "í›ŕ„r!8°Ńc\Ž`&(ęiĄU®Úę«ŮbŮY nÎą`MĘK€KbžŃˇd>NŰŕe4ŕ[–ŢHnşíž»n¬ůîŰofn(vÁ$‡ŻÁ&)Ż"™Ff<¸ Ź]US6ĂPqE"®đ€ÄĆ\¸ĆŤ$ćÜóżQO]u‘g–ëÂy@ś·’vŔ`ĐŐôkhµĎ0VTŮf¸g ´›ĽrŠ7ŢňŐˇ˙ŹŢęÖ›}wÝ/ój)ĺp†lÖŰ>>(§T+–·M`člQÚÝ(ýőIh_úűńO™‡ý÷n62ě!…µĄ¤15h†x –¦Íăőé ,đ éŁĂ2Š4î# R˘1´üŤ„Ëâ&P¸Ż Ä`‡čÖóFâĎ}Á ďR€"čÚ\¨q]ŕaë…XB%.ŃNĄ;QŚ‚J™¤+_ ËFČB łŕĐ.†ÁC3ŔŽŕ1c¸l‘)’ŃŚLtăáhľř%Ř@ź“DmdXcmş˘>x F`Ă<+ŢŐŞ#†D˙äăIINň-ľRâă G9aŽs2u%Ů  rc!op9x€‡¨Ĺˇ¦H€TĘ’µ´ĺ-}$–h€@–(eŁ'îźH ‰Ke.“™*f3ˇMiBOk4ŁŢ4±™Mmn©šëć6ÁNq’h7zń&Ëň"«Čl¤I¸ÔbŁÎ=Ž“žőÄenĘ™’|b(ňÜĹŢ)Ú“ Ť¤żxSÎjĺźűě'6ÖI‘v”' h€j.–$“!@€č< R‘âϡ mhIgÖĎfD”+î„çN`c´@ ę˘G8 €Ž”§=M]ëLÔŮiMĄ,@˙_ZĚůx°RKŐHcÂTĄFµM“Ôh0Ü# ĆÉN}V±Ş¬šB *ELęQŁN4©`Á[ß ˘·î€„¬\ăJ‘ąÖµ¸"·Ž%DaD GŐ Ň±.–±Ë*«YTˇEť˙i)EÓęôCk ÚŃ|ŚŽ9šýg={ĐŠvt@=ś°lěa  X›[ÝÚé±BŤ¬9ů韢2ÍĄIŔ ¦0…5 aPX¦†!tň¸É]nsźÝé2@ôĂ+ň@ DHCP"ÁínŃ›^-IÖ¬ uhbŮY\Š8‰G! DI_Ý—9";Á+@!˙ *ÔiÄ!|Ő›`+©·íŐ‹B)V¶öddŔĆZ [BôĎ#ç]đ‡A"źŐ¤żmť<«…Ôž0gŰŘұ«rÄĂ!¶ńŤo3b7ĄÝLlµ&Ěć<@&0ŕ¨oÁ8vň“iN´Î.$űdňJm¶:ËĆ@9eáC™ĚeŽ‹•Æfťbyq.íň›á Ů1›™Îuö pőiYŽ(%Î}ö3dy”S;šĐ÷‘˛p;Rb|&zÄzž˛o iIçä›´«4~.=iMoÚŇxî´§1}MNŹšÔ)±5JY,Çłp ňoQĚcŹşÔµńIAÍ:˘˙ŞÚ¨*–‹ŻaÍćŕ~Ҷ6¶‚şË’6Żvµ|™üQSĎÁǶönŐŚę…j@ÂĐ~v«;şj'®Ú×6÷bE­ĎŘpiw¸##Ük.Óç¶·Aë}ÎÝ0ŰŮoé·N?şíě±—Ę÷68ľÓŤj~Vvv˙nËżQśPz[9ß·¸6+ţé†VöźŢ~Ë»×o‰›×CMřĹQ>Í“k|ˇüö¸[ đ‘?¸›ŮNůÍŁ™q]WłŰŕ†ąÇąÍć™ ¸6ÇůŃ•ąc• 9â y[Ú]T˘łŇ:GúŐá¨tuźXć—MŞż˝ýPŁN{Ú';ÖŃ~Ď?ź•ĆB÷ú\ś-uFłý˙'+OűÝ•¸vşĂ;Ëţy:[˘ô±ŹűŇvÇűáG¨÷E›˝ľ‹® >TeěE–u·Ľ$íčß^žóť÷üçAzŃŹţ5—ŤáIźz{š>6¨WýëĂÉúťô8׏f<ěqOOŮë„ęµ?{î_ĎÝoŰÔßüä§\ö˝ĎýöÁwľĘ‹ýťäp®˛ďźźýeß˝:î}—GâzíŹ˙ Ň§˛÷»źjë_?{äwż-ąŹhĘ#źěCÝ|{wŢü÷ď?ëćďI±ABüřoďg÷(ŤđÚŻř„ 'Jnĺ°)Đođ"ü°Ż9u.pe6°Ekp6JpQ0˙UpY°]đaýO.ć-cđéäעO}PNtP-xP˙~°»$ÓbŤp ë ďĚÓ& ĄđDśđ˙ Đ§0 ©pĎě {P Á°DŞ'”0 ÍđHĆpöĽϰ ű… ᢠÝpG$ yo é0E ßBőđíĂ) ±éC! qM űĂ1%q)±-ńYtŔ8–,-4‘=±%ŔŚe$JŔŞĂq”bbŔţpáŠ0±7‚® taáu‘W¬Vrjd@a|^hpHŕmŃ˙©ÄDH$Ş*ed& Z @Â*¶1*L`d$@˘1@5Ô¤8ŇQ!,J5˛q%@*ĽQŔQë1Ą‚*¬$@ŚŚq@tD@VŁ,ę*R"clX‘"<`XAs¤‘!( ĚS€6Ŕ)<’1Ş‚*@Ł( $QŁ$2ćQXä*BŔ€iSÎŕŕ x…$Ŕ–ÁęAÜŕ_1…Á®(…’(Ť˛PB nÁĽĄ#6`Śé¬!Tŕ'µ!ęˇŢ Vń!)5B,ÉŇ,˝ĺ Á úA”ŔB«ę˙~`J ŇÁčá<`" ”q# C0r$*` Ra0óRŔ<  †rR ¦fަNŕ¦<ŕÁüáơ#0ł03MA&9ŕ´ˇž 'Sî@Áhˇ D@*’ÉvÎA ˛ ú#< žŔ„“8ŤłB@šR@˘aě§#愣kx@8ĺ RAŔ’s9›S<ÉÓ<1€ňŕ9¸ŕ ŕ€HŔ‚Ŕ0 ‚`dşŕ  °!P"1G~FŔ1iČ#FưÁţ` Î$đD6! 4á8 € ®*«¶* đÄá č˙@”@…q$…,’A0 7ŹÎ˘hŕň2A5AB"_Ŕ!z¤2+1/a~ô‚ô0˙'NA‚†ä#ҧĽłŕrĆG `î!V„t=Źô¶´K!Ç•¨ H€E‚Hrn€!`Zá{to´9Ąt|`@6€R€"ŕJá`‚Ôţęk° +aćŘ´Fęî4O  \ed`â@ĐhôިäĐ`ʡLŕ6ťÓ§1Ú€ŠŔúTxl§V/ŕVs^&JSţt}ľKĂóHy€,˘AÂbW˙“V›őžµ8`nÁ4! Z ~âM—FUŕ´áZaiö”1Ă´A;‚»ö!h‘! HiäVc ň,ڶ ¦zŕŇ´ r@‡Ě]ŐµYc÷A ¸(UíŤzŕ‹Ě‡lŕ&ť“YmWuő]ŤÔWŐ´Ş°á$ŇÇTn®4K™UhžU"¤•!$˛YOŕfar´`CŤá.fe\= ގ‚¬a]uV1ů”dAâ T‚ě•wx dc ĽëAĽzJŔP5‡3•–iťv]'c˘ÁLJ,öćŕ Śˇ˙$Ô>źgl˛á€pAHŰÔ&`ŔIp—p…4Ś –al€¦<Â0R”ugťU$L:—qE×ZI7ŕŽj1ŔhůŕŘTh–AŘtjjŹŞ¤Áv‰[—X€q)Ą6ŕ`Z MuQ` wNŕ@! č¦(€MąË$wu—x×w ¨ ´ÁpîçŕNATŕPahlě!şú!˘1AčŕÁ Ţ q/!÷·%"Š%:¦HU¶Lá ®€hÖqF·t9 €¸€S×gí`ľŕ ˙Ľ 0ainĆô` Ţ@hXaŢ€ jO—Oö!ćŕ CUňá ćŕĺÇ8"ôľ  †řB3tCĂ`6ŔÂţ@4Ś*`á nŕćuFŔ|ˇh؆u¶Âč}oAPUg/ćˇŔ®J ŢáLĆŽĺŽ` ňˇb:a†ŔcbüŔ Ţ. ‚ˇÔĄ2Á®ěŹő"y’+ů’=`Á3¤r!  ‚2LîřČRţŔ[( &“•“GJ NÓ®ŇAł€LSŹSŔ0îŔʲ(¤Ĺ6& bĚ˙` ÂtE஠˘dŮ[\‹tÁhÔĺä$ĆFDŔ#7"CCĘůśď1& 2Mb$:|Ż‚S zUc* Ű2 S@H’P˙YBŔśÂ!µb+*€# !%BťŃĚV$z"Ôą~Cb#Ŕš)Dňť™ŠěČNúˇóůťrĄ˙qxdŔŇ ŤĂévvŠČä¦=Éľ $Ş<"ňŽ G˘ ¨š. jĎrŞb;ân@ háVC$H ¤Ş¦/N§G«•hF;" ˇ4aÔHŞ…ŕ,ÄŞŃz'°`Łî X ”"HpdH ^`äŕ˙”"¨%Ö:ň”â­Óz°[aŁěkž xÚ#:€ś€±@ †!>„¦ ±ÁG±%›°ßŻ82 d”Z?†dôš0D ″AâBáŽ`0(áľA F› A >[$N;µbµ[›¦A;ő˛Ę@mŽä±‹áv$DZ ¨;âŇŕ(<ľ(!ś€(ŘžY ąź;ş§›¸‹{¬ hÄĄ%BşrĘŐr'"W±ĽJ‚,ĘAÄ‘6ę%^ŕ Ö H  bˇîaę¦H!¸ŕ°@ÜÁ Aś€·3˘Ş=˘Ŕ˙<ÁĽÁ<ÂŮ»˝}Ş1Ş®‡%@Ă`$ѡq"ŚÓ$&ţ[kg#ö °@‘ äb!ĽA<~`†á ň#:X ZŕaĂÝŔ`Ŕ·0@É™Üɧ:ʧĽĘYś§ zd4jE`%U 0Řp@¬ĺęü*0Jy)`4TcdŔ|ĐU =R)*ň"…'"™D Z7Ł Ő)˛Ĺ|DĽ©6Z+î9 U#AhRŁŰ1(š ϱ&Ă#ĺ\đü˘îü¨Ľ`¬ $ň |xÝ(á^@âŔ$€ş)â Š Á¨Á˙4|ĂŐÁĽ”ý8a¶="×w˝×=؇˝ŘWüͧirŞŐ%3ýŕęá ćŔ•ań„A>ŠÉֽ݂–·4O35łňD ¬ĂÜc@0µ™Ž˘1ýÔ9Ón r0Ó=˛’ßsˇÓ•* RáüÝ'úŔá Ü[ArĽR1ä’.íŇ( ^čx…ŔAč9@ Öo}$Î<Váxť×ŐabÁ€Â@§|Ŕ¨ÁË˝<6¬¨Ň@ŻŹč€^臾čŹ>é—ľ®Ĺ]¤¬§Y\҇|a ĆÁ r?AŔ˙´‚,ňíă~îŹHÔDá`Ě@® ‡ ”@y=  ¦ Ö€`ҧH7˘]+hě  Č…Ăsč!C#?ă-§ťřÎä ľ€(ˇa á…`áF  TŔ’Ćâóćł>I`XŔń!_ň C Ĺ䦍vŢÖ3X2@HěcÁ RĚ…ŔŘÁG!Ň`ĐAęÝâŘë?a`>bú«˙úy=ű·ş?ÜĎ>šŇţÇ˙űeGÁfrp¸ Ň4Táj”y4OĘ… $H¸@ŕĆľ50tqa P”k˙"ĆŞ\ĹlŘP€B†&ÄŘf§ăEs>"Űô‚Á‡{ŤtŔ €YŇ^těXá§ Ž@eó±ĄZ 8ů°¸8FĹĆ"dMR”$’ÂĘ–/7xŘrŤ‹ŤÍńxZŔË=)!˘†š!ĂRëĽýÁ ,2Ć١à )ĐĐąSÇλŃě¨Q:˘Ăeś‰7~yrĺŐ´kŰľŤ;·îÝĽ{űţ <¸đáÄ‹?Ž<ąňĺĹxĆc‚ËFYŮ$1 V+ž:6¬~=űö =nĄCĄĄEŽ Ě 5ŠGŕŇUă')ćĚš7qvçIýŕăOţĚ3D ×č‘tĺHâ˙Ôe|aÂSCîŁFC°aĎ.4„&ú$˘Ĺ2J°‚yš„Ń &$P}öńJCě˛ x)a{$ač†AB|s´C!"”DŰ RJÉIhV˛Ž7|L™‚ě­Vä‘I.Ů䓪1‡fšj®Éf›nľ gśrΙśĎEç’$ŕĹ$w;}7‚u|jÇC(`*ďŚ3„„N¤N8h1O(ČD“M…ů÷g{ÖA4Ń„ ęç6a…˘b¨!‡L8p ą|" ´°đâZhŇŹ1'N N8LaO~!0Č9G,B &ćŢ/>đ–˙ Ôü„Ę P®vD(±¬"B!Ţ C–ĐHÁÇş_¨đĺjÝ~î¸ĺžKgŔLpÁŚpÂhędÎ |đŇž!ô©a$ c¨§}6@AG ČĐlLÜ O‘»”âđŃ@Lň« ©–PUXˇ°Í!-¸ő€ &J7ÂÁS‡M%Ě Ymł ]IăĂŻ83MłóIĚ”„ÇlgŔĘ-ż\ŘQXG4ô—ŔXĽŕ(‘pň‚/śAÍ7”ĄdqĹ>Ôe<čvµî“ČoHÜ'{ňĹ wŕ&3†îŘ]2KdQŽ"'mŔAŘňĆ­ŽÇ>ĚńĆĐĎ)sŚa‡$€‡>ŻwˇOS†GŔýHÇe„? × 2†A\‰? €Ičöđ…'xˇóś=é…@)ٰ†=4˘´¤sűTn0ŕ!Ďř†;ľŃ4äí0/đß~P Ň@ĂŁáßjů]…*dˇ a(C!Şn‰Ll˘źEÓq`y°†?ŢŃŤ9ČĚĽ@>€ŚL¨ 0&ü‘S˙°`\ô"Ĺ8=TŁ@ŕČ Š·# ㊦hAV4aĹztă™J >¦ !eLE:Ň訠!ţ$L ł=ěŃăC!ł‘(¤˘h4EfŕmpŇ“HŔč1D!\€4Y zd‚!(Ł&ŇqĹAžä 5Ŕt†Ô"n8Ón¸`¦|bgČŔśy(őáÔ Ć&[PĹ8ŮrÍ’H“šÖÄfß ĎxĘsžôĚ őH@*ŘŔ$Â$`*X(ŕ(@"đ§$0¤´ PŇCS°ČŹpźUˇđ%µ@˙ꤍ’TQ jˇ"I&\4ţT@E! ‚–*±!ěYŔM“âT§ h?Ŕ€śĘLů„P{Y…žT^äŚÂ*¨0Ŕ¨"č †`&XÁ/ČWćHńŤgôá`xÁ(ÁŤbśî¤ÍWĂ:Ö˛ÖsŻ|í«_˙J:€ýƬÄŮé &XĂ(M)—"†.<`BáhÎ%aAD`ب€Ĺp„ú^° 3Ľ n(F!0‡›É’Ͳ¬k_ ŰŘĘv¶|•Ą5Ň!Š!„.9™ą[]łŮ>ř #L Ç^Ha®żé­ąh ÝčJwşÔ­.sž‚üö8,˙Řn6ť9„D¸ˇ«Ř-pşkÝôŞw˝ěmŻ{‹óÉÝ Žˇř‚ofß‹ßüęwżümďSŰß xŔ.°Śŕ+xÁÁń‰5ţ\ś„§¨ÁĘdĄ k*0r€ kŔ6"Ţp‰7Ěŕ«xĹ,~í&@ŕpˇpŚą-śś*.°†lŕ]¨”¸6;Ŕ‰3Üâ$+yÉLF]†=@»d8 † hX¨ШŚkŚW$íŔ‘ĎŚf4ëxČDNłšŤě憸ůĚM®łťďĽß Ű…?RÖ@ üa¬GĂ0ÄűˇŚ-íht=đń‹ yΔ–3˙Š--bSúČpŢ´§GŚçP‹zÔŃÍđCřüä €Ŕ ÉđFňŔŚ?pá p` <#ô AŘ\>=b5gzÍĂľ °Ź j`“zŮĚnö^őÜ©¸ú˙A˛Q *¸ĄĽ$8ȇT¸Ě ;Ů™.v§/}qŹÓiv¶»ß ďÔAŐ®¶«S䏵Čţ6ćĚnvŮÜE66›®ndÇ{á o¸Ŕćí)Ű{ĘÂ"–±ř­4U?7‡Mđ†ÓÄN¸ÂŽň”«|9–Í€u3 ŔbVé60¶˛ťíßekĆ–:˘IďXŮçFr»Łbň¤#|ĺLoşÓy˙Łçę]/{$Čđ†p§;«>0‚¤P†Uf=čÎQt.zśÍnvt 9éę^úÓß÷¸ëř‰|‡)ŕěËR®—ţĐ%/ÍÜ€.,Ł”N¶§?ě‚§›íeoĽČĺůČ3|Ë7Ąj†ŞP†N‘©JzŞ™+Đś3Ô‹†ß4âÝnđĂúôE—Ľë_?y9/'Ű%7¨á|0$#ýöĆî ÉWcîW ˝ńŹ?`Ţďţń#Wűn”ŻŢô€FľőŻź^wÚăË7ząuźíŻ™áÎ@ J‚”HdŔ€$°  öďŹ˙R_şŘĐxëOüç|óÔ,Ĺ@˙ äŕčđ č@ ˇŕ2 l PČ”ř^QńĄ&Đd‹€Ś‚EW‚kgz8‚Ő| ·‚«ń‚n1:™Á¤Ŕńŕ<č€Ăŕ«Ŕ lpH@1ŁKŘ^ŕp`ý±& `şQn—Qp&0‚¦ĂiŠ•†#°sŕ…ÝgbĚGTh…_H'H äŔńŔÔŔ— Ă@äĐ Q€€LH˛•aöa€"(‘µV 6¬'–Đjă×fFw“8 9Ö& öŔ Ä‚ýwsögňđ ˇaÖg‡˙p˛‚x"Ö¦UCŕLšh‹˝á‰ (ŠÇÁ…°včńĐMĘčî@ C@U…HŤ±Őo>deP±7 śČ}HrT‰XȆ@Ž<‡ĆAöŁ Ĺ(p·Ńc?¦ei¶2€ °‰ ńb16cżF†´#jxfÝcZµůP‘ŽÂŃŽýđŽ‘ELP Ęh‘îЇé zŕ%Őč‘LdR2%…d p f_@_31 ŁđQAepeY¦Ń 0UAg“B‡b$ "0S QTJÓ8‰S*`‰ţq A9SHV˘×R(q79Sŧ Á˙OAWv …-ŕ•’C \će/’a6feV”N5Fź’ŽÎe‹8mX9’)aBuĚ#OqbEŐ•0|É“3©°ŕ%3U@)”yن%S&0|`ŮŻR––‰™đPpAeüdXĐžáĎŘĎh‡ŞŽŕů‘ł9:¨¤ é Ho —dyŕĐnđ‹Öhí€őđ 1 ×đ8Qö6hNč·@Jťä(vq{Tăś>©{¤ú›)đ% éĐ€'€‹RZ–‰—@ăPŕ» “ôŔ%3h@ťŕ€6ŕ0˙ťőÖéť(ö`ř dG–©„›Ý › Qh‡–h& śŽi’fžŔDYÖś¨{q5éZźŞe…¶ ţp ×đ—G–†` - epôPÎ ťěńµ@śřđňđ *žâIˇäą¨4xő  n€™1Đ Ş4PZISZĄÝ€ ĽT·` (h@ ßę@ /D ęŔm ŤęĐĺD›uj:–pr€© ``’‚PD@ a×@Ľ¶€o“€ ``KŞĆj˙Fâ É Ě`9Ŕ>ű° °#;‰7l|€ť°Vŕ(#Đ_˙x€ |Ŕ=ö@O@k0Đ”9q ö] ý0v°ś\@´:’KŕńŁ®©c°©ťş 5 =𮢓§{Ú§P=±6kµvką¶k˝Vu® «˛J@…ń:vj)ş!ľę¬ń#>€ @˛š#±(br>°40=pi@”ęĹ+;A `Ş¨ŞŞ¬jXŢŞYĐ ý!ŕÚĘ­ýˇ±ë±'ˇÍŔ) Ѱ&°°¦iz?`łnJ5[łßŕ¦Ĺ te§A›0—0 /@+p‰Zń4]ń ńm9Ű3 ®`d8±Ô¶˙¦Ab,ó0÷`d š– F‹´‰đ†»Đ žŠÁtEŠ” g9¸@ ě v&0€+P( Ć0];áuGv@ŃÖg䨶I+3ئmoŃmµá¦]o«q;·OŻ8±)z¸‰»¸'ĐŰ@)@P‹†#bpóŔ[Kó@‘ş)$aĎ‚¶™Ë¶K´Iń˝@ Ľ´ş$űĽJ!˝d§ Xđ4«A3ð «0 ­éŠŕß@nú Lp_BKżo˘‰ Šp!k`urP»qŻóC˙˘[{©‚‚„R>× .aHf‹ŽD.ŁS„‡  ď€ Ř0ĺqé1hń9 qmŔ (b ’ ×P¤äřP‹ŠŔ*łeW˝—K‰śżŔř¦o.Ŕw˘pÁĽÁ¶ŽˇŇ9śa ňÂ"Ă(€ű0‹·Ë‚BN°ذc˙»Ä k!ď± )ÁÓòy¶ ±&\6ĂoĚqĚ sübZ >d2Ëš)Č‚ěłiXż‡L'DŰ'ż˘ýŰ! ˇqz ŔgoĽŁŔ ŇŔ2–ĄşĆŚ\Á,Đ ÇPAÖ°*…(ŠÂ(˙·ŠŚÇ(Üu`*¦’* \N`*D@#Ŕ|f„’fN¬é8 5,Ĺr"’Ľq–jŁ\ʧ¬Ä©ŰÄ–űÄÍË»LŽć>Nłl ¶PcB¶&i§a“K˙ăo°ŘkLÁ1±uDA<vb>' ÜÄmÜ–ú©ßă¨@=Ö=Úł!ý`˙ ÉÓÝ0tĐ™đUĐ 9r/© ŘŕýKŰ>|<ÉŢ€-ŘNé«Ŕ*¬paUĺŤçťŢ¬qy€) × áŰ…Gđ ěŔCŢ@ ¤ŕV6{ă6.b@R¦-äi˛© ~Äž™ŕʨ«$ng)x8e áR–wi´F\¤_Fýt‡é ýĐ5vdE~ä<Ú ™p~Ö ËůÚđ)Đw  ňutG¤Js\ júiI&ŕ„Z ă`K, Ľ`o4FivHonw0€ćHľćĘw~—]P>xÔ%đć¸)çzyP1ŕHô)¤Hj˙čśÄ€'G•”Ed !GEĐ@—DFf¤wG{dw-Péj®äÎKóPź÷I{ ţ“nAÉľětžuP Đ R}NAZâŔ Ü Ô°V"`łŢîíĎ@ ŕĆCÎîÄ1šýšpJ•§S#z8‡^mŽy,ĺPĄ•u–`°q°=f÷îďóΓPqďú”—»z–”)»›/"‰Q!UáŇO OWPm>t{yS)  ď ËyNU•OqďđT\&™µROŐB…RńńŮSÉń´.gm 47i6ŔH ĹR11ą5’+źüÄ˙đĺj •7żó)ݤO™5  y­dTHyüD âŔöĎđ ŽŔ pĎöŕţ G€IíŽ÷Ľ5bÚµŽ#·Ő—WPS Ł`M°îAĺç}‰E$Řä]ŰNń˛wnőČ{JĂ÷´÷…ŢwŽéjEćř͇zĽůˇď”¬Mő,Áî”/ë>đnĎöć>űĹ Ep÷yŻűô´†đíŁ`ěüZe‡ť?Šgç{‘XsyÎPPb@ łoýâ \6łűŰĎéýß.p‚×dMĘď&¤š&“/ú7€ĎGŠóT^BCfŔ|Pf )ĐáÜ˙$XĐŕA„ .dŘĐáC%N¤XŔ?Ś3B°ŘŃăD !EŽÔđŃäÉ!A’<©ĺK!B¨Pń‚GŽ&HŔäŮÓçO A…%ZÔ(LŤI9e*äÓ¦QA()ŐęK ®nĺÚŐëW°a­&Ő¸T,̧,Ď®eŰÖí[¸qĺÎĄËěF‰P[¦uŞ–áČľi]Ö%\Řđaĉ/ŽzŁŮ‡zM ,Ň!KÁ–oćÜŮógСą:ţ™`fĚ•Qű5¨—ŻęŐ«EϦ]ŰömÜśI›0Ußżş–ÜwnäÉ•/gŢ©cްQK—ťřoăÁťoçŢÝű÷Ů»‡§>ŞÝşÚëŮÍgßŢý{řWwW-˝ýřp@ \hľ”ČŰ︅ônAě4«Î@ +´đÂćÄKP=ĎăËľ1qDKLLĂÖ8 qCôTĎDc”qĆŃ Ż8!Ě/˝ă^¤ńG Ň#ë{í?wŚ<‡tňI(ź,ň´{3R3+ťęi0%ń‹ňK0ĂqĘŢŞĽ‘ËŻ&sM6Űd/ !ů ,#‹!ů ,#‹!ů ,z©5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(dH‘˙:^4‰2% &H@d‰‚8OL`xHS$„ üŃ*#"EŠť=7BHЀƣ|ŕ2A ˛ĄĹ—Đě+WćŞ5Rč§YąF,l\ëóŔcőŚýaA˘ĂÇŚVÜ:%DEŠş%Ů* ÁaçLÁ9pđ´"É»­>nĚ1 !ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,zć5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(dH‘˙:^4‰2ĺ… @€ BD1gŞP CK/٤zç/Ł!Üçoś›'EB(„18_Ţ|©0AP=Dc]ăĂă§YŇ^XK˘BŚm‚Ö•ÍÇĎÍ0ń HÉ>5°±ÇänŢ˝űţ <řŮYÂ^t ‘[¸rAIł‹B€+ý¤a-ófB×k`Ĺ’ý4U˝˘¦:ŕôŁ­é٬5, A„ͤĽkŢüIňcFâ$Yv!ů ,"zĽĐ@° A˙*T(p Á‚.Ä đ!D‰+ZÔă?Š-vÄr#GŹ 1pŕB$%EŹ”y€©áµ95=‚¤ëÄ&*0㔤Ŕ-ŐbŔɇĹEł&ől8b5&}‰´,cň#&ŽÁÉőIZĘ‚đĘŮ´łĚ}Š«@€Hü ÔŹĐH‰ ܡ7„A”|\g   ¨!YaI‹:§Ô(Rn@!ů ,#‹!ů ,*z˙Đ@° ABřǰaC  J$PˇĂ‹NÇ´łO„€YxôÓĎ-íđ#‡bxŐÁťĽÓÍ,r¦ńaXŚ  -P|AF3­đ@Żqpi«ŕ‚>a ™•06Ô€$Ş`"cLĐ@Ś˙q…'ö)śOLEIŘc‹†5Á ÉňÄNěŔ–l‹6ël~F+í´ÔęfÔłA•—őŚă!TvőhH BU0E*éř“ŹRöM0E>™xB ÚůCĎönŔÜz[ghä˘/#ö2y‘şěúóÎ)0x0‚ÖL÷‡ ¤’OŔ×E=ŚlpÂ#ŐřÓ-šFĚ;Đ $¸ÎĆô° >J0çUF|! đS ÁzŐ¦>XP?δWôG ,€AŔŇO!`«ÁjŞŚÂ rÎ%XcŠ pđ6;°€(>řř‹ Y飏@o¤p]w€˙ăŹŔFúˇŤ@ԡ۪]$Ps>`€AŔóv űA4uHžř˛Mj­učVkú騧n“čůŤŔŠ/cŚ1É5z7BSD ?k h6Ćü1_Äx‰0/L±MOŤĐĹPŕ \á±Ď&Y\±hÚQ \LŠ VP6ýä“‹6żÄ >ú “N?Ť0>V¬PE p\6>ŕ…6ňá„`` ·ČE.B`~*@ł°ÄF0YáG"Hซ\ Ř Eč_„Ł6Č\PŇVKřBŮ8´¶ ¨Âö Ű؉sř`H†(˙<Ŕh/O‚®s xđ ťŘ‡&PAÔ#V¸ő(s9 !úŃ,T¦”`ç` =ô#\ă6ڰP° ;Ŕ`/maťĄş>úńŹ€”ČĹ WhŇđ¦0   Ť,h\€) Á¨a ;´ Ž’{ŔE°‹Vä@ ĄxďŃ Ä Ž‰ ›9| BĐś ŘČD đ)éŕüŔ‚–fbf8D;Đ€}¨AžŔG#(đ€´`† P€vĐaăG,đÔN*?đ€ôĆÖjŕIŔĆ)öđ7Ŕ"NH!.p˙>™C µlV oČ$á¶gö† Č`qn°Ź5H.š´D6^@€Ü#âÚ† :@ eĂ˝á¨Gq#2–­×0é0“ÎQŔÂ9čfjÂvtăb±™é ‡Ȣő¨§*F*ŕ:W(Oó8BJđp¤Łü„C÷ÁR÷$+őhÇ&xĐÎ!ŕÚx2°Q)č!x¤$€„~ŕĂxőÇ<†Ŕ,ŕál`˘z'ud8°4ÔĐ"¤Č€;´ŁËPDrŕ»ZŕBíŘ €_”ú “p¨„€AôN _„‚ó˙ŮÂ=-đ©OĚpŔ3đ?lŃťa„YiÔ$Úáyôă r%8A€+Ü  Ŕ *zÜxmŽşŚ[ĂEŔ{2[b4Q' 9)]ct*śż€ŕ…Řr@˘ah§Â”ŞG¤řŔľ 5ŔÔB>• ó`BRŽ:ŕ` ödđŃ ~Ő…¬¸ĘęNŁA‚5ÚJ;¸Ę•:čGh ˇ *¸ÎlţŘÁzđ‡=i\·ÁŚ)d!ŚhĆ.– x Â!ŔŹ|ČÁ•ĚŔ† Ę LŃ~€ř@5śě΋4*ŘĆB`\Đ` ˙ÍČ&P‚pl…e~çp~$cAŔˇ©&‹ ˇ"H Dâ¤}™(w1bś`˝t݇Ć[ŢójeΗVÄ’ĆÓ˘  ˘p}ËŰ—ř@·ć,Ŕ¶ Ë /ŢŃš` `1íTYŔ Öŕ0=‘1Á ŔŁ9S…˛Úđ)@'péą@?EB03\ŕz´Łđxe Ep,`c.-°š b˙đ*01GčÚ ăQ˙ íP.™`80ü`,ĐfAQ6ň` ţ€ď3Ŕšp “hfS1P)`'Ł8 épаť  &c yăApXR„}‘NŞŔ StĹşP'ä±`Č ¦ĐXŘpÝP/Bá~3sĐNŃ8ŤáBu `¶o°đ[ŹđF†#Qn 7ˇŽě(Ž~p„ćŘ­2ws‡kAřŹůŹłŃŹlŁđ;’JX­-c-Ňx±"*° đ«A$` A0Ň"®B=pqŔA(‚$Žm*@%,é!˘a)  ˙0(ą‘C*‚G`ÂU [˘AĄ1&PCáRf-Ů$0©Rb" hˇüuP d¶Z@ŠQŮ%ö Đ °"er‘/Yr±7 o!Đ9WCw©’ůŕ_i“†@YůjA“†ł•y‘íx\hy-¦’Íšą™x—™! ĂsgY!EŇN×áB§é™™™W€;Z0 öĐ^Ąži±í„6’C‚‘ݰ ř`-`uŇ9(9Aő›§ Ń› Á+đú@† AFpZ@ żSqš˙đ›!žäÉ* 9 ©ľ™›riű8Ă!H·Išś™źú™ź €9±†đíŁ`}Ňéd¤2)řŔ ›őśčI™7§€źt ěFQŔ ő  CŠ– 1źď1ű™˘*ş˘¨#r’ł›«˘0šť{wź3Áśă)„(*9‘sžM±w¬RĘŁEʢHš¤Jş¤LÚ¤Nú¤PĄ"ŁR٤¦:&-WZĄ\ÚĄ¶±Ą^ú`Š:$ŞĄT¦hš¦L1¦Ő‚-üČG¤gš=(eŠş»i@^öŔm’ź t@ ™  šĐĆ3Vaf’ •86‹@I&ŕ‹e»ľđ›ąć{ż|4©öű«›ű­uʤK±ě«¬Ýë«N‹­¨ű˝«µ7ęÂř›żŻŰ´)"­„<$•AU·RçJë Ół`źđĚ ÇP)Ç–l›ÓÁ0Q` p 0jDLąň«°kş}5ż1Ľş?|źŁ:[ćŰÂwÜľ7ś¬z¨dĵüÇ+Ćęµ)<^W˙ĐŇ@żgz­p˙Š˘%,ŞDĐń<¶á«’1Ýş¦2Ý[ Ó¶I§” ¤qšŽZ@ ş ®€ZŞ1¤)±žűÎDj›6]Ő‚ŠÔDá^öڬˇ ÓáÖřI©M::ýŐS]ô‰ľq:ź8ÔvŤ°D-×»ÍÖ˘0Ô¦p,¦Fť!í§,¤‰ík‹}׎Ík×±—!j؇BúŤÍŘk]™ýŘžýŮ[ Ú˘=Ú¤ŤŘZ]ÚrŞ×¨˝Ú¬}`ŞÝÚöyÚ°=Ű´íGŻm`śëÓx]Ř»}ÚăqŰ\ ÇAśŰµ]Ü´ ÜGeŇZKÜ ÍŰ6-ŰeíŰśËÜĆ]Ýů‰uĂF‚Ń‘˝—˙9­ Ł«)p*¤1&µĘ0’«"°«˘s^ˇ(ÉHŕ?""{ˇ¨R"ס€aňÜÍßÝÜvě˝ÔÍĆĆüËšŰĂ ÔÖýŕépđk1‚!®vdÝ7ţ ˛čš0Ŕ®î Ż%CŻö:.bx.âÂŻţš; °Ł §P ŕ0Sâw ĘaI®ÂဓN=?Ţ1|“Ťn j°ËcÚÓ)M©,ËÍÝŰF}ŕžĺ>ř ŕ´P"ŕ!Z˛'ű);V„0đ˛1;ł5{ł9»ł\đ´, ´»łE{´I»´*ą8ú y€ p°G˙€'ú€=#0i޲ZNx°čY  ŕč~E’N=Ž–»ŚŕfíŕNîĎĘ˝ŇlJęZľęww)4đů™P! ·r›8 ňJP'Ůp·y»·}ű·6¸MŔ›$`¸€¸ŹIŔ¸Ž ąd‹łRÍĐYŔĘ$—JÜ ÄpşNR&ĺŰţÝţíáu'µÎľ ĺ1MŕŁ.ĎđnęźëƱý¨XÎęúľkXwh°ĺP& €1Ŕ‘i ¬ć»Ŕ+ĽÄkĽČ«ĽĚkÎkUX%˝@˝Ö{ Ř«˝p]ÖŽíö`p6ŇiÓĚ€Y0i|'ź€˙ ň,ďňťfĚ mĺZ­ę˝Lżž«ÇYÍŰďy˘m˝ďFŹw"‰ÍI,˝ađđ Q+ ś üŔ<Á|Á&Á†a|! #Ě$IpL0ňŮ.5@;< 4ßňüň5(Ý„°»Ěj8Oą:_Ř<Ďqüó¶śóa[×`{ôŽĎkpĆPÁ3ZIüK şyRQ<ĹU|ĹYĽĹ]ě@ȦJal'dlĆh¬ĆA‘i­ś]H@RPî °¸@ #ŔpNśH¸ŻűĽßůQ—H$|Ң>ľsěÜE­ŕĎ:Ë<8\ŮŹ_ý}„·p B %˙ť|ĆČŽü€ćÇ7/ËC–ŚÉšĚÉž ʢ,Ąlxě%~ Ę¬ěĘw‚×utu]ŹľM]4ő 3b‚ zĆ şĆ‡‡@‚Y&\ŘđaD<~R¤H%Mš™ŇcG•#Y¦,ňäL’4I¶Ä™óăL”:wĆü T¦JžEŤEšTéR¦Mť>…UęTŞU­^ĹšUëV®SCpŔĐôÂ…(©ęůËgŞC‡~´7§€wč a% ö óçŹ^&!(ÄĐ”Îß»n:|˝P0T2Č’ŹĺĽůšlđpÇZ=eoR„ĐŕN5qľS˛›˙Ř®n-·OBĺťúĺM™Ă{_i´ćIâÁ‘çTsąńžÇavĹž]űvîÝ˝^|vś^° "D„Ń`=&4Pˇ˘"8xP öÜŹ‚ P€˝ü4řŠŽŃ‡–ŔOŹöëo ” R(I>ß› ˝Ó@Dú a·ŕ„›Î&ç®kÎ%—˘;Ĺ ^äQ8žZ®8ß’»n<#ŹD2I%—d˛I'§Šq¸™0Ŕ 9”Jš >ŔA btń „!s<ŠJ§¨ô¸Ô¬DQÇ(iұ§ŽŕT®©7—ş1)٬ó%<ÓÔP<ź$´PCE4˙QE—Ľ“ŞĽ¬IG”!HČ’(E×lTÉ<ťÚtQO?5TQG%µÔîćj1¬ę~ótĎD…|*SSgĄµV[oĹ5W]wĺµW_6Xa‡%¶XcŹE6Ye—e¶Ygź…6Zi§Ą¶ZkŻĹ6[m·ĺ¶[oż7\q«ęń§r{u\u×e·]wc=wĚsÓ}·^{ďĹY"us^éÍ7`&ÔL˙EXÖ‚f¸a‡·łTM6­KŘÜ"Ć8cŤ7†*âُbč8&ąd“9v5P‘y{Žß“_†9fŚWFXf›oĆYŕ„[ć1gź:\Linéą ŹF:iP780AöžĆŕi©S˙A©Ů‹új¨¶úęü˛äÔĺä[iłĎFű» FČĺ·ĺůGNin»ëˇŰí¸ăž»î˝ĺÁ»í·ů6%ô°»8mĹg\«±‚x"rÉźŘňÉ#ŻürĚ-żxá‡'ľxăŹG>yĺ—gľyçźß ¤Řpý¤ű$ŕčă×¶ 8ŕP‚Ů\°ďérÓ8 (0a÷U}“çřˆľ~űg•ž'ŕXË(n©‡64Q zĚzE1_hŞAš9¤ŕ)ş8ŕ↵Ŕ¦P†Ŕá˙ &]Źx&ťNÝĎ„'Őúp€:Тżđ€űx„ftÁűŕĂ!–±ŕ<ˇČ&,‚Ś€!D‚8Ä0Ŕ'%…?hQ|¨JDÓ µ¸ĹOQ ʰF5A@LEˇa˛@)JP«÷ RĽ  č1NmBwE6|@G;â‘… îCGä™(±82.VŇ’MA3褠’D#ÔhŹ66c Y0IčPD¨Ŕ±%ŕwpwąo~÷Ű_˝Á Ŕţ…›~‹ Ăú6ř·`ć‚ŕ_.&„),a K>ńo×ç{`-¸@‰KL‚€R@Ĺ'N±ŠcŘâ?f¶!ĆńWoŕ_·áŁ1 °Ţţq— ŮÇ@ć±Ű˙śdáĂ9†˛W1p@rXÂN@<ÁĘVhÁną.c'Řr—żć1?ˇĚB€A2Łwş×Ýîqż‹!8ôîßŘXh¨¸đ‡'fQŠ#Ţń HÄÍóxĘ7‰ßÔÎJ^ôWŢóFşĽÂŞr-%ă8ăçUžĐ‹ž*°lvŃwŻŢöYi=η2\˙đ·>Ärt­`ŕ~ňą2|Ýoĺ–ó8‚ňĄ˝hÖ°®Ç nŔŹ&Ö~úßWČr´¦Y“{lRçÎ>@ Q°Ŕűŕ‡żÄÔÔu&Ť… Ě Bâż˙fˇÇĚ ĂáżL3Q(DŔTŔdŔtŔĎ7±¸,ř÷+Šűč |Ŕ şŃó€Gh‡9(Ľ©XC¨ą0<TAZŰ­Łč¸wĐxx ÁkX†eý[ÁD9âSЏ^{hJ©ÁP GâA„Â~‘ óŇ‚kŕ‚đf'lЏ‚{° "xŚ(4C)‰Š _8˙Hđ`ŕB¦PĽXČX?0I˝3ěÁDŠ 8@ ô €)xĐ@8=P‚Ýą(€0áC(ôĂŁ 1 °0+:“`ź„šx˛I\AěC H#ĹT„—ćSĹV> tĹXě V”ĹZÄ=Zd ¦é©ÉŻţ±EÄĹ\d›㛼±›¸©µHÄ`$Ŕ\ŠÇŃĘáśÉŮOrĆlLŠÔą١ť™ŕ(mÇ™ť<ŠŘĆq´Ĺ(0GŁČ;8řhFuT>× ŘB´ô€Ah‰‹ĽŰ»ľłÇÄ<“@Ź*¸Bx©A8€AŘ0( ˙ÁăĄúŁ@ňĄ€K Ś±*˝ÓŰC°LľŘLȰ٥^2§Y§§Z§“€H†űŹ =ÚĂËéS˛Äł4‰đ=‹ÁD§©©LÍ{„Ĺ˙§"RJ˝ 2"Ę$ŠĆ‹]2(N°‹ľßTM?TĂmhCOÚ«ĐŤŇ8Ťźd ×Č’-!\E-ŮľîŁÎĽ´Î Ř‚v„´,ń“LI)‰_Ű,(C“P?ösżő >YÁ€Ô‡@8 H{Çí|„kAž°?üł]„­ŮšŞq^´P®ÉĐ ŐuŻzĐî29úa.čǧĐ-ĐĐΓđ?fřśżé›żQĆĽąAĆż côQżąĹŃÂ9ŔU4ÂbŠn¤ HĐŰjj”Ďé*Ýśi´RkÄRjśFĐQRĘ˻ԱMŰüĆ“°ťJ;Ó˙׫ndť(eÓr̝ΠÓ]+Ǩ@G5”őŃ$­ÓVcGwÄSGzÄ @/řÎ?Ĺ5}äÇf €HŰÔ;ľCÍPYMȇ2H‹_ ¶±‹h†UacTeH‡„H•HŠŹŔHÂ[PBa€…~ŕz*dS¶˘°żcČżcK¶Tí. A?=aI_pÉ“ŚIßx…_𒸶l۶™€ č…öĂ€lŐ¶V5Vë˛IśÔÉeÝ8˘4J¤„8Ą,•H‚ŠÄÖ 8·tăÖí‹ ŕsC7r-WéňÖ”ŕ4-­äJŹđJ:ý” 8rPť¤zł·˙™¸%x`‚סXi Xčň˛äJF7‰Ëą$˝0˝‘•ne…–Ë’Ţä 5 ™íXŐľôK‘YßHĚĹÔ€Ć|Ě Đ@Wx˛‡‹¸Đ1M7ČĄDZ‰«Y›ĄLłěČ! ÍÖÔÓü˝ˇőVP…'븏SHZ° Ű5ĐÓ¨e-ÖĽVÖ ŔMÝĚă 8Žő<¤§VU9–s9‘BYQ0Ł“ŘŰ–{9µ}®N)¸KÔ‰ŚfxÎ脾Qé@}Ŕ‚Ő9žsĘ݇0HGČÜž3ÜçşÎěÔSň4Ď=Ô>îXEŃpË)Iş»€¤\ĘTšÝŃ%]÷„OŤŚ ˙ýäĎ=üĎöK[ń yÚBž :«Ĺł…»ĺµ[ÝE®5„­€ đÇ}PrĽ€űË?Pů5}ŕś‰Ż ;Á;ͱC_±Ł^ç:Ń…R¨đ€ pQ­ž @?=”¨9ĐżŮ:»´ó˝«…ľc_´S»÷u.'­)(M4•°¸Ý21ÓHKŠZe`áŞŕ ¦ÄŞĄ5K·Ý7–Ě„Ľ9ëó :‰H‚{ČŘDaan°ÝŮřŽžĘŽaDŃaţ.gŰ'Y»‘Ɔ†jaö ě,óĘ0G 8âKb•6)biűa†á%6ch1ą6z((n$®â˙ żŚŁ–řayíb…<śĎ ,É’:–-ťă¸Ą`[€¸‡4¸¤řá4Ţ.!yş–‘b4ÎO%VHdIIć!ó˝€I¦d“°d0±¸‚°Ű‚tX‚("ČDCžbDö.E&92q:†š5.îaş0¸é90ʱŔvh|`ZąĺČĺ]ľ€^ţe¦%$ 'XlŘ18Ą8dVĆ.WF-X~)YFLH.‰X)‚5‚쀂)!ĐNpgr6gtVgvf ‡8x…< D0cG¶ćěŇć|*âFľTZ–QoŚ­Ů9@7ť4 fhŇş¶˙Wa ‚Z€…ç9čDż|-ŘboŢólřxfBŢ“¨ćަ.,–é+ţ  J8®eí@Ź=Ř'‚tŘŐĹ]¨3¦bŽéę;-šfN„îôxp¬ČęTˇvéU6ękKu áˇn( ĺËó4ŰX¸—Îj›ayńęw˛%f>ř1볎.Žň‹­·ž•kfŠ­”Wűk±k„Űkʦë÷ąáWIëÂ.§La\qlĆ&.˝La“é8V§ ›nă}‹lÉŢ"îš~c’FśFÎÖ=}íËŃÖb¬~dĚNÍ6 Žéˇ;ěÖNµ˙Ď~l7&ę$¦m$±í’áN 5ŢŽ¦ĹľąÍn“@í%‰n—&j–şŹŢmĺ~ß>Š”ŔíŮÎé#)n‘žâ¤6şÔnhân”{ Yö‘ń6’ń¶é=Ů‘ aîô^žőnî>c‹5í#™îŰ®nú¶’Ą9üľ¤űfÁřn€ďńďň&đ¤žýFpÉn‹Spµ6îço&)n ožSĽpSŮpfAáŞ˙6’ço€¦Ž(±đ•o–˙Á4ajáxpń°m#¦q4ÇńEAr [™đ_’!qGě#_ň$?”+/.šYëťđÓ&é/j’,,÷˙-ßňĽ&?Úš“ÄF’5ą´ŮşÁ¦3ßŔó–ţŔţ;w>Ŕ„@÷óŐëŕA7tŃYc74?tähEg˝ oôçztďP8úaôIoěD·t§ăj4Ôt5®đ ŠĹÚ—R—ŤcńOőęŞô*Gl‡:®ÎôVď­WWk Aj2_uH·őäÂuŁŃőiccöţuî ö­FőjóWYµg;vdçôî`mhŹví ví°aX¬őkG¬lůŮ8V÷öćwm—óđ+w­u_ďtr_wĺ‚wC™÷x·÷{Ç÷|×wŹťvMá§nßwőî÷$é*€řř7˙wI?řŻ:÷ń(x˙†oxšzxńřzźřÄŞřE_xŚĎx°ÚřHżn‰˙x ůď¸xw/ů~:ůwlŹ_ů™jyjďx•ŹůgšyîHů›źě„?’ťçyáĘůW|y›z.zmŻůŁ˙-·<Łgú¨—ú©§ú‰'°N૏«Ďú­§Š0‚đMа¸Y̰€°†Ŕ\čĎŞ¸‚~аOş·{Ľ— °ZMŠ…i¸VčV.Ă\`1ą÷>eآ‘čN5/Á‚HĐÉŻ|0/ěa±đúšĘÚěY &ć|ńIËW€Ěßüő |Ő‘ő€ (#Żt˙÷PÓ§}Př ’¸L{“đ€`Łĺz“Ŕ©¨­ŕ€ I€çý&®€'¦€ q•¤‹ßţ`b¸öPtübé ZжX ÚPöÇa0_öwe€˙čT(Ś[¶R(h°ŕ†ĆPyčđÁZ& ühKWŻŰ›bXű‡OXĂ‚+^ĚXđˇjţú)Sbb˛v2ëáűuˇC‰\éüŃűă!DA•¦ů8¸Á*W!€lZ°Â”T;ó!JáÁĂťjő”ÍI‘Ŕ±@+ś WĆÉGÖü˝W†ś;{ţ,aÍ” i+ÂÁ)ŕŔ‚.lř0â˙ÄŠ3něř1äČ’'S®lů2ćĚš7'ţĘ­2"R¤Ŕ X€Ąsj˛tę&„‡O\)eŠZ5k×BčhĆ(…¨h;L®0‚* ěÚÄă¶$©ôÁ{ví ©ŁOŻÎ!ł?\ľŔaAÂC#Í ˛€]ľ@ÁŤ B§ń8h<éRUPŘóÇp|‘BxčłIš¸Vçř° ôpO ÚCČäÁP|ôه_‘X8ÁÉâg1Ę8#Ť5Úx#Ž9ę¸#Ź=&–@4<’8™ĽuÚ%ÓĽŔŔ˝ĂB h[’K6IĚO‘Ď)ú`Ń|˙€×KrËăśU°Â=‰\Ŕ#L”šl&‡ÔBEi@¸ĐŚ9Т`L Ă>qć#˛É*»,łÍ:ű,´ŃD ±O9Eđ—S¨ńwkĚaĄJjÉ·„;îL‚M)>+ćqepćsIňŔb4ŠěV®mčîűAżp°Â-ţhF $Ŕ zPş˘Í;Č`Ó Ą“%çĄ1@l"»Tˇ<čn ˙QäCÄ Řě1P«€¨´5ÄUŽC.9ŃŤ‘e5đÁ ?<ńĹżŘWSĎć5ö%ټи< ¨“Ŕ ¦)=őÖCy(Ć`±Ě"6ŘQÚĂř˘ÍŻ"K]ýö˙Ý“0?Áő‡đŔŕ‚cPŠăĂ ţ¤·eâO¨ĺ€JH#đ1XöhÁýÍË ŘŔ `ФŕV©°ëŤŕ·E0¨P PŘ‚  ŔźFfI,°$x`QVm`"Ç;"“¨Ä%2qF¸Ĺ)„ P=zöHD ŃŹ8 zˇĂ5á†7ěďWĚâ—’‡cđI ×ř :X)l¦řÂ7ŔőĎ~ŁÉČ?ÁŮa_x‚š J1ÇzĂôĆŠeĽ 5pĄ´Ź@Ěá řŕw°7Ě!LN©Ŕęx /tˇ” zP„\3‚˙ Äě*X6Á ě_¸Áö‘ ĚÍu°$&Šm€ Fl"4Ł)ÍiRó^”ă`ŇDŹyÔ€ HAâ҉wĽĂ0Đ&7˝™‚,!uĘ:1Ź!€-0 đJŢ‘, ÁhYş‘‰“śćěç?:PěţŕI& ©taţȇ)R‚qZD'b ŚţqI[LÎâdk)g Žrk\Ä ŰâŔ¶Q„D!\°Áö iDبJęáQp üĐĹMŞ)Ő©RµŞVĹ‘^“&a@ ÍAĐ@ *ŘjWżš‚ 4˙@"ŕ@€¤¦7$«2@Îuđ*˘D2Ö˛Ş  čë_%$€¬n]J¤*Đ>6bĹ«Z ň:TV°dťâ`(Đ<Ŕ«fÝŔkÚ 0 đZHł`Ŕe!°Ú‚tÎiŔćU+Üá·¸ŤApĺܦÔÓ¤‰©g —·in8ËŁ[9»ueĚn ZüBŃu 2X㲷˝î}Ż—[ůÂwF0 LQM !Ú5 „Ŕ‚ó&ćľő=0‚¬ŕ7 "Ŕ®iXÓč ›Ę^° 9ĽŔ4)PŻb aHÁ˙&>1ŠS¬âa –îžé¦,pÂŚ …aÄâĹ0P‚w Óâ‡3Ć9^1’“¬ä%oćgČ\Ł ¦UtřX"ŔB,„âG€ %ľń )<™ĐP‘ 3ĺ*äĘYţ/“ă,ç9Ó AD 9&Ú¸?Đ2 T´ ČNyAžA xß %2ŕnP¦T3 ü hAÚĐuţ4¨C-Ł[]˛—c “Â08 hÁ.LvTkČăüaőAXTI|2jrĄ«b^p†uP AbQŽ{ Ł0¨.˘:.Ľ ęp‡; !' 9Ń.˙ڰ‰mld+›ŮÎƵ¨Ó­îućVUŔ0Šâ´3 …i p€ \t± @ń;ÄL»Ô°‡|`ˇą†ÁŔboáŘřÁ0†qÝ6!`A Zđ‚F`ŰÔŔB ` ŔÔŤřÄ+ž^Śkśăěľ9ÎAmŘą("xÓh?K׸6ý5Í­‚ą~ŇS˛ú€ŕ}„ęíjMă°âRpˇo*@YôŤŚĄŔ ¸¶^§$}°* »]ÝžŐ\ 8ě:+Ŕv@XWkĎEđÉ_$^؇ăÖ {Ž÷%~đ ÄÁđtA˙ÎP h@ĂÔđƵ±­oxś'ľ Ĺ7ţń‘ź|ĺ/ŹîśÓľö ^@.ĘK–|0â*~¸E=ü1Ž9h´#˙FŔvżßř ˇZŘâ–„Ľ˘řŔÇ?äˇűčD©ßdÜś ˛y‹ ąŕIďŁ4‚č炍X;s/…TĽă˘ŚXJîá»Á`ŹPFIŔCĚ  „J°„KlD÷iĂ7m8\%$ĚÓ`€á!ŢĂý@ ¬Â78žă©Ă:Ä‚#„pq€85”\ÉŶˇ ˘5@CtXwi zŕ:€ ’  ˘ í !šx0ě‹ÁI˙‚q°‚/ŚÁ€3A x<×=aNˇŻŕÁ‡„¬Č€ŇB|”ÁD$đĂÜÄ„ڤXÎSL€Ô p(Ňs =@HľźË@đ1(Č|AL€ Ô"ŚÁ \~Đ,śŔ4 83č €‡x‡yl ¸!ĘáQh, Ŕ+$aážěY` d€B† č–Ę ć™˘¤Á0  ş;Ä;° ~‚­Übę"/:^,ü˘ă0!7văpaÜ®‡+Ś‚`€'Q LP9š#:2Ă"ÍJ­˙|pÎ ěĂŔĹn\Ŕ`€0€Á5BßdÎAxL«ĹŔ6ŘÁźĚŠ9ř€¨l‚•ÜC#ô`Ŕ,TĐźüÉFl‘OëlA5Ä0ś °‘ ,24AźtŃP@ $×Ĺ\ĂOEŔzđ@¤€ÜŘâ`<ŮÂ:xĂxH@‰ŐUĽ€@2Ş;(c3˛5P¨« %Q%R*%S¦™7–ĄYZŐ ˇrM*ĹAPÇŕˇ;rť[Ń.áŚÎđLňĚ€>D Ŕ#€C:T?HBA†_ĺ´cSő><ÔCÍS N#ŻąN.ŇA4Ő>¨Aá±˙=Á &čC"hÁ2¸¤ĂÂ4Ś $@ faňC(„4Ô¤| _&=0·F. Á7l¤\!<ś˝s2''T%t:Ł7 s¦ŔĎ Ćp'Y!§ržĄw~g5ăZ2!].…].&Ą´ĄyÂe]ěĚNC@>®ÁA@*€Cŕ€ĚC(`€ú)ć2&ôCĐ€Đ@pâdJŚeZ¤Sdć©q¦gJh2äÂ'HhĐk.@áôĂá€}‚CŕŔěĐRŔ ŔÍ"Đ÷E_ţů!FŔ5üZ„› Ć„B,¬‚‚7 ĂU:˙#4H 騀ĂĆŤćčŽf@Źţ(xf©–"‘PĂ čZ#¨gś§E‚—rdyŽ)\ŢPɀІŔÜŐť# ¤s żđšeĐaŘi$ T lĂ!˘Ŕ–¨„Be~×DŮE΂0ĽLXG~$(HŔ˘3LCĚ‚9|‚Ŕ.ŕ)Á f«E5ŔA4‚ą$Ŕ`Á „b`p €°QĂ7Dž ``Ŕ čB Á <§36#’˛‡ő.`Yk®îjŻţęQ ë–n+·ZÍ–B(M¦)™$‰©]R@/ýR0%p€8&˙’Ń\Â<đÁdA9řK”„Ň(•RááÁ&uŇTŕĂ)ĚÁŘŔ+kčCEş\\A?H‚”A$AbQ˘%ň@ŠđC!Ŕ$č!p@Ň!%Ň"ĄIľîkżî“Ś‚5Ř­4ͤ>Ŕ*P8‚A<Ă7¸Ă74BŘęˇůŻţ@1\eç5#7čę řŔ“ąu -Ń-Ň*-Óv«ŘŽ-´pŔäÁKuĂŕ‰+đ‚ž}2DP„”&\”)°Ŕ´íŰĆ­ L€P=TQĹë­C•@Ĺ€&¬ĹEüA`ťTJ”HĄIŮ•ůůĂEpÁ¶0”C ßŔ˙ßAÜĘüF!ĘHp.˘$ŔĐĂ0€ËphîCŃCD…Ýî„>1®]@ Ŕ›ĘB>¸Áě5(ç |‚Će@b§iôÁ7P5l€-P:Ă—mŁS/\oň./نŻř* ĹÜťnőŐH…©¨Ŕ^2šląŐĎxŐ_´oäÖnĐ%€i©@{’ÖvšWÓähŔfUÖ#B@i©ŐĎ(€ŰÁ]`€Í Ve0ÜýőĽž0–c‘í^ťťžé…¨HĚA0@Ľc`Ŕ(§X#Ľ@” đâ3ôÁ €Á ü%pC1ś g ĂĹ Çđ Ź˙/'ńŤhďa1dhíĂ1‹ö6 “č'1čBJ®š\°@–A1€eš#<¬†™Á ¤€C!L+vx±€±Ď1×ń łj:Âhëe ­˘ °@řŔź09ĚÁ řś±cř1Ú1$Gr$GŠ· Żc°Ŕđz×$‚žźČqa`˛$Ź2)—rrwíŞ@)ex®)ż2,ÇrfDŠ˲-ß2.ç˛.ﲊąšGÄSÚ©žšł1Ä»]|{@üľŐp0TÖoKÖŘéYż4aKsr8Uű÷xö‡řcCt[Ď´vˇµS3‹†‡óL8c8‡Ż¸ś w‰¸ŤĂr‹7÷SCuq'FŽWô ÔňŤ˙ů7ő3§uqĂtK÷řBWs’˙ř! řŔP%)PB` 0@°DĹą™×±Z§yŚŁµ4ř“ݏ›O9 ¤A1P9¸:|:C(ř čč€T@pžąˇł]**O†h‘†%oxS4úJŹ:ďřšw¶AHşy#yś‡V8z´ Â2ş şĂ ŕÁ08Â*pÜ€:­3—ŔËŚ4TĹŁ7yqŔ ŔŁ; S[ú¦§´AŚṞ́ëx“#;a𺯇: 9Ŕ`<Ŕ 5°Á%$Ă09tB Ŕz­Űx1'ó2k!=ď˙™0›‹;yi?µ·¶”Żů4†·Ô茀Ř'¨ěĽç»S°{<´]ÔÚ­%ä«3J›ÔÝśZ†GsĽźZŞ­šř LdĽŔĽeđ@!,ă¶źz<@oÉc) °Ą{‘˙u9ÇŃ\ľűçz3ĽŐh§|SŁŤŚ»´“Ó׿c¬.€<\9›3C˙[Ŕ ś6ď[E<L<´´»Ýü ×ŰAęKÇ =ŃSCɇ˝;»Ř{\§ËĎőe-0iHsFô¸U§ŚŔ(ŚÂ˘fŃť$]/ť řv™·ŕű¶:ŁUţ Y@ËÄßĎUĎ‹ß%pŐjIłŘ=@eů˙ýjq—ä˙6iËĘľ¬}ţň3l@ ´+~„«ŔŮčËĽĚód÷ýŚVĺ—ţ`€éäg˙NW€Ďäłi RL]Ő>âg–`ľ^ŃŁśEB HżWuŃΙWŤő2žú b۶ż #řŔϦ=MŹ„EěS1ç8D˙LČ„őŐĂ/Ç(\Ă;Pl4@ü–ゆ üÜŞçoÜ6x¸Ě_˝qn:tа‘#.éÓWŻŰ›”Č•ÎăŹNĽ|7® /q~ĽDo\=p€Rl€&zŚ<„ŕŕŤBplx@¨@DZŢ`í˙>aW54đŁ-I“?ŞćŻź2%& k7·ľ_:¨LçŹŢź¤Tšć㥆Ş\…±ń`SźPm¦ÝćďÖµM<4fŐŔ±‹+ś W¦WTQ«>|˙äýRR¤Ů“9qŠ]VQ™bpőúĐŁnŢľwCĹ"D‰[¶Rŕ~‰Ň·xęHąűFJ]=LJh ‡{Ň  Ä1ĺ€j $ ”č`Ç Ą)T#‹Nú #ěÄS1“]¶ŮBСFR%šL@Żě®;ă‡s»#Ç\sżé®)HŔŔżyé­×Ţ{ńÍWß}ůíW˝K¦y€î˙I€¶¤%Âpˇ=rŹFq­ č‚ŔH4qWFńÁ„‡Ž)ĺ… >¸gc9;úČ’l&8‘Ś0x`#viĺĹAć‘â‚ H—ăś@Ę€&Ŕ…°#Ä8&*h@cFąä“S.Q38 `Nő)ŕ ^ęZ¨H ’ćŕ‰)&!Łzţ9č8-%§ ŢÎsŁ®ż{ěz؆ŽH@ŕËŽÝŁ®‡‰-ŇY"ŠyŕăK=:š€öYcolůÄ™îť;gŕř bcnwďý÷¤ #źSôÁbaôH˙ 7žaVYexĽsGGľ!§»oČÝßńÉ/ßüóŃO_ýúřś­h!‰Ř=-ÓĽ'@|ýqěR‘Y‘  ­ŕA šÁ‡Lĺh&%ąńfđăŔpmĽŘ0`zp‹t B - ČŇp"7Ő]  Ě@AúĚĐóB ®QŹ…řĺ¸P-6€ ©-Gžăöd UPŕŔ náM„ˇ$ţô ¶ p ě uÄş—±SŔˇgŘCĚ/ ŔŔ6‡™ţmD~ôpÂ"°±‡1Ŕă~ Ă”G0ŘĄ`üü°užöńŕh-,˙‚ ČX)›‘¨‘Ěxä&ŔˇRř@^âĘÎx°JQŽň]&čäúP™JU®’•­tĺKć‘ŔO~űPCýěq?äo9ń_Č45 †€€Ä!ĹXIh ‚Z™ŕf©° ǨC€` R€ 0*f2 đ%*¬ä űQ!Đ`ťMPëŕ„u#`Ü P@"®-’€)$4á§,@ šč‡1Ţâ‘]fq#©ć5ł ĆÄýŃŤ+#<ĺIzÖň–€#ç|©  qxEhiđ@^~ÄÉëYÎFsZS*d%IâQ’…–´¬jŤsÜz”@ö˙ş3ĘPŞ©äńA/_U©N•ŞUµŞG éř,aIk4| ěRPʧ"aŽ$íDy*ćĘš±‰—”ŁYŰžţyHE@s‚¸Ú[@¤1@ö„$mę>,€ÄGˇ˝QŔ&`Ů'^°·¤1nĚÔ]UçIŔ&HÚ3őŞ<`o 8ÇšŔµ’€Ż‚HÚ[=U iĚVK™-X`Z°,™ĺ €“0¤ŕŁrě_FpX€"M¨,l'  ­Ľ Án Ź0Ś)@m@«;ś5€RC”oI+ܦ˝€˝î AĂŚ…e,Âź9OúP˙ v čĐž#q=u°cÁěŔÄ ®a O¦×y€ â§jP’<"DsČÁ#Ź=Oýö‘1Ľˇ­Šy«"A+"M8Z†ŁËŠeĽ 5bö/Üŕ)NźÎ±†.0+ ŹĄ>N1‡1ŘÁ áb>lQ†1BmET1=w× p€vĂH€aĹŘa_x‚Ä„)ëaĹĐÔ1Ź}l@OĹ(sĐD… @Ľa$řT?lˇ".O`thG&ľP…¸:·Č$6ţ`<BmźJńŠťĚd¨ÍjN/!«tĄ,‘@)d6s©/‘j,ĹA1y8FŢ´pŤL˙ź2'8Â3ŘáŤ`S/8ׄťlqAPµđłˇmi[u©F B€LŚS,ŕ`Čěú´.,ă%0qFp˛ Ä@ţȇ)XŔ&^h @F&T°"éČE?Áę0cĄÚ×M72QtÂKďĐĆRĐ€;hCG&`°±óe-čŤ ´B„ &hLň!´7ľWµ6 ,üď0 Ží \*{ _2Á”4`Üî6ĹCh^–‡ëNE:ŢťŹ” ţ°y ¤Ň”Ž iŔÖB’9DG:~{:„t”ĽRën÷»YĐŁ˙"6oAÎľm¨‚„óđ P¦Cs›Ă€ď~˙IÄ—Ź:Tjť°!ť¤Ó¸AÜŕ†8¨Ń‡ŕ\•Żü3H±SO›ôĄ7ýéÉ—€¨ ߀2Ň€@*A4’š¬'f=uA(ŕ(@"ŘŔ^ĎÍ,@9ţÓ(0«8\ěłXQ=ë7ŕzŘw@ö€NÂöĽ>A!gqf˙ \Íü–€ú%PţŁ źöČ÷Ćż‘6ż 9âěi/TŕúZďőžE€öŠO1P"ü`CÇ/ţČŽ›†ŃŹö$ËočŻöT`# V‹üČΗ  ˛˙ mŔ#‚ďo/Ƭ€üpő pűé„AH07f$z' ŠŹ: €őŇő(A¤đžÁ8Á ĄđňžáL@WPď Á0 Ĺ0?rŹpxí=Î/= /'ŕ Ę` ´`ěˇ F/'ŽĹ 37ö†>öp:Đc C*=´+lBJ<âűđÎP:„bmŘCĚŠ(ŃCJŠH>q ‰D0ń 'č ץ#|ŕ¨P =Ď‹AŠ  ǰ]ńaQ•ŔޡŇaĚ€ĄZ´ü#+ń®*1>|ń^:‘=ŠŃ>. ůÄ€L±š|Ŕ´bq˙©±­Ń?0ŕfÇŮľĐĆŇp? q= +Âě>Âńôř¦˛¨Ŕ ř€ Á ” jęé±íńńŃ_α=‚Ń>öńôő^€rŕ¤12!r!’^p¤!ŮC!r")˛"-ň"12#5r#9ň¬†1?x±'±f:˛$Mň$Q˛"E˛>Bň#=’$S2&er&iRÚŽFm÷pR8€hŻŚhP˛$PD ˛* †ŹŹ2D€™őŃ%@^„0¶IĐ  +)°&Á2,Ĺr,ďĺh˘ ŢÁÝA1$ÎŰ.‰AţB>ŔćŔŇb-Úâ-€c%˙ęA€8ŔA”0 áń ±#` rÁ´áŞĆ."î ęAĆncÚ’!0"$Â213‘,Ił4Mó4qŁ’€ľŕ ľŔŇLe >ŚčN`Ü eôŔĄP…6€Ţ0 Ö "4†Ŕŕ€aꤤ@ä °ó`DfÄ šlfł6»ó;›eQ3=Ős=SŇfA iŘ al‹aƶ bň \ŕÖ4 š@ořF)$€¨"b ® l 3†‘:÷A € z ěA XĆeęwN€>¦aćC˙_ D§ŮłE]ôERBÇ+8 —Ž@b‚@ô!´`ŢŠŇaŠŞČ ҡř!<Âvá2T l€NČQIŕ0TC9Ô (‹z˛…^(¦>%—ş”ľÔ§`4MŐtMŻQF®F·«L kŕ >A踔  ˇL Rę¦Ŕ°Ca¨J«RŞ”’ŕ C7´Cʉ‘z*LŐŔ#ĆôjĽ´§‰MIµTMőôÜSô‡2’«>żĘžÓ¦!fÁ>A)X«µ^‹ `\¦‚KâŔŕ ˇSŽŽćÇhD čÁC˙[†w@jF€>˝ Ŕ EËľNő[Á5\­*® ¤Á5Ëŕ 0‰Ă<ĚAx€»řˇ`ôt…ÍÜ ÎT$ć– ʡ‰B wFÁ:/ŞŹ#ŕJĄ€Y±´<»5:•/a7‚˛ @ůZ6š€2­á2Mb1$n-[–$|?6kµvkőŁ  !'oo ›PŘËö–0))@UZŤejł‚ĘŔö˙Ž+3 ü´RÇv.Ŕ+ËŹk7qw>\˛0B &7fÓđXz´€tAęÄ1 %R=:wqY©JAwt-˛qOLtăŁe­!Da‡tńuawvŐ%pki—ô€qwż1w}÷w—|x·xĄŤŕpYéh¶qŽ $ź·^‚¸Qްy•·?L•†ww÷{ő¦Ź/2@ Ť—#+Á”–×ŕŔĐs{ÍQvĄ×}á—E© +Ňw}q—>äW}ş—őĄŕÂw Ę@nĎw#Űbř1zW‚ĎăuîZ,˝čw>Žfĺ„ţ>@ě˙8 ˝Ŕ¨ <"÷Ń‚ůŕsSÂäá4ń%É‘Kنo':ř7F¸„OXh—†1.Ŕ „{7‚7Ř׆Źć'ő¤_é= @”ˇŢA¸@ä‡%i‡mXÓf”I†Ř„ń—>z' † řŞŽń)Ř߼@R3Řy›Ř=ކ n-ţ·= \uˇ_¬ˇ7ĺĹ…ÉIŹ%k@pى‹+ů’7V¸Ž ‘9‘XWř‰Ń°wmJăÚzňx!îîŘ?&č=h! ¦ Š ąY’:“!}’I h‹ą?˙ ńÂ`ާŤE7ŕ%®Y16 ›Ţ¶öRă%ľoŽđ6'›©±B<|@5FaŕV®2›_"GA«ň&ŕ_“zAXŔ&.@lqďihO ˛đőV‹őŽR Z€™6† qŕľ řňmŢYü¸2ť×bîjo:ń˙^"n™é&·rl™PU@1Hşlâłü 1Ŕš•Ňm%š™´ňý˛’#j:  ‚ ąo+yŇ'!(W/â‚(ŤŇm÷ČŽ))ú@4®śÇvY±˘k˛¤˛¸H`'ů=†˛(‰—ňš;y@H§ż=Tď˘Ă€)Uŕˇ@˘˙Ç:¦{řiDđc0=Äz­ÝÖĄŃM:ş)ŕč ŻőúXÚ¶E Ů¸ďŻ!PĄ7űšn癟Püj/âpĐo~Ňä¨y|řn,^B/ŚÂ/B@ßÁ¬Ž&0ätŔJŞŚ†ÜŐťŻ!-÷(łó2ÇŽN>ŔĚsßęŇBĵˇĽ0µý%Ö¬dÖ,&RŚ8ÄI ¤ÄE` /†7űčVńD|á Ć€CŔŕEđŔ;3¶Y¨Ó:±S;çÁ<ŘBMi8• ŕ 8Ő9:—ů(ŤŚá¦Ŕ5ÍëxÄG€dÎqCQš!*¤‚ŕ>…ÄČŇě Lâě<ľ]„d@Dá Çŕ ¨oJfä8‡D>Oië»~ ľţ(ٍ^ežŮż@)˙d W~%X0VcC`—lAÜŢ Ň¬\f’A”śŇÉÇi Ćľ G€Fh˛¦hŽ&ěI&fű‡ `J.&ŐG€TÁŠTd>eTţC@E  Y)•C=tLrŚQBělSÜ>ĺ“ěo”Őb?Z€¤´lŕ‰§b‹Ł]aśTź côKÝwß'€Díóaz¶’†g|FňG#đ+žs÷ýi˝˘xŽĎ˘âfwn‡Ţ6"ýŐ¦÷ăS>_5[&?"ś|X\Łbc˛&)0` â  (×h‡-׸ŘĐŚŹ Ě(E„Zşl˙‰ÁÁ®.pć1DkDŚm‚8*›+‹®ĽŕáP-* †ŕ Ź %Uá  (¤ !ŕR¶VÜKÔˇQŁ.¸h¦'G’*xPĺ*DŁ*Mă±rÂN;$HdÎÇ޵óěđ3¨Ź 7öĹyX㢎mzÁŕĂ˝FęŢÍ»·Ę— “¨08‰Ă‰ Ě’öµJ*ŻqŘ!DçR/,čEŚEÍřäh[8Ŕ•}`&Ȱ¬yłöíÜ»{˙>ĽřńäË›?Ź~íĄŁÚ0+bÁ"mďakĹŁBŹ[éPii‘whŕĐJ/č’I÷ČW±’˙WÔ‚_ pŔîˇ=RŃLYŘcĹ ŘÔSŹ?ţŕSN!pŕÖ5nä@H°ôŇ+Ü€&a´@‚ ŠhĎ‡Í ´ÁxéŐŇJoé1F8!~-)Č ‚®Ô×4E€Ä>żiöa#M°Bź}VjĐĄš.µĺ‚Ś4ŇyÉ_mą_’K†Đ’–ü5ÁŃ(žzÖŘĚŤ/ąŹ+•yć[Ah˘O"Z,Ł„ ;¦ă#&$PÂ#ŕ¤S ?ˇ´$Ó&í°‡Ęá€!i‚ÂŚn[¬ÝH(  R•Ą+#cĘ*:c…9>qG‡,’Ź<0Ŕ.JŃE9O‚5ŕŤ@0 OŚ˘Z´'“Žŕöp†NxRR*f3mÁŁůTÂ/HF® P´ ĐËüĹ:ěŕB`Á~™HhF ¸)LP°ŤC,˙0Á7ăĚ|‚””ą—·cĆ´ Fi‚Ő¸4;˘<„ Rđ!’`™tÄU(ŁŹ0xŕ!)Ř"ĐE値cŘłPş‰çäp«\íŞWsh‰s¬ˇ ťčGpV,ă \¨Á.Z!Ą=â 7¸Ă>Qî`ý°…ë¦Ř‹a’¨‰Zđ ŹMtAnaS5¦"•©Żc „@(„) iąÔú! 8|ˇ oČöđ…'xr\›€pB†€×@„Ţ@µ `ćĂŢ0ÂJrN‚˝ä`![1‡Ŕ˘¶cÄ5ř0ŻĎ†v´Ť˙IëZŰúV;öąsxB Ů}pv@t ëXË˝d¶¶Ĺí0!j?ônVŠdŇ®hI; LŐ˝. ~"“Đ!rÚԮ皖…r0Ę…5Št`Ż}˝ŔŃ´=Ŕ üpĆ F0ŕwL;Ą‰°j)/ěŁYN#®˛lă_čŠ(nÝO;ŕÂVič{ŰÜÎËąĐ}Ă*@|śbc°NĘ+ÇغαWęčťĂęÇ>Ř“ke3Łą1Čň–»üeé€öżoŔż’QYÜŞyY`¬^PČě ŰŘx@”ŻJzŇ”®t˙wŕ‡jřŁĘpŮ:P‚NĽďĐĆRĐ€;hCţG&` I”†ČGP×ÉK˛pE AK4â ^ @F&¸â;XÓoH˛˛i€QČG4‚ůc\h.Ó"]µ(¤ţȇ)<°= Ă G&X@‚)¤#T-‘·lŔ | őx‡)`p˛taĺ>÷‚ť–b{»îőK|ůkśÚ% @ R‘Ł`ZŰžCŁ. î­d@ˇ~G:ęajYăćö@űm—`ZÓśö´â0PrĂ`©F *p‚ndÂdZÚ8p'§"EćVËĆ;˙ž–ÜC v>şíu«ČÝʱ¸&ŇáŹwtăÁQ °!¤3—Ö¶&öJ`Ť9Řčŕ0†Ë1 ¨[t-HŃş?¸N‚ l Öű8ć0— d…÷w xîs  Ý{g Ňᆬç˘ÖąZVžŽ–w hČŦ»Á03ćO?|pôckđhDëőp}®rţoŘÇaó¤7}=Po‚¶„Ľŕ/‚‘ÖíďhDŮż÷ôJVąŁ ]Hŕ‡.‚céěkű\m@ đ Č&kZ‰$‚T €ŔůÓO @@; `€ D0—-]ru‚(ŰŻ7p~Da*p ˙â—~ Đ* -Q÷#  Gł \ůâ: đ} "!  ‚řhR˘‚× (%ě÷!(x „2€9tŃĐ&#¨éGqÉ“>©40kq7 ´đ Z•ŽO •Q)•+QŃÓ4$ICĄˇjC˙””V•ŇÓ•“¦•µŔ•.3–ei[âjiL攢0R¶–0‰•Si—w9QŔ ő  C †x i—˙@…Yó§2R—6t+;9—‹cC2•Ť aI”i™6¤s‘™nX‚ šˇYq+F)š§‰š[e«‰©ů’Säš±i—°)›µi›·‰›ąą«i­©›I›ż)ś•‘ĂiśÇ‰śÉyCĽyČů™Ę ťŃ)ťÓIťŐůUĚIľ)śĎiťÝéťß žáYťŘůÚů›Ü)žé©žëÉží•ä 0™t‰ ž)‘ŮCź"YźůÉ–îéź˙  * éźňiÚźü‰žóI—Š ‹9  ˇ*ˇęY  jˇő™ŹŞˇý9ˇęˇ ˘ąYˇŞˇJ˘˘)Ş˘+ʢRYˇ J˘0zź2ş  Ęź-ŠŁ9ŞŁ;jC/jŁ' ™&Y˘?JźzŠ5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ 6há*R€„řáQ®tţŢeR±RÍlé™2Ć ‰š7›ńÉq቟bĐŚŹ‚Im‚`ƇG‰Q— µŠŁŇ©NŻ~Ěş"ÝşN„@A b/z%ŘaaMŹ+!ů ,Hzň5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(dH‘˙:^4‰2e‚*TT¨AÄ @€@‡–äú%óD>F<řąUĎ߸9~˘„ Ŕ0P”“Ta+_cĆ€bf&ĐŞWłníęj” aât€U¬Zueĺ*‰µZŃťŠďZŻ}C|¶’ą>”Ó‹8„âŔEBŕe_©,WöQćkyqćŤ8lČcÍß»ns8xpĹ @Č2©şgbnŘ B ¨0;U  Y6')]s@!ů ,#‹!ů ,#‹!ů ,#‹!ů ,Yz]hHp y˙*LA`A‚Jlř˘Ä…+jx‘ˇĂŠ;fŮŃŁĆŤ%˙Ť|ňbĂ[NĚ“dÉ•ebüČ2%N‹7yćô DL˘Ž=©SáO>!ů ,#‹!ů ,az˙h¸€A†‚ XČ„#FÄ 0ˇĹ„ >”(‘âĹŹnäŃăG‹!’śXń¤Â#Išt©!eLŽ&)4x @‚„)8lPŔ'Đ›+V’*ťż|Rxđp§Z=esR eYˇ‚lĆţLó%E<ú6eŃÔ/ĚÖ’*Śđ †Š Rp¬Ô‹ zó°.űua±F3=<8phĂlżÂ.@C‡Ć× _¸@ąH=Ě6ś€ŞEŠŃ$öö}Á`®^ ˙ŁXaðľt™CâlÚµmßîVš…—5ďLĄŘ@ŐÚŐ7Zuçl ŕѻ͎ąĄÁŃ(` (R»ů“6µ!ů ,qz»Ô@° Á&„ €Á‡Jd8bA‰ ):´Hă†;zü§1dÄ‘$Pˇ‚`… DŚ$Ů0!c-Bh¨p‚^™™ °9çcŤ =îĄÚĐŔ•yG¶¤[e¦cDÉGd¶=cŕÁ Fzq^˘…(›¬ÄFś¸*•Z lń ;b×?*a#´e77&8pŘł­H(é¸Ř {A&L(Ŕl‚,Ç'=– 4 !ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,~zš5(Âżb HĐ`„ |QâDŠ#JtQ#CŽ1PŘ @*T€|ÁÉGÖü˝Wd%Äxězň ›  š'ĺÂ$€f¬ĐăV:TZZäPúO$FPÍBC HȰ'IĆĄ{}ąqg_˘® öTóç\¦źg«VhpR‚„)şZÔ Řb×€!ů ,#‹!ů ,†zž5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ &h‚!B€„€C‰\éüŃűăA%G#ş|‚+[bx Á®V9VnŘ€ŕ¶wȰµzÓ‡NÇębmęĘ '– "Ab@-Ż7'Śpĺ«—G©b„X˘S5ő´ýI±R`’$HHÁ÷¦Ç‹sŻ !ů ,#‹!ů ,#‹!ů ,#‹!ů ,z¨5(Âż HĐ`„třđ`D‰(VĽ(QăCŽ =BLĐ@…  @Č Ż˘ĹÖLťäđH —D:çc‡d˘D"Ä Ę>0dě‹#Ôâ„าOJÓ&TÍ@¤i>®^¬Ń¬Ś6L9Ä j80iqbH ?]:¨Ő@@†˝4Ÿˇ…Ö/2ĘĹ…Y=MCr^!ů ,zR5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ „0qa#GE8X ÁG–^žě ŁF†,=^´©3g͉7ú\y˛çÉ€!ů ,#‹!ů ,#‹!ů ,˘zž9pĐ@° „&ÄP°ˇ† 2tHbD„)ZĽŃáĆ~”  ¨P1r!Ž[ő´iŞFoNKŚ@šu1´ŹĎˇeEę]Ä٬GzR€0kâoč? 9ŤÚKÚ̉СP‹•â˘S§Y©Řč !'•«ÍŽ-ëµ)Ö)é” 8ĺš·(01Ţ xAbůĐéSŠ c!ů ,¨z˙Đ@° A  „đݎC‡ś¨0!Ç#śh°âBŚ%r,čŔE˙4Ž$éń$H•+¶DŮPe‡ @PˇBC‡ $ !E —5†¸yśżqn:üôp§Z=esŽŇL)p AďŤtŤŹxômʢ©_¤!(QRMP@eóáX© ô"ća«Ć%Yö©Ń€!{Gj4ÓÇ6̆řŁ©±G–{k:†\e0©ÇYŕÜş$đ‚’Ć×ď  pőÂ`X —ŻőÄ’5‹V-[·p!°¦ÄŞOçt±Şµ«o´¶n`ÂD…ś;E,ÝpA(QŁÉkF”şR Ť&{ol?“s@!ů ,#‹!ů ,#‹!ů ,ąz ˙Ô@° A  „đݎC‡ś¨0!Ç#śh°âBŚ%r,čŔE˙4IŇăI*Y,ůcL @€ B…†8(H ABŠ5C Ľ€ó8ăÜtęáNµzĘć EŮPĺ‚ę!3čđčŰ”ESż0I!&<c› $€Ęć#±R/,čEĚ×” QdŮ·†`6öŽÔh¦‡m ńÇUĄâ}jC–Ś­2‡ ™‹Ôë,Řş‚Hä%­ďß ŕę…á°× aÇ–=›vmŰ·q»vscâg«Pçt±ˇŞ5¬o¶˛Ţs§ !€^ZôhrÄY Ä ňüMő.}!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,$Š˙H° Á&ÔŔˇÂ‡#JśH±˘Ĺ‹3lčPŁÇŹ CŠI˛¤É“(SŞ\ɲĄË—9ÂśIłćGŽlęÜÉł§Ďź@ úS&Ńť8ŤnLšs!S‹L*Ä9P)ɨSŁ65¨ő¨×Ż`ĂŠK¦Ő˛*±:}а+E­[—vxV¤Ú¶nąŢEË·Żßż€Ç|ę6ę… @€ @ 6ćŔaq $P‘€b0Qˇ‚$¤HQ: DV·cíŰy ÂĹ››î^‰¸¦Ú[÷o‚»ĺ&ĚĽąóçĐk — Ŕđ…(©ŢůŔ(„ç;ŕŚ˙sÓĂ#e0kř`mŽŤ†Şč§L éąŇŐÓu p˘p$ó qµU7ťpĽ±ĄWq :Ü‚ć4]VwśoFçᇠ†(bUµĆPŔU@üÇo|QÁ‚ÔČ\#°ś0B*8ŔŚ6äÁĚ| $lŔBSD ?klŕ&° aĂŻĂC…`vX‡T=!„†©fr R·V]$.7âśtÖi§X·±ŔÂ,x˘VĚ"Í $JB1l#Hˇ€’Ť[Tů`áÂ1Tذ2M¤€$„pHŔ ĺ4bĺ×paCÍ˙ÂĂźkZHá›pަ\™Őę+qiÎ…«°Ęyç±Č&«lZZ†G;íŕăFH¬|ŮHěŁC°aĎ.4„&ú$˘Ĺ2ö­pK:š„Ń &$PÂ#ŕ¤S ?ˇ0äŔ.›đŔŞ6Tűë‚Ă‹\‚mşQ…ĆĄkÄlîŞp±sHqĆËvěńÇ ÇÉÔ¬Äa ‘­q€­¶ që-¸â2áŔ1päň‰4tĐÂB˝ hˇI?ĆŘW@*ŕÔĂöHr™śsÄ"´Ŕ`‚z3Ř0Ç[Ě±× [5qpÁ:lćńňÚl·]gmj€Áp*Ě n˙3PŁŇřŔĄ3ÓD0‹9ź„ŔÁźbÂ1­đ`Ŕ.ĄĽ0ÁŃ8­ÁQXG4\–5Â[g˝±QpЬ0aŁ‹1Ădn%gĹn×nűíeŔýHóbo@ă57ćČŔO!L!„`Ç_<áE3Ů pÉ<|,‘E9ŠtŚbŤ=RÜşÖ`w…prjżn¦µë§NzÄ ·!îü÷ď?PY; vęáŹ|E đ6ü1Ž9 (w Ç…|pAŘ2¶CŹL° &ŇáŹwtăâăŔj€ /q ~erÝü†•ٱEL±kŮĆN— [µo‡ŞS]S˙ö÷ż"ń+a4°€Ď@—!  ›¨@ `Ŕ9ŕ$`1OĽ LŁ€Ĺ\Ń1”‰Ŕ1ô3Ú&~ůcZ–ł1ޞsŁsH?Ą¨Í†2D˘ IHŹ2W-Űcéšň)…t@ äá‹ôl$+ Z SW•ü‘mťlKŻŕ8!RrEc1Aĺ`F •Bşň•°%'M‚¦„PĐéĹHđČ´śî(v,›"cIĚb“śČ#— q>1%D’yĚjZóšŘ̦6·ÉÍnzó›ŕ §8ÇIÎršóśčL§:×ÉÎvşóťđڧ<ËI €9LbĚH˙Ĺ}2F”±Św<ł™řS"MiN“šŐ´ć5UĽ"ę4P<ŕh&Vł  ó§D;ĐQ/6´3žůĚ{9Ď–şôĄ)ńž`‚fBD€Ů)`wBĐđ0<ćAĎ@ŮăřTĂô±˘ňłźţ @J 7ß4` ąđ‡6NQ pĚ!Vş|”1T«§ŕř)ŠÂZŤz5řNZÇ"Úő®xĹČ@áZ”A«±éAVÔ˘ĹhF5*Ţ5řŔůHB"’‘ţŔ%1ÉIP’•¬„%-q <,ô!‡<`:Bđ ŹMdahaÁ‹ŁĹ˙"ʵ®…­lik<äő·Ŕ .AdCGä™(‚` ¨AęP‰Z ő¨HMŞR—ĘÔ¦:ő©PŤŞT§JŐŞZőŞXÍŠ)˘Ý‡€ĐŚd}j¬\Đ bś şyŁ®âű‚ůÖ÷ľŠĘŻŁ|ŕQářŔ/­çаŹrÁ.ČË"35$\ă*׹ҵ®v˝+^óŞ×˝ňµŻ~iŕ_XÁ$Üc˝í}ŻjĐ 6R¦ Ě@Aö±šŤ‹Ć6ćŽuĚă ‹ëN˛’ßIࡩbAÁ2áTŘČö°ÎtĆ3źMhD3Ň”Ć4§…jRŁšŐ°Ć$á˙L`Ż{ŃWk°ń0CŢń·4€á#°ĐĆČł·°Śä%úĐă<ŔŚQcüI,eî,î–·˝őMş€Ü+g8Ä)Žqźz\ä@9áaNsśóčDÇ™ĄOܢ‡ÔÉŕ‚#.Ł@8ţ2ŔÖ¸Öőtyí"úŘČĆ&nq !p†— Ů]ď~÷† O±Ś @$–×<}@OzÔłöx =îy|â#źůЧ>»X 1{÷j[ŰÝŇČFµÍ6n_ŰŹŘŢŰľM¶ŔNLĹ-÷!8% ¨@:06ś`ą€ nĐü`GX¢q…-äÁ ŁÂ€,ä/˙¤`>šVk¸ő )ŔLOŹÚ@ńµĽÝp ±:Ľ®şĐ‘HŠÄµ‰`„"OUJEŮ\1‹[ěâ!F’Q @×ŘƤ0ŔŠ´ŃÔE° |TXMuDJĹ \Ŕ¤ŞA)Ű3ôşŰýťŤLH/#9ÉJ“ůÔ3e÷»ţđľe.wé›ńŹľ÷Č}-ő±ö1?óÉŹţę—˙üűÉľúż—ľöQ&‡MÔt´wţ˙Ř´ű훿ôÝÖ÷«/~’ çŹ꩏}™ěOŘ—żţŃĚúż˙lĹ×:ű7€˘g6¤Dľ‚+čµGDř€‡—}ȱ€ŘÔ1~ď瀸 ·d´ ‚ "p$(‚)¸Q'XF$xE,}«ÄJX˝·# ˙°ňđňŕ§ =8„ő„;č>„B„ňP„:ČIh Ô"M6X…V‡O°…\ř; …]¸…_†b†a8†d¨Íd€W؆nX‡qŤÓLÍÔx<×rŘ8P‡"y8‡yó†‚8„X†xЏŚŘŽ˙ř…”‡<‡˛‘µR"Ő$Ĺp§v)eFšXR pR QO÷‰¨čyŔO@g8p űˇ Ő@sđhĄV$ĺbĺV_WąHW»Ř‹oW!S4ey©¸ŚBWO pu@ ýđ €OÁ^]`űŔ‡° |"ďpó–[ý¶[řÖ[ăČoaE±W}őWĹŚňHpMöÖP ‚@ őw!gY k@Ŕ J ř(`ŹÂ_ţe_ř5ly ňE_ÄđAG\Ć…\Ę5ʉl Đ ô0°2Ę8ţ>ěĺ=†}d"'d9¶ck@h*ycĚP6Pа` ˙ö`–‘Ws!ps9·s=GsT›Ľčr·’)’¦9ś†vٱ‡ Đ ĹtŹávť(wĚIRo7Šq§EGśŘ‰h !x (7qÜ˙Y~ŮYžćhžę)\čIMëůžěI |2ź|D…đ™źúąźüŮźţůź : Ę6öW:ż4öç€äY ú?Ôt0ČIřů Z;´3 0u`$Ą‘‚W´ˇ!(Z Ş" ‚$zś?tˇ.z;*.Pŕ°K@ŁP(A3ZŁ7šŁGŘ<ŞŁ=hŁE`ŤŻÓ /ş¤wBDŔdĄa&0Q:ĄQzĄQú™-ʤ`Ú1î9őäfę'ŕp¦g*@lŠ"jʦfę¦pz¦(Bw #aÚ§;q:şřP1¤Gř$¨‰˙Z¨‡:¨;¸¨Z¨Eŕ_ę§Ú¤‚ŕZ¨…X #p4€Ođ©VĐpZhŞX@'@Ş¦ŠŞŞĘŞOŕŞB`5;Iź™Ú«É2KŰů)"(x•×8€ s¸7p¬P¬źr¬rÓ8Ęš" â«ÖŠ;ÁJ‡á­ŤÓťró­ľ1‡á‰¬Uĺ×z®šÝšIQxźx–ǧč:ŻôZŻözŻřšŻúşŻüÚŻţúŻÚWp> ś{°G:°i€°ëJpľ WCš{±·S‚ŕ E §ű±IÔžň PCp ›˛(!˛# \b («˛2k,+˙QxG`°3ŰłoÁ˛#A3€”ëłFë{í)0´€ ôr´Pűł5«´#@Ëp¤Q›µ˛´ řG6éyP.ŚĄµd›6ŢçGc’Hh۲!]łe·ž¤?KŔóŔ<+·|[p÷ };¸Î±·„{¸›¸Š»¸ŚŰ¸nČ+«xYR“Ž[ą3a‡Á^Db¸–Űą á R p빤[˛Z:»«Ą»ş—g¤a€¤¬;»źë&@>Éđ –J»Ľ«ern—» %Eۻƫ€q.`g”{ĽÎű0Ľ‚/;şĎ[˝ň3á2…f˝Ü;?Á7˙ŔëXĽÝ{ĽVq9Ä ,@ľĺŰ»{dŔ TíŰľ .Ŕ „@-ő[ż-ÓHiŮż<Ŕ\Ŕ|Ŕ<¦q§±ě›N'ŚŔýz|fĺŹĐîÁెPÄÁĽŻ *´ď  đđ~be‡×° Ë0ô; [ˇP—Ŕ B`Ť0Ł 4€\3LĂ‹źĄˇ­’^Ŕ `Pı;÷ AD >Fü°ş‡â ‡`)€ž P, 9@@I–”ĹKDp€@qESđ00Áq{ řtPměĆ;¦f *Í4Fń˙8đö„–{^JČ˙jᇔڏJšÉŤ«Ŕśě¸žüÉŚĘá(H‚#˘¬Ç˘ŚŻ'Ż8ř„L¨„Lčőp@¬ÜĘ÷Ę€‘…dč…fŘ…;Pyş<¸qx zȇQ(Ĺ,·xyřŠÍěłk P ±Š/" Ó|´«µ„Ь,ěĐ ŚŐL‘;ąÝ|ÄUp „đ;u°`Ŕ™[c6€Íë<Ż+`ý˘˘HŠźřO<'7 ±ŁĆşÔŰĎüJwđbíĆVľWrĄ‹ Q Ä®ra9{Ş ŃůĘ0Ćm”™ĺ8[çx™Ý9Ł-Ż»$˙íŻ ÓC+ ‘&I` ˇ=^‚‡¸«»~YÓöę/»€ 9@+1É’D–”}ĆÚ6 _ÂE ĽÄ‹ÔúzÓK}^ Qgwć”DfaQy!– >PĘËĽ\ÍŻ'ÍÖâkŔv—FlŢqP ĄĐÔí:˝q˝Ż@čclăXoĺřoůp‡AcfŔŤ·Ű;Ř÷Ú7_Ľ2psĘsŢ1s?·wkŚ ^ ľâĎ–=Ż3˛íűĽŮÓ‰vž8w˝$°ű€X<諾ąśÚLŠ¬Ýą­Za%Źp îa‡ż™rĘ!Ę$h‚Đ ‚Ň‚Ôí‚Ń˝‚Ů}˘˝˙íŰVČ \ЬRv[ & Ů ŚżGb˛<„´<„¶l„PřFHßMhßłśßLč„A…ü ŢŽĚj⓯ŠĂÁĚ…hx† ^†żüŕÂáŔüËjHŕ©XCöÉ®ů¤B‡aVfĄĚá‡ČÜH$>&>‡{ŕ%ŽšâÚ¬˛«á}kŠMăqKhđ1‡ăq»še&đHK°Ęx++9päëăüĘ ýŔ5…< ۰ŃÜ’ ˰P.ąw !âŻđ m ;±[ÖÖ ęË7K±¨ćČç> ö,˱¨=áŔޱß˙mç¤çC 2'>$Ăs&ËF.đŔ*>é­čĘÇčbm¬ŕ´˝$ŘAęaęś~çîgła%¨ŕ ěł:+Xo=-&ë;›ęɇ¬îV ŞŔŽBK´Ů Zm,5ěkčşţyÍ÷!jś*zş´Mű´€»˘p5AíN»sÍľ{žŔŁ…â¬ćU{µÖHîűŇĽ´V‹µßŢé¬CĘ}Qv0`¶ćě[€ş"mü>¶óîzcnÉ÷îOöÄá¶^ŇĐł` 9 Śżé?z°Ő˝× ‚ST9Pł"°úŔ+\w›·™ËĽĘňz{ńŞç9˙ŕř˝„Dh .űK7"ŹPr@żvř·ëpµ %-¸‚ ó©çËdHá>ÁŔó=?1#-đ#Ţ®ÁĎNy«ř‡tčâÁĚ[[źĽś¤h?|kŻö›üő҇đ›är÷ŕţö9D÷xo÷Ó—ç˛1ŮĽ7üfLřŻĽG€Ę÷ž—ř˝ž÷€ż–‚żçpć řđÇölËřCGćqC‡Ź ™B+Rů,átŤˇćŕ< ˘OąB|śßyön1ľř¤Oř-‘†` -ŕKeĐú’ĎGnż÷łźlČŹ1·_üŘ«űŮlŚŇâwĽŇiÔŹ"áB° ˙@Đ÷©™źřH1ÉOűË}®?úQú…źĽz2˙‚Ą'|rň0˙zR˙{Ň'ѡŔ•yL¶¤[e<„6*64hxxńbÄŚ#jÄČQäH’%MžD™RĺJ–-]ľ„SćLš5mŢÄ™SçNž=}ţ:dČ™ hŇŚĘQ’Üc1!y˙úÉáŕÂ<íÚás“〩UŻfÝÚőkXHč9Y„mĎxGP&­¸ń¨ŃŽC!ú Xđ`Â… FśXńbĆŤ÷Ő[ÔčEĽ<Ť 1ÁŠ)SÖ qxˇĂ S IŃ,gĎ µŽ.}:ô˙âĽĘC ‘4Mâµ0ÓáĂGž\ůrćÍť?‡Ţ“ŻĚˇz5L¬Ń)Ô0|ŕ;üC c!z/Ţwy*śxJ•Z°lĺPý›bpČÖŤWŹ.@$°@D°9ă^ŞŽ(ŕ´Ă,° *›?Z‹NşN)ţöâ ŔżL°DOD1EW<®ÁD|8˝.ă.¨±öئ€H‡ B(‰29ň Ć=b1I%—d˛I'Yt&#±űp»Ě€ëL0ARř1Čëö)Äé>BňI5×dłM7ßÜ©A9çŚR"ő˛r0ń ĘŹ$!ł#’NˇÎ„łPCE4˙Q(édtNŽdÜĆ+“űÓ†2˝42E7ĺ´SO?U¬ŃF‰É!ŚzîTđL:U8A…5VYgĄµ%9I ´V]wĺµW_6Xa‡%¶XcŹE6Ye—eVą<›…6Zi§UVRjŻĹ6[mß4ÓŁg·7\qǰHŁľ%7]u×e÷ŇŽĐ|wŻxăUkŰĹ7_}±­SÄ~ëŐÝ}&¸ŕ`]ta€ńŚĐ`‡†V…'žláHŽ8cŤ7fs˛żćńÔŹĺU`ŽOF9ĺO15Ye—_†YÍV]Ľ7f›oĆĹ™l9gźz9T3z¨ç ŹF:éĆjVşi§ź†:j©§¦ş˙j«ŻĆ:k­·ćşkŻżMM#4l°ĎF[Ń3Ë>¬l¶Ó†;î&×N3Ôş!“;o˝—¤{lÄÜľ{oÁ7°ďˇ˙ümÂg\čş' pż§ĽňĆ ż<ńŔ-çĽóČßÜ0É÷ĽtÓyÂś±ŃOg˝őśR_lu×g§ťAĐ']sÜkç˝÷#Q…|0Ů}'ľxŘíö;řâ—/ýx˛u'ťy雏şÝ§ÇľÜĐłçľű”÷>|ńq"q|óĎ· |ô×gż}÷ßżiOřç§ż»úďÇ?ý÷çż˙˙`8@Đ€D`¸@6Đ„`%8A VĐ‚Ä`5¸AvĐ˙l t`NpHŠ! M(“ 9@I ¬Q•iô5ţ\tŕ„ ˘p…~čb…($˘řXC6źH €b>xČ&@ŕ$XbĹř PŔ$PIH `š€… ?jdŁáX HŚ H€ TЧl`}ě@ĐAⱍHA â8Ç:ŢqŤŹŚäCđ €K€ÄÁ5Ü  R‘k„@)C‚ďŕ5ŹFŔ W¬%h€–úIl@ Ře )ȇL(" €/“,¨Te)H\€™!˙0yĆ8@Ŕá &âHŕ‡eřŁĘp *Ă Ăw$§9Ń©Ît,A na‹d#0*ŢůkdBăÔF:ęŃŤ7H’ťřp'<şĐ†>䆨†?úˇ %`ČđJ;ęŹ_¦ąH‡?čńśP•¸b!= ŠZ†q$B*RšD¤Ŕ¸C5Î9aÂ-Ň{čQśŕÖđÇ;ĆQ„ďś4Ą+m© MˇpŕÚ(BV¶IŔ€Â´("·ŔçPC:ŃŹ0„Ŕ=x‚+jÚÖ·Ću®ađˇšÁ";0I*0Z Ŕ˙.6Á·žCHH…>Ŕ€»ćuݍěe3»YäŕÂŕŔx Fh!Ŕ„ q]řđ€ >đH/­aDKS[–dBFŔ†1ţ08|!Ŕ>6‘Mеl8‡@ ôŕi€®=ńŐÂŕ!·Íín{€HdwH†(<0Ö.’ŹČ82AŐ’¸r/`ŔzA |ţ“¸.}%€LŚ–€ ů8…>°Đ4Ţt˝p,dŹ1Y˙ľ€+¸G".Ŕ ŚŕŔmMđ‡C̢THÁwH@‚jş zČ Ů <ŕ!ŘE+đZn"ţ¬bG˙ŕ PŔ@ @ Hc”â XŔ€ @#$! Ŕ ć!…­Ěř;=ţqs€*ě Á>âŔVúúŻŚ@Ă>ĘQ•#n­áVÚŔŚ"ŘÉĹ4MhhqŘ(…čĽŘĆ>v¦ě+yđŢh(‡‡v©%jČiOs`·đ‡&ÂĐ$6Ö‘7ŔBď@6Zadŕů! 6 mö‘F¤7ćAW(äšK]*Đ[¤ZhA Yë[çz×8‡"†¸)˛Î¤@đĐŚr4‚6ĐfDü«č şĐŔ­¦]čîÖç°‹qGŕ ˙UčřŇÖôNĐéUâ{Ţ g¸4 …꣣˛íNŁA‚5vÝÖ"ŇÄIÉç@<ÖŘ×ő˘cĐŰĽâşÉ†ʨ# BŞCřiÇ?ňoW@Ń0@$bznŕ ƨ‡rYkny_"/hpA`{`°€ÁIŕĘ«g}ëř<(Ś…e,ÂHÉĽö Ó˙@Ä/0÷°ĎďŔľ‚cŚçĂ f¬đebƨĹČ€JHCńhě‹'A =ŠŘŔ `Ф ĚS®2€°őśŕ }@a 4€3¦Ť=$ÁxÇ“˙ň’?v´ 2=€¸Ĺ)„ )S˝ęöHD ŃŹ8€±«t¸"Üđ†±_úҧţ*óp ká€bÜ9°lâ W`ÂGťwE¬rÄŘ×>÷˙^˙Řa_x/hL0˛Č2=7P8VX†7ŕ‚2#®}„9x;šµ<Ŕ@x9¨0‘¨€ `?ĺú‚.đ@č’.ꢫŘ€ ůȨ€=„/¸;¶ 8_¨ŚŔ¶…m0(>ăűźŕ: W˘‡y¨p„~"Źč„wxS€&tB(LX‚|¨ Y€N‡!7ŽX?Ȩw`¨˙X€T†xŹnČ„w *´B,|Ă8śĂ:ô€=@P©LŔ'Őh€.(§|0…wÂC…҆?B ťRÄ–şĂT*SBĹĘ^€Ş+Lą»kX¨tę*Ń‘(čX€=Č(Đ/ó*̨zxD)l ~ĐŃ0Bę*–p%a`ŠMJĆa„¤€ %8%g‰°=fŇŁŮXAÚ>’€DŇ$T:Ćaz2n´«_b&RZ%Ő¨€\zt M"FŘ9pÇod&ć3 \RLz˛ řĄ` Ř’.Ču´Će´GNBHX9{H%ěEš·p’ź‰ä˙m‚Č‹|ç[ňĆŤěČŽtŚ­ ‘üH—8€ĐZř…A: ČoŚČ˛H”¨Iq™/’f¨M‚€Hpľ•ČÉ™DJDÁX‡` p3ű< kxUpÉ–Xʦ€§Lʱt ¦„ Ř'Č€´$‰`'hK‚a´„%0I“0K´$ʵśK˛¤/CĘ€ €F'ˇ°UĐJß,ż,‰…g8‚ď „oř)(LR€%Ě“HĚĹ|Ć|ĚŚĚ ú'D(°)Ëbř3€ Th˝ŚHg  đhř˙r „ pn ř@ĐdŘ”MÚ´MÜ}p}f*¦ Ł`şSY˘ĄUşVŇ´;˝¨€ŔsG?M 8vK$9ÉSTR=}ůěŞk I ¤.DĄNâ’I ¦5Ő€hT‹/Ř+đ—ˇ Ą¨ĎuVo „x ;€ď“3(h€o oHPUođnpÖgŕ„ʉ^ýŐ`Öb=ÖdŐP4ݚȅ–|Ź|`„źň[¨‡9`Dúa <ő€wŤ×y}§Đ{ިšŞz…ŻŔ‡uŤ”˛Ĺ(Ľą;0.‰˙@\P©v  Ř\ŕ‡FčÔŮŠ(H…wđv]Ą¸p€qpĚ{eh©‹ ¨9°‹Ę¨Ťę¨ubXmÂuQ€Ć€„2ôŽ[ÍUŠŃ! „Uř`VuX‡Xp" ‚0đ#Iő pj¸Ň+ŤE‡±Ej€†4ĐĘ’ü¦}Z¨•Z޵Z¬­JsÍđ`Ř´•„Ĺb_1f0p-đ„şľő[ŔÜ5Ăń"/8ŕR + Ŕ %=()Hŕ‡5ŤáŞ)‰-˛Äť;¨@ŕ2Ŕ z.Đ٧ŕbh®7ř‚ ˙A¨DA¸†‡ X8hpfx"ÓB-Őb­ `ÎýÜĐ•;M€…!°xĽµU\µ‚Te”j€ RhŰX°NÚR!PÖy¬Ha@‡Żuvv`‡˛ý2# óE_őVöu_€ßrĄŰ¬±[Ľ•Qô\,WŔ€ć%ľj˘<ÄŐ€žŕ f ł1;=<%€؇5ʏ€ Ŕ `€m„†;9GŐ^»Ú;±03 ˛M€€FU91€Y°ĽX§mč˝´Ëą-¨†€uňłE@†&1 Ł  €~áv“»-¸.°˙-°Ýđ‚{ň•ÂüRXoř€ŕ xJGI¤h¸_u`‡üĺ_v J8€H:¶c<Öc>öăĎ\`¸€»ÍŰvăŰZň˝Čă‹°á ž%Oţ=¤6kö|%€8aŹHxpH‡jŕIá­áÓŐ€¶č|DA,Ă€9ŇŰ"n5&@˝h‹}P[e{8 MЇDĐ‚eč¨SKUc5H€ĺZć‡P¸,0c%€·^N{`Xó‚ohRh(¦ÔZyţgN8äî_oHĽN6ĺKôµgfĘç}†ÎKţš˙Î[ŘŰR^ĄSe^îäŚĺ  žóąqş(áW‰Hp(Đ‚y ŘŘ–c e_®‚ĺ%f=xc¶Ýd~]fFg†fxv€c€\ři Î牫¸ŽRip¨Ý[%€[Z»Tmĺ_ X‹É †€ Č€0…Ĺ|Ď#…XX(o@‡Dî_h>°ë/P ĺ´^kM¸M‰Ž›—2‡8ĎFččĐh{‰„Çž±É>eŰĂ=ŕęşBĄ`HȲ2N“ @BŻ“j3ł—Ę»Ľ @m8„Ňë1.ˇ˛P(ľvF˙#žax Ę&†´“đ^g†sř$ĽÁ+<0€]8íĽĂe €(°8†@ ář,xwšgŕ„ú¤†oVĐ1Á€Đ…@‚čţĺß˝f‡¬ě]ŔK.ôVoövď<Ö1ĆN¤-…,°\ÉĆhĘeh¶ÔlP¦´AL ŕ€N†żĺľ¸„yŕ%Č‚rđ´Ť-­ ě@°U< @ ś€  |8…9;p‚É‹®ď} âˇ®Ž "ih®ŐĽ!AČľá˝>ĽHŕ‡B€IĐB0!˙@$@W2qWq °Q°{ ł˙ˇ>€TŔđ®iQÁG"gřwř†FHóŚđőţbHägĺ_nHo>/Ě/MK8—s:·s<·C?›^ĘOě†9`1WŕÖüd0¨T•DM8YS` ŔtŐŢtšWDČđđ­0‚@ĽB9ŚM€Ş…úNĹ€ŔÄ+Ü I¤DSФ‹5§nđDAś×­Ž‘M…zŕ@(yťDJ€; ‡!`€(.Đ€? ÄAħOO)6Ěu$Ľ€řĐdÓ0„|p~.ŕçř&ÍďŔŃ´t>řj †M`0°j@‡b¨Ě z˙{Çw}‡ô˙łŮiONŇĆC‚ Á2ČWß”#R2¤>’çŤĎMB“6&HŢG‡vÉIŐ_izŐđÝ<’E_U°#O€ŘSĉP…ĐřĚ:SősLĄš§D}SbBB ˛X `$đ€Á€!ŕg°Gx ČŃŔÁő}†>x0x n(†3Ű”čúŻű±Źř¸Qx±›±š!Ščq>Wq—ń ť˛źPřü0—&]°Dxa’ŔÄ>3xLŐĐŃ%^NGp¸J3xpb(çKË˙ĚDĎ{Á)źLÁNEŮvkHQ‚ż ˙˘H$ň6#áü>đcr8&){[á“đýׇţ–P U`•ŕ ĐZłůř€!H„QZÚř¶$ÁţŮŹţó÷‰éŮ‘‘ýđPďRňűĺűć7ôG ŕO’]˝Ń±]˛ (hđŕÁ *Ô€đ!Ä'R¬hń"ĆŚ7rěčń#Č"G’,iň$Ę”*W˛©€Ă–2+6$XsbÍś -ć„Ůp&Đ B‡-jô(ҤJŹŢ4H@‡=NBĐ|ŮńÂ…»JÁ´xŔ•6—^´šQgχh×ĆÄÉv'ٸrçŇ­k÷.ŢĽnÍ pĄź®©U zÄZ0˙Ś.¬é±®ŢźßBNHą©ÄËmőrîěů3čТQR `‚Ä[ x !C *(€Ą…†Ş@p ŰDA H„H `ťŤCŔ1$BŢ$0aÂ8ŽknDP±WłUđĘ%óý~9˘řň ĹŹnďţ=üřňŹz€óÄÄă· ü,óWO™˛Ĺ`Í?řăArě×ßVC7¨°B ·Ř’‚r•@ŕ?ÂäpAR ý(Ł„ Ó‹őŕó 襷ӌě D5f™Ťóůř#A éă řCK"¤B~9 `É9jdŃI?a„ŕAO¸âJ!ôd”˙SVŮA:4ĂH ˘Dł kEäA xrVy0ó_ŔÁ pŃ !`±q2ęx(ZëU–cŹŐh¨fCJ:)Ą•ZZT ĐđH>ŕdRD“5 pÉ4/0đA/ÄL¸ÁŞp饣–zjŞ„ůś˘ –(DX=t‡ÔB“@¸ĐŚ9Đn"zíK’ńD™yçu›áĄáŠ;.ąĺ2ZÚhěSN&pŕ¤%Óđ€UĚa«®vůeĽó^Pď˝L0 6Ąř€OŕňtÁ · I-ЦĎęÁĂXŚîpLŘ’7žzßb¦qz"kk.Ę)«Ľňh˙QĐÍĐ 6\ŕ$©ţŚo«Ż~™3˝öÚ0Aµ`sÎЦU– , …&ý˘@ @‹±C›ń¸Yxź2E?Ť¬ÖŁćqĽ1Ëi«˝6ŰDp…1őóź âśÍ 0€‹ŞĚz0 ,0śF¨xëÍ7 Š1X,ł -Ŕ*6E‘c<đ€pL+{Ţ /,«őÖ^ťÖŘasKöŚ7şŮ6íµŰ~;GÜrŠ*¤0íZŁÚ“Hôq™Óq "nĽAř%Ă|—y¬×üá°±@"cą{|ń„Í`‚ő»ŁÇox™ęŘ*Ť¶ě˙ §ŽŁëláţ?x»p TbSȨč1Źz€JЉwĽĂ0HŕŕŔ,!uđŇ:1Ź!ÜLŃ„? ‚ ě)¤G&&”śtaȇ)ćg-ťŤ‡÷ă˙č×Ăîĺďd<"“. 1[•0D ś%)d5€@ TEd ŕ:)ďĚN":,6 €ă@€;]JNZó.€*9jbýx2°őoi} â¶L¨ÄA˛ňÁ_DdĹ„%Ś4"Y9=Ń@çâ‚HtĚŹ ±IëHČm ‘eł–!S©JµEŇ"­üź ]ÂÇ˙ýQ#F4WzŔJ®˛—ľüĺʲ¶É’ “lś\Ȣ6RĚůP‹>8%(A RP" X’Ŕ6D`L&8Ă)NU.s‡$)g|:Ŕ‚4äp:ľb„Â2Đt`€ |sśţü'|°Ň9j… X’$IbĐ%Ń.kYh Zф΅ZL ;â፺cx†#VÁ 6Ü  @SŞRĐ včRPD0 %€ đŁÄěa:]‰LiJQą¨“äĐh<4J 6\"Ă 9:L ź+˝*V•ň•°¤#`…Ďb‚­”‚ÉĐ“ä…NŽU˙$­>ĘS˘"Źl:Ů<ţ!/„M`@™0‚cfŐČX·rŘ‚ś* CxdZ둸JĹŽ%áA!2šTŽĆÔج;ÜAŠ!x'«¦=-QÓ„y¬ű댷1-Š\ë-ňJ ř0síjC‘Č mFŕ…Âa »Ă †¶Śí`˘Čô60–% бŮńşŞäő†DŔKÔ˛·˝±˘k$ŔPX*đŽť/pG¬Ĺ(`_üGżĎy V €+Ţ77ŢTŔ‚ »íd‹SŚ(ŽSîti€0}’ČKDńÂ˙i@6çĆ$Xn1ń‘Ů@ř6>1oâ;ßúJ@ÖÁŽvúK­L]‘Ă!čÜn=đŐWMň 61}Ąsf¶Zcig“0Ç99`íŕ}„!Ć–/†#ß×Ćà °qµÖü›Ů‡8ĆąŻ•Ň> cَý3g9şQGřŕ»î=4˘éëm¤ŁÝx†ppřcn –ŠXÔ|ÔăÁ(®ńŽJĎ!ŘĐ?:ô! Ë·¨©´ÜÁ…ő°4µš2*}čĂŃÖM r‘Đă¶ÚŔ a Ľc B]A8:đÄhČ…?čÁ[qŔhx˙58axŔŐ°Ç4cżHÝŠf´Ż1,˘jřĂD(Ęt‹^tS ;ŰƶŁ*ÜĚZ_v$Ö·(n„‰hţ¸Ĺ5Ş ‘Â’@N@Ź2 ZŐ ňj-6ŤŹČăZĽŻăťçčđÇ?Úç–7H@šP….$ PâńP)Üń R¨CŁD­:6Zڤ%şé‡“ }€ˇ#D=1†A\<đÓ55(V±ÂoÁŔ8ÉI­h­/Ć0P0Ă 9ö±‰,\aŤ°®/> ˇű°‚FĐ…/@Řđ:ŢíA'č ›ń˙ŚŻÚáŕÔǰaxKđ>Q ¸"îsŻ{V>I,i‰É€şÔ©ŽŘé\Đźü(AęÓ‹oüăy@•€Ëë ^5xAHozÔ7bŔşÖoXCGź çđÁh@´{¤qňDóÇ€ô=A‚:0ŞÁţđî~¤D%+Ń~K0˝=”čߔə¤ÉšGDt@ĐýÜü€94`~CŃŔP9ť¦”¬Ľ¬Ŕ=$Âl t ,N6ř@łXL„ xŐ(¸‚h€0&|Č0Öx•+Ś‚`@ ®OC)ĽŔ|Ŕ=ü…˙Ć“ŕ͆ µ`ŔěB+ÜÝ Ě BŰí]‚áLßś@ ld€ Ŕ 8Ŕ1T@‚1ŚŔôŕˇdŃ P@Ďü_>a"t›± Kç,Ë B‹´PKHaATáę†ÜÚ‘¡Ňá ôŔ6ĐÁď @ań€ě@\Á<0Á¤ĂDÁ<ä ŔVŔ ěĂ T4ˇ‚`"Dt ­¨Jä‹í#Ş­ŕŠ®đŠ J ,`< Ă*¬Â0$Uh)‚#|9Ý70Á(n 8úSda4( -vź=@XŚ(ľÝ’™ÚÔBč|˙I, Dkq ĚcčÔéäŔ @9H,aL(9*B!Ŕ!hĂ; 6„NôŔ-¤*hA |D(RĐ @ô>řHúĂŐŔ5Ô¬ů>”Ăl€kíŁî!B# öKBv4Ś?@ŚÄ  ;„71¤CBdčD[,R"ô€I˘¤H®$  c8Rt‰"Dś#=8Á"`ĂŚ<0Ý$:Ĺ ¤#$ĺĚMr_´őKĐÜ MZţ‹Đ ÁL"GĐmÔxÝĺ]ZŕO…#_Š#Yž@9žă>¨:˛ŁXÍĹŔQ<†?bŤâăb6¦IFK@$ŕIB¦B˛@'C˙XC蔆*4ŰśţŤ[zd?ÔĐ@l6 řc8AlŚ śĐŁL"e1ţe9v‰Ó@ŤÔ HA ćaÍZg~fhĺíĄA¬eAŘ&nŇ€n &aŔTŽ" @>ÄÁ+ä- ‚4,Ňt¦_AТXFq*Â˙­¦Ľ¤%Ď$%GşeŔÍŃ0ť3R:$UŃ᥀ŞCúŔ7öĄ‚®B~@9Ž  ,ËâHCˇŤä@Ľ`d§@€ĺކşcg4Ă&á”C#äÎČKBNŔ ,  á<ž, Č€=H‚YÂç¬,1Ă”á!ř† ˙á'ĽŔ!’Ů˝JcN±Žŕ,KglNç|NQZ(¨Ś.K”@T‚4€č„uŰ$РΆ“*Ë –ˇ Ŕ@ |çCtŔś,€B04A-Ŕ‚-Ä™~č˛ÔŃÜ™ý ¤Ŕ•ĘgŹNŢěMߨiŕ Ž¤Ž0.Nă„Ďäc—4¦D=Ź!¤^éÄŁî)+,ĂpV´Ćí |Á ÜÁ°z!žĂtÁţŤŔĐ>śÂŚ8A˛>ŘBŚ˙ A>ňÉFÄpŔň4Ďó­Ěöd%!8¬°+NVf2ČÝż’ĄBęIŹć%ż2Źó@ĎROXöhŹpAÁ3°78-5 8ŕ<­ŐЍ@‚Ć*×"ѤB0´@ĆuC&ĚĎ~Pş±( ő)™+đµ|2d‚ x Ä áĐ ˝­„€ÜŇ-˛B:¤C.ôC#JN|mŘŽm&ÜŚ˝Ľ6üA Hš6Č?x $‡šů˙˝ŐÜ„5ŔµůG7p Ü-ä8p°@0đBAţmÝNDMPÁ€âŠí -ąµH ŃW ůCŰžÚ5ÚäbŘݦB:´-UDP*0›)¤ą}›ęrn4Ŕ|n7ĚAš!Dłlot¤éRĹÝć­)°@`…¸Pµ@î2îýéÖ%(µĄYíRaPţrQEŤĐzD¤€7p8PCĽ€8 +đ3Âôh×f°Ý™U€pPK}©€>6€Š‰Ŕl@H€—8Ť ¬x„qG GW,ä@ +@ĽĚ= OµÔo€Kł˙\ Ř…m’ś™†ŃjoĽŘ€Ř€Ąđt„ kä{IG q_Éٛƙđ•1ʎYA¦¬Ž1X 4‹ß׉ĄŽ}/ť(€u( Ř@Ëđ—ńľ6@L‘ €ńă™ÍWcŃÉ•šy‰QرDÜ%'?Ă38'˛'3đ3»h°*Rµ4â\žÍĄNfD\ALŚ‚=4#rdŇz0sÄ0W’ľ’ÄPµň03PpA03í’„2żňn łýîBPŇ+DřŔ€˛'Op8,´Ë»¬2:‹SnÁ:-€!ĽC;¤˙Ă(z¦ó\TóFćĚ6[ÄĽ°B8´8ôśĆZŮ3B»\Ŕ@mmB—‹˛XđA!¤ŔkÍŇCw´Gô{D—Ü× đ@Ľ€A{HŻt…’J¬ó'%q´,É4Y EçŚKď4î¸tJŔô%ŃtC uPŰôRřO'őÚt _ř´Gµ2őOőŤQMTSS›EV›“I”ŤR‡5Ëčd8őYIőSwuHőýQ'±őÖDőVoŚZłóAcuěµ^ËGi¤4aÜ«9™t°©YćpŔ˝"ű}‡ŹÉF%1šiarĺÄ»H˙E%2GYŚQ,¬‘]ÇŽöýĐHíHSdH-)Íj“µ·ěĐxĚvjRŁě5o‹F}ÜG“ŕ6VDA*ŚZ>0B—H8ÄĄqŔ#(­ÄXĂŘŔĽ•ȉ°Ő68Đ€(„Q@‚,¶iĂ)T8x/ĐZ5ü‡÷‚rWÚĄuŔ¬Ý‰(ĂĽ"í¶VĚkŰ[ř_ŚJò˙äµnĎNÉŘvm÷¶„F‘I’ Z@đ1ŔÁĽÁĐ*ö×yŔ ŚmÖ`côŢď퉓˛Ŕ-G$đĂĚš&ŔÂŘŔĽ0`MMčX˙,7ÓéĂŢEMŘ!öá*äá’g&€•Lε4ř[gy˘Ě5křżv'ř3u¤@ř™O¸šëE¦lJ§|Šy„Ě™. ťJ((¤ŕTC ŔA>` \Ź ,24A˛ÇPŔf3€@Ŕ¬mÁ5p ”čˤů>H4Cd=HÁˇÓ¤ ’  ˘ Śz†-@/Ŕ„x „ăöˇü—8»‰€y™yšź6˙¬ą°ß…ËP@ş¬‹9oy‰®ĎBpg°®ăł&čC"hÁ2 HäONL”Ŕ#€C:T?„‚@8Ŕ.–¤+ÍäD Á=p˙ş§şřăĹdN˝x¤XJßĐűř|Ó˝Č:ýą·ü®ď­#Sn9xY/|,ńŻüë »ÄË…ËŔL3¨hÍÜŚŇ,;÷:ŞÁł3ÂA.|‚4Đ›^ÇÓDÍÔ@¤8ÔL=ÔQ.Ň,-–$Á=0A§z¨O¦Î0ľw§ľ×6čúÄż¸W?8Á›ąÁŹů»Ń5Ă“ąĂ˙ş–GřÄŹ}RĽMÜĚMÝ Ĺś Ă 4#Âäů ‚…ö¸3LCĚ‚9|qΖCAŔVD4đ¨L@XDC ltCćj€UŠ:ľęđÍ’ žS˙(«.ŔzĎ#uŘł‡Ť¶×hýÖ#<Ż·¶K>Ů·ľQčďřđ Eü…4xx€ŔŘŞÖ•xˇňC!Ŕ$č!L…Ŕ˘ŹúÄ%Ě,A”"čéڂ5„úľéD»ż»@śă»ăť’w“›ë“—řčIů’ă×zŔ# Äď:(ĽŁ üÇżęË´ú»>ţ™w 7@¤Ş€`‡ ühó7nŽÁwč a ö óçŹ^&!(ÄĐŔß»n:ŕpˇ6`<8Đ0“ćLYňá abľ&<ܱVOŮ›!4¸SmaĂ@…čFCM«W±^%¸•˙«Ě¬_łz[“`رVŢíZlÚłm׺Ąąő-V·qĺÖŐ€—o_żvüöµ{Ă‚÷ľ7núňëŮă…_r}ű÷ńç׿ź˙˙ýbo.ý4Ŕ®¬ęŔ¦pĐ‚]<@Š.ářš‰Ş;>útŚĂ˛(d ŔE ŚÄĂ´°Bó¸âP­ Al=i¬ŃĆq˙ĚQÇyŚ,«‰¬IG”!HH©Ç#‘DňĹîXDQ»$ˇŚRĘ)©¬ŇJ_L©4 ŻěŇË/[| Ě1É,ÓĚ3ŃLSÍ5ż„‹Í7áŚSÎ#)h ě»ŕ ŠLO>Ť”óO úLłÎ;çLLĹMËD R. 8ŇK1˝±81áQÂ.đ;<óSTR%ôÔRÓÜ´ÓO3˝˛8q4Ö F@¤ RŤŐ×_ńŔ’i|H¬‚Xq…ŐŸá>ŽMvYÉô\ˇBr¸¬1t°‡z=Ŕ*r (Ze{ĺŞŮg Ä«käůg`UěÝxçý´Úks–ص¸őÜŔö˙ĹVŰ1H 5=7›¶?¬”éçe¸P$–đ^yéÝq‚Ę‘€ţ6]Ćř Ś!ęVć4¸$_ÄÎu1Ľ¸‡‰śW~LO2Ž!÷1®čG—·rÁ=l8hĽxö9fĚdŔ”![ ë­‹íjč˘űµ9du“^:č¸Ć6şĚwi˛GxaÁ҇ÍĚdh cŠ8ŠhiĄ™öZk®uś…’ \íČX"ź0f®üÍš…A‚ëđµ“ő´_:Ď!ôäg¶OyĘĂść8Ç=ďĎHĐyďđD&ď@Ě‹ôš—Ę4LB PX ˘7˝ę)Pä^Dp˛ÓÜÄyŢÝşâ€cô#Ő-X@űµŻ/!¤žővş  đduz@ 9w@ö%aä  …¸Ŕđ €ôKJ˛7ť='íŁ@÷pÓ?j-˘ NPŽFđ{Sü"é>gße‘6ůË 6P€ aČÍt—€%&%4ës¸’†™ŕ`–s˙$jFŹqÔ€ŔS r‘Žü!B8Á#¬Q’q!}×xAćP›"qđL]@p >§v¦lJi R ˘Ě!żKÇZ<4Üŕ@DÔĽ2đ#”ŇSRńäžů€!Ňe(Á8¸E=´ˇ‰jĐc5ţaxŔH @F;ŕ‰Źzüu¶dHi¸ËYţE•@\R¸Á ĎŚć4«ŮLj’ś”P?˙)Áe6“‘śd%{yÎt®ł IG=şa®(“™ÎĽ4ĄIMĎ(E ă (ˇŚäÖ ®™ÍmšŔś™§%Í QT*Ç˙öÄVşrmqŔ.¤°ŕ†9dé@É—śúC›Ü\@.~qşP3B*4™ŹZŐLú©Q`¸wÂłňĚ„9Ń©Nvr˘a«rÁFĚ”/Wu©AĐř\¤´škĂ(ý‘ ~¬QŁz5Rb‹Đ•V°Z J:‚Ľ˘řŔÇ?äÖ\î2—ů€b5ůŽL¨ ¦¦ČLµQ„<’·ű©™=ŃHĐ0$Aľ<`c–Ŕ=ńŔ@–/Ţ€I` 9PĐfŃ[\€u`É#ŔQž^÷ cŘnwť«ŹMdA}ô €»?čŁ ÁLŔ˙x0a&H?‡/Ľá ”É3ţŔ…/Ŕ!‡@¸F ±>bE°Ažŕ tÄA0Â5† ěW¬Ŕ®{ąë]ś7˝&ŕ§?#V ˘Ă dÉ#XÁ 6Čq“»ÜY"˘ăJ€Lßw¸®,ńDĚ*aťCHH…>Ŕ@(‚@™ r‚üóŘÇ@ž%`q‚4A`Ôá çp,(â ~¬(š€Ĺl0€WĽ„ ŕ/yű"C8,9x-DËć/zĘł„)L‚÷ń@q%ăž°aŚ?LAÁ)¨<ř€„NěĂ {ŤK‰ŤĐŚ@˙¨¸¸r–{ŐdsMŔőČĐ L8ą+kîń¦gIčCĂHŔ ‚ót=bH›ÚÖ~÷ŠŤd+[ČF3y#+ě#A‚:ßůÖ7 žA3lˇ‡)ŚÁ ˘®Ä9|0˛d"˝ux°.‘Ť4`¸ ĆG0đ‚ `­ČA1)či+#pĹ(.bçJk€A)đ߳੪ ÁzOžrfTÚ7ĄxAĐ b /»Ŕ*ĐQ#‡3Q´-x0ĚB ÁŐIŔ˘TpH 4ŁY ‡€Ŕ %Ř@´Ş·ž\Đ =ä ˙¸¨sE0U^®Ź ć7żńĽ$m˘$8(˛á©KăX/R2ľńŽËXŘ]yzÄj&qŠ[śĘ۵lł`÷HŻry‚,ľńX7çŕŻ~řÄoˇ1€C>°ŕ‚˘Ů`ČhÂ×Ă~ `@ X\#€˛…kpÁ¸:p—Ă<Ű|ÁŔS»‡y0á†#<á ŹxěVl[ď:đC0Ů‘zq’8–/@ôQ ˘ŽřčKź¬rîr§{ô9 <ô‚ Çoěŕę@Î| h&ŕű Oöîö!Ŕîę®Ć76áZćú+pÄ:€(Đ]Ođě ˙L`ŹęZďęT˘Yöa ř$zîç‚îâBŕßř [ü‹`ŢŔ`d ŻćáP1ć‡ô¤ lAްˇx zŕŇ´ r g:`j gBA ¤.\îä *Ä ±°ä&8Ŕ QŔěâb°ˇęa#𡊀7.Ŕ®Á r`'"ŽÎ*.`nÁ4! ZŕćĆ®ěěíš lW+â8Râ Ë0bÖ° Łň6f$Ŕěáśoٸŕ¨Đ ±PĘ p+ŕ®–° ™ÁĂ8QÜ fd˘A: vŃcâ™-Ő`Ěđë˙â.4AA –›1"q­§ҡř!śj6”oíö$%Ú%~dl@čŕ†> fP[‘/ńżńćF­ÔAÚöA˙‚mXHíŽ1űâˇo+†qZP ú6b#ŽŠjô‘€™Ŕ Ű𠢮aîJÍd¦ăóFěD27ú!#ý᨜`f`·B2śĐĂ@€öi+iîÁ / ™Ň1~ń~’:aę €Ŕ°FÇPáĆaDKZŇoçđŽŔ ‘]ŕL8€ń@ \`-šˇś@h€ ˙L`'ň`MA^Q.€N ęË”€*Ńěč4q"{ĺß@éÖŇ3Ú’ Ě-IoÜô1?roR"= ގ*Żň}1 â2s0}Ńl€QY2ôćeNŕ=6ÓR˘4534ů‘ $->A臬głÓ Ŕˇp` ěAłłĹŘ’,5Ŕĺ6ˇ â,.o&€¦-oŔâîd‚+¬€ ĐŃ@®nAN<Ąn„ádH 0€7˛Ç@@ŕăŽJă2đşŻWŞyIł€ł§n®·‚©ťš‹ [&5ňhs "µs€K@;ŻiCJc…TĂ«µ6D$Ŕ(®oÚ7€ă9Ľźđ"°í¤—*`sÂŽ·őů Ś8»ŞůZ±ëDč:T`XCh;[+űşď$]˘ç°3{tN›6t Âłă‚·O¶fC|ă‚:¶ű~¨y{ô[pvľë›^`†Ű€=wЧ:‰sÄG;]¤ÍŇ 3•şĂ/Ä/â±1ĹĚ˙t€Ň@AŢcÄ©Ă_sQôÄ VT|0Ć“0&ĆÄŃG^ü$‘i-B|+ęĹH v<ĆëăÇ×ÂHZ¦A„°ĂX Éä’|Č˙âjXśŠ#Ë3„+ŽË Cʧh+ŕ´€~Ár=|ÍĄ¤ˇ;ąÄ=Ă€ąѸÜ?ÜΡ„ÎkÁÎ!ĎýÜF€DH$ÇŮ|FŁ€ęA†ŕ¶ýŃŹ„2ÚC,¨CîÜ?$}Jö„**ťÓqDK–Ň;Ü@öDĚEýÔQ=ŐU}ŐY˝ŐďŁIC+ CÖĺ„ÖĎÖ]]Qp˝Ö—$×}Ý?z}0l]ÄťM†˝LŠý×c}×ă„,˙ND١]2]F4 eF×ĺK’Ý0l};Žý=äă۱˝IÜ$;¦=L¶˝JĘ˝?ÎťxÎ"ĹwÄŮĹ}Üź=ÚE=ݤÚÓćÚcÝgß—ťEĐBÜ·}Ţű=ŘÉÝä/ ^ÝĂă?Ú]áá˘á=á#âíťÍµŇG˝+X;l Śľwdâăy*ş% ěb{ŚĚť&@ écWţ„ śţ[7ĘK-Ś‰î¤Şw‡sV^J‡H(`9Â-řÇXE.`‘ěÚŮŻG˛Ŕw¨Biđ~ţNĽĂÝ»>Eş}ŕç#Ĺżľă§ýIęíźdEŢěÍ#Ű˝ŢB,>îżĂíçcě˙ŐĂß3ţWDĺ üĘ@î„®±bËÔ ~¶ßÂCŹ'®\…ˇAKçÔdéÔ/L‡:š1J!*Ú$üf¶ôLă„„OŔxL@˙QNR…¬|ŤŠ™™@~¬PÁ6c¦Ŕů’"}›˛hŠX€Í9 hLčq/ŤR{„ž|#á._ ŕÁƇG€HS'|H&ĘO@šu1´ŹĎˇe;Xz‡hĚ ki•2uqÄŽŚnú4ĚÁą=Vnl9aGĘś5lîüYsćΤK›=Z4fƧ}®Ý:öÜשK7 {ökŮ—wÇÎÍ;¸pÜ´‹?Ž<ąňĺĚ›;=şôă Đx”\¦".piÚ zcbĂU* ?ľ<1!ÉwJ–$€kŮ 9\p *±äL2ŤŕĘ(`ŕ˙3đDŮLľ€ P S ,`žWĚsÄé,Ĺ»´’CUěĆ2ěGw•ŃŐLYĐ#Ě(ˇD5‚đw(Ůřđa)/ŚhŢ Ĺe)"‰çą—Űh«'›žyffmýٚqĂůgśtžv›w¤ÝůmiÖ‰ ¦MGhˇ†Šh˘Šš€Ć>ĺ`”-4 ¶ÁL6¨ÇŢd Y’馝Ú0Á“`Sа(4C Ŕ/•ÓČL¬Dµ´b+e ™ČD•Ő€pŔ§1D‘`łÇđQ˙A·¤Š-ä°Á˘Í;Č`Cě1€ŁWě#EOśŐĄ¤=M6łDű¨°aĎ54ŁĐrŠB›aƬł źĘlyş–¦›{g±ĆpŞy$›ĹáŮ&źÁ]L™śëÖńž|z,ňČ)Ϭ›ť(Łě2Č1/ĘsĎ>˙ ô˘Ťö€G3Ľ˛`Ă—†§éśz j{ WŞÓ§^U 6çłG"1“–{ ĺşë‚ż$,±”]@Ŕ``Żg5\㬩1ô@OŻB "W:Ş€¨Ľ3ÎxĐÉ1u„5íV H4D2Ť¤á»¤.$™Ĺ=kt4pÁ5`“0V7L˙Űč[íiĹ%{”Ě5ohom š±r$slrî0«ÜË·ç|óďÇULłk˛ŰޱÎĘktôŇOO}őp…1őĹ qĎ^6/4Ŕ.ç‘Ŕ“Ŕ †?~ůcVi Ë,bC !Ü.k€<-€JCWŕ•ŻÚ“¶bů¤8,@Ń‚ĐČC `ľśŕ j [đ 0бě!‰ ś`‚0P¬2hcB—klĐ“ş@IJŞ’4°˘ń`‹ˇ .h>ô¸n6)[ŢÇś;&6Qx™Ó™˘HĽ*>4ľĂ™mŽW'˙@ńMZ|žőÎĆ4˙ޱ8¸Ĺ)„ ‚}|—°G"ş‰~Ä!€®7ĽA%uĽcăp< )ĐÂ5ţ`WˇékµĽ°ŹRda^˝˘ ‡Ą@źT`[ʾЅ9ôg)IĚ®ő,„@ö/ÜŕűHÄä‹:pˇ;˛Šm€ 9¨á sŘ .řĄLaX‰0±ŻÁfdD5»Ú)‹á$çÍxEŢřÉśM\gđ×§t’ xłÓÉUFŢ­qźüěçĎúh¤Ó€‡óŕ& Rđ ” ďx‡)`0Đ‚‚ă  XB>ę°żtbCPÚ$WŽ9Dň˙#Ř@ŕŹwtcés/4‚ #*›k*^X#Ą¦HÁ™B:”`‚„LÁJ°î ŐqĚa"? j=šÖŽŔ3u*^%9ĹAĚyő|'>q+}zqžůd'óňŮŘŮLž¨Aí*KŘ0Ć΋ţě¬g?K(h•ó;—†PÖ€@)PxL+ ¤ h€DŔTG*]ĐZKr €€x[. @`#Ŕ€šH(ŕ±mí. €TW‚˙€ĄL ŔP­qeŰŐÔ®6¶HAGÚfŹ4T˛ďx˙ـڷĽ«UBŔ@ěj˝Şá«€·ë˛yş.ł ^“cą(<*.V°”Ýť:ÝÉĽŃ~Ă•ťY,–©k -±‰OlŮťť‰j”“*ĂF¨äP9´Ć®R<$Ö˝›—ě #Xąúę÷e… @@Ő{gŽËÉ—Ľ<-ĽphlXl¸µ8ĹZŁ]XÓcă1HËŘ€ůĐ{á˛jĘ  & {e…Čhi™2GĘ…®L® ŕ÷lTl\­1¨“H‰*bá P8Q®ŃŃ<˙!âk‚8®}!Żâ{řńĺCP¨ @"T€_T„‚ $CäpĐP Ř *´ŕ€xA‚÷1ŘÖÔWa›!Ô@< A)pĐy÷ĺ÷‚ .(‚Tł…Đ@ Vźä!"’‚ ŕ¨ăC†(d ˇź ć5€Łxv°|´1TÁ¸ Oä¨BŘ)ßw-FyŢ“D IěĂÄoQĐŔAćdwd€pX"P§‚}*©bç1ČÁ÷…`ÂqMrŕE;ú€A€řô“™u#¤ŕşŐÔsq bL WUp=exŕë¨ďŚcůîKOż!8kŠ pđ6ET˙Š ËPwAh¤“Ź ěQĎá&TŞĐłIZÁvÔd4 !)!`±`™oŢůç Ü Ź(eL1ĆĐń#GŘŔÉ&§‰đ€ çđÁh0Ü# Ół!žđ…'"„čSź#Ć´$C@HśčÇ%@ šŽL`†Dŕ›x>pŹFL ۰ H€AĂ‹rA3ôŕ6‘śd%/9ě#$ zHÍčAě!… \@•^GŕŠQx`Ćç…K]ú‰—ľ¦0ypČRĽ -ŤĚ^Cp‰i(ň˝ †«0) `­Čf!Ť¨ň“«‚5ń‚Q`€gJAäŽ˙T ˘0 (8Íjľ€+¸G"Ú‚ ä›á„Ą,ďńĘk(A ‘Ě€ Fé°Tć0ĺŚB‚@§Lĺ$ëŮŮđDłŕJ 0#9 xrL_€>Ł@ HĐĚ$`Ů4Ŕx·…t,! ó B%çá› ’Ŕ, }(8ĄW…}€a(E%BŠ€ĺŹ b€“rTČ…ÔŕśěĚZ€„~ŕĂxőÇ<†€Mę7ˇ+>îš×˝žtr8 čJŃ™ÚĂ )fófC‚Ô˘}‘ě.)kYĚÖ |Č\%šiZ"xCi3¨€EhăČŔf#ŕ©˙Ť`×Ŕ#†”€<é¨?$A×}ŚČç[ë-ŕŁE¨ŇăNË´DCxBŔ!^[Ěδ¦ÍXBŢŃŹĽę•Ż!Ŕ Ś›6±')î˛@{0Á±ŻlFr:ä 4ăSČg˙š7ŐĆ ů  °±‡1D­=¸E:Pˇ…ä 'Úĺ®l«p(‚‘P¸|`hx‡>ś`Ź"ä­-tĐŹ:Đ@4BÚl° k?âpă Đ  9xďY$PT“˛¤eĄ4{Ěu6łąś¬Á® cŃz†-üĄ&j/ Zętâu¬1ŰÚĆć˙¶°p…>…¤uŔÁěŠâŞ!ÉMŕgëŕŽrqBÄ\Ý\—,8sš×ěÝXfŞP΂>l,#ďxÄ!eŻ[‡Ř%ű™ľ <ÂwĄŕä(‡" Ei Jűb¸ň µĚAč‡W‚)°cT´m[“´šŮ\]FĂ‘Ćj2}Xw誳C†B´jqd¶qä„|Ú |’‡(Č0@ČPĂ÷ l˘(ľ‘ŕĘß ć0':­|Ůľü;ŕ+-ŘW®LŰD¦Ą;ď*h6^Đŕ‚'8Á2áîĚłăĆ Zš Đď˙č‡ b€»<óŃD·ˇTâ3‡üÄ Ě2I0ÚşŠ€Ć9n‚+Ă’R€ĺE­!RéNďzç‹Xź2±AÁ61É—JC¦úŐLŇ›±O¤?(Ě=”I• ¸řNp P µ…-xĐ LŇżöůĐ'yĺ7Ł ÚŔÄ\‚ć|‚ t… ’c&ăAĄČÂőH|śbc°‹˝ sČa oŔčЎχžĹJŽ/ö!„0V •Zŕ>zŮląŕ¨Ţ}ď‚+ ôH„#hí]˘]HyćΊeĽ vÁlpú! ř•á ľg˙ŃŹ/Ř`–Ä[Ž Oŕý"®‘ŔęĂe „ čÇUłş0§Ôg}ŘN#° ö*°Ř@ţ´€đ7p»7Ľä uP€Y ° ŕ‹çfµ"b›q.{ .ě2ߡ+#ĂmŐ]0/ů` @ą˘*Sh6dÝ €`F†ÖżA1  Âb ,°®Ŕ VńČĐ3WÁ†n…q8‡ux‡>s‡é ýĐ%ĺ|ô0ő˙S)%Đ ÁňÚđ?r-Y¸?sř ôPz8*#óGQ†,° Ä 1x5\0b ÁĐfÓ ™đ‘8‰•SJĐVS` J`# +ďĐ Tř0öWŐ–q'c•8Ő-PÁ8Ś"a N`ŘHĽŔ6¦çrÖ02ö’7{° Ńé°m °Űčŕ P„/ť°Ť c‰¶‡ü  Ŕ,G ÉҤ¶D! Ň !püa'Q4'Tr‘ďq$ĐäŤjŐ'§"'Pä‘8R)GĄÓ°’ Đ’˙đ’“9P“ Đwf$f— "p$;rH Đ"8™“4˘æp-ĐRŇ"+Ŕ 27R‘Á'>S8B&Ji'ő‘nđ“„ôO9$đRůń!9’ R°–…Ô– @HS ""^bKzb'żi~ůOi9$EŇ%d2`iPy áVřf`vˇ™QŽĄy¦™$W;Z0 öĐ ŚFšŃ!´™[°S ްĂx©>ŃKĆx¦q#v'śńÉCÁĹéĎépZ@ żŔcśYśâ)˘3I0±©Řé0 fŔ´)›˙מ*±`Í ď€ TäąźLĚPš!!ů ,#‹!ů ,zDPČ!„ ¦1€!‡8/`ô a@!ů ,z ,+$*¬x1ŁF P8@@!ů ,z 8PČ!„ ¦Čú¸yřÁĺ#Äß{7ů«%݇Y}ô×XdŠ5^líI×Ux©}& |ŢŃ— … ^—qüŘPaˇ˝‡Ô|"‡ o^¸WÉ=¨ŕę‡ß]6AřÝmrŘaoČ”tÝ‘X „Ő5¸c‹FÖ†#n.F[~I™a ů”-Ną‘ĂM'Ł”łŃČŕ’÷5yccńi¦ŤP&äă„·eąŐśŮŃ)[‰pą&™ÂŐůźfęšmŠyžŠéĄY%€^"j˘×M © [–¦aź/fęg‘†¨™ bjgg)ÉĄ¦śYigĄ‚Ä*uĚ,ŞčEQ±čŢ«dŐçťpŤr”^GT®ú#«¸Â‘ŞńôsĘ.›ěłN…÷P@!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,z¬˙\B ,aMŢżi<’ĐaŹ©9ĂÂôY0D—ä #qÂ8pá"v  ¦ˇMHŕJ?]_Ĺ ŽXcP)&(UÄĂ ŕ’ă Ď @Pˇ@‡ dެ˘B….ô…ŃĚŮ´h  ô0‚•«`w ¸„ő kXZxFŘ „° 7Ž<ň‡řü#Ď/ĄĹK:őhH mŕ*·…•čĺSN ó q~hCb7o @whCˇ2sřčPS¤’Ž?ů ’‚ÜQM=D¦€!Ć´ U'ĐS†NXaG”0˘?ôüáAT™˘<˘Mx†F:ů8ŃŔőäiBť yž`ĺ]mľŚ1(Ě‘CxŘCČ_ŔČpĹ>„źyPĆQ@ÂĎtPÁ,â¦چ˙p`O¸Ňâ‹–ś#©ŕ·Ş ×dňEÍl2TC¦Ť1LÇ)@ŞĎ&YhŇO°qŽ Đ0A÷¤©¤”ZŠĐ]|ŘđÁC‘l;ÁÉ‚)B (ŔYÚI`‚ ů뱫ş2Š8Ŕ &ď2Ź>‘@‚¬ܰĎ;EuÁHŔ ĺ4‚†­şŔŔ]Ŕ¬Ţz2o/°Â=‰TĂ6‚ü‹Ŕ1Ć9‚/ Ŕ h)Á1ĄĽŔ˝cŔó±E:KD18 ńď„Á!°K+ŹV±ȰOIĺË $pC(°Şm!0@-­đ˙PA·¤Š-3\¬P(<N:Őđ#ÉČ-»šPÝ)V––`5o4Š€ÄĹ Ŕó± 1 v"Q)TC3zđgĚÄE>D ‚ÍcŔsÄß^ř p6ď MßKú¦RÔŔťů`Áďčă„ &_#Áµµ¸wß„f*ń`ĹŠ'T@*ŕ”ó„‚A$»üâ÷ ĺoůnž;čD·5 Ät= Ô H5¸Fě|B»ô€qxĹ!hlř€ćCß8ÔçNŁA‚5WADĂ‘QBN˘+ŕüáÂ/sĽ@bwß˙xĐ HLuö\&pŐ Ś)@P^đ9I đŔ$hÁt ¨„4~8±h°€I@|NßÚ†"$¶ł.B°E R1Ł!í X.1‚ÜÁ B-@a "‘H”ÄN° AHl|Çz]´‰$…ůD' APÁIQHذŹDŚá AÄ &)°@|áwh%80%CQoĐŰ%ćÁ‡%dˇŠĘ8lâ sńŔ©9ĽÁ3*ŁĂ5á†`¶ńŤnAĹ61<\ĂŽ ©Ŕ¶°¬?|ˇ Ń”µ¬†l@wPÁ"°A˙żŐň–ąLÄFŕ _Ô @éŰ‹@± p€Á“ ů n|’±*„1Đ“LÁ‚ ¸‚Wü22ˇ‚ ěˇţđ82]úÄČ )Z`3ML¨ÝřCVR¦TČÔGUR>L±&”©ďx‡)`°€T¦'čF&öHĽŁ·8'ş§ db2E TtkŕÔ âŔ¶Q„D!:\ŔISşŇ– ť@i‰ţŕ#ŃńC©  X€) v8 ˇ€D#6uZš rPÍT'eŕWrJšh¦*ŘérXÔĐ( ±–«,R î ­°éT»fô“« ‰Ž›ˇ] ;Őˇđ/Ńü«čąěŹ’›ľĘŔiHe}Pb…ě'f°E!Bź—l#ŇEHMd‹âma SĐ.č±=@q·» á Dľ+‘Ü@ ´Ń10+`?ýŃî`Ě TŔÍÇ;\ĚŤŔ‰3ęˇ Ę¤2 !ů ,z 8PČ!„ ¦iö z0!Q•Dq*˝¨ó„‡ICúśxÔcTŁA—jťŘ´cĂŁŞ†­J¶ěŘ©g§&µ 6-Z¨eÉb5ë6îĚ®E‚µË7îÜź ŃŠ­›w0ÜľY+F7o଄íFVĽPpŰĹBc¦8ďä‰%ŻľĽ·;DőôqC–~ň©řŃ˝'{‘ Zuä‘V [ …gŃ@‘$^lŃÝ—Ů{_}ÔVBnĺ!‚Ű}(ц!ů ,$†˙H° Á&ÔŔ°ˇĂ‡5ŚH±"€‡ 3jÜȱŁÇŹ CŠI˛¤É“(SŞ\ɲĄË—0cĘśIłfÇŠ8NĚÉ“˘Íź@ J´¨ŃŁH“*]Ę4%Ăť {JťĘł©Ő«XłjÝʵ«×Ż`BŚJµ¬YťaÓŞ]˶­Ű·păŢô)íΧĎâĽ;V®ßż€ L¸pŢ í–¸XoYĂ#KžLą˛eŹŚń’uĚą±âË C‹MştXΨ-š^Íşµë×°G¦~:›qě۸sëŢmXbmŞžmóNĽ¸ńă5ĚŚąóçĐŁK×JwşőëŘłk7é[ůöďŕĂ‹˙OľĽůóčÓ«_Ďľ˝ű÷đăËźOżľýűřóëßĎ?żCŽť÷FË=晀Ěý'\ 6č f˙iŕot‚>U÷ŕ†v`b¦VWSyhâ‰ü©V ‰¨­ČbO(Ć(#}*Z¨X„$ňUˇŤzé_3)${5!˛č˘Y>îµŘPF^‘<ľ¸—†Uvge_Rvé%tX´eŹ.6iĺ—h¦YÜg›µX´U•jÖiçjŢe¤ĺ rYf’ Â(ŕť„Jä‚bšYRždęčŁ † 餔ŞeĄfŞé¦śvęé§ †*ꨤ–j:ŘĂ !…ŞŞ¬’˙t€Tä Q ÖČóĎ4<`Ŕ1Xó>¸tĐŞ©Č&KWôŁK¬E1ë,´"ą`Ť6řŞĐ2ŕĘ4>4Á4ŕ€ .$«ěşěR@ $pÔ@< A)PA (€E t ĐĽőŢ›ďľHn ¨ ‚Ŕm°AÂt@lŻ)¤°oż˙<0˝w<2H ‚ &0ŚĂ5n ÂĂÓ ÁĚ!„€\«¶x0+®ä¬ < @Âs° 0ťĂ ´o"Pđ´(W ŔĹ(ăÂĹspĘ!p»lËçO´B ř±Ś?ő(ㆾÁ˙+Ś×}wŢ{WC7¨°B ·Ř’BŚ` *€`M&*Ô­M:őtó†Ç}ăówŕ~lŢůç}`H5ţôŁŚ&,€L;´×Ď/tPB.éřCĎ+@%ŕ´Ş­nBL‘Jďů ’‚ÜQMŢsLm1-´ZÁ ô”áÁ ŹXăĎ;ă±óî˝˙<®¦¨ŔŹhSmç˙Ţ řCK"čŘÜ "KśC YčD?Âôŕ ®Pž@ xŔ.ĐX:h#R ŠhěŔ©Ŕh t`»Ř(($¤B`Ŕ€!(A°Đ…0ÄňŔŚ?pá p` ˙<#4`Ââ5‚.| xŔxĐŞáńŠ "LžŃW#`Ăľ‚ŕA›Č‚&X6śĂ  ÁzpŹ4Ń„xa &>1ŠS @$Ţ8$CĐź"Ůs1<"ŕČ„úŇłiĽ€č19- Ďg—Ě$1‚2äăúŔBâuö˘„'<† +ů¬ŕ‰¸(0ON”¶Ä%0lěa đ8Bzp‹t B -ČĦZŐ«fXŕPłö!Iô°äˇ@đĐŚr4‚6XGqŠR‘úô“˝HE:ÇZ`ăGP]ˇŠhÖt–8ťŔ všłËţ’WŞeíŘ …5˙vAYrĽNŁA‚5˛:Aâ=•·ßÜâA.@€†„c˝†SQĐ#Ż8-‘ ¸KF@ú†@=ßW¸­€ ˘a€H±đĎ®`Śz€Q†ťl6^Đŕb“ËôŔ$`x‘ gűíďwP ËX„ şwă )@€M+™ÓČö&°9Ôś=ŕ;Á1‹ÝňáĘTí2ˇĚÔ‚¸@%¤ăxu`“  Ńlŕ°E RPe®łť XŔGp‚[€"T¨(lÁP@™_µ‡$dLcŘÇd-60a«řş9˙;¸Ĺ)„ ‚tćw˛öHD ŃŹ8¤k~t¸"Üđ†_"Ď{îsÎňpŚcjáČV…9°lâ W`jaëaEäL—tˇIÜéśŮa_x‚š‰§˘ĐzĂTËŠeĽ 5ŔćS͸Ź@Ěá ‹j°7Ě•©Ŕ* Ć/táŘfDŁ8‚ ´ő*X6Á ě_¸Áö‘ ŚŔľ¨®u=APl`hó›ç-ťp¦é=ćQpâqÁ@ :ńŽwúć·żSĐ€%䣭Z@'ć1Éd~`Ý;<—‚¤"-ř^728śŕ˙‡ÇA.r’{`Čđ‡ď2ˇ85  wˇ)7đwpN8bđ<ťĎä%HĹůLđfć3x ŽwktnoóŰĂ6Š‚(¤ 6XŔXçŹHňg]=€p şČ˝çťůy¤gÂÔB0¤@x×;ÇR0ČŚ5óÚA:ŕe”,QvŘ*@±ŔŮěďT3'ĺ%Đ@¨…M9X’ö™ĺ¬ď{Ŕw`úcő˝Î AšJfÎ @Mjk€XÖ/–ŤŢń?YĘ‚€ćÚ# ř¦»ňŻĂc "Ďwór†Dż*ěť>7Blš@Ű˙Sjń+dű9Ŕ ´@‹_<,#$Č@Ĺ–O˙5i`ú<Á€ś“H„Dő  CÉ'$ ,€~Ńő×€‘Á'Ř÷X ćç+,ľ2PE¶J$ŕ+/° rđľ’ň÷Xp¸‚r‘!a.(8°O8ŔNŔ Ă 7J`~Q7p:(„,…ď!1g«´ "¨-"€qĐ„ ńˇđ G°3”đ ß UH Đ PY¸…Ń…_X€Rx‡â9P°<‚ńĹđ ¨ĐJx/Ď@ ˙ŕĐđ ä@ ŕÜ@ 0€lpČ8…x‰‡˘¸•kĄp\!Ia0v,ÂB,b…vą˛+˝Ň…T’ 2]A6*/pë@ $P±P÷0 uŢ'M0Ŕ/€ęŕî "ŕnҤżŚĂXŚÇŚËh‡ŁXŽGPU€ Ŕ.#Á1.ĺr.é"Üâ-ďĹ€¸]»¸ů€·„? ńŕ B@ŚđĂ0 g2Ń@!Ŕ-Đ/ĐÔčÔđ/0€ y  éiŽ*I™w5" K Ŕ5P5“€˙ř|ä§A “ł/ŕú]Łűň“á+BC4[´3Î7 P'Özç5pŽ5ËuŻzŚg3eĂhăz Ăp6Ł2ľÇ/K3x.0Ľ(ŕű`!3?Śë°—Ţ@ ?đv ˇ8gP Đ Ţ@ Ţ0ŤÔ¨Ţŕ ÜĎŔ exx©—|é—€)„IŽ+š%±ąŕ~ß“Ś@=~p őŕă0<',˙ 9P} ¶šő °)äué9ŻĐř€˙ ¦ĽÚ/x<]Ő|ÄĂŽąŕ;©‘S>ţ üĐ\i©˙đţ€š§wŕŕšnđcŹ  G–36 :¬ă:°c8Ľłv˙f8ŕ —@q€sY—«đ {ą—ę°±ŕD@a 00Ĺ>ŕÔ‘ÔŠÔ i ‚ĺ÷Ş  Ú ˇÚ˘ů˘-!ž 9ĹŹ’ B¬ŕ c0 Ŕ fDžŔ+ Ł: =úŁGz©2p˝A Fće0Q ü°ą“E5ťDŞ0vP€ŔdŔj+4ôF\ęť XIŔÄ0Fođe*ő€c0×0Et '0M Ŕ ŘÂC>˙DB´,Ą[ÚĄÇŁ °060Ż@ŁrI—Vŕ‡a6B@ ( V2)…p“Ă€ęěěŔ ú ˙„˘Jަş—¨ŞŞ0ŔŞ  ŁĆÚ2JŁű‹Ł5 €‰ĘffŁccڬϭ<ŔOţÔd$ Ěuű°;c,°  ŔŹŤĐ*®ŐÜÄŔ˛ v Lüd>°N›J÷Đşh0 <¦LĘd8ŰPf Ö][P 1éŤf‹€ M€L.@çš®Žu<[p `GÄS^pRŞ Q…?@ ëŕ ? ŕ\ *˙óR ˛Şě@«·ĘÔ@ G v¨˛,ë˛0+ł4ű†ÇÚ´#13ZŁŽ…ŁEcf7Ćbеd:4U{fÝFWv…Wµ©0áę €ŹéP ü ­•\Ëó®d‹ý€2'sWҕ˚‹ ˛­Fn·j —l`GĐLA  úZ° °CTépTIŐ2%°¶mˡ B<бJYĹ—öŔĹŁ*ßđĐ0PX€/P»µË =›»¸ę /V»)đ’ ±ş­‹2°+»­ę´ČËÉ*µ7ʵ9ăµY[¤Î^[^â5äŐ®kŕ˙ ŕP8 ó €ťrKtëvýP4 4‡Ę·Nő·ýZ‚‹Š…{¸9–¸LŕÇąđ Ň@BÖ2´e[°ľŕP80b–30 µ´P`­R¶ż ť‘0@ ?„ˇ ‡ qˇ « …ŕ č𳸠RŔ,ü*0Â"LÂ`Â(śĽBڬ•`/p‹Ť@µĎ{µ !HF<°Óëµ^¦L pEů¬$($.& d ,P c €ŰpKFM,łNˇŕ·ŕXWx˙* /°JH° Ňŕšę Ół`ź`o(˙–b+ư í¤Spű+Q` p °E đXđ%לđ"đ‹Ôđ ~)ŃtđşC𸋫·Ăě‚}  XŔ´¬,ʤlʨü˛«<ÄĬZ Y ĄIĹL|Ćl@n˛¦ÄÔ{cŞ÷má6n‰ °¬É°Ł…6—0|°YP<U;DlĆÖ­gŚ˝ökPt€§0c`N@цĚ] üŞ€Đ,Ň0Fe0k ‚ö§š­‘Ŕ…“ „Ŕ*§–j«Öj=#ÎälÎĆ‚IŁ` öđOs©€™Ś˛Áë"@qđ ßŕßĐiđÉ˙ń>PĘ?P ?«·Ę ŁlÓU’8¨Ň,íŇ0-Ó4]ĚJMN“Q× s0L®Ŕ }řČ€9! C§ ĺi ,°S­!`Ő3c'sffsFsr1  €7Ýđó'pJ'u 1tE·sŚGťtÍőr1çšs𝞩К:W1šcŘ“w@CŔjĹAs2G4[Ý;g×öv5 Žf5 `ůŕĹZ\0»/𠙼ľŇß@ Ô° L¶@ čP exĽńÚ;Űł]ŰK˝ÜU `“ y­ňN*0¶ŹŘ/2#1 Ă˙`Ý9ĐwŕÉĎÍ4Hé“@Ľ4#|u¶××Ëz eZ0'1 –`‰kł6Óz_©ŤĽŘ_* Ăäy7ßŔ–GهółNNE €1"0ł+Vŕ/ Ă ¦ú }đ`đ?@ ÜP gࢪká;áÎáĚ˝ÜÄ-&ÂŃ0n$BB­­]31TľÄ  ďyˇlr;Ă_¸ăȉŽĎh/nP …ŔËÁKÂĄä"Ŕä1ţĺćaŮÖ˘0ĂĚÓÉ I,Đ> LL@sđX#)>iN˘`ľçî!0ÚŘă"Á­­„C1crg˙>‚Î猎& ʤ<37ŹŢč–^)3é—ľéśŢéNű*«‚Ň"áŠĂR,ÇRŠŚŠ 1+µâ鮞Ňň,˘ňh.čręŽëČÖ‚-€ţęŔ~î/ňB2Ł/l2–W0ř‚ě ł0 ó~Ń”5Ä07™“R™–+Ó2 đ2133•ěâľo7 )8xŁ7|óŠŁ30v“î…s8‰ł8ŤÓt†<5„+˙0›µ9ôŮ:Ż;łS;·#wă~đĽÁ?ţ@DI„@ Ä@3A9Ó|oAa€AÄAd8¦[¤CúTŨ?DCTDG”DK4ë˙ň¦ŃHŹ˙I“”o „IšÄIrŰ|7/J¤dJ¨¤JěL®•}°UŮGLĆD±ĘÄLÎMŰóReQĄQ0hR•5R;–Y›ĄRŔR.u}DżľôŮGTF…TJ%MĄęS?÷­ˇXŚĺXă¶ő—Ĺó`źRťőYGŔE_\W4ďT[ýp[KĄ[N÷żóU_÷•čt ć_d"¦LĆ_šĎ`aÖ=AĆC&P9 OĽLpbŚĚb.Öcůů¶Oq6gufůŇ3Ćg~foj„fhżŻh!ŔhŽiŮR¦Îdž¸ĐüóSѪƦńj±öI˙}űŢöÖÚ ×o˙ćh‡r7ţ ×p—Ő' ÍtyÍt±Ő]ýŐš=s57—saĘC DPáB† >„QâDŠ-^ÄQăFŽ=~RäH’%MžD €‡‰. !ABŠ4€!… —0eŇśĐ@„4Pˇ˘ "Ľ™SEM<(P0”Ă r ‚`…€ ‘RíZ¶mÝľ…Wî\şuíŢ•ërʦ 185¨—„–’Ä@ďbĆŤăV¨pÁ°cĘ•-_Ćś9諒Š ö¬YôhŇo{ô`1ąôjÖ­]ż†[öěĘ˙:đđq†%R¤(ĄÁ"A6l"l`I[ůrćÍť?‡niŠQ#çÝ7tÄBů‘ˇŤ’KGź^ýzŹ’Ű^KˇÍĐĺÓdßń>Ő’űë/¶Ť R؉ǝÝŹaY…6î@‚€ÎËŻB /Ěďŕ°#¬µ€‘ţă¨81D !aŹ9R4 DU´‹:RČ)0ž©aă’d†!‡śN˘@a WD2I%I;Ŕ*r(¨‚XqĹC$«a—RřIKöŠČ)1!ňrÚ"@{8á -Śš|ňˇ¬‘çźÎ kţÁ—Ü„ŽŮ„ˉ°ÔŇ˙Př Ś!<+SŃ‹Ň\łÍx(„@ڇj6uÇR†PjISOE•1¬Ńä¤ŇĘ‚$«`Îě’3Ió©‡@c‹€+úŃĹRŚVm•Ć‚PĚ,h‚ hŔ\H˘A ­V[q-%ň ă Á6–Xc?b˘Mßu'Hx˝ŃCŐRĹ7_}'Šęź¨Š ‚¤0Ş®ůb(6a”QX)ŁĽÂa“¬¤’9¬8&xˇžbš‰ŞŁľR!¬ (ř8â†Fţ· *0 ­Śř÷f R2¬°h!dúŤyhś @LH ÝPض“!!˙ĺ¶ ¦¬ŇÍ›‹řf 塣˛ Dh‚Š/N{\Đ' Ža.ą!˘3HÁźZč˝ű†L&l›NŞl„:čC…śÓ tćl÷Ĺ<óĚđC›tęéć €ďÇźqܰmdÚaźz~‘r”kŢ1}±ćüçar0LC?n©§ö6đŕdü©çtřrI}@ť rIÇzţđ „ NxÄާ]˘gśzŔ`4r±ž‘ě9đ ŕÁAÄ<ř=řqćhˇ ôä“0ú7´Î}.tTů€!ŞáŹ~(C &PëÚQ|üâ^ő®—˝‚ ˙Đ2ńTѵYĹo~ő#L·áŹ[\l I€!ŚŃ‚´Tŕô(îtÇ»´Ť íŔ>ţ!Ź_đäÎ^ ?,yĘpßňŚsN¬ĄŘ T° %¸…-řăJ|#ę …;ľA uŤ˘R‡ŠqÍŐŃŽůňŇ9䀄Tč  ę1 â|ŕ‚`„k AŘĂXá‹7ŚaŘC O€©‡“Ă@Á 3ä xŘÇ&˛p…}4Bh q <ř€„NěĂ Aľ<`‘§´!žđ8Ŕŕe—°G"ş‰~ÄAJvx"¸@†f`‚˙`C2—ŕ}4˘p…/B9ĘR.±„=x‚+H€<`ŔňŔŚ?p, "ŤĐ GB’Čĺ.{‰Č´xĐ“QÁ­„Mmrł¨€ ŮËB]® Ř<‡@ ôŕi @8éI–¬€•B”ĐXβ–·4g-q5dˇýC<€NuZ)Ź5˝iţ¤f0"˘ĆLŔ¤ńŚgřATŰH¨Bőm,†H ¬;vŐ«ŇŃË °‚{$âŰDHpPdø€ šˇ‡„€±s…ŕf`‚w0(—¤äŠQx|µfŽQŠLŕ÷pe˙LŮi‰l•¬‰° P좦Ä<¤ l•!.©l&€ bś ۰CL€AĂ8F x@Qc# ¬a»«Yq€ ]gXÇZVř˘TJ WąŇ•¶é€f9ëŮ$°aBÝ„[ÝňÖ'čÁ6č €PNˇ,¨•!$pj<†±ŠU CGˇR„#ľAŽ6~ ’ýjŚeĚśH96Š |ŃlŇŐ…ď'«ÔÔ˘\ú®í˙Zä#× |ČÁPPI``Áş˛±"¶‚€ChăČŔĆ‘+Đ[¤ZhE¦+É´(ČB?đá:űcC¨Á5ę<ŕŁ‘Ś ŕY↹>ý˛Ü¬ŕţĐDZ@‚Ąţx®\B—˝ ć#wĐżŕ=´›ňĽg:ű:NőŢćNX6ö0xř8É!Ŕ v,ŕĆY˘ŰĚŚ"Ř ÂŢ˰‹-­K–ÂĘjj¨Ţ5mjgF3Ćv¶i# śŕĆ9އxlŕŇcáZXŚäO+9ëÎ3]ĄLĺW"„ŰŢÖ2 :qŚ:Ö82Xf˙T€oz]s˛/ŕf8÷ŁB Ä› '×Á 'FŔńŔČ….ȱÝtď‡% Đ‚&úaŚÄÜzŔ´öÝďwšťíy¨ Rń‹Ó ăŕ7¶ä„ůĂ+ň@ DHc07?(Ľëb߲˛7›NlcëśťZwó˛{P lśĂǦ:tÔFjŻ]Xőڵ=wşc†ŰľVÄYQZ¶JĂr07”3p×tżű㍄9^PZXumÝhĆ&űr4by°ěőŤ»˝ AČvÝ  @i {HB, §đAŚĽöSÁ–¦ŘOĽ 1Ą•¤ăĎ M˙00Aiď^ň%1 8F§˙äĹ“`ó{ôîP i4ź`đ›-X|(6¶—î]_+¤`čćěŔN PŁ µ€…-ş €$Ţú!Ŕ ęfX¤`řŠŔ:są„ÔbÖÂ'ěű=îC­h€|°`+cŔ‚eX ˇ…`śb`‡ dÇI1G01u`dLxşCÁĚŚ˙«€ „k $CB¤‚4s1xߊĂł9lÚ‡DŔÁĆS·Ź€H e2„n‹Şş˝Č2őc…ex.Č1Ű@ř‚¸¬7s™©5č‚   |8…9;p‚Ůb˙}°…2@‚Ćçuk ŕ:€A7xřż°°=ř‚'đ‚jâ’Ôě¶(śÂ*ä’SÚ‡@7 äČl„7Ŕ¦~°…P’Ă :h‡Lř‚*<˘CĽ¤?°X#„GdÄAF›·dĄ>üC&üşdZ¦f–•ĐCDŕC?D&eb¦8‹<8čŇ‚kpEÁ€#xvđk¤Rx¨úkôFq;$Çrt‹H…`hę†LĐ+Î)ťýYžč'Ę.^°Ť@†LH™ŞMđ‡{dpâ…%äGÜžCH‡tČ…~hlYtTGvĚ˙Ă(N ťwІ?H¸m‡L€ăśʢ("Xäé.0 ‘:.đ^°˛„üG†Ŕ€Ś|‡w0 ČuxŞÎěĚg … ŕEsdÍÖD ÄY ŰÓK›˛8 Ř€ Č H‹˙“S˛ ¬ŠŢ” –Î(NĐó¨8¸®…€Í M  ÍŁů˛€˘Y˝1ŞhAđ—’‘Ś–IŠŢDš‚XNĚL€Ů‰é¬NťęŠŻ¸ÍÓÓÎÝ ‹€)3Îú”™Ł™ ¸2ĎR™łŕÎÂP€ĄŃ°‚(ά¨Ođŕ ÔH•ÔÖŔ€ xŹqě'ťT鮥ˇ3ŕ>(3P‚ŔMEŐTUŐUE‰°HŠŕxHeŐZµŐ[ĹUŤŘŇ\ĺŐ^őŐ_Ö`VŃhRMÖcEÖdŶb5VeuÖg…V…8Z}ŚĐŰě€ÚT•Č +©Đ©ĐOĄń› ŔŠě¬€µ!ł)•„¸O Ŕ Љđ íPm­D芍Ö}ĺW^Ý'¸6‡Ś(HÚÉFČOŇ1Ôá€GP€°†9°˙Z z ˙ˇžzІôůp…˘HH¸Ě˙h€%`m8…j‡¶$ž;¨†,jKĂÉxDťxŮU†™íמőYVýPđZ( †(€$ŕb€/x/hA‰*¤Câ:€…‰ă«V™§zş'ŘŇ(€~XâŃX€W†B+$Đ9¸D8 Ů#8%}P%• ß’ZĽ&<ĐŰ,ŕŰSýŮĂE\×< x„|(Ińa…ę+-Ć?ľk+Ř‚j8Č,pf|Edh‚č–  €we€)kâŮ‚kŕ€ĽXŚ/“ h†Č{Ĺb¬˙“s0×B+µb+·ňÝŢLÜĺeŢÖ¸@}(‡8µQ€¦A9•c9(€T‡:Ŕ)(˝°€A0»E ŕcBH‚{`ÜŐ]ŢŤ768 7î±Ŕ†Ţşb{ŕ&vâ;:€+0†z0†?Ŕ'“\axµĘ Đ;Ěő»¶u†i€Y0‡O˙H ŔK>0-™Ľh0=<‰k€hĂ•:Ű5 WëÝĹJ=Öj=´c8^X<Ň'fäFƸ…S‚©N†€a‘†¦-7–ŚAŞ­?~(„} „6 ÄA,Dkr‰yŕ%Č‚rP„?a”Q°Ţ˝ …ČßýĹ5ý•‚ĽÝ„.ŕŰ1ü[PÜ˝Ĺ)=väeffő.ť• ŘŕąGÚěśÚ‘š; ‡!`€(Č.`J:ه§ Ľ¬žwč†?ř¸Bâ·­ŢpÉ‚| –čć|h‚—µ†,ť´É’Gí)ž}î†(‚ćfFč„–Ť•8X€ŁA‹ÚÄV˙um@Ű„źů¤šú¤rÝ—™P,k@ eŰěÍ|倹ִ؀ Č×U虦işŰŐĹ —Ŕ- ]€Xڏé¦hŇÄ<čš6ęŁĆ¶n¶†t…!¨ä?ę1Aꩦęr$±(j‹Śf­ę®öęŻë°kŘCµT+ĂÔn9ëËc÷@kŮ(k\őŹôčÍ Č€˘ëő0ÉęĐQfŚřëYä×ěŔŤ˝ŘZ•‘ˇë@„2XÂĽVŹ2‹ÂÂŽ»>Čě’Śŕ'5SfuJa“l“`ŠĎVÎć €9©“AĺÚ¶“BŤfŃ&„˙°ě˘S“ÔŽĐí,Ő Ř”ŚnŐl‘”‰(P†~xeŕȱJqܶí¸p,zëÔ^Ź`Gékʉ¬ÁěÂëđví‘ 2hF(á•b=ía)–lAWŃ€÷FöćaagˇŹđgąěh–ď'Ao\ĂďđľĂ XpúfŤ9QÇ•x^`´fn]™@Z)"htÉďeiż‹y«˛ď~đĺžq!óž ĽÁšŞQ–é褝QŘ™pA lŤđ„[ ňť™×)Py×xý™Ć“ čQ`Ś‘h±ץ9 ™0 çčŔᙣ(˙„©†qĹAň[yR @o{ÝË Řň‚A™°Ŕ]©iąň,Çńř2˙Oń s˝ˇt/—tP ůxś)™@o¦90XUó á™='Ó'G Sß™Ťn™Şakđb™ €¨ĽA×uĺh”ˇMšÁϰV©ŕÍ 8Ŕ)ŽiňzĹ ŹLu¸ęÖ™´ń#ż„ň9LŞČ ëÁíáďź"PóŮ©ÜdC@:Ä6 Úر÷ý‹ś•YAGŮtPY–m˲wĚóĹd´«€â%_ Ü`¦b‚J˛$LšżOĚe‡ N:‡8]ţJş¤LfÂĹ©¸ťŰş˝[†J„mę¦ ř'†&(¤]Ú¦}Ú•čZ{‚|‚kčCŘ>8„e"6zQŚÇ„€‡>űiŇOĐŚ-zL1†$¨tŽ|Ś(Ü7#Ť5Úx#Ž9ę¸#Ź=úř#6R•Í L€ 1,„€Á !°K+90ČRŃLYŘ#E»`ňB b b afËfĚ"Í XbɇÔB`@BJŹźĚ(aCkިm.4ŁG!d9Â(®Čře ĄąfI5.µŮ1l#H$J6>HJ©Ą$Ť“PvŔŻM=şŮE™ä© µ—Ló+Ü“Ý]«Đ˛•ZZ°‚`yl˛[Tů`áÂ1Tذ2M¤ŕ)¨P€ řÖd[\Ă… 4C\0f™gއ»tÇő‘MşáÍÂŢłŹD î$#,áNŘĆĺŻb& !Ö xŔ~ŕ{Ř›ÇîóÂÎ jgTkŔŠf’@đ€ ŇwD>úáG˛M!Ŕ ö±†“ OËű  @ŔŚ›d-ŕP®p˙+t ‘ť»%.s©Ë]vîs<ÝčXЉ]Ô!@°Ćę(@ďÇZc;„/=:"ŕq„áU$@Ő\¤ţ€éĽ{HÁUňęŕ!Đ€D R–‡]XĆ#ž4ÉýC $©\€ŤůŤ€iö»ßô×ţu“šT6µiËűč‘O1T [xGtâĹůÉá˙ń7 \ ¤qÍ쥊×}jG]´~NcĘ%űQ°3|‘ŽIČŞÓ#Tr˘MçĚ|óČHö,h,NKŘ Đ  9¸§ GJF˘•ޤXÓ‚#h Óđ/c+ŰŮҶ¶DŰAŚś`‚0 0‹Ő5€XzkT)2M=Ô-3ŘD†VŁu Ě]]áp‹¤=‘§ô°ÂśBń‚ť)m0Ú*»f!Ś+Đŕ)#Jň«)ţxŔ“€…VdžĹĺ łZn5ő Hť¤pA<{’T‚YYŠ×Ľ@! ˝­·˝p©o±”`§TŘ]˙4Ż(Đ{[ä6Iň/€ë38Â4(V±¤:L÷ÂkXŢ0fś1ŤĚÂź€Ż§\_`u2ˇT0(XѸĆ]鎆c»¸‰^agŚĂ\Ű0WYuřηľRŞ„9^ŕ˘r4BK°E RĐ8_šđ®i6 ę(š˙ü7Ŕ$ …-\lăyf’ zŐ”ËëĚ^Ű"mŢĚą°Śl‚¸aÚ’=>„ RĐ$ŕć˝;NK&p}„ÁźJAvYŚ$%I,)(A^ş‘™Ú¶ŘĆ>6˛}%–5tˇ ŞŔ X±Ś7pˇPbÝń…ÜaŤÖ˙qg>Cě•< ˝.6Ôˇ.|( ěî%ő”ĎŚa €BBŔ§0H÷qýFOĘđ†ĺŮa_x‚t_ʎ_ü ®7ĽÁYŔ.Ě!‡1ĽAšŢlną<XČĂŚ3Ɇ*4‡7L&oOşŻđ<ÚÓ®öµe•ż!]úŢżŐ2Âs0ŰŮ!Š">ńŠó9Ž~ţyĐe(s€Aŕ-ÄËí’îHđŁ„>Áüŕ GUćÁ‡%dˇ(´ńFaŤA…F!á ŤĽĘxÎĐ Öë˘q ě_PĽ°ŹRdBuÁó‡/ta3ž™Ó˙ń:š:6íI—8Ĺ-žň@¬|!ÁÇ)ć0;8AŇ(1}ŕŰ“5ĆÁ˝6R7ăIĎ+=ô´·˝”'@Ô«žőx›:ÍĂDłdÔ»âęöDÄ Ô˘D ŘĆ6¨ ĽdsżűŢ—müP ÔCngJЉwřăÚřC pmČĂŕČ $ă ^¤ëČČ„ ä›!äĂVü™I¨Ö2Á™č˙…€˙ dÜ5”ߤdA>Ľ0@äCH¨Ź?ŚxĆhSʨY¤Âőä)xŔě2`=dbLA:đBŕ Ř`ŔtB=Ľ)Ŕ@-5@,?¸˙ l /ĹŞŔT€ $ Ć„‰<Â5ŔßIP@ ¤B:0a„ź6Śŕ¤Đ¬` š‚G¨ß;¤C=Ľ_ („‚!†Ŕ A @řŤ_ůť_ĺ`€! ,@*C @[7d‚Śäá҆.!ގ”á8śa$ŔĐĂp`>pÁBČ Ú`xˇ&¤CűuĂ \@ `fě! `VQ XĂŘ´1x@„8!—ˇÄ˘?Ô btKXCű]˘˙T@đ3a ""*"#"Jŕ@:¸Áž„ ®!zD†á Ž!äůu¸1’ˇ0†@ë ŽH˙†(ÖĂ%M8ľ!Îc 4@:®c;B" J"Ň]€Ě ¶@N`7śźB¬@:ä˘-?čÂ}Gv¤GI4<€ÜÍ7†$@€H@ ¤@˘<€J˛d pŔH$Äť¨ŔÉ5¨€řŤ@[4<éJMJ@ĘädlŔ(@”dK2@¨€ (Oúd+*€¤$U¦—ÉQ‘L-€HB€Ŕň4ŔV’ĺO†€VFZ§´ĺVd¤d Teu5@|•e·d€ŕäč¤PĄëцV¶d.“”%B $ř¤˙„ĺX*ć/ŽĺJ&(“VJ¦¤|ĄI $Iš˙äI0f]&@P%H¬dPlf€%eJJ&c:f&NĄ \ĄYz€SľćZR@h%WV%Ň͉ţ„fOţ¤6š4@KÇJ‚Jl'Ń\@¤ĄdŇ$Z¦d Ř% %I˛¤ ,@OŞsJŔ0ăt¶$W‰¦v"¦dľÄHVć7ŢÇs"Ä4@YŽŤ0ĺu6fUŞ…zÖç}ŞÇĽ§LŇF,€nĆ4ŔSz'S:%|*Äy JĽ‡=¤c}¤†n(‡6…%UQ†fNč?¤Áq‚hŽŕç$]0’ „(ŤÜŹŚÎ¨„ŤŢ¨ŽŚh‰ž(÷ŃF‹†c}( Ť†ZÔř¨‹Â˙(iS¨EÚŕ€.řâĺ$YŹ0iŠŞ(ďiWUQŽ(鍀)Ź$چ¨¤c!ÖÜ€ĐÂ/ś\‡Ć©śÎé±@Um“lyž¦XĆ™˘ÄŤţ) j@ŽŢiźÖ–žÖźnΡ&ę±q 5¤( ĹŃ)ĄVęlE3Ô& ÁjZާ~*¨öČňŘV)DˇšO ¦ęýčȨvh©vJçĽę©Ţ’GřϬ†*®ć* ©•ꪯţ*°Ę) Ú±ú© +˛&«˛.+ł6«ł>+mŃhŹŕ(´V«µ^+¶f«¶n+÷I+ŹP+·†«¸Ž+ą–+·€Ř'Ś]łëŽüéAͨąÎ˙+˝Ö«˝Ţ+GĆR?č»2« ‚kŽP+Ľâ+Á¬Á,ą*págBe›ô¦`A @’UŠäg¦ŔĂ6g&Uň¨gre p¬xV@€çígWňčeâĄŔ'MB¨LŠěýGÉRŔ@Zv%$€I@şl,m¶bJÂÓČčI$@¬d|ĄllöçÁ¬e6-$=mZ&Â^-Öf­ÖbŽŔÁ€†źţa›Ä€5ü>CtXĄŚ­ů•m7 ‚’”Ŕ-ŘB|ŽĆlO<ŤĆ•–J-1 y˛@´śF”‚”©ÄPĚI°Uţ>Ţ4‘Ŕ5Ĺ[­ŃF@ąť3Ä@Á `ĂŚ6µÎëÄÎětKMęĚŚ+Á…HÁBÁ+üřI3° uŠYÝ2ó0óŇba3*Q28‡ł8ă*ô4ť±€ héIUVwř˙’;Ű×6XUŤ Ř*ń@Óŕďź[,ź%Á•\)dS ô=ÄÁ+- B˛`f3=ÓôWG}2Í ˛–k+µ ˛9eÁ=ŚF˝˘)ĄÔ6—I+OJ Ä8Ç´LĎtGŔC=bđh¶đ䮑¦šŚő4ěZ‹1`Á2,‚ lîĆô?{GśuÚ·5JDŇ ÜYž5N®-’ŚŔ Ü(Ô(@JqőŤ D™D5 *°i&«·.\~5!ňŹů@Wµ™ˆőµ‹Ń4a¶aÇÜÂ)AŞM*EUĹUdE€ĘňôÓA6VhBä˙Aż¤€lá‹nĚiEµ )^îí+\MÚD^qPžĺÝpŚŔôň¨Ŕ"`ĹT@¶m[·%Âl‰/ÔεBJ\8pıĆk 7ż0\3pA ł‡ sôÍ6LPwlȶć¶w7xóH„ô)UĐĂ<Ô8B|î#!–÷y§wü-A>ÔAB,@';w EZ¤IĐä2¦â`Ęţőß˙Qč}@Ł4¶ź)¤ŔCÖCDĆěÁ6pO¤Ä,ŔŚźýáź ŞźBÄ!^RFÖ>Ń(ę L5ś Pn<6řC’üŤ_>*qóB$ †·Žď8ŹŹF«âUDhgŽ˙e]ůË$€šĺlęě}LhÓ<ޤiÖäMîě_Âéhl§tg]>hŐB/(@¤Áe˘¤$HŔ}ą…bčr3÷ýŔĺ[6@¤ťyc'ů|FRS†yŹ˙9 :ŤřRV]ŮҸőéqbéŹĐ†‡NŤ.T‰ßČš¶iŕ"ÖŤzĘŚb€…ŞjşŞn:§‡şŞ ş©ź:%::˛,Ž`ަrŞ-ý+©×ş­ßzŞ˘ş®ď:ŻÓ©ŃŽ)Żöޱâ:±;©÷:˛'»˛ű*ňA+Şâčż6ŰNű°ę˛g»¶oű-Ő®Ž¸z¨z;·Ź;ą—űh;Ž€;¨˘»ą·»»'˙»»~»´ł{śÂ+»—ú»ç»ľ‹3­Ëë»zëŔRŞ˝˙:µcűľ<Âó°Ľľůż<Á[ŞżĽB{ÂWĽĹ_­ş¬Ă?ĽŔ˙şÄĂyĽ_ĽČŹüĽú{lüŞzęĽsM„o¦¤äc€äW~ @äW˙>ĺW>]b~ZV~Çv¤±ă{´G˝č÷}®ç<ă;>ë‡3EäÂ?Äľ<üCýťěĎ>î×íÇ>íÓľ?ě>îÓľîĂľěűľ)hů÷Ť~ęăś·ýĐ«ţŕ·|ëO8ÓF<ög˙ěŔők?ösż÷÷{?ř‡żÜjl)˙ó3ü¤ł˙ÖC{Ś>;üź;ő×˙$Óm$ŮŤ6@\¸€ ;P¸°C v ±bE‹1fÔQCGŹhiäF“'Q¦Tą’eK—/aĆ”9“fM›7qćÔą“gOź?:”hQŁG‘&Uş”iS§OˇF•:•jU«W±fŐş•˙kWŻ_ł~¤(¶*Y°gѦU»–m[·V͆ôwî[»wńćŐ»ŔC„4 áÁ*thĐ„É7pP`pŠ 7~Ü!ňäĘ—3R `bâ۸qy’ý(R#jľŻaÇ–=[čOŕ4ÄăV=mšŞŃ›BńpţĆąi¸ÁĂťjő”ÍIq@ăČ•snţ<úôŚŕ<1aĐíéş>WË=Ďq=m÷ďáÇ—@´‚uhőű塴E Íş0d>Yfy‘1ą†ŔCźM˛Đ¤ź0FAzlđÁ'¬đÂBŔčPüˇĄ ,#/-óJR¨¤ĺ’‘µY˙łŃĆŐxĚń"×ć RČ!‰äŠ‚±¦AÁ„/ú݇,č‘f”PbI‰%"8¦”X bNaA¸ôL1É4“ ¬Ŕhx$p2)ÂE´`ô±Ç…xÜѬmŻ" ‹lÔŃG! „fč †:řÓżf¦´ÇĘf–Čb5 € {ލˇ=xŕ€6AAÔ52UUYuÖ"lĐH´Đاś"LŕŕĹőť+QőÄJtŮŤŤTÚi©­%$,§O“¤¤R 8ÍâZ°5Ulr˝VYG­őÔsÓݵ×ĐzŔŁ™raÁęEÖßô–ÔŮg3˙ŠÖÚNŘŃ<8Ť\Úů%ŚLŕ·˘˙¨°!ˇ˙˛\’ş”ćÍ1XbFPSŹCů…’O¦Ł®0¦cţ`„„Ô t,e Ő‘P eÔq`TTᥙnÚ= (h@tFgŚ0Ö€˙¸@C„PB -Äp‚ ; D˛G¬ł"n9ERŘ™-źrÖ$ťîŰďżŮrh Ť¦HG šÂ%l`Ŕ9äćč ćî°¦žnÜ@Ľ¸j —śrË1#É9Đôî‘ŢI$‚ŮŁđ×aŹÝ.0q hŔö sLâ6¸Ŕ3 ,ìw~çLxĘ #Wń˙Â=fÓkMiٱĎ^ű«˘!ž3ę>%ńá“>o’öľ~űőŮoßýŁĚ—Šď÷éŻßţűWr}+ýńďß˙˙@€4ŕ@. tŕů?ř)j~´ŕ1H Ĺ5ĚŕA¡l°(TźQBŢ„„D1!˙VCF% hLcD Tŕ†7Á#ä yČ'҇ ˙‰–:¦ĐŹ•´dODăMz !¸Ŕ&7I†Q”ťü$(ů3ĘRJ|q”äR(yIYÎr&7đ˘ńQŽśŤj‚-{™Ë]ŢŇŠa&sYHĘFŽA‰%-ˇM”`ŕ.Â"ź€!Śŕ4Ŕ6`…ŕ×ü&p‚n~óšág9źpN!Ŕ Xłi&Pž)M}îó"@A"ŔŠLd )A!ĐJfľR)ůäçE÷ ň9  !čAě‘…ÔtĄ‘ŃăDb”Ą˛ěhHU˛Ń!Ý3o*­cKqšÓĄŃ4ĄúC©NÔ™Ţ++ęQ˙‘šTĄ.•©MuęSˇU©N•6€Ä9|PRŞn•«˛ €ö‘†®Ž•¬±«Ŕ |!'I´¬mu+µv(_(“­oµë]‰Ô0Uxőë_‡4€WŘ‚€5ěa«ŠxA«uěcŐB€Ś«®µěeąRĐ$@fAZ¬h–ËxŁhQ›Ú¨`\Ríka›Ľ…Ťímqű°aLhlnÜ–ŕ÷p‘›ÜüVąÍuîsˇ]éN—şŐµîtmsX a^×ő.ŠüG6`îwŃ«˝ęÍÇł(…mÓß÷­W>Z¬±ä›_ö…7/ ‚>Â˙Gý8vü˝Ëđd|n#đýf`»\ xyŘw+ a LÂľ€ ®QŢ Źi¶ KXŻa&¶‹©ćqĎZ.~ nŔʉeĆ=ŽŹŤÝ2C,౏‘lĎ'ÎF d`rd)ËČmˇŽ AXlĘ]vĄQźf.{™Ě\r™Ń,Ĺ*§™Í\s›áĽŔ7*)tvI\B;Ë$D`ZH`wä8ş%s¦/ť?ł|ňíy©w#?+d†¨GäÎKhMźQ(9H$ýi ‰Zoˇ®©="Ůwh/ŕä¤éĽ ŕŕËXƢiQ˙ŞÓş>Ú¦ăËş‚‘š×źnŞýÜkdk —ŕ…ěŃ»1ëgdŮŔF đ)×ËV–· ěôűŘá^vąÁmętk`‡Z¸Rŕf€!«C]Ip…{€aw $·nsŁZÜÁwŇvík˝!\ŕĹwbŕ‹CŘŕ2žĆH’ĹšöĆ"˛.<[áo.xjUÓëE‘ŮĂąĂf(…\ŕ€ Â4@)Ľ|ľ7kN°%LäP€CČ3>r’źÜ»)źtµÉMp—7ĽäĘ®‹B äĽ-˘öĐÄ‚ڦb‰’®ô3ýşäf¸Úźv¸\˙Ô-Ô¡>w–'šíÓ];IôwŢę ż»ĘWNř¨ó˝ďŃüÔĺmęAŢŘjŻú©űĚřÁ+ćĹnüuyz€9ńô}9şßp©ţ„-_}˛MţyĚňµg ß‘včőGEüXzŻžˇ˝d ˙‰|ßéĆzżoMˇí|lŮçżw® ćŐrí\ ‹ňđÇ)¶ßý+ÖĂĚź#ĺy˙ő;Oźý>Č5ąřr™ra]ěť˙Ô¬Y¤/}ŃüŻýP#Â/şç/*âcJč<Eú&Ą"/͢O% °%üÂüTóžHęŇÇé$p˝¬Y\â“ 2Í"˙lľ€M&2Żő–Z/öD©*PŃ:ö°ď˙Ňď""BöŠ%cšáAÄŚ´‹»/7÷$ŹÝîý*Ub~X/±p#¨Ł ®^€8Ś`ö fîČ Ňň. î [ÎzŞĐ ťŠîb°˙,ŹÎ`mĺG`ě!4@ä4 3Ç2hä04 4jĐjzĄ#Úë˝@ĐÓü°ô2QîâĐďđĺOęçţŽWŕ¤ŕń·:¤ç¬ 9˘#*€ÜŤ l #ěë8@ŘPŻ/ďL±=q©NOňNOćŠńńJN,nô˙ݦ>‹Ě€Ź‚9ě…Ţ,b¶jK!ÚËr ¤d¸i3xźpO»Ó÷pBQÇAˇ6@DD}H4Bku ť Ę´ÂŞô8)cy‹ Ć+Ä´•"v«·Jř,lp‡×Bb%–+^4F=`´űśTüäü<`lG%ęʲŚJ±˘Ş@˘Ś­Ë¸<€ k»J*ŹëË”ŚĄ)K߯LßTM‚K1˘{,•* bdĂGO=j#Âx*ü—‘ŹęNłô4ě’BY”!%YŘÇŘĚ„xgźP“•Ĺ•Y–cY/Îř%~Ń—$#÷ó•ką+ď/kL8 î!j˙9mÉ^3ł&@98^a01Ń+‰y>ř/ăy‘iYśł™™Ń×™ˇůÁLg˛šÉůš’śŃ2śĎ±›{†łŇ:]ó:fż×źłx°!cl¤Đ™káMp±2@¶N6 :c”Ćnóů&ź±1‡y?y֞˟ő. aČw»tI?Âśß3ˇŐ 5É" ÁZ@äΊĘ`˘Ďťëč›±óŁ=úY¸9¨5¤ż‚wEş]Ńr•“đş Z.Jö™?B :â=ÂŞU$´«ąçŐT°jh`zŕŇ` ś…§›Z¨ş?Ůy0SÚJŤš.F:;]®˙_z‘úŘ*z^ZšŞłš›°uš°ë:â ۰A±Y€“ ŕ zk Ňa ˘`@ëÖş {‘Ěr;ëk‡şnݶ®»bŕv¶äś‘©‰ş´q¶ŁWŽĄ™ÍĄ;B¦±¨ä Úˇđarq·˙A·yű|¸'—€ś`°aĆ`±Ž†­—Z´?wóôŁAŘ´OµµBµŐŤµ+2ŻŰZ¶˝ű–“†¶§š Äb¦` Ö`¶ŽW¦ †S4 ŕ[ľé[ěżő;@č!^!h¤AVĆşą7+ł›ĽŻ{ c®+aĽą˘Żçšńćn»©Ž=˙ţú#Z°›<G0¬Sś V\$&şĹ5 fOŕ@A¨ `Á†ńQJܧbnź;7¶Ń{®9üž9w1ý÷¦öPÄsŘxş¶Q\¨÷®6+`°áZş EÂ_ŰČUÚĂ/Ľ¨“ü*Lzk[sÍ3üÂłÖ{CĽ`¦Ľ˝ő™É\ö`” Ň\'“˙Ü®?śQú×"OÓµÓ<µçpČů™Č»ŰňĽ7Ąym#‚<°Ý»Í o5pîjÇrgW˝Ľ@1\Ń;/˝»›ĚýEvźÎZ^ť=€YP ¦&ĚY!N<Ó‡O'L‡gś<×oť&BMĂ´ŇSłČ[}§˙V]/„˝˝­B؝Œml´›]atY/dj+ş]H=ŰĹ]Y·}ÜÍ]ŃÎ=ÝŐ=¸„}×™ÂÝ/ŞźxÝ=1ÚŃ™)¤=ŢŁšŢŁ]C ˝Ń}Z›c⯛ů™ßýŢ/Ćłů]Í®¦ťzÂC;Üq˘Ý^)ŕť"¨˝á5wŐ‘¶?^ž[ÂŢ~)ň]ăĺťăˇhwC¨ ý¤sÂŕ"ă“‚ćBćU~†6÷•şWáÎĎźÝ&,ľä1ţâbăs>…v>žÉ\˝UťÍ×Sţś‰>)Nţč§>éUĺ[ţŃKÚëg“'plţ(Ę~ěµ^w#˛ë™ť»ŁÜ'†>ťkŢčo>ëÓ^í˙ tĂţ ďÍĄ~ßË…îŹâęëđđĺcűÜ~Żżű&ĆľěŤâěţđĄ*gS˝Öá°(â>᫾đçÝňŰ*ęŐ‚äĺ)kě^ôß*˙`ăŰłöYöi_Îčš0éYäĂ›ŕ5čöë‡÷Á˘Ü{ řÁr@‰?,Ž*’}–†ÍLLř—˝ůŃŻ&ŕůĄ=¸©wY÷„±Ü1¶÷I?'hč›ÂëéŮń:Lú5śúłźŘMďŃż˛ý­?ŃŢü/Ő9™aéńubüĹ˙€Ŕ <¨!ˇÂ… :|hp!ĉ+ZĽ1ŁĆŤ;zü˛"C…Gšý4`Č[UűMë˛ZÖ‘ÍşžęŮ6WLJ+ÇŢYxqîÎFo.NöńŔZ9őm<1ęéÔ«[ úË킝GŤŢ;şÓ˛ăe¶Ö-Ú+näčź+Ő\|ßó’™Ë'Ě>{ř±Ă‰ç/zŰ}ř]G`™x%éÔŇw%˙U‚ŤĆ›z)×ĐqüEř—v?iĹ!†ŞĹU^Ůqř_s$ź„ö­(\‚ŇÇ]Ťîö˘„˘„`Ź>ţ8Ú‰ő Oö—…˘8Ů~´-‰ź‘6BůŢ‘™ÁŢE»1i_’3^FŘ“ĺńŚBČ”Lţ­‡e„Ë gśrj)`pgŢŘ؉jf\ovęx[]z¨ˇż)ö'őÚ§sŚę™4¦‡¦|)Ήi¦š2¨yçµI%ʞńąpljhsiŠxhŞBZésHfÉŮŁ‹rJ[¤‚J¤tńm l°>öą*‹]Â'y_%öj˘®;&Śńšˇ› =ËZ®Çâ˙"­`v i¬\*Ú«eÔ扢¶Â®Ë®i`…ć ±.Ş÷š{n> –_Š \˝˛îXčUE–Ą§ÝĘz0™^ţÇp¸âvGn†únŰişă¶‹qĆpÉ+i›¨ĺĄmĹŘŃÇĂŞË"Éí]śÉ3‘Äg©˛ĚKrjŘÝŚsU+śąMtŃ2ž&ôŹ&÷tËKŁö¦ŃRO-2ŐV_='ÇA&…©Ö'/×J‰uŮS«kvÚjŻÍvŰnż wÜrĎMwÝvߍwŢzďÍwß~˙ xŕ‚Žöŕ†ŽxâŠ/ŢăŽ?yä’gĘ2Ĺ8ťkóc]=¬°˝*RÜaçńV>y馟>˙÷Ó–Óµp·® ·°gő:ę¶ßŽ;Ö’Îúîç®űŽyˇŔăZgîĆŹ|Ć»˙ÎŞ~Ľ<{l Ö60éÉ_Ź}ö×-.ćôEż4żŐg»©kjŹ~úęoÝ´żÜ’K<ĘâŹ?éžź˝ż~ţúďź÷ńkżŕEŚ~‚˘¶ Çż*p0Łž‚*ÎÝÇYĂ9`ëÁ fĎfłú_±Ő¦pDá·đuA Şp…·ó¸<迣ĺëi 2ë*7:žŹ…<ěˇöL´t˝¬%saKĘ\6Äţn%7óš ăĂ(J}Ş“ˇŢš6Ĺ,j‘‡Ň*Č?ľF0B`qXܢϨŔ.˙$ŚlăăĆ8Ę1}jĂčĆ9ęqŹ|T[rG1öq„,¤Ćţ€@~1ʆl¤#y˛¨%R‘Ś„¤%/‰ÉŃP€& ÚůŹJfr”¤,eF<‡'KĄ(M ËXĘň đ-Ę ‚¤€•qĄ, LS& 4xD>Ŕ‘‰"đň ľ ¦3źéČ„lňhŘG9Š`0“’Đě¦7÷(Íŕˇĺh lpmň•ßl§;yx€+ŁĆř HĐ—5óťüě§p‹SA)Ŕ§ĽöéĎ„*4!ŕ+?ÉÍ…Jt˘Řă$‰PŠjt٦CdF9 Ň*Î Ł©IO*¸€!ů ,#‹!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,#‹!ů ,#‹!ů ,z˙5H€Á˙)\¸Á‡"dHŃ!ÄRdhńbÄŚ66ô(€{ś8„H(ň_Ç‹®ôÓĄ’ĄH @x !C *(P€Ą€67âôłĚ_=en€Ć°öź0HC¶„ ŔŇ95Y:ő ÂCŹ'®\…X©ő¦€KÓ^0řĐ‹‹F¨R˶ĄË®Óx\¸Đ†Yy÷®MZńmŕÁ…'ćËăŰl/0Ŕe—“`Á0A‚„_®—ě%ę©_!8p s ‘›7¦·ľĄ7Ż8@)ŔP˘Ó»w§Rś~+L„ )‚Ě ‚ ĺşáňŔđĐ ‰Ëµs/ňt@!ů ,#‹!ů ,#‹!ů ,#‹!ů ,"z¬Đ@° A˙*TA A.l8đáA‰ZÔă?Š9zLrcGŚ4€đ@B†&NJLég™żzĘÜÄůQ KçÔdéÔ/ŚĚŚ\šö‚Á‡^ÄŽ2ôiiŹ Ú0“JŇçŇ«Y™I7’˘Ňl/0ŔŐ‹kϤ—ě%ę©_·LÁPJo^=p€RŕMˇB©0$¤ĚÓěW ńzµ ůbŮ€!ů ,+zŕhH° €đݎC‡4¨0!Ç#N¤Xq!ĆŚ7ěčńcCŤ"GvĽheJ’,?F¬PA‚!$Pˇ˘L“'TŃ ‹%nŮJqp%Đ;„ĐŃŚQ QŃvhZ1&ĆB “ď”>,HpUčd&LÂVĘ•]źF|;ˇG-lçŽü ±Ł@òl‘Ť!·"DžcTRhąöÇÉ’“,ÉW'„†ťć ą Y&€ DŕĐ!Ažk-ę•xŕÝÁN ‡Ůúk@!ů ,#‹!ů ,>zů5HP€@řǰaC #&D¸ĐˇC NS°lĐąPđ @Á?†82ú?!«ßĽ!ů ,PzŁ5HđźÁ!\¨ˇC… :D1bÉ+FÄѢ@Ž˙ 6h‚&L€„řÁP5ý”)QÉÂ… yýáň +/x8T‹J H„X©áŠ[ţ4…iA‚&F hŃÔĎŘĚ•8Svć­ĐŕÁš1:LLŃëF !ů ,#‹!ů ,#‹!ů ,#‹!ů ,$v˙H° ÁtŘăÄ!ÄÁ‡#Jpaɡ’cb kňţMăŔ„ÖţáĂŐÁ!Ć—0cĘśIł¦Í›8sęÜÉł§Ďź@ J´¨ŃŁ; \é§ë"҇J™:­éš%#.Ô4'L ..źŞ]˶­Ű·păĘťK·®]( ń˛A$dHa˘B °´ĐA _Ŕ‚ – m‚*T46¸aĺ4Čü8°„) #VĚŘń_Ó¨]C€ A„ —q\s#B„ćĐ!ř—Ffŕa+WÄ'Rhđ@eÔ6(Hp=ĹĺĚ g˙AA»‚Ůŕž=<„čĚ.ĚaâÂÝűřóëßĎżż˙˙yÇ&,Q~,ăO=ʸQJ* ăÁf*Č ÄĐ *,„PÂ-¶¤đĐ#Ę„X“‰ j“N=ÝĽ‘„řHHˇ.Â(Ł@RŤ?ý(Ł„ ÓΑőŕóË”K:ţĐó‡. PÉWmŕ*ĐĄQS¤e>¤ŕwTĂŕŢbL Up=expÂ#ÖřóÎ8Eç$”RRů‘)*pŔÁ#ÚÁ€Ś6ęčŁF*)~€â-e€š `É9jdŃI?a„ŕAO¸ŇĄ@ž‚**©-é˙Đ #)Í&,@Ă=ܓƿöňD¶0d.şę˛@$OđA2˘x0éČ$—lňÉ(O* ŹäN&}B„Ü4/0đA/ÄtHâĽU&WóÍÄPůś˘đuĐ®˝ř ě1ĂÎü+Ü“ČP0ϬúLµŐxpH-T¤` $ÄçB3zä@h`đ€@ěŇJŤ˝ËC–[;˙«ëľ€ P SĘ ,€łWĚsÄé,Ĺ`L Ă>qpšňë°Ç.űě´×”×hěSN&,j§#yŢ3EذłłŔó <ń65 6Ąřŕú@»öúëP›GŁHKÇÓ›|÷ßs°Â-ţhF $ä ŔÚzě Ŕ p6ď M+ňëÍ7×aŔęтԀm<0Ôđb…|aŘŘĂŕq„ ôŕé@…ZÎŘúăßIŔˇĄěC ›©ť WČÂş°QčšQŽF°ŔöůÝö–WĽđő,x^ń˙V lśăŮ•+Tń6ěEm{8÷ăĂ®Ť$ŠStĎ´@0c I @ @´Ô‰cÔ!@°˙Xu%ůŤ±oô:Ȱş@üĘ€×ßňbĐzÄᇠ"˛áĽ(Ŕ¨ŘÓÎTĆ3¦Q„D4  ,˝đ’̤&7ů“\ÁőČ×¶R¨ĂlĽ  ŔEÎŇćIŔ{!rL‰JUvč 0–±Ŕé Zr% R€€ěÍŚ{ČâZůĘX“|ÄyŔŚ‚c¬aäĂ ĐĹem¨Ĺ€JHc›|é@Ř&A ÄŇuŘŔ `ФŔshKÜâ°˙UŽŕ·E0¨P PŘ‚  ÚhItó›$ç8Xm`˘#śĚ¨F7ĘŃM"ŕ§‚ GJÚ#]€D?â€CŃápĂdy‰“¦tĄÄÉĂ1ʦ…kü+ŔäŔ°aŠ/\OĽb2A¬˝4¦3}ćR‰c‡=|á ^h&ä,sča o"+–ń.ÔŔnňű×>1‡70†~yŔ Ţ0Ą¤jľľĐ…şţ+`#Ő6Á?¨`Ř *°@|áwŘG"&0Wř˘fE+«@± p€Ł ­hGKZI…€Ó{rč1Źz€"JЉw˙ĽĂ0Xmk_›‚,!upČ:1Ź!äđ đĂŹŢŁ, Áhśş‘‰ `¶µ˝- žÝéV×{@†?˘”‰5¦]PP>L1!ÚľăEÚřCl)1­—J×-A*ôdŠŘę* ĽČÓmS Ą;XF2Ô¶Q„D!\°Áöđ#Ľ¬b íŹęßŘ üĐ“JKâ›řÄq1TL# t‡ Ź@ TŔbź&h@o8śô¤ ťMdRŔĎĚl źˇPpfüÂ!Y¦Ú{D@śĆT€:č qbübRZvIŚG‘é(6„»Ŕvşc(ŕ˙6ąÍ•…|cŮЦΠŁ=ŇZűůĎ€ôPŽ9=Nş ÇíłRRŮhz›‰ŰrŚsĎ„Ňi4Fp-Đâš‘ 2A›úÔ¨NµI‚‘C«'"{HQM !Š „ŔMĂ$ÖŻ¶°‡Mě@cA. 2P’ĐÁ3i$(É V!‡”$¤–ɱ“ €eűŰŕ·¸g‡@ { ŘÁ2€î‡t€N`7¤0ŚXśJŔ4FĘ}nŮŞ[Ţă¸ŔÎŃÎd <®]ŇVaí¬ qč7D^ŠgÁ8”řĆ7¤ppR@C —ČÂ.‡G<×˙OąĘWn2!˘ đRěŢ]Ś„*Z ďĽ Ď <Ťop7(»Šś5żyÎwŢs–[ýę÷ÜYKáFhŕë`źÍÂ0„\ź$%+)`†A"V ěa/ÇĘ!‰Ö@î{Řő÷šĽG3yÁÖA d€eE9î1Ś:ŔŇp^€u¸ĂĐ@¸MDđ„7<âĎxÇŁë¨O} =Wl,á»Ř†‰…,fA‹@¶ŇKľ]ď™ č~Ç»ă="˛÷:ß5p“ě!X8îľ‹xxC‡ĎŔ†1Ś3Đć!¦ ˙ ZĐ‚4âňî †b`ôÚ×覾ő±?ęíw˙űŞĎżţ9Údńk pˇ‘€·†ŕ9 čxńDń€q. a0áqÖqc ŘĎA_g„v PŇf…łp5Ë·€0fT (€g(ó_×Ń[ÁQrĆÝáĐc*đuŕű`ÉÇw˝ń·Tč ”đ/ q``1xĹ Đŕ Ôŕ –wyęŕ ŢŔ bř śpq…SX…W…[Ř…§·z¸‡°łąjr’Śp&~p őŕă0í•˙ 9˙p č…x‰8!ň„'zÂ'$ň í€řđň1đ$[_§%<wďâp×h Q2!@" üĐ0¸|ž©đţ [vŕăŕęôĘ@%_—"s`=ň#A2$BŠÚ[˘Ŕc Ĺu°„M¸|Ęvđ° ß@…T¨ë Ž@D•ˇ€˛çŽ@ č‡~ńpyčĐŹč@ ĐÖvićŽę¸ěčŽđ(ŹŃƇů´#ž Ü3|’°+¬ŕ c0 Ŕ fÝž0_‡‘É‘Y:x1í§2pkA ńäe˙0Q ü°L"/]˘ŠmT’`ő\@Zµ7@Ă“¸Ř1XIŔÄŔ/ođ0‚P0p A°p#Đ*ŕĚpŐr-ٲ-Ŕ9ą“=©%š C`đ ©„Lh<`B@ éŘŽV@ě'^¸|żŇi0 čŹîŔńŔěđŹźĐ9A†‰T ‹)ŤYu™šŞ9)I‘ÂGwJ4 €jyQńQN$©±9›µÉšĂ9řD H7°k@i!p€ŔĂ×TGůuzóu'± v€6šc>8›6Ť˙p„1hłpNhŁk˛ …K„´Őp}.°S6°ČĐfhqŔśÎYCZ˛×a.< •ŕ÷ Ó)`wp?@ ëŕ ? ŕ\ Ë&ŚŃ/ ĐP™ęŔ—©™ě@ ”p*kJˇЎʡ!·š6zŁŚ2Y‘5„‘ĐQâÄÔ9”şé?*Q‹uA´Aʍ0Ćv €ŹéP ü Ń™Š`WťNŠý€ă5^ĹUyÔIžËw [őuńaű JČöpkš ‰ Ë0$ç“ęĂ>¸QUzĄü _çÂÂ˙Ş8ä¤I`LŔĘw…)ßŕ}Đ0PČFŹâř˘*Şś`˘¦ş™Ţ M˘š˙—š©łÁ©žŠš8Z«¶z­Y‘p‘FJH:¤ąéŁľ¤ ¤HBśQĘ|P©e€Z0ˇ€ł(ťB™›Öu@B@A€–fŞ‘¦Rą¦Ké¦y†q:§’ęÇąđ Ň@í„[ÔECâ¬ŕP80 E0G´´K<ř¤żŔŠ•ĘwÔđ ˇĐp1(G ±° "PŢ€(ş™Đ |б_ Ňw±€sKr·:ł4;V˙b/0wŤ ¬!đ«°18‹6<‹¤ µP2°&q8›$Á˛8Ý# pZ­tŻ ółć„N€Űpö$7·‘8ˇ€Q5Äcĺ9 ÂđIĂlë9¸$ >°—Î0 0 ćđ §5MÔdM<`»µÉ¤Ą0Q` p ‚€/0! wśđ" xÔđ W(o#{đşC𥺙š)˛ěPm}  XPŁ1ą•{ągą›ű65{»¸űŕX Y “;Ű«=¤s*Y`5´AJŤőX‘•ŔŻ™ 9Sp óŔKĺđ=łH-rEWÂůłx˙°Vm5@řp s0vŕä0ĽŰú0žçĘw°ŇŔ/0g‚S`y |@N‘Ŕ…“ „ĐUuUYµUČQ˝×›˝-a3Ł` öĐ9çz©€‰ű ‘‹Ž DĎđ îđ Ť |đ>pą?P (:†šÉ •ËÂčöÁ!<Â%|ÂÖ•»@Ä?‘y `Ý0aă Ľs€ +ÂôĄ żh ,°J<µMĽ"@aă™Íë9F ^·%]1  y#łµ_·Ą|ôe_¦ŕݏ ÝŔ˝^â…s‹|·‹©Pq^8ÂÇ ‘w@C˙ŔQ\ z<^ôP^!ĹPÂ\k|ZP®—@`džnŞ‘ v\đ©/đ Ý—Ţ8Ž}Gi}đ Ô@ ›Ŕ`` Ô€Ĺpq´ú§l©ĽĘ­,ÄÄ\Ě7±6´adžŃ8*ФC‡˝Ń”A©Đś1F_€ÜqP¬g«ˇÖÁx_÷ea¶•!@`ÚqÎ"Ŕ1h ŕ€/{*@eHJ9čR&TVÉH§Ĺ‰?pÇŁ!{WĘ0ź*Vŕ/‰ż×wč†ĎĐ//đ”Ŕ Ĺp ů=Ń}ŃĆÜŇ.=˝l*<ö˙Á¬±w|±—Ó?vĚjÓÜ̬%áÓ:Ýwę1mw6#­Ä  řőÓ!Ôčö˛ˇĂ×âH$uŽŕ$0mfđ)ŕĹP®ëŞRmT-8üŇlÝÖ01ÓȇӥĹČÖ˘0¶Ë6 ŽÔÉ7YÝ>€6L@sđă!&-{Ý}íÖŮűם—‡1q|,Ş®,ÓŹ CĽˇü)•Św™]Ô’ťÚŞť»8ť‹:-Óa÷ą˝ˇ˛›ý­}®«ťŰş=2-;O(×<ÍwR ‰p×ÇWÜ»ťÜĘ­xŐŻ#Ž˝ ŰĄl۲ÝË}Ý·ŰŰÁ2Ü˙-Z÷·^·i‘nęÜůÜQĘÎÍŢČ-Ý ‹ÝňťÝpMŃÝđ}¬çz0QWˇŮ˙ńŢĆąáŢę]ě=ß žy±ń­~1…q GčuĄîC–a€ô|Őq€€ ĺB·‘»1ŰĆmŕę ăŐ}Üß=ŕ îÝ0ŽăÓ˝ŕ<~uB ¤,˛ ň hg#= DŽ!Â!")±ń˙ĐŹ8ĎŃH$F‚$J˛˛?-ă=-ć7ţÔ9ßgćîÝălľr•r)™˛)‚Ů*ˇ2*ĄÂ,Ş˘¸tţ*a+łR+·bú!é á9m˙ oÉ-Ţ.âB.říĘd>éW-ŕjľăh^ćnŕmŢé·2-ó2}2ç>c38Ł3ŘŞRcęACS4GŁk.G`ľLcS6g“6?nSjNéŔÝţëńmăš®ăęéĘ>néL¸Ł;ĽC©|—<¨íóuđ#¤Ě‡ŢrMăÁwúí™.âČ~ě›^©Ë~ďŕ–Î2Ô âyCÄ­wÇTí>Dť;”íCÔEtD-ďy·¸ůÚ^$čF ťîÄîÓěŢî^ă ˙ĐĂľđśţâéďř^ň€ćI $JťłtJ©´JëÔLh˙Óňµ”3€KşÄKľÄÁç-‘`a(Ň´·ü#ÚŮ„NčííżńżýńóÎđ żćf^ě&_ő¦öQ!5R+Ďň5…R*ĹRýT2ES6őő9µS)ĐS?äNl‰0`( ŚUéŞ]őUolńľô2őĄmďOOŕS?ëVřvZlďńĎZ®eŠ#č^ÚĄ[‚ [ľ\<8\Ýě!ĹQĹáĺ0Éćáé÷eěd®ôň4!řżÎúPŻú$Źř¶ĎQ‹bďŞx -Ö­¸d4Ćűó<9¶c=&űI/|źŰá€a&• áY&‘>ň~Żű˝ÝöoÝŰ˙oř?ű·ţ¤…Úáj9mhŰĂ)‰Vŕ7!Ú–mäŹŕQ˙6qŢÜß÷ŕűůßB†ai@ŕ@‚ DPáB† >„QâDŠ-^ÄQăFŽ= pi CŽ,ůQĺJ‡\ľt©¦††3m¬8“ĺNŹ=z°¸ŔSčP˘EŤEšTéR¦Mť"¤ů’gĚ–4â”z‘ęS–:đđq†%R¤(ĄÁ"A6l"lŕŔUî\şuíŢĹ›Wď^Ť[!ÚÜč—/Ĺ,ŇŁFÎşoč…ň#C*ÄśYófÎť=/ĽpŻE)4H‘"eÇÓ©?°u žł˙WŰőĘ„»xîz»„gŁUśŘÜAB ć×Íť?‡ýăpě„Q´DŞ?V€ČÄmé<čüóĐÍ.¨‚sFô‹őćŰď?0¤úQF OĽťzđůĺ‚Ęgoţö¨$Ň6đ€*d&ęLďxÖ+ ú¶áŹ[\Cg<3„1Zť ś€e°ć4w´Ô˘˙řŔÇ?äń °Îućă^Aň¶ŚÓ)Ă Wű>·µ¶đ…Ţë*X‚ÜÂ;(ńŤx¨îř)ÔŃ%~Iľ)Ćî6E*VQ/:‡ }€ˇ#D=1†A\<đ@Śp B€!;+|ń†1L`ČAAŕ‰iŔMľĂ@Á 3ä xŘÇ&˛p…}4‚]«»<ř€„NěĂ ˘Aľ<`㌇´!žđ8ŔŔ_!±G"ş‰~ġAvx"¸@†f`‚`C*—ŕ}4i®¤ ™Đ=x‚+ř.Kdq‹]ÄňŔŚ?p”,˙ AŤĐŚ6ľ‘ŽÓ$'=Éěđo$i±#\ę’—Ť@Â8ĆN inědĂ9|°L ÷H‚°Çs .+`d ‚%t $’¤¤%Ĺw,Ş! ťčGBpĚd.ł˘Í(ŹtĐ F¤@ŃŘ Ň#ń ?€éÉńŇ—~c‰Ĺ eEžöÔ§;9É °‚{$Â{ŰDHpPdø€ šˇ‡„€ …+< 0š»€9÷äǸbŔ@Wmc”âřŔ=Ů.ť03B%j"Ľ‚¸»h…!1)„:µŠABr×LÄ8A˙ ¶a‡ 0‡pŚ@đ  …1FPÖł¦Ő«O"Č8@¨s"ÁkQŁwZPA5   *UŞ’Ŕ+ŕ«@ţŘť‰• Ór­@6ŰŮφö=ŘR@‰Ĺ@®0&l!KÂ<€°öoHˇ!Ŕ ö±†ŃđhCwjQKCQŘ&©ÄŘ!r=ZßÜw C>Nˇ,(5!$hi<†±ŠU >^R„#ľAŽ%~ Řýi†5ĽaŠ8 ®ŃP°^|Úă.áíuÉú¦  ­«X]â&‘ŔĹ0®A3ř   ’ $GňaEp`8„6Ţ˙ lŔ¸=¸E:Pˇ…lpxz M‚,ôţł?ć1„\Ł ó>ĘÇ7ٰ¨-~×ÉĚ!ÄŕŔ náM„ˇ$P)R,¸ YÉL†1HĚ{ÜÖ.łĚgłšQ0â4ŕGÖĹ®éá„E`cc€‡ßµč`$ ĚŁáqYfFl çýąÖ˛ž”Káť „Ą^zU°…ŤSőpŘŘÇFöźô4€XÄűPC‰O¬LUĹ4ĆÎŤclŢÇ,Ű/ćA™©Úă?˛®Şnv‘YЉcÔ!@°Ś) /# âwCđ€˛Gk.÷ŁB Ŕ› ‚˙×Á 'FŔ×Ü ˇuž†śně$`ZĐD?Śá>T[C »Ý ďDŹş „nôś ~p$üŮѧ®{  qxEhiʸĄVďLµlŠßS⯾€–eńí;é±¶?kŤsúŔ”@}–(l­«ă¦>Ŕp˛Ĺ>öžŞÚΊ8Ş rËTiČ ŐŢq®ęíhŰ%„9^[l×ÜhĆ&Ţúr4Bu71;™˝ ATÖĹŁ@n {HÂč@ bŚ@˛‡Pj(2¶~âŁÉme¦m…Pg°€ r›xE`Ç`ŁÁ1ývď˙ť‹W»Ť€TBľgWô&A Čžl Ĺéq{UÉ )y1;0‚ŔÁhB-`a b?ďČÁnŔ4´’ ´źłb/ÁX<›Ę‡˝óű‚Ôż!`*cŔ‚eX „@›b`‡dµ‰0Gp0u` dLx˛ĂŔ ,»e;» A¸†1*Ł3r‰Řs1xŃzż±»c}Hě;m€H U2„^€ČÚă>VX†7ŕ i…ŁŮ@ř‚¸L,Ĺj¦5čŚ :Ŕ‡S1°'°,6Đ[(1! 1lb˝„P-:A˙7x€ż°=ř‚'đ‚Z4=PAfB"4Â!9¤}„9xv‹<Ŕ@x9 \ę[¤2ś€ vČ„/¨‚Ŕ›9đ@;úč4BÄśÁ7Ŕ3rK†@zĂ8Ľ˛TZĄVĘŕ6D7„ĂK€EVŠěČc°--¸†PÜ) 8‚g`oHFj …€©PĆh10 ´ĆkÜ•H…`h ę†LČ·ĽśqĂk€.`ˇ|0q^đŠ@†LP¤€ĐPGŘ€vÔ€€GyÔťCH‡tČ…~h„Lé›ĐFnôĆLŘśč„w€wІ?H˙¸m‡L€vAĽQźzp!•ę€XžÓé.0ÚłÁá``ŕŇřÇyT €ČwxS€…ěĆřFěŮÓižLءť9Çt\ÇʉHľ©Č©ÇTHuÄK+TđSHě™0.PĘ=Én *¨"Ë"č H–ĚŽzĽÇ|ě€Đ0ÓéÉʆś(ůهy8žäťŚČž„âLäąČQ©ěX€Nł[9›pqŕnjč˛LË|RŘ€ËĂĆŇ4Íč i  đ ŽQ śk– Ř€ ´8Đ  H—˙ÚÜ€`éXČßT€ €ŠßşŠ™HÍ XÍÖlĎşń—©©¬ńŔ_a Řl±ÍŽÝ´˛„ŕPé\ÍŤR€0„ˇśŁ™ÍÍŕš€y Îý´rI¨*Oź!ńO P°PN°OŐj€—÷LdˇÎ`™/ů ¨ö,!€šÔ€€P–@P„@J‡}†gpNČŃĹĚg8ÓŇ!uŽ­®^KȬ('LR)ÎôĽ‚2-{hŇô5_Ťđ‹-Ą/^“LŚX#S0-Š1%˙4]$Ť3ER— ˘‚ÓÔL‡ř­ŃĎěÓb…"R&%ŇB5T©«…HT…XCx‡vH‡Q0@9Ôş©ÓŃ7m ŕM1 …>Uqč='­ÔSEŐ*ÂŃ Ť°KUTĹ-ˇ3ŕ>(3P‚€?yŐ^őŐ_Ö»q ě@–ŕxR˝‰`eÖfĺ wŠE %%;^• kĄ‹ Ń€ŃĐVSuÖo×kĹV–Öľ×c+׎HWąčÖv ×w…WŽhmRo˝j•W| z•s%eĹ“ŞĐW† ×Dőׇŕ׌hWmŤ×†uX ÁŠEMXŚ8X˙‹XוX„­Xw X%T‚•Xj­Řš¸ŘśXŘŽ}Ř”eÖySVŞ pą×„Í“ô• Ec“ =bÁÎŹěÔ véČí pŤ¸ĐPuÍdA—zůדíÖ'5—ŤNŽµÚ®UR®ۉť×«őZSµÚ'-[IŰ‘Uٶ-Ôęx‚ńČŠ Ť(H…ČÉFŔŚ(xeŔ—řk@źjöqzІäńpMHĚo™‰XćцS¨p8K ťj Éł ľśÂť;P\eňŞ×µUŰeť]—ĄÝşâŐ°Ő †ÍÚ˙eصý®ÝZâíáuŰäíŐ …2ÔĐÜ›(€$ŕb€/x/đŔy€ä:€…ëŞ5™¦jş&ŘŇ(€~XŇX€W†±˛‰@}E„Ě5}P¤Ś«B0#22Ł[ÂÎMŤňÁÜM×€µŕŢĹ“ÝŐÝ´=Ż˝ŠŰu×6^>^ÚUŢ®T”ˇGČ‡Ž m5€Y8ľÜú&¨ľµk*Ř‚j8Č,p`Edh‚ŰĘ”  ĄeÚ‚kŕŮ9ţă6a&ä!u‰y;4؇rT° <[’Š—A“Ş Đ}H-X÷Ńłtčł? ™xpH‡jŕ‡Pp Ř!‰b%°Í±‰@‚{Řâ.ţb+Č±ŹŁE-ă2Tk§#Ře YŁăŹĺŇá&d>®Z>Ţăq˝ZfNfżćß=[ö]AäBöćk<äŔf(<ĺG~‰Hć_ d h'&Ř,8Č…O:`ľą¸ŚŰ8(€T‡:Ŕ)°‡ „Ş[Z˝ ž H‚{`.öb˙07¤óĺ,€6i«lĐc¦c…ŕÝ@†fe~‘ć]?X‘ei”}f’6ŢáEáo¦ik<€+0†z0†?Ŕ¦+¶‰†0°’Č᥅¶Ë_g†sř„ĺx€Ńx»c¨ËÓ€ k€h„]mč+, Đ´0n« \€Çň<¤Ňá¶[cŔ7fč éîă—=fB]ŘŮŐćk^Ň˝ŢćŔFŢš6l˛C€[8!=ßęÖ iČŢ2¨‘ Aćóă‡B€IĐBP‘9¬Ă;ĸ„yŕ%Č‚rP„ťI’Q°0¶ź ˇe[v łĺC2ŕ.@`˙+ś'Ěv`–`‚>滆ăfö]˝.nl¶ÝĺfnÁ^W >ěéN¶ĺ^;ľ‰şM…zÖÔÉ9™; ‡!`€(.Đ(J0٤ ąßé†?بÚčýŤ‹ a€,Č"päň·& ;°’ü›ěŔHő!Gpk€nSÁ6n»^ćhţc—®f —n•ţZáŤî™¦îß0ZôÚ 8Nc˝M™×¤ś˘í?1‰žů¬O­P—rY`«ŹCn€QŁŐ€ŰśOČ‚YĘŮň\aÉđ ßŘă†r”nnŰÍZ9ţëe~î–ÎÝ ×róźBgdöm%Ź˙™ «$Á- ]¸J.ÝÚá SM]S¬µó% ŚŽóčD d¶W8ď‹=d=i&M,2'ěóEOYýîęt…!€NF7Š’}rŠýrJ×ôw…Öťˇ:ßôčČćP'őR7őĚěSWu™ ‹ŤörUŠxőV“YQçhu1Gtٰ \±Í Č]őŇńő 뿍HöëŔŇçhöeoŽb/¶¶eď8“iAĘ~öa?6 •‰č;ŤHŻ{ŕq_‰ĐXnZOT9‘Ń”YjA„(w>`Ó€ˇŽŘ÷ˇÔPwvwxw'„vçŚÔ śív˙•p(P†~xeŕ1)Y‘ďw§€«rë€_•ŤH’%9voĎŚK•tG/€hźŽ `śwr'CŃ”Daz_&—y&čµFy˙áه”p' ›Çy—gçť?ůÖszy áFZ|^`X_‰Sy@Z)"hTáyPz¤y˛’—úŹ•Raůňx˙D™úśÇÜŃŔŞQř×4‡Ń™µZđ„:qśjqs™Zi€GöüŔž”^ř–]ń™íOźE™`1dÁ ‹aăh–g‰–i©–kńîa|ÇO–ÉÔ˙]ńd —Đoń”YÝyI™Î÷ü˝Z‰Q}­ĐŚăGţ’}rýŢżY3ť˝Č”ńIýě ÚG’ĿτجVA`>ZÖIď'ý%üńg—Óx€…Ńĺ),h0A×Âdˇ˘B °´Đ  .Măˇ` "„Á”4€A… ‹"*pé°ĂE•6PP€Â‰rŤ J¤h‘ŕL‰6Uŕ 9˛äÉ XşT!bC… ú…©Şbź$$HőAŐ ŔäpÁetŇ­k÷.ŢĽz÷ňíë÷/ŕŔ‚ n¤7®8˙@”ȕν?Bl8ńČšżwăŠl1ęÚ;‚sBtĐ ˇ|qNšníú5k|xđ Ú߸Ń6x¸S­ž˛9)*L§Ň4·€CdăŁé 7řĹÉŕöB”Tďüĺctňˇjţú)SbÇ­zÚ4UŁ7§B k˙đ ós˛vúńŐűUÁövą‘fPlłá%@%Óř`Pw€›8I•ÝvÝ‘ÖŘc‘MF‚ Ş$uÖvXbĂĹ7_}95ŕ‡6éÔÓÍ‹bu×QČťw!4řŕ8rđ2đ5sŘžx䙟cę)8˘pĐAĚ3Ä ¦ÚIv9°‹4˙đ°Ŕ‚ ´°@ÂŽâd’ă•gÂąüňĐ Ý!WÁ©<–")l¤Ź>/Ć“NřéW™Ŕ'}öÔá‚ ˇ‘ dŚIWš=âÔ#ąT#]ť]ćO.ü ubŁ9qę)Ž'50iĄ“ąucw#ŚđJ;řŕóŹ|˛L6ôđ„+®t €Aq !`±Cg 3ŚŻľ;UPđÁ&HL H=Ś1l˙2č#Ščc•o?đ!\á^‰.®ď}™`ĺ×¶.5¸F)I* ‹<%óŹă‹|ôcÍţ¸’†UB€Đ× ¶-onl0Ă@*8A€+ÜĂ ¨sbC-ęQ“ú@Yđ[tbu¬Y ôĨĐĚl•Ţ“¬wµľn đŹ#ŔV¶!XďťËËŕÝ@ .PI3ęŕ!Đ€DKsó°‹Ő•Fż˙µ01c(Ű˝¤ł±^2‹— ',ďEŚ˝^‚{Ř ¦ |9ěaű29ŃáM'ŽńęX 8Á> %´ÍíźšÁf75%| G%á۶ÁEüMďůî;Ψ].>! :ÉĹ w?Čm‚¤uŔÁě!‰“đGX-``‚Łâ%ČC.Ă2PA }/żv ÷¸ÍR*/Ź‚ áuę L\CŁË»ĹĽ5ßHčGh@í XŽP!:żń č{«$Ů#UŢžwĂu‹¬}ă`{hĐ„hĽ nmtAÜîđI3Ł <… ˘a€Hx¨ÔŽ<äC˝Ř«.€Ä8Á ˙–!łŔl(€H§ËĽi 쵺¸‰&ŕä×|E M#oÓň€®”˘ďńmX 6Žd±JĂťr° 2€ Ž$# 8)ů΋P 6đ€& ťKyÍAP‰ŢÓÓž Ý,H6ŕ‚<ěým•&"Ĺ)r‚BhĆ r©|Şk‘ó¶ďű“Eź(ěśÜLĺY^-’öq_KIX—Y] !áźţa€üŃźýµŽ3LCĚ‚9|óe„÷AŔ.ŔŃ„ÍÜOE5ŔA4ÂШë™]J4Ô.̆Ľ‚=8EŤÓEŮĎ…Ň4ß 2QT˙‚9Ľ€ ĹŔ(´@ H")Ř„I C…ˇpTr |ÄÂ*ˇŔ6‘ ]lŕ6Ő>Đ^¸Q(äŔ6”xáöqž €Uš8‚ ¤qŢć_ňNH‡>„ÔS Ř,ŔŃ@­MJŘVtîĚEä}"(†"µđÍ9¬AtWTŔ °Â2ĽÔŔeÖÂÜŔ\ŮěµÂ·i@ěü‹ë™ĆŁ RlŤŻŃžu €NŘA°żŚÁ‚„ŔiĚW´žŔô4 LĽËŘÁ|ÁxÁIƸÓő…\"¸Á  ˙Ŕ.ŚÁčů\0DĘ-0KA¨ ÍÁLŔÖŔăýđ€_qŁ7&ä*¶â+Ćâ‡áÁAÖËZŁL‘˘)˘b aĽc<Î#FŕI0GÎ6vă|ŁB CBŽCF?BL‚>„€8’Ł9ĘĎFĚ,A”C…MŕŚ‚5t×ě@/z"]ř€đ3PŽL>ÎďĚüd9NPxÁ>”BlĐPŚŔ<Ď|AĚÁršA„O5 IĘ#=d äL >śÂŚ8ęÄ_nĺý䀕UŰĄÄĂ%ZZ^ÂŁ^6¦ňÍČĐA`faš˙UKF$[‘T2@ă<ŠÄp… đś€Â6lŕ–(Ö¦mŢć]¬x‡Ŕ””@'lÇ;hèĹh<ř8d đ†+đ‚„Ŕ ˛Pă–¬JřâńL9'tJ'u~EoXpÄAĐĄr×8pÁE¨Ë°5—iLH*w‚lŔ pŃC&śÉ¤yÄ: p|@'ÔĂ; |ZtÁ2Ô§P/ŕÄt"ËT€ p§A,Ň#\CqÄ€žä}vŔŠhnĚ…aG*—‰^pľ‹çbŚh‰Úg¸çhÔJřÁn*CoNĚč‚ÂŔ¤˙B0´€*vC& Źú¨|¨)4‹¬(N$ŔĐĂ0@äM~îg†Ŕj‚±tĂČ•[Ô6ĽŽŹ^çŐ©D‘‰ ¨"8Ăd¬ʰ(Ś)dô' DS`†fčFd/ Ş)¤@’.i“>韤ČF)^ަ‰ÚÇ«PĘ‹pÁaÎTŠbih–jčoŚi=äĆšip)«ĆAŽŞ?”Ş\¸(•Šä~.h ü yvCoÄ ¤‘€š|ń.|nN+µÖćYH@Y-U@ŔXD4Ztk pŔHPŁ©łh@0€UĆŻ©b4˙B\F4ŤEsĄklŔE”E]¸ÔÄKÄ„ÎÂ@ÂV|jŔ´”Ë4ÁBEHÄXěÎaŔZ¸D ě·>ĹUl@HJ諼Ňë©€THŔ"EO(Ĺnë»4¬M„Ž8¬¸Â¬DP,!%,H´Ä`« hę¶~,BŔVŚNmÖ\ŕěĂę,Íš•4L´«U,’OäěI$ÁÂÄ6±Ś•¸+Ö2”4€·VŔXHŇŐČL]@L¬Î’«ÄşD ,HlŃ’… ,€»>ÜJ€LÍÔÝ Ď%­ßĆ,Ĺj îËęÄÜ.b”„TÚżî˙mÁĹJ8ěÇN@ćŠŔćfÍL®¸JE,؆@ł¬E·~Eż&@ĎŔâŞĎĺŹ=¤ÁcV+đ/©Cýî_FJ€đC”A¬VoJ\ňaÍhνUď_Đ%`(/óV*äIĹő>‡NoA°]N|/ž‘o¶ŻJäVá€.\Š`ŕ_Ŕď^HQüŞoĎ1Ô^Ho^°_Ô™ńţ®GŻNŕŕÜ€ĐÂ/¤đV°_0µŔ ŘaAoµ4K#­Î‡šs°m‚p-đµ ° “š—ZC:ÂĐ#×° OK0C=hÂDí ˙01ËčD6¶F¶d˙ FÜćO+cěéă]iŚpW± gD–đŻo1w±1‡±Ź1—ń㹆` ¶¨1ł1ٱ_đk±DZßń Í1`Ô1µđ1űq ë1W« Ź1gă '˛"§±†i€Ř'ô¤´üZ‰QµÔ1ň.±J`˛µ€rAXrJpň'›2!űš¨yr^übőОă2*ď1+/˛-Ëq-óĹ#oŁ.Pň`rr%ňs˛0Ä,ď1»^)3]$ó´3bĺ˛]¸2"Cłaýâ7ň-włÓçm˛]뿲!MP„\»-¶¦Â®$-˙-SŚňk° ĹK¤€€+ąŠYč3[tlU@CPŔ(<Ż$€Ă:ÄĐ´Ĺ[ś«\łEŹĹH-Š:¬HBW®J´í&´5s3E·´_3,«1LëqMc˛M;3=[óîŐLw2Oű´+÷´({đ3ł4#óPËôM7uN×´7Gő y< (,S׳D(o" ޤi¬W ©Ww*Q Ü‚-hŞŔ‹cd˛ÄÉś¨˘ťx€¤ÇŠÚ‡*㉞pGź`°‡>‚1´5Ş"=”X˘nFF`dHF”€5‚ °Ě#< | ˙ z¨{¸idJ„ěFoü†`ź.•v°Tˇ*ő);őKłSňlCµP˙ômó´mqK+µö55ďtoóvP×¶q÷PKµr[Ë€‚?ĐB€@`µŔ˘dHŢÍĎŹiX7vs…\é@30B B4ěŔaŠ‘÷ˇ ±Pń”ž%Ś/@#(0č‹5[JϤj’P° - L@ÜC¨ »<ĚŔ€i Ťą KM Ńř%ÝLÎěĚÉ;peşŕĤfŘ ]ü·jR#ôć˛8wk·¸qÇ8Ś˙ökwŤËxkß83 wlóMç¶6#7Žyp/˙·‘ű…EÓŔ#äĂrVÇöäaŐ]Q×uw5I91LFA>ś‚>`A.ő¸i¬·^Yá{3ó¤Ń#¶RŔĽ†Iˇ”J±]áîŐŃĚĂlA:,AĚ8™ą >€i(‘VÁ>–`A•,›Ćąa’&)TE1•íŮŐĺŐĹścz˝rŁ#˛oguŻxl‹9‘y575qźşŹu© 95«úQë6ŽĂ:‘9®32­ěC9€oŠß0VŞIZźu÷– žBŢK)ř@2 TAąĆŇý?É  žŔ8ݕɕ×č[q€cĹŔ—Á `ĂŚÁ°igy˙hE“ŘeŤT dÚ¦í´ąŔś[wQ’QvĆ‚X0Fłőtŕ…ű¸«š x0+ăôpCőĂ72«›ş,ßErůq 7* ˛&S|Ž7sL‡ü¬#µÉĎ8É»6LJ|RçşËă…iP@ŕA3 ŘőVwĂűĂ픕;Ăx-`Í…z{_ĄµfkL™µ—1í‰Ńź=á|;ž±l±Ç@ĐCĽÂ!Đ"ô­)€­áöÜŔÉÚHi¨â1žüÚŁ;[%eÁ=(YÚ›BZ±|Űa¸»Ă;ĽKń§Źş%ź|¨[<«»4Ě>Ť‹Ľ¬+>¨Ż:¨Ľ§§ĽĘ·˙ĽŽ#/Ä?őŽ'ţĘç¸Qż<éăĹ\1Ôôś żżF3µk%*Röíáş1@%†Ŕ.,Ă"Ř€ag~´7ĂÚ,=ţÔ@áÓk»kěĆ H!šůśOâŤŔ Ü(Ô(R荞 Č˙Í_¶G˝€{hařwaśP’¤S:ú€$R"1Ś€¦żP?©8@h8€4aC‡ >”8‘"B Ô¸±âĹŤ;†dř‘cBŤAR$1äĘŹ"˛4 “ćË‘.qćÔą“gOź?:”hQťnť˘"‰\˛—¨ ¤~qH„ŕŔ˙Î5DnŢ:µęŐ!ňŁ’B˵?60€Ś3BřŐ÷Dđ`Dˇxç­÷S’8¦W`SO}ŻŇVŰ‹¨dU!ňč;ś,%ISMGuőĺ•%­yŐúZľ4gśŮożŹi-Ú裑NúŃú˘š†‡¸H‚Z٦źţ荤ţą VbÔ'LSč‚«?Â@j—¸^§nĐ‚–_TH'ł Š«ą]2ű'˝‡ryé—ćóŮf‰–Yp˙ç©đŻÁnu§Ć/µ?Čç(=ZÜ ˇWÚóĎAÝ?ŞĎƉtĹMžŐďXŁ`¦M†Čˇt™SťsÍ‹ZiďlďÝ÷ß_Őřá‰/Ţxž•ţ”rXÍľŔlľÝ˙;ţďĺ'Ç”úÝ1’^ű퍿‰űďÁ_|ńgßüóŃO_ýőŮoßý÷áŹ_ţůéŻßţűńĎ_˙ýůďß˙˙<­€4ŕ@˘ěz tŕ!A NP(µ™Ł¬G3Ú­”™ŕHµÁ‡edUˇâQB®PVáy4řBóx ?,sˇ fAî‡=ôˇ ;—CĺĄLgů)˘ BD "1„?tâˇ(Áť-R˘˘bĚČDťçZśbÁF1úď‹ Ź_Ĺ&ŢNŤ^ôŢő“˛NŤ‘Žu´cüĘ(Ä Îń‚&‹ˇĎÚčĆ ~PŹfÔá™HE/ʆd˙Y¦ü¨Ä° ’doL#%-ąHMn’“»ž#UITý”‚Ľ ÁÉCv’•­teîp×ĹIFęŢSI&g‰ÄĂÝL”Ą4!_La3zŚ{#§P™Ë_Ʋ=ô©b,ÉŁÇ-ň‘Ő´ć5y˛ đëWÝ„ĽŮÍ€›ág8EN 3Z\[4˛8x6°Ź«d‰ĺćIO›`“źýô§F60‚\ü ňř‡<üqŠ”ˇőP(AzĐ„.4˘ňpč@ *QS  ʏüçGAŇWŤ-O0éIź°’˘Ô¤*eiKWĘR—ľT ĺSß'EšSťîÔ'cŰóâb7’Üí§Ď€P˙?BTç¨ ýôÉS©N•ŞUµęU±šU­n•«]őęWÁV±Ž•¬e5«Š ĽmäYĹzŔ˘ĄV‚A ®ă@ÇVąÖuwٱrB ŕ©g5ěa­z<ws nQmh˘ôĆppřcn¸[ ŞQeĚÁ^Čěf;űY%…v´Ąu‰ŕđرµµm5«€Ôýř… űátÁűŕĂ!–±äĽ9ÎŽt0łťÎŚ@9Í}Nt´Sťł¸ä đ-Ę ‚cŃö¶ĺ5Ż")ĐGXŁ‚ ‚L𡕧Y ‡€Ŕ %(ˇ˝N=(˛á˙Ł/(W/q‚lCţ°€ lŕ ň-Űłhđ||©ä=ď‡A F4a€A :@^úfÁřmƲ°55l°ÇjĐ =đ`+m` bĽ†‚ÔřĆ9ŢqŹ™Q–@Ă>ĘQ(…ĘUŽ˘.SŽLa'+ľŻ šQß{DĆ16Ž|YĆC¶ń™Óěc%¶xhF9ÁÍĘ}öł Cŕ !ířEB`>oD8ÄášpöŰ^ŕżŇ€p°\c Ĥ+}édzÓvÉ®`Śz@†Nůó«a=A ¬K.Đ…0Zí’F˙ÇIÎršs]čR‡3#@uýÜěrÇÂAŠRâęXO›Ú ěŔOs§9ÄNxŇźü(%YcPO’ëž8îD•{¶h3PµáďFĚGĄĹ~…1Ť…¬^z˝XĆ6&Żż" 'Q’÷Áľ@ĐíA¸ŰDŢ‘2á·8U騋ośăĎ8É:r‘ßĎ>›»]MHxŽśĺ-wůËas™Ďść5·ůÍqžsťżś„˘$á2§iśÚsçEĎąGq(I”ťé:ůGo«`§ ˘>u TýęYď&±ôĺs˘7ťěúF\ŽŚâ;X‚Ú3JŹ!¤}˙ím;D *wşG”íE®2W^vÁ'ü„IeÁKŕĂł4&âŹxÇ#~»őtáŕ1pŹnD°đĽîć |ţóYńHúŃ“¸Fýçď¦1TŽ=óµ‡ő5r¸ĺÁÝ!úąë>ř˝˙ýî :|ä÷žËÍĽíˇ_ńc…*éó>S>µ©śĽéśÂi+•?Í3•(n# Ł*j˘*ę ęÁK@!t!R®'HęĄR*¦PjR,B9T(|j©ô©6bŇ:´Dy˘¨˙ز ŠęAM´EĂŇ R4,9ľ Y\ÔEĄcˇ©îҡ #.˘q«1GçSŞŕád(úęaŔ@l.`»Iásě!tD ú ŻË´.FÔęD(@ GÁ5 BÉQKá“îŕ¤ŔMŔtµD‹´®ć´8˳ޤ( 2«QŹ€át@5@bS1bؤk¨ Řś‹QOdva5ç±µ4ÂR1őM4`Ŕ ěŔĚÓ,Ŕ8` ˘‚Żműń;•:Âvr@TŤŚÇ8`Í‚ĚÍně  śFlä2!gµ7?őVy@W#’˙ĆĆW۬ĚŢě Ŕ€Á â!#ňH—Ő4u[1‚TGMÓ8ÍÓ@ ,íCĆjˇrµ . Ë1\K3Č Ĺ,lŘş :Ś Ů&UE/ ÇĚ/4Â#A_MS5·ˇ5±rÝ”á RŕC2 Üt‰*Ż  $O’ať®@!¨&` Úş‘ß2`L÷ ŕrö HS#Zň%cRdŹŽd!ĐRÁáD%"IáV„$Ć'‰?»É?˝iśśöW VśÔ ťŞöW¤vťţ3nt6«4€Äö^w ¸ ©h\¶@ L+7âj‚ň-”ˇ”ˇôˇ2 ˇ˙ o-Jo´o+ę˘đNنňkŻŠ0aqťh©ŘĂÔ*o0@+8COj¦dĘraĘB17C5÷B-´¦« 5ŚJŽrdQE9Ŕ§Â2,ET#” ¨Ž*r“ęÚ@4¨hw#b—©śjtżV°Ţ6)}WK) ľ b‡wV@ňˇ RŔ¸Fy°|Ćfšr@z{0y©“ @ú ÚM‰Đ%–V-r€|‹{Wđ™P®~ŕ~[OC ™đImvz&1 —° ŮQbß'’€J B © bJ22€¸ řIé}&ŕĘAÜD­Ľ ?˘Ćŕ `÷˙ɶ‚ë‹âg&€1m0ň„cx#f…9†x}’ CľâpĄĆ[Ý J÷‡éІ‡S÷|’„TˇňřĐ5âj’•×¦× @‘éT~pĎžÔQaUâk#Ä8·ţ.¸}:€@°ŔGOc$‘Ž÷! X´ŽďS×Xđ,™xŕÁĘĆŐđµt±F‘úÜ7‡Ç'IěL3?BY±MgÁdg%4ů„#ąécjż ťčjW~8QgÉź 3Ź€gŹ@5`×6˘’ŕH¸{z8l@ˇßéě Úć,:ź<:a:˘‹G vMˇĹ® 3:äz®o¦°8:¤‹F+Íô4* DŔĂ\¦'ĺäě3ĄYî§gŹ%>:ešVŔڎ>$ éˇ tš˘Iĺ–¨7ĄÓh!ŠşĚŽš`·oĆć«˝Z­Ŕšlî¦Ćxph`zŕŇŔyr˘¤-Z„&ÉŞ5«}z§˙ÁŐˇ!:nYŕŻ˙ZjţZądů;°5b°Yô ŕ nq Ňa ˘`@;ăúĄ+zŹP×UđÚ®5ŻłĂ#-ĺřZ¤ © Şä€ÇÚˇđaݵ˙AµYű\¶‡XMčÁ HcĆ`»Ś˘‡h”l ´=»Úţůq~n´7€űZ#`¦` Ö`´V¦ †+§»şŻ;»·»»ż›d€âŕň€AŞ&®‰[łÁf®…&ą’O:"ô:¦Ł[EŤJj  Dg÷śŹęj$ř^„ jäú”xiĹ5|äąmľ‡¬«eĺjö`JB®äŚ3e«Ń#“–»Ĺ?;ČeŃ0űS@śV®ćúe_ŕyËS«1›®Yeh„ÜĺĽ$R’Ľhf%IZŞ}:‘űĘý,Ëcś8şM{xÂś§U®fĚˍ螣¦žżććN—vţ|Đ ˝Đ »üĐŁ’Í˝'ßĂ$˝ŃSąśĆ%ý‡¨$îIB9}Ó;‚Ń/}=bZN&"=ÔA±eěč4îÔQ˝U=Ö®=@ýŐCqĄMŽhp=>ČŐm] IĆ×ý7zÍ-}ŘýT*ýż‘}"˙Qר™˝Ůg˛ÖĄ˝Ú­ýÚ±=۵}ŰY0uĘqçŰąý漝ĂHžĚ}ÜŤ®Ü«V,HÜŐťćŘťŁósłŰ=Ţ‹nŢ{çÝÓßwV×ű]@řýŢýýßŢa Ý ľŕÉťł>@žŢ~d~á>Ü~âeNßm'â5^’Ţâ!ăEţă=ä%ŢÝI>ĺM^ŢQ~ßWľĺúĺ;>će~đJtrţćyľç}ţç>č…~艾čŤţč‘>é•~陾éťţéˇ>ęĄ~ꩾę­ţę±>ëµ~ëąľëtŔ8˘\(& ¬áđjvllăMyâŚ@'˝ľăŕ ˙úAČ>@X¸űp˛‚`«Č•'\Ŕ¸1ťë>«€I‚`ÜĄeM ęř Z€v!_$żęŠ%+˘®ťp˘— Łň˛bGjćJŕˢ./Ý`YâF‹_«`K¶ę°ü`üA´žD5Ó„A–q_÷yňc PˇÂJŕlŕ\"ITˇ‡ ˘Ňţ„áp?Ŕ¸¤”aN^»ę~ˇg˙¬şë»ÂË;]"[ĎA ˛ ¸Ăzŕ \AúuĂŢ?ţ9ăOBG3F)DEŰa€Â… +ŚPĺ*D…‚€đ4Ť‡Â ň0űĂĺ $*iFL$&2|˙ 3¦Ě™4kÚĽ‰3§Îť<{úü 4¨ĐˇD‹=Š4©ŇĄL›:} 3AŹňËTĂL—¦˝`đˇ1!6<Śč’«W°b=„@&ß)}X: i˘ÄŤTʸŃáZTR`Ŕ@‚‡ .šéÉA˘d¨”+[ľŚ9łćÍś;{ţ :tR  ŮW® 1XĘȱ ł"6ň˘UčöŮ´'L„­”­xĎî]čđĆ·üi Ó‚DBŤőhŤ=»öíÜ»{˙>ĽřzŕiV® Zwĺ{vmăißÇďÝŁ¶sGlÚ>ŽŰ_×)”ŔZhŇŹ1JL‚cŽ˙a„NHa…^!M\aL=ĆüAR[]’Í 0€ËXŠy0 ,0W%ž"Y€b Ë,bC .ĹÄ‹´°# Z‰9/$Ʀ°°ÁČřă=™%b],Ó­)§Â oĽňÎKo˝›5©W )`«P @A *čËŻż)LĐ€"pĐT*¨`“Ŕ§©( €Ăl @;,‘4đ$É?ÚËrË.ż s̵ľGkŻ/©ĹCÍŇPsQ‡É tĐBM4Ľ8÷ě^FHÍtÓN? u†˙LM5Ő´ŞAÖZo­AÔ^ vŘ-WMöŐ¬rŤ¶ŘjŻÍvŰR“m5ÖhoívÝvߍ÷gpÇ}öÜZç xŕ‚>ÔŢS›­SÚEů­â6Ń €ßNyĺ–[nř?çäřPŚGÎ5NˇKžő妟Žň:Ű™oÎétw şëťż¤řÜ ÉŽ{é©ďÎ{ďBŻ.Sîş ?yđˇÇ9ňÄŰî{óÎ?/đ1ßřň4Ő~üň˛CĎ}÷Ţw)=LÔ+ŹűőŮźŻ˝ä߯Ď~űß­;íÂW?żůÉ#űç»î~˙ţ˙ŻřMŻ~ăł_ńđ—?ě Źtl x”đÉ/}㨧=jpĽ‰[GÁ N}ĺ#˙:Ârđ <ž ËçÂ’†"Tˇ oČ>Ň/†!< ńö‡ÁâpDôť•7˝ĆŻq·SŠîjrÂ"JqЍ;b grĹĐD‘Š\ěbŕ!ů ,#‹!ů ,$y˙H° ÁtŘăÄ!ÄÁ‡#Jpaɡ’cb kňţMăŔ„ÖţáĂŐÁ!Ć—0cĘśIł¦Í›8sęÜÉł§Ďź@ J´¨ŃŁ; \é§ë"҇J™:­éš%#.Ô4'L ..źŞ]˶­Ű·păĘťK·®]( ń˛A$dHa˘B °´ĐA _Ŕ‚ – m‚*T46¸aĺ4Čü8°„) #VĚŘń_Ó¨]C€ A„ —q\s#B„ćĐ!ř—Ffŕa+WÄ'Rhđ@eÔ6(Hp=ĹĺĚ g˙AA»‚Ůŕž=<„čĚ.ĚaâÂÝűřóëßĎżż˙˙yÇ&,Q~,ăO=ʸQJ* ăÁf*Č ÄĐ *,„PÂ-¶¤đĐ#Ę„X“‰ j“N=ÝĽ‘„řHHˇ.Â(Ł@RŤ?ý(Ł„ ÓΑőŕóË”K:ţĐó‡. PÉWmŕ*ĐĄQS¤e>¤ŕwTĂŕŢbL Up=expÂ#ÖřóÎ8Eç$”RRů‘)*pŔÁ#ÚÁ€Ś6ęčŁF*)~€â-e€š `É9jdŃI?a„ŕAO¸ŇĄ@ž‚**©-é˙Đ #)Í&,@Ă=ܓƿöňD¶0d.şę˛@$OđA2˘x0éČ$—lňÉ(O* ŹäN&}B„Ü4/0đA/ÄtHâĽU&WóÍÄPůś˘đuĐ®˝ř ě1ĂÎü+Ü“ČP0ϬúLµŐxpH-T¤` $ÄçB3zä@h`đ€@ěŇJŤ˝ËC–[;˙«ëľ€ P SĘ ,€łWĚsÄé,Ĺ`L Ă>qpšňë°Ç.űě´×”×hěSN&,j§#yŢ3EذłłŔó <ń65 6Ąřŕú@»öúëP›GŁHKÇÓ›|÷ßs°Â-ţhF $ä ŔÚzě Ŕ p6ď M+ňëÍ7×aŔęтԀm<0Ôđb…|aŘŘĂŕq„ ôŕé@…ZÎŘúăßIŔˇĄěC ›©ť WČÂş°QčšQŽF°ŔöůÝö–WĽđő,x^ń˙V lśăŮ•+Tń6ěEm{8÷ăĂ®Ť$ŠStĎ´@0c I @ @´Ô‰cÔ!@°˙Xu%ůŤ±oô:Ȱş@üĘ€×ßňbĐzÄᇠ"˛áĽ(Ŕ¨ŘÓÎTĆ3¦Q„D4  ,˝đ’̤&7ů“\ÁőČ×¶R¨ĂlĽ  ŔEÎŇćIŔ{!rL‰JUvč 0–±Ŕé Zr% R€€ěÍŚ{ČâZůĘX“|ÄyŔŚ‚c¬aäĂ ĐĹem¨Ĺ€JHc›|é@Ř&A ÄŇuŘŔ `ФŔshKÜâ°˙UŽŕ·E0¨P PŘ‚  ÚhItó›$ç8Xm`˘#śĚ¨F7ĘŃM"ŕ§‚ GJÚ#]€D?â€CŃápĂdy‰“¦tĄÄÉĂ1ʦ…kü+ŔäŔ°aŠ/\OĽb2A¬˝4¦3}ćR‰c‡=|á ^h&ä,sča o"+–ń.ÔŔnňű×>1‡70†~yŔ Ţ0Ą¤jľľĐ…şţ+`#Ő6Á?¨`Ř *°@|áwŘG"&0Wř˘fE+«@± p€Ł ­hGKZI…€Ó{rč1Źz€"JЉw˙ĽĂ0Xmk_›‚,!upČ:1Ź!äđ đĂŹŢŁ, Áhśş‘‰ `¶µ˝- žÝéV×{@†?˘”‰5¦]PP>L1!ÚľăEÚřCl)1­—J×-A*ôdŠŘę* ĽČÓmS Ą;XF2Ô¶Q„D!\°Áöđ#Ľ¬b íŹęßŘ üĐ“JKâ›řÄq1TL# t‡ Ź@ TŔbź&h@o8śô¤ ťMdRŔĎĚl źˇPpfüÂ!Y¦Ú{D@śĆT€:č qbübRZvIŚG‘é(6„»Ŕvşc(ŕ˙6ąÍ•…|cŮЦΠŁ=ŇZűůĎ€ôPŽ9=Nş ÇíłRRŮhz›‰ŰrŚsĎ„Ňi4Fp-Đâš‘ 2A›úÔ¨NµI‚‘C«'"{HQM !Š „ŔMĂ$ÖŻ¶°‡Mě@cA. 2P’ĐÁ3i$(É V!‡”$¤–ɱ“ €eűŰŕ·¸g‡@ { ŘÁ2€î‡t€N`7¤0ŚXśJŔ4FĘ}nŮŞ[Ţă¸ŔÎŃÎd <®]ŇVaí¬ qč7D^ŠgÁ8”řĆ7¤ppR@C —ČÂ.‡G<×˙OąĘWn2!˘ đRěŢ]Ś„*Z ďĽ Ď <Ťop7(»Šś5żyÎwŢs–[ýę÷ÜYKáFhŕë`źÍÂ0„\ź$%+)`†A"V ěa/ÇĘ!‰Ö@î{Řő÷šĽG3yÁÖA d€eE9î1Ś:ŔŇp^€u¸ĂĐ@¸MDđ„7<âĎxÇŁë¨O} =Wl,á»Ř†‰…,fA‹@¶ŇKľ]ď™ č~Ç»ă="˛÷:ß5p“ě!X8îľ‹xxC‡ĎŔ†1Ś3Đć!¦ ˙ ZĐ‚4âňî †b`ôÚ×覾ő±?ęíw˙űŞĎżţ9Údńk pˇ‘€·†ŕ9 čxńDń€q. a0áqÖqc ŘĎA_g„v PŇf…łp5Ë·€0fT (€g(ó_×Ń[ÁQrĆÝáĐc*đuŕű`ÉÇw˝ń·Tč ”đ/ q``1xĹ Đŕ Ôŕ –wyęŕ ŢŔ bř śpq…SX…W…[Ř…§·z¸‡°łąjr’Śp&~p őŕă0í•˙ 9˙p č…x‰8!ň„'zÂ'$ň í€řđň1đ$[_§%<wďâp×h Q2!@" üĐ0¸|ž©đţ [vŕăŕęôĘ@%_—"s`=ň#A2$BŠÚ[˘Ŕc Ĺu°„M¸|Ęvđ° ß@…T¨ë Ž@D•ˇ€˛çŽ@ č‡~ńpyčĐŹč@ ĐÖvićŽę¸ěčŽđ(ŹŃƇů´#ž Ü3|’°+¬ŕ c0 Ŕ fÝž0_‡‘É‘Y:x1í§2pkA ńäe˙0Q ü°L"/]˘ŠmT’`ő\@Zµ7@Ă“¸Ř1XIŔÄŔ/ođ0‚P0p A°p#Đ*ŕĚpŐr-ٲ-Ŕ9ą“=©%š C`đ ©„Lh<`B@ éŘŽV@ě'^¸|żŇi0 čŹîŔńŔěđŹźĐ9A†‰T ‹)ŤYu™šŞ9)I‘ÂGwJ4 €jyQńQN$©±9›µÉšĂ9řD H7°k@i!p€ŔĂ×TGůuzóu'± v€6šc>8›6Ť˙p„1hłpNhŁk˛ …K„´Őp}.°S6°ČĐfhqŔśÎYCZ˛×a.< •ŕ÷ Ó)`wp?@ ëŕ ? ŕ\ Ë&ŚŃ/ ĐP™ęŔ—©™ě@ ”p*kJˇЎʡ!·š6zŁŚ2Y‘5„‘ĐQâÄÔ9”şé?*Q‹uA´Aʍ0Ćv €ŹéP ü Ń™Š`WťNŠý€ă5^ĹUyÔIžËw [őuńaű JČöpkš ‰ Ë0$ç“ęĂ>¸QUzĄü _çÂÂ˙Ş8ä¤I`LŔĘw…)ßŕ}Đ0PČFŹâř˘*Şś`˘¦ş™Ţ M˘š˙—š©łÁ©žŠš8Z«¶z­Y‘p‘FJH:¤ąéŁľ¤ ¤HBśQĘ|P©e€Z0ˇ€ł(ťB™›Öu@B@A€–fŞ‘¦Rą¦Ké¦y†q:§’ęÇąđ Ň@í„[ÔECâ¬ŕP80 E0G´´K<ř¤żŔŠ•ĘwÔđ ˇĐp1(G ±° "PŢ€(ş™Đ |б_ Ňw±€sKr·:ł4;V˙b/0wŤ ¬!đ«°18‹6<‹¤ µP2°&q8›$Á˛8Ý# pZ­tŻ ółć„N€Űpö$7·‘8ˇ€Q5Äcĺ9 ÂđIĂlë9¸$ >°—Î0 0 ćđ §5MÔdM<`»µÉ¤Ą0Q` p ‚€/0! wśđ" xÔđ W(o#{đşC𥺙š)˛ěPm}  XPŁ1ą•{ągą›ű65{»¸űŕX Y “;Ű«=¤s*Y`5´AJŤőX‘•ŔŻ™ 9Sp óŔKĺđ=łH-rEWÂůłx˙°Vm5@řp s0vŕä0ĽŰú0žçĘw°ŇŔ/0g‚S`y |@N‘Ŕ…“ „ĐUuUYµUČQ˝×›˝-a3Ł` öĐ9çz©€‰ű ‘‹Ž DĎđ îđ Ť |đ>pą?P (:†šÉ •ËÂčöÁ!<Â%|ÂÖ•»@Ä?‘y `Ý0aă Ľs€ +ÂôĄ żh ,°J<µMĽ"@aă™Íë9F ^·%]1  y#łµ_·Ą|ôe_¦ŕݏ ÝŔ˝^â…s‹|·‹©Pq^8ÂÇ ‘w@C˙ŔQ\ z<^ôP^!ĹPÂ\k|ZP®—@`džnŞ‘ v\đ©/đ Ý—Ţ8Ž}Gi}đ Ô@ ›Ŕ`` Ô€Ĺpq´ú§l©ĽĘ­,ÄÄ\Ě7±6´adžŃ8*ФC‡˝Ń”A©Đś1F_€ÜqP¬g«ˇÖÁx_÷ea¶•!@`ÚqÎ"Ŕ1h ŕ€/{*@eHJ9čR&TVÉH§Ĺ‰?pÇŁ!{WĘ0ź*Vŕ/‰ż×wč†ĎĐ//đ”Ŕ Ĺp ů=Ń}ŃĆÜŇ.=˝l*<ö˙Á¬±w|±—Ó?vĚjÓÜ̬%áÓ:Ýwę1mw6#­Ä  řőÓ!Ôčö˛ˇĂ×âH$uŽŕ$0mfđ)ŕĹP®ëŞRmT-8üŇlÝÖ01ÓȇӥĹČÖ˘0¶Ë6 ŽÔÉ7YÝ>€6L@sđă!&-{Ý}íÖŮűם—‡1q|,Ş®,ÓŹ CĽˇü)•Św™]Ô’ťÚŞť»8ť‹:-Óa÷ą˝ˇ˛›ý­}®«ťŰş=2-;O(×<ÍwR ‰p×ÇWÜ»ťÜĘ­xŐŻ#Ž˝ ŰĄl۲ÝË}Ý·ŰŰÁ2Ü˙-Z÷·^·i‘nęÜůÜQĘÎÍŢČ-Ý ‹ÝňťÝpMŃÝđ}¬çz0QWˇŮ˙ńŢĆąáŢę]ě=ß žy±ń­~1…q GčuĄîC–a€ô|Őq€€ ĺB·‘»1ŰĆmŕę ăŐ}Üß=ŕ îÝ0ŽăÓ˝ŕ<~uB ¤,˛ ň hg#= DŽ!Â!")±ń˙ĐŹ8ĎŃH$F‚$J˛˛?-ă=-ć7ţÔ9ßgćîÝălľr•r)™˛)‚Ů*ˇ2*ĄÂ,Ş˘¸tţ*a+łR+·bú!é á9m˙ oÉ-Ţ.âB.říĘd>éW-ŕjľăh^ćnŕmŢé·2-ó2}2ç>c38Ł3ŘŞRcęACS4GŁk.G`ľLcS6g“6?nSjNéŔÝţëńmăš®ăęéĘ>néL¸Ł;ĽC©|—<¨íóuđ#¤Ě‡ŢrMăÁwúí™.âČ~ě›^©Ë~ďŕ–Î2Ô âyCÄ­wÇTí>Dť;”íCÔEtD-ďy·¸ůÚ^$čF ťîÄîÓěŢî^ă ˙ĐĂľđśţâéďř^ň€ćI $JťłtJ©´JëÔLh˙Óňµ”3€KşÄKľÄÁç-‘`a(Ň´·ü#ÚŮ„NčííżńżýńóÎđ żćf^ě&_ő¦öQ!5R+Ďň5…R*ĹRýT2ES6őő9µS)ĐS?äNl‰0`( ŚUéŞ]őUolńľô2őĄmďOOŕS?ëVřvZlďńĎZ®eŠ#č^ÚĄ[‚ [ľ\<8\Ýě!ĹQĹáĺ0Éćáé÷eěd®ôň4!řżÎúPŻú$Źř¶ĎQ‹bďŞx -Ö­¸d4Ćűó<9¶c=&űI/|źŰá€a&• áY&‘>ň~Żű˝ÝöoÝŰ˙oř?ű·ţ¤…Úáj9mhŰĂ)‰Vŕ7!Ú–mäŹŕQ˙6qŢÜß÷ŕűůßB†ai@ŕ@‚ DPáB† >„QâDŠ-^ÄQăFŽ= pi CŽ,ůQĺJ‡\ľt©¦††3m¬8“ĺNŹ=z°¸ŔSčP˘EŤEšTéR¦Mť"¤ů’gĚ–4â”z‘ęS–:đđq†%R¤(ĄÁ"A6l"lŕŔUî\şuíŢĹ›Wď^Ť[!ÚÜč—/Ĺ,ŇŁFÎşoč…ň#C*ÄśYófÎť=/ĽpŻE)4H‘"eÇÓ©?°u žł˙WŰőĘ„»xîz»„gŁUśŘÜAB ć×Íť?‡ýăpě„Q´DŞ?V€ČÄmé<čüóĐÍ.¨‚sFô‹őćŰď?0¤úQF OĽťzđůĺ‚Ęgoţö¨$Ň6đ€*d&ęLďxÖ+ ú¶áŹ[\Cg<3„1Zť ś€e°ć4w´Ô˘˙řŔÇ?äń °Îućă^Aň¶ŚÓ)Ă Wű>·µ¶đ…Ţë*X‚ÜÂ;(ńŤx¨îř)ÔŃ%~Iľ)Ćî6E*VQ/:‡ }€ˇ#D=1†A\<đ@Śp B€!;+|ń†1L`ČAAŕ‰iŔMľĂ@Á 3ä xŘÇ&˛p…}4‚]«»<ř€„NěĂ ˘Aľ<`㌇´!žđ8ŔŔ_!±G"ş‰~ġAvx"¸@†f`‚`C*—ŕ}4i®¤ ™Đ=x‚+ř.Kdq‹]ÄňŔŚ?p”,˙ AŤĐŚ6ľ‘ŽÓ$'=Éěđo$i±#\ę’—Ť@Â8ĆN inědĂ9|°L ÷H‚°Çs .+`d ‚%t $’¤¤%Ĺw,Ş! ťčGBpĚd.ł˘Í(ŹtĐ F¤@ŃŘ Ň#ń ?€éÉńŇ—~c‰Ĺ eEžöÔ§;9É °‚{$Â{ŰDHpPdø€ šˇ‡„€ …+< 0š»€9÷äǸbŔ@Wmc”âřŔ=Ů.ť03B%j"Ľ‚¸»h…!1)„:µŠABr×LÄ8A˙ ¶a‡ 0‡pŚ@đ  …1FPÖł¦Ő«O"Č8@¨s"ÁkQŁwZPA5   *UŞ’Ŕ+ŕ«@ţŘť‰• Ór­@6ŰŮφö=ŘR@‰Ĺ@®0&l!KÂ<€°öoHˇ!Ŕ ö±†ŃđhCwjQKCQŘ&©ÄŘ!r=ZßÜw C>Nˇ,(5!$hi<†±ŠU >^R„#ľAŽ%~ Řýi†5ĽaŠ8 ®ŃP°^|Úă.áíuÉú¦  ­«X]â&‘ŔĹ0®A3ř   ’ $GňaEp`8„6Ţ˙ lŔ¸=¸E:Pˇ…lpxz M‚,ôţł?ć1„\Ł ó>ĘÇ7ٰ¨-~×ÉĚ!ÄŕŔ náM„ˇ$P)R,¸ YÉL†1HĚ{ÜÖ.łĚgłšQ0â4ŕGÖĹ®éá„E`cc€‡ßµč`$ ĚŁáqYfFl çýąÖ˛ž”Káť „Ą^zU°…ŤSőpŘŘÇFöźô4€XÄűPC‰O¬LUĹ4ĆÎŤclŢÇ,Ű/ćA™©Úă?˛®Şnv‘YЉcÔ!@°Ś) /# âwCđ€˛Gk.÷ŁB Ŕ› ‚˙×Á 'FŔ×Ü ˇuž†śně$`ZĐD?Śá>T[C »Ý ďDŹş „nôś ~p$üŮѧ®{  qxEhiʸĄVďLµlŠßS⯾€–eńí;é±¶?kŤsúŔ”@}–(l­«ă¦>Ŕp˛Ĺ>öžŞÚΊ8Ş rËTiČ ŐŢq®ęíhŰ%„9^[l×ÜhĆ&Ţúr4Bu71;™˝ ATÖĹŁ@n {HÂč@ bŚ@˛‡Pj(2¶~âŁÉme¦m…Pg°€ r›xE`Ç`ŁÁ1ývď˙ť‹W»Ť€TBľgWô&A Čžl Ĺéq{UÉ )y1;0‚ŔÁhB-`a b?ďČÁnŔ4´’ ´źłb/ÁX<›Ę‡˝óű‚Ôż!`*cŔ‚eX „@›b`‡dµ‰0Gp0u` dLx˛ĂŔ ,»e;» A¸†1*Ł3r‰Řs1xŃzż±»c}Hě;m€H U2„^€ČÚă>VX†7ŕ i…ŁŮ@ř‚¸L,Ĺj¦5čŚ :Ŕ‡S1°'°,6Đ[(1! 1lb˝„P-:A˙7x€ż°=ř‚'đ‚Z4=PAfB"4Â!9¤}„9xv‹<Ŕ@x9 \ę[¤2ś€ vČ„/¨‚Ŕ›9đ@;úč4BÄśÁ7Ŕ3rK†@zĂ8Ľ˛TZĄVĘŕ6D7„ĂK€EVŠěČc°--¸†PÜ) 8‚g`oHFj …€©PĆh10 ´ĆkÜ•H…`h ę†LČ·ĽśqĂk€.`ˇ|0q^đŠ@†LP¤€ĐPGŘ€vÔ€€GyÔťCH‡tČ…~h„Lé›ĐFnôĆLŘśč„w€wІ?H˙¸m‡L€vAĽQźzp!•ę€XžÓé.0ÚłÁá``ŕŇřÇyT €ČwxS€…ěĆřFěŮÓižLءť9Çt\ÇʉHľ©Č©ÇTHuÄK+TđSHě™0.PĘ=Én *¨"Ë"č H–ĚŽzĽÇ|ě€Đ0ÓéÉʆś(ůهy8žäťŚČž„âLäąČQ©ěX€Nł[9›pqŕnjč˛LË|RŘ€ËĂĆŇ4Íč i  đ ŽQ śk– Ř€ ´8Đ  H—˙ÚÜ€`éXČßT€ €ŠßşŠ™HÍ XÍÖlĎşń—©©¬ńŔ_a Řl±ÍŽÝ´˛„ŕPé\ÍŤR€0„ˇśŁ™ÍÍŕš€y Îý´rI¨*Oź!ńO P°PN°OŐj€—÷LdˇÎ`™/ů ¨ö,!€šÔ€€P–@P„@J‡}†gpNČŃĹĚg8ÓŇ!uŽ­®^KȬ('LR)ÎôĽ‚2-{hŇô5_Ťđ‹-Ą/^“LŚX#S0-Š1%˙4]$Ť3ER— ˘‚ÓÔL‡ř­ŃĎěÓb…"R&%ŇB5T©«…HT…XCx‡vH‡Q0@9Ôş©ÓŃ7m ŕM1 …>Uqč='­ÔSEŐ*ÂŃ Ť°KUTĹ-ˇ3ŕ>(3P‚€?yŐ^őŐ_Ö»q ě@–ŕxR˝‰`eÖfĺ wŠE %%;^• kĄ‹ Ń€ŃĐVSuÖo×kĹV–Öľ×c+׎HWąčÖv ×w…WŽhmRo˝j•W| z•s%eĹ“ŞĐW† ×Dőׇŕ׌hWmŤ×†uX ÁŠEMXŚ8X˙‹XוX„­Xw X%T‚•Xj­Řš¸ŘśXŘŽ}Ř”eÖySVŞ pą×„Í“ô• Ec“ =bÁÎŹěÔ véČí pŤ¸ĐPuÍdA—zůדíÖ'5—ŤNŽµÚ®UR®ۉť×«őZSµÚ'-[IŰ‘Uٶ-Ôęx‚ńČŠ Ť(H…ČÉFŔŚ(xeŔ—řk@źjöqzІäńpMHĚo™‰XćцS¨p8K ťj Éł ľśÂť;P\eňŞ×µUŰeť]—ĄÝşâŐ°Ő †ÍÚ˙eصý®ÝZâíáuŰäíŐ …2ÔĐÜ›(€$ŕb€/x/đŔy€ä:€…ëŞ5™¦jş&ŘŇ(€~XŇX€W†±˛‰@}E„Ě5}P¤Ś«B0#22Ł[ÂÎMŤňÁÜM×€µŕŢĹ“ÝŐÝ´=Ż˝ŠŰu×6^>^ÚUŢ®T”ˇGČ‡Ž m5€Y8ľÜú&¨ľµk*Ř‚j8Č,p`Edh‚ŰĘ”  ĄeÚ‚kŕŮ9ţă6a&ä!u‰y;4؇rT° <[’Š—A“Ş Đ}H-X÷Ńłtčł? ™xpH‡jŕ‡Pp Ř!‰b%°Í±‰@‚{Řâ.ţb+Č±ŹŁE-ă2Tk§#Ře YŁăŹĺŇá&d>®Z>Ţăq˝ZfNfżćß=[ö]AäBöćk<äŔf(<ĺG~‰Hć_ d h'&Ř,8Č…O:`ľą¸ŚŰ8(€T‡:Ŕ)°‡ „Ş[Z˝ ž H‚{`.öb˙07¤óĺ,€6i«lĐc¦c…ŕÝ@†fe~‘ć]?X‘ei”}f’6ŢáEáo¦ik<€+0†z0†?Ŕ¦+¶‰†0°’Č᥅¶Ë_g†sř„ĺx€Ńx»c¨ËÓ€ k€h„]mč+, Đ´0n« \€Çň<¤Ňá¶[cŔ7fč éîă—=fB]ŘŮŐćk^Ň˝ŢćŔFŢš6l˛C€[8!=ßęÖ iČŢ2¨‘ Aćóă‡B€IĐBP‘9¬Ă;ĸ„yŕ%Č‚rP„ťI’Q°0¶ź ˇe[v łĺC2ŕ.@`˙+ś'Ěv`–`‚>滆ăfö]˝.nl¶ÝĺfnÁ^W >ěéN¶ĺ^;ľ‰şM…zÖÔÉ9™; ‡!`€(.Đ(J0٤ ąßé†?بÚčýŤ‹ a€,Č"päň·& ;°’ü›ěŔHő!Gpk€nSÁ6n»^ćhţc—®f —n•ţZáŤî™¦îß0ZôÚ 8Nc˝M™×¤ś˘í?1‰žů¬O­P—rY`«ŹCn€QŁŐ€ŰśOČ‚YĘŮň\aÉđ ßŘă†r”nnŰÍZ9ţëe~î–ÎÝ ×róźBgdöm%Ź˙™ «$Á- ]¸J.ÝÚá SM]S¬µó% ŚŽóčD d¶W8ď‹=d=i&M,2'ěóEOYýîęt…!€NF7Š’}rŠýrJ×ôw…Öťˇ:ßôčČćP'őR7őĚěSWu™ ‹ŤörUŠxőV“YQçhu1Gtٰ \±Í Č]őŇńő 뿍HöëŔŇçhöeoŽb/¶¶eď8“iAĘ~öa?6 •‰č;ŤHŻ{ŕq_‰ĐXnZOT9‘Ń”YjA„(w>`Ó€ˇŽŘ÷ˇÔPwvwxw'„vçŚÔ śív˙•p(P†~xeŕ1)Y‘ďw§€«rë€_•ŤH’%9voĎŚK•tG/€hźŽ `śwr'CŃ”Daz_&—y&čµFy˙áه”p' ›Çy—gçť?ůÖszy áFZ|^`X_‰Sy@Z)"hTáyPz¤y˛’—úŹ•Raůňx˙D™úśÇÜŃŔŞQř×4‡Ń™µZđ„:qśjqs™Zi€GöüŔž”^ř–]ń™íOźE™`1dÁ ‹aăh–g‰–i©–kńîa|ÇO–ÉÔ˙]ńd —Đoń”YÝyI™Î÷ü˝Z‰Q}­ĐŚăGţ’}rýŢżY3ť˝Č”ńIýě ÚG’ĿτجVA`>ZÖIď'ý%üńg—Óx€…Ńĺ),h0A×Âdˇ˘B °´Đ  .Măˇ` "„Á”4€A… ‹"*pé°ĂE•6PP€Â‰rŤ J¤h‘ŕL‰6Uŕ 9˛äÉ XşT!bC… ú…©Şbź$$HőAŐ ŔäpÁetŇ­k÷.ŢĽz÷ňíë÷/ŕŔ‚ n¤7®8˙@”ȕν?Bl8ńČšżwăŠl1ęÚ;‚sBtĐ ˇ|qNšníú5k|xđ Ú߸Ń6x¸S­ž˛9)*L§Ň4·€CdăŁé 7řĹÉŕöB”Tďüĺctňˇjţú)SbÇ­zÚ4UŁ7§B k˙đ ós˛vúńŐűUÁövą‘fPlłá%@%Óř`Pw€›8I•ÝvÝ‘ÖŘc‘MF‚ Ş$uÖvXbĂĹ7_}95ŕ‡6éÔÓÍ‹bu×QČťw!4řŕ8rđ2đ5sŘžx䙟cę)8˘pĐAĚ3Ä ¦ÚIv9°‹4˙đ°Ŕ‚ ´°@ÂŽâd’ă•gÂąüňĐ Ý!WÁ©<–")l¤Ź>/Ć“NřéW™Ŕ'}öÔá‚ ˇ‘ dŚIWš=âÔ#ąT#]ť]ćO.ü ubŁ9qę)Ž'50iĄ“ąucw#ŚđJ;řŕóŹ|˛L6ôđ„+®t €Aq !`±Cg 3ŚŻľ;UPđÁ&HL H=Ś1l˙2č#Ščc•o?đ!\á^‰.®ď}™`ĺ×¶.5¸F)I* ‹<%óŹă‹|ôcÍţ¸’†UB€Đ× ¶-onl0Ă@*8A€+ÜĂ ¨sbC-ęQ“ú@Yđ[tbu¬Y ôĨĐĚl•Ţ“¬wµľn đŹ#ŔV¶!XďťËËŕÝ@ .PI3ęŕ!Đ€DKsó°‹Ő•Fż˙µ01c(Ű˝¤ł±^2‹— ',ďEŚ˝^‚{Ř ¦ |9ěaű29ŃáM'ŽńęX 8Á> %´ÍíźšÁf75%| G%á۶ÁEüMďůî;Ψ].>! :ÉĹ w?Čm‚¤uŔÁě!‰“đGX-``‚Łâ%ČC.Ă2PA }/żv ÷¸ÍR*/Ź‚ áuę L\CŁË»ĹĽ5ßHčGh@í XŽP!:żń č{«$Ů#UŢžwĂu‹¬}ă`{hĐ„hĽ nmtAÜîđI3Ł <… ˘a€Hx¨ÔŽ<äC˝Ř«.€Ä8Á ˙–!łŔl(€H§ËĽi 쵺¸‰&ŕä×|E M#oÓň€®”˘ďńmX 6Žd±JĂťr° 2€ Ž$# 8)ů΋P 6đ€& ťKyÍAP‰ŢÓÓž Ý,H6ŕ‚<ěým•&"Ĺ)r‚BhĆ r©|Şk‘ó¶ďű“Eź(ěśÜLĺY^-’öq_KIX—Y] !áźţa€üŃźýµŽ3LCĚ‚9|óe„÷AŔ.ŔŃ„ÍÜOE5ŔA4ÂШë™]J4Ô.̆Ľ‚=8EŤÓEŮĎ…Ň4ß 2QT˙‚9Ľ€ ĹŔ(´@ H")Ř„I C…ˇpTr |ÄÂ*ˇŔ6‘ ]lŕ6Ő>Đ^¸Q(äŔ6”xáöqž €Uš8‚ ¤qŢć_ňNH‡>„ÔS Ř,ŔŃ@­MJŘVtîĚEä}"(†"µđÍ9¬AtWTŔ °Â2ĽÔŔeÖÂÜŔ\ŮěµÂ·i@ěü‹ë™ĆŁ RlŤŻŃžu €NŘA°żŚÁ‚„ŔiĚW´žŔô4 LĽËŘÁ|ÁxÁIƸÓő…\"¸Á  ˙Ŕ.ŚÁčů\0DĘ-0KA¨ ÍÁLŔÖŔăýđ€_qŁ7&ä*¶â+Ćâ‡áÁAÖËZŁL‘˘)˘b aĽc<Î#FŕI0GÎ6vă|ŁB CBŽCF?BL‚>„€8’Ł9ĘĎFĚ,A”C…MŕŚ‚5t×ě@/z"]ř€đ3PŽL>ÎďĚüd9NPxÁ>”BlĐPŚŔ<Ď|AĚÁršA„O5 IĘ#=d äL >śÂŚ8ęÄ_nĺý䀕UŰĄÄĂ%ZZ^ÂŁ^6¦ňÍČĐA`faš˙UKF$[‘T2@ă<ŠÄp… đś€Â6lŕ–(Ö¦mŢć]¬x‡Ŕ””@'lÇ;hèĹh<ř8d đ†+đ‚„Ŕ ˛Pă–¬JřâńL9'tJ'u~EoXpÄAĐĄr×8pÁE¨Ë°5—iLH*w‚lŔ pŃC&śÉ¤yÄ: p|@'ÔĂ; |ZtÁ2Ô§P/ŕÄt"ËT€ p§A,Ň#\CqÄ€žä}vŔŠhnĚ…aG*—‰^pľ‹çbŚh‰Úg¸çhÔJřÁn*CoNĚč‚ÂŔ¤˙B0´€*vC& Źú¨|¨)4‹¬(N$ŔĐĂ0@äM~îg†Ŕj‚±tĂČ•[Ô6ĽŽŹ^çŐ©D‘‰ ¨"8Ăd¬ʰ(Ś)dô' DS`†fčFd/ Ş)¤@’.i“>韤ČF)^ަ‰ÚÇ«PĘ‹pÁaÎTŠbih–jčoŚi=äĆšip)«ĆAŽŞ?”Ş\¸(•Šä~.h ü yvCoÄ ¤‘€š|ń.|nN+µÖćYH@Y-U@ŔXD4Ztk pŔHPŁ©łh@0€UĆŻ©b4˙B\F4ŤEsĄklŔE”E]¸ÔÄKÄ„ÎÂ@ÂV|jŔ´”Ë4ÁBEHÄXěÎaŔZ¸D ě·>ĹUl@HJ諼Ňë©€THŔ"EO(Ĺnë»4¬M„Ž8¬¸Â¬DP,!%,H´Ä`« hę¶~,BŔVŚNmÖ\ŕěĂę,Íš•4L´«U,’OäěI$ÁÂÄ6±Ś•¸+Ö2”4€·VŔXHŇŐČL]@L¬Î’«ÄşD ,HlŃ’… ,€»>ÜJ€LÍÔÝ Ď%­ßĆ,Ĺj îËęÄÜ.b”„TÚżî˙mÁĹJ8ěÇN@ćŠŔćfÍL®¸JE,؆@ł¬E·~Eż&@ĎŔâŞĎĺŹ=¤ÁcV+đ/©Cýî_FJ€đC”A¬VoJ\ňaÍhνUď_Đ%`(/óV*äIĹő>‡NoA°]N|/ž‘o¶ŻJäVá€.\Š`ŕ_Ŕď^HQüŞoĎ1Ô^Ho^°_Ô™ńţ®GŻNŕŕÜ€ĐÂ/¤đV°_0µŔ ŘaAoµ4K#­Î‡šs°m‚p-đµ ° “š—ZC:ÂĐ#×° OK0C=hÂDí ˙01ËčD6¶F¶d˙ FÜćO+cěéă]iŚpW± gD–đŻo1w±1‡±Ź1—ń㹆` ¶¨1ł1ٱ_đk±DZßń Í1`Ô1µđ1űq ë1W« Ź1gă '˛"§±†i€Ř'ô¤´üZ‰QµÔ1ň.±J`˛µ€rAXrJpň'›2!űš¨yr^übőОă2*ď1+/˛-Ëq-óĹ#oŁ.Pň`rr%ňs˛0Ä,ď1»^)3]$ó´3bĺ˛]¸2"Cłaýâ7ň-włÓçm˛]뿲!MP„\»-¶¦Â®$-˙-SŚňk° ĹK¤€€+ąŠYč3[tlU@CPŔ(<Ż$€Ă:ÄĐ´Ĺ[ś«\łEŹĹH-Š:¬HBW®J´í&´5s3E·´_3,«1LëqMc˛M;3=[óîŐLw2Oű´+÷´({đ3ł4#óPËôM7uN×´7Gő y< (,S׳D(o" ޤi¬W ©Ww*Q Ü‚-hŞŔ‹cd˛ÄÉś¨˘ťx€¤ÇŠÚ‡*㉞pGź`°‡>‚1´5Ş"=”X˘nFF`dHF”€5‚ °Ě#< | ˙ z¨{¸idJ„ěFoü†`ź.•v°Tˇ*ő);őKłSňlCµP˙ômó´mqK+µö55ďtoóvP×¶q÷PKµr[Ë€‚?ĐB€@`µŔ˘dHŢÍĎŹiX7vs…\é@30B B4ěŔaŠ‘÷ˇ ±Pń”ž%Ś/@#(0č‹5[JϤj’P° - L@ÜC¨ »<ĚŔ€i Ťą KM Ńř%ÝLÎěĚÉ;peşŕĤfŘ ]ü·jR#ôć˛8wk·¸qÇ8Ś˙ökwŤËxkß83 wlóMç¶6#7Žyp/˙·‘ű…EÓŔ#äĂrVÇöäaŐ]Q×uw5I91LFA>ś‚>`A.ő¸i¬·^Yá{3ó¤Ń#¶RŔĽ†Iˇ”J±]áîŐŃĚĂlA:,AĚ8™ą >€i(‘VÁ>–`A•,›Ćąa’&)TE1•íŮŐĺŐĹścz˝rŁ#˛oguŻxl‹9‘y575qźşŹu© 95«úQë6ŽĂ:‘9®32­ěC9€oŠß0VŞIZźu÷– žBŢK)ř@2 TAąĆŇý?É  žŔ8ݕɕ×č[q€cĹŔ—Á `ĂŚÁ°igy˙hE“ŘeŤT dÚ¦í´ąŔś[wQ’QvĆ‚X0Fłőtŕ…ű¸«š x0+ăôpCőĂ72«›ş,ßErůq 7* ˛&S|Ž7sL‡ü¬#µÉĎ8É»6LJ|RçşËă…iP@ŕA3 ŘőVwĂűĂ픕;Ăx-`Í…z{_ĄµfkL™µ—1í‰Ńź=á|;ž±l±Ç@ĐCĽÂ!Đ"ô­)€­áöÜŔÉÚHi¨â1žüÚŁ;[%eÁ=(YÚ›BZ±|Űa¸»Ă;ĽKń§Źş%ź|¨[<«»4Ě>Ť‹Ľ¬+>¨Ż:¨Ľ§§ĽĘ·˙ĽŽ#/Ä?őŽ'ţĘç¸Qż<éăĹ\1Ôôś żżF3µk%*Röíáş1@%†Ŕ.,Ă"Ř€ag~´7ĂÚ,=ţÔ@áÓk»kěĆ H!šůśOâŤŔ Ü(Ô(R荞 Č˙Í_¶G˝€{hařwaśP’¤S:ú€$R"1Ś€¦żP?©8@h8€4aC‡ >”8‘"B Ô¸±âĹŤ;†dř‘cBŤAR$1äĘŹ"˛4 “ćË‘.qćÔą“gOź?:”hQťnť˘"‰\˛—¨ ¤~qH„ŕŔ˙Î5DnŢ:µęŐ!ňŁ’B˵?60€Ś3BřŐ÷Dđ`Dˇxç­÷S’8¦W`SO}ŻŇVŰ‹¨dU!ňč;ś,%ISMGuőĺ•%­yŐúZľ4gśŮożŹi-Ú裑NúŃú˘š†‡¸H‚Z٦źţ荤ţą VbÔ'LSč‚«?Â@j—¸^§nĐ‚–_TH'ł Š«ą]2ű'˝‡ryé—ćóŮf‰–Yp˙ç©đŻÁnu§Ć/µ?Čç(=ZÜ ˇWÚóĎAÝ?ŞĎƉtĹMžŐďXŁ`¦M†Čˇt™SťsÍ‹ZiďlďÝ÷ß_Őřá‰/Ţxž•ţ”rXÍľŔlľÝ˙;ţďĺ'Ç”úÝ1’^ű퍿‰űďÁ_|ńgßüóŃO_ýőŮoßý÷áŹ_ţůéŻßţűńĎ_˙ýůďß˙˙<­€4ŕ@˘ěz tŕ!A NP(µ™Ł¬G3Ú­”™ŕHµÁ‡edUˇâQB®PVáy4řBóx ?,sˇ fAî‡=ôˇ ;—CĺĄLgů)˘ BD "1„?tâˇ(Áť-R˘˘bĚČDťçZśbÁF1úď‹ Ź_Ĺ&ŢNŤ^ôŢő“˛NŤ‘Žu´cüĘ(Ä Îń‚&‹ˇĎÚčĆ ~PŹfÔá™HE/ʆd˙Y¦ü¨Ä° ’doL#%-ąHMn’“»ž#UITý”‚Ľ ÁÉCv’•­teîp×ĹIFęŢSI&g‰ÄĂÝL”Ą4!_La3zŚ{#§P™Ë_Ʋ=ô©b,ÉŁÇ-ň‘Ő´ć5y˛ đëWÝ„ĽŮÍ€›ág8EN 3Z\[4˛8x6°Ź«d‰ĺćIO›`“źýô§F60‚\ü ňř‡<üqŠ”ˇőP(AzĐ„.4˘ňpč@ *QS  ʏüçGAŇWŤ-O0éIź°’˘Ô¤*eiKWĘR—ľT ĺSß'EšSťîÔ'cŰóâb7’Üí§Ď€P˙?BTç¨ ýôÉS©N•ŞUµęU±šU­n•«]őęWÁV±Ž•¬e5«Š ĽmäYĹzŔ˘ĄV‚A ®ă@ÇVąÖuwٱrB ŕ©g5ěa­z<ws nQmh˘ôĆppřcn¸[ ŞQeĚÁ^Čěf;űY%…v´Ąu‰ŕđرµµm5«€Ôýř… űátÁűŕĂ!–±äĽ9ÎŽt0łťÎŚ@9Í}Nt´Sťł¸ä đ-Ę ‚cŃö¶ĺ5Ż")ĐGXŁ‚ ‚L𡕧Y ‡€Ŕ %(ˇ˝N=(˛á˙Ł/(W/q‚lCţ°€ lŕ ň-Űłhđ||©ä=ď‡A F4a€A :@^úfÁřmƲ°55l°ÇjĐ =đ`+m` bĽ†‚ÔřĆ9ŢqŹ™Q–@Ă>ĘQ(…ĘUŽ˘.SŽLa'+ľŻ šQß{DĆ16Ž|YĆC¶ń™Óěc%¶xhF9ÁÍĘ}öł Cŕ !ířEB`>oD8ÄášpöŰ^ŕżŇ€p°\c Ĥ+}édzÓvÉ®`Śz@†Nůó«a=A ¬K.Đ…0Zí’F˙ÇIÎršs]čR‡3#@uýÜěrÇÂAŠRâęXO›Ú ěŔOs§9ÄNxŇźü(%YcPO’ëž8îD•{¶h3PµáďFĚGĄĹ~…1Ť…¬^z˝XĆ6&Żż" 'Q’÷Áľ@ĐíA¸ŰDŢ‘2á·8U騋ośăĎ8É:r‘ßĎ>›»]MHxŽśĺ-wůËas™Ďść5·ůÍqžsťżś„˘$á2§iśÚsçEĎąGq(I”ťé:ůGo«`§ ˘>u TýęYď&±ôĺs˘7ťěúF\ŽŚâ;X‚Ú3JŹ!¤}˙ím;D *wşG”íE®2W^vÁ'ü„IeÁKŕĂł4&âŹxÇ#~»őtáŕ1pŹnD°đĽîć |ţóYńHúŃ“¸Fýçď¦1TŽ=óµ‡ő5r¸ĺÁÝ!úąë>ř˝˙ýî :|ä÷žËÍĽíˇ_ńc…*éó>S>µ©śĽéśÂi+•?Í3•(n# Ł*j˘*ę ęÁK@!t!R®'HęĄR*¦PjR,B9T(|j©ô©6bŇ:´Dy˘¨˙ز ŠęAM´EĂŇ R4,9ľ Y\ÔEĄcˇ©îҡ #.˘q«1GçSŞŕád(úęaŔ@l.`»Iásě!tD ú ŻË´.FÔęD(@ GÁ5 BÉQKá“îŕ¤ŔMŔtµD‹´®ć´8˳ޤ( 2«QŹ€át@5@bS1bؤk¨ Řś‹QOdva5ç±µ4ÂR1őM4`Ŕ ěŔĚÓ,Ŕ8` ˘‚Żműń;•:Âvr@TŤŚÇ8`Í‚ĚÍně  śFlä2!gµ7?őVy@W#’˙ĆĆW۬ĚŢě Ŕ€Á â!#ňH—Ő4u[1‚TGMÓ8ÍÓ@ ,íCĆjˇrµ . Ë1\K3Č Ĺ,lŘş :Ś Ů&UE/ ÇĚ/4Â#A_MS5·ˇ5±rÝ”á RŕC2 Üt‰*Ż  $O’a#ł&` Úş‘ß2`L÷ ŕrö HS#Zň%cRd#ĐRÁáD%"IáV„$Ć'‰?»É?˝iś”öWVśÔ ť˘öWśvťţ3np–€ šŠ&Ŕe ´Ŕ°r#®&(ßAJAŠA*ŁęˇŢÖ˘â6A鶢. ď˙4j(·6—Š=<@­ň´‚0ô¤fJ¦¦,tq3´q/ÔBkęoA±ä(GU”|*,ĂRD5B©€ę¨7©® DŞt7Bt™Ę©,wkËl“ňuµ”Đŕ *–vgu4!Ę L€ktËglV !†·u—: Dˇ¸ Ý„]âhŐ"Ş·›wź ĺęÇ^á¸ő4” ź”f' `’p ›°{Q%6ń} ¨´ ¤ Ó· & $ă 8`«P~O”ŢgN ÁMÔĘ Áđ#j  t!ř^ ¸±(~&`XÓ#1Dx#˙J89† T}’ CľâpĄĆ[Ý  bQŘUXsĎ'IXA*ŹýP#®&Yy-aúp t‡™ná7ńěI VE!ľ6˘Šщéۧ ô |ô4F@)Ćx€EŃXŤ9Ő‹Ź~Áň‡7¬l%ČŠo疢ʷ'’7]@Y$   ä`'ť°Ń8ŕjWŮŃ•Gň˙)¨B_ r7@5€—{Y>yn>—^ubFť4€Čą’yH±P4uťDŤ ĺŔWŤJqţŔŽ˘*ś;‰0!źźšČ}Ńži›}蟋ȟa 3Ż~gŹ@5`×6˘’ŕ*¸{z8l€ˇßéěÚć0şžű$:a#z˘‹G vŤˇĹî 7:äz®o¦°8z¤‹F+Íô4* DŔĂ`Z¦'ĺäěsĄY.¨gŹ%B:išVŔڎ>$ éˇ xÚ˘Iĺ|X¨7NĄÓh!ŽşĚ’š`·oĆ&¬ÁZ­Äšlî¦Ćxph`zŕŇŔyrâ¤1Z„& «9Z«˙ş§Á˘%mY °[j[ąJů{°5˘°Yô ŕ nq Ňa ˘`@;ç:¦/zŹ2×UôŻ5ďłĂ#-ĺüš¤`© Şä€ÇÚˇ𡆯Fµ˙µ]ű`[¶kXMčÁ HcĆ`»Ě˘‡h”lI´A»Úúq~®´7â~˙Z#`¦` Ö`´V¦ †+«űşł{»»ű»Ă›d€âŕň€AŞf®Ť›łÁ¦®…fąźS:"řz¦§[EŤJj  DI×›Źęjř^„ j"Y&ůú¸“(gZżíŹżH#şú´‹¦ę˙@ăZ€4î˘>čú”x©Ĺ9|äAĽľ‡ě«eĺjö`JB®D‹3Ą«Ń#“šűĹC{ČeŃ4űSDśV®ćúe_xË“«5Ű®YehÜĺĽ$V‡m|Vf%MšŞ:•;ËýlË­ľsCşQ{xĆܧU®fĐ\ËŤhžŁ&žżęć0—v˝Đ ýĐ—<ŃĄŇÍ˝'ßĂ$ýŃU˝<Ŕ)]‡¨$îIB=˝Ó;ÂŃ3}=bZN&&}ÔC±eěč4.ŐUÝY}Ö®=D=ÖW5UćÓĺâľďI%`×’d‚]Ř˛Ł âÖŤť!‘]?˙Š}Ůď1s‘Óˇ}&•˝Ú±=۵}Űą˝Ű˝Ý{=ŰĂHžÄýŰź8ÜŻV,čĚÍýćR‡ÝOłłÓ˝ÝŤîÝË]2Ţé}ćě}Ţż2ßď}ßq®ß=:?ĺ˝ŕľčľwÖ=ŕľćŢvŢß>݉Fßa‰Ü)ľâi.âEgâžăÝÝC~Ü^ämĎăCäQľöTtXľĺ1ďĺ?'ćeľŽKŢw6ţćyľç}ţç>č…~艾čŤţč‘>é•~陾éťţéˇ>ęĄ~ꩾę­ţę±>ëµ~ëąľëtŔ8¦\(& ¬áđfvllăMyâŚ@'˝ľăŕ ˙úAČ>@:¸űp˛‚`«Č•'\Ŕ¸śë>«bwŽI‚`ÜeeM ęř Z t!_$żęŠ%+˘®ťpB– Łň˛bGjćJŕˢ./Ý`Y⦉_«`K¶ę°ü`üA´žD5Ó„ˇ”q_÷yňc PˇÂJŕlŕ\"ITá… ˘Ňţ„Áo?Ŕ¸¤”aNb»ę~Ág˙¬şë»ÂË;]"[ĎA ˛ ¸Ăzŕ \AúuĂŢ?ţ9ăOBG3F)DEŰa€Â… +ŚPĺ*D…‚€đ4Ť‡Â ň0űĂĺ $*iFL$&2|˙ 3¦Ě™4kÚĽ‰3§Îť<{úü 4¨ĐˇD‹=Š4©ŇĄL›:} 3AŹňËTĂL—¦˝`đˇ1!6<Śč’«W°b=„@&ß)}X: i˘ÄŤTʸŃáZTR`Ŕ@‚‡ .šéÉA˘d¨”+[ľŚ9łćÍś;{ţ :tR  ŮW® 1XĘȱ ł"6ň˘UčöŮ´'L„­”­xĎî]čđĆ·üi Ó‚DBŤőhŤ=»öíÜ»{˙>ĽřzŕiV® Zwĺ{vmăißÇďÝŁ¶sGlÚ>ŽŰ_×)”ŔZhŇŹ1JL‚cŽ˙a„NHa…^!M\aL=ĆüAR[]’Í 0€ËXŠy0 ,0W%ž"Y€b Ë,bC .ĹÄ‹´°# Z‰9/$Ʀ°°ÁČřă=™%b],Ó­)§Â oĽňÎKo˝›5©W )`«P @A *čËŻż)LĐ€"pĐT*¨`“Ŕ§©( €Ăl @;,‘4đ$É?ÚËrË.ż s̵ľGkŻ/©ĹCÍŇPsQ‡É 4vTŔQĐFŤ4S8÷ě^FL' ő—=ôŔÂÎQ_ŤuÖZoýŞd<řp%”B %i`!I°ÁFŠr wÜrĎMwv°F1Ôă:ß CL(~Č :Pku/ÎřĽ6e4đďÓAMţďÖĽÔć–&¤°Ź;Ą»3˙Ă8˛ 'lܲ6N{í¬^ŕvřTp bXRŔ ź=Âsß”ďŔßŮݤSz<ĄSĂĆ%É C9ťDŠŰN~ů`9(ä+hi _5ěRĘ:ÁŹ?ţ¸˝Ćü8ĺ_«×řŕ2Đ=8Á•ń}ęłI ¬!Ź8 5ţ\t@4ÁŔޱ űÝ„#ó«CŔ†! *7"äI@¤đ ¤łŢéâA jŘĐî Ĺ(fľ Q<.°†€ö˝/~ŕH°Śö$Îüw*Ödi–!Ŕúˇ‹ţ¤G<Ţd€P˙LCŠľˇp‹–čä!䉡(E…0@Ya`΄âE0ŠŃ(L(† éŽî!ŇzŐ†ÉH&ĹbčWć`1L ®ń‡©Ŕ,ŁĹ4I±%Ŕ“CČ4Ŕ‘(ŕb*Đ@Ĺ1Zr’ŠLD%±µJ…@Ůr©I`&ľTXŔ*2H$– ř%5u‰Ş— ŤcXh'6°J:“€D`$ źt(%#•‘3‡á"EFŕľăPó—ŕ$ŘÂl.Db@ZD°Nŕ •Z©Ŕŕ}„–ÍĽ¤L() ¤ŔŰT@7żINTR˙Ł­@żZ˛Î‰ t!č:LÇĂŢđt¦s„8(ÉśęÔ' đ6ŇQŹnĽ[ ¸8ü17HfČh‡SńQŹ_`ُĆ;:‡tŕ˙ř‡0rpXzŔ·¨VOµÜa\őHŞdx‰›KčCAŞJ‹t€pËNđkXkYa"3/AŹqäjWCC.ĘĹ· e"lŕ±–ő¬+eź1(Śwaҧ@*¶>`jřŁĘXSťÚŽzŕăŘj^ËŐ×´ü%ŹH«^\‚;Ęćę˛ZAí6üq‹k4& 0„1|”ÄĐŁ \ő*X“8‚Z´ř˙ř‡<~q0ąŇŐ´ť ŘUe¸ŁźĹGh·ÔSôŞ—˝Ý@YJp [pî% Ä7âˇR¸ă¤PGé ÜCu®ýŮ©ĽלCHH…>ŔĐ€˘Ă ®Áä)Y‰YXá‹7Ś8`ČAE.’řµĎc(a†űŘD®°ŹFěR‹VĽ<ř€„NěĂ §Aľ<`#Ä;¶!ž ,óf—pśää;Ľ\ çx0)7-Áúh„C]Acă8ťĹ]žŕŠŰXŃ®đ…1°¨Ź„d$% ÂIJĚ’©>9ĘSćÁD’ó ‡üV!iNÄ˙šŰ< l¸ĂR!N'u,€čÁ=Ň@‹`ä:¬Y„ (ˇ\9r’—,ZfňY YčD?ÂÜ9ĎÇ‘0Ż}† „ AČL: `źáÔ609¦=ío¸R0„ż €+¸G"*mÂ.7ʆSť„€…+< 0`í‹€d<WŚÂĐ7¨"pŚRĽ`¸‡;×=—Üć– ?ě˘:Ä<¤P4#–Ë3š@ŠNn;dŔ„9|ŕ€c‚'…1Fđ|ß-l"(@ź¸z…â‰Ň` s&1Ć1‘L.˙®Ťs\DfČ\ó™×Ü'čÁ6č &€ť-ŔćÁ„-¤c QšXő&^€7ŘÇ ×LĽÜ‰Üa×–±”%čE|[Ţ—ąÔ%R1!A´ă1ŚU¬bÖăˇ"ń rřL(o¸?ŻS2<Š ěNi6Řăđ«Ů5 D­ T‚¤žOĚžJ5hr0”C€8‘q6zE| ‡ĐĆ; *U ·H*´Đ‚ëĘgńAAúr‘ Z5¸F=Ěę|”cČ˝¨¨TśIď9#ÉďăčHG!®W˘ď|ĐV$ VGxĺw˙~ä˘~(pziŔ3tDv1azôŕ‹€ {0đĐ`q§0¨‡ďQ85đ±ňquűŁĽaľÂń9ĐĆC‡D5ČmĚz9č`Čw¤gzű ©·zđÓ Öq±»×?p{°‡Ohˇ„ĺ÷Á7|CVEČ÷¤‡nę–7" 7e%ľ—@oO(J?H˘$‰„JͰ ÷éńVĽÄ„"ŘŚŠ0'° ‚°rł0 ö $Xx_±Ä@ #n‡&@é„pźđIG'…€H¸Ó"/#ěHzń$Q2%Ur%YňŽńJHi• YÂIA2 CR$ ‰ô–n‚)Љ0Ń#p° Áе ¶@g’’$&pEp$Ěx‘˛H"&‚"*‚’.R$2•57’#;Ň˙#$ŘRĹŔaÉ/uyŽ@yęŔhÉđĘč–‘Ä”ŠP wâa ¶„˘brp)8—OIÝH)–ňá ôđ&†Đf긎ô׎8É Ëđ\0?­D{_pwP)#w3|¶]€l#0t€§0c`NŔrl ¶PcB D$!’3q`'x˘'q)šÂ)ž* ˇ—ĄňďX™—™™×±cűsđś¤(Śâ(2)ý` 5v›0tĐ™đU@Žs †b„ťy)öG…ÉPcÁi‘±¸}]Ö'rB'ľy'y˛'úůe2˙(…‚D1Gđ ěŕ J ¤đÔöjˇâ *€Śoɡtł© -P'Đ ™ †=uTă0é¨.ěâ-pĽ € ™@L -Üâ-ŕâ Ľ !@Ł6úW‡é ýĐr¤Ž˘#Z˘aő+ďď  €,w  ňŕWwQ~ Zéµ^śÔŽĺAĹ&\ÍT\ŕ, ĽP|AJLĄÂL*˘$j˘ .äb.č‚IëŇ.§Ą@UĄŘ˘-©/:Ôb-¦™EYä2\.{¦Ý0űµ‹ˇ©EĐ@i:9Ú.,Đaă",- ˙§Nj˘ĺU,‹0ľ,xZ«Ç’,ËŇ,Ď-2Ń)ŕâŔ Ü ÔĐ/ Ôf¬Ćú ¤°üءŐ*7)5J&%’‘I* MĆw2Ń´đ˘`…ŁÓ1"0®ý˘L°Ł P÷0'[ÂKŘşÚĘ­  ż®ć¤0[ƵrŘ2—"eM€L3®ćD ®Ź™d0ţŞ­Á2##MZ•D(ó*“Iü”-ÇÔ®ÇŃ­)° D MâdQ/Ń é$K&`Ă®*Ó› –¤Ű/~Çeű‚˛ýT0ᥴ Ă01 °I311” YűÚ ĎŕśĐµY‹¬Ďp«a­eK;[ňtźCd/!šk †•WPS Ł`M@­ •¶ ±e?ă~«–±?Á4h ¸€[Ë3Đc3Da¸źcOüĹeÄ;øŽé°µYű¬ś[ ˛ ăc¶ŁIn;¦+ `ďĐé0 f€Š¤Ű‘Ë&4#®b@ śË»âĐ>#˛+ĽĂË_9JĽô‚éDfŔ|Pf )Ŕ;Ék˝×‹˝/#ó</ĽŮ+ľăKľĘ{ąĺ‹ľ­!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z q5HÁ "¨paB‡.@‚ x€óĆ>€ňG«Ś)>HЀƣ|ŕ2Q)°â4űĘ1Áˇf<ÍĘ5baăÂ+ĆęűĂ‚D‡„nť˘"…Ó!8|ĚȡçD!!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z *˙ 8ÁT¸áż„ !*”ĐáC‹ flŁG‡†|!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,#‹!ů ,z 5H° Á*\ȰˇĂ‡#JL!ů ,#‹!ů ,#‹!ů ,x L1@H° „äÉű·°!Ă ü  ˘Ĺ%^Ľ¨QăĆŠ!~ÄHrdČ‘$=~„č°aEŠ!^ (hcÇ/FĚ(ň˘FŽ%rś8Ň"K“Ź6†LY1äK’7ĆDér%Ă–”É&H•{&ýI´cO›BqFŐŮԨϥHžśů4«É’wr +XŞ<Éz•ŠUlŃ®g¶­ 7§\­nťŞŤ»íX•eµňÍk5đW»[ßîE<îâ©w;pipx-1.6.0/pyproject.toml000066400000000000000000000050511462701651400154210ustar00rootroot00000000000000[build-system] build-backend = "hatchling.build" requires = [ "hatch-vcs>=0.4", "hatchling>=1.18", ] [project] name = "pipx" description = "Install and Run Python Applications in Isolated Environments" readme = "README.md" keywords = [ "cli", "install", "pip", "Virtual Environment", "workflow", ] license = "MIT" authors = [ { name = "Chad Smith", email = "chadsmith.software@gmail.com" }, ] requires-python = ">=3.8" classifiers = [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] dynamic = [ "version", ] dependencies = [ "argcomplete>=1.9.4", "colorama>=0.4.4; sys_platform=='win32'", "packaging>=20", "platformdirs>=2.1", "tomli; python_version<'3.11'", "userpath!=1.9,>=1.6", ] urls."Bug Tracker" = "https://github.com/pypa/pipx/issues" urls.Documentation = "https://pipx.pypa.io" urls.Homepage = "https://pipx.pypa.io" urls."Release Notes" = "https://pipx.pypa.io/latest/changelog/" urls."Source Code" = "https://github.com/pypa/pipx" scripts.pipx = "pipx.main:cli" [tool.hatch] build.hooks.vcs.version-file = "src/pipx/version.py" build.targets.sdist.include = [ "/src", "/logo.png", "/pipx_demo.gif", "/*.md", ] version.source = "vcs" [tool.ruff] line-length = 121 src = [ "src", ] lint.extend-select = [ "A", "B", "C4", "C9", "I", "ISC", "PGH", "PLC", "PLE", "PLW", "RSE", "RUF012", "RUF100", "W", ] lint.isort = { known-first-party = [ "helpers", "package_info", "pipx", ] } lint.mccabe.max-complexity = 15 [tool.codespell] # Ref: https://github.com/codespell-project/codespell#using-a-config-file skip = '.git,*.pdf,*.svg,.nox,testdata,.mypy_cache' check-hidden = true # case sensitive etc ignore-regex = '\b(UE|path/doesnt/exist)\b' [tool.pytest.ini_options] markers = [ "all_packages: test install with maximum number of packages", ] [tool.towncrier] directory = "changelog.d" filename = "CHANGELOG.md" start_string = "\n" underlines = [ "", "", "", ] title_format = "## [{version}](https://github.com/pypa/pipx/tree/{version}) - {project_date}" issue_format = "[#{issue}](https://github.com/pypa/pipx/issues/{issue})" package = "pipx" [[tool.mypy.overrides]] module = [ "pycowsay.*", ] ignore_missing_imports = true pipx-1.6.0/scripts/000077500000000000000000000000001462701651400141735ustar00rootroot00000000000000pipx-1.6.0/scripts/gen_doc_pages.py000066400000000000000000000031171462701651400173240ustar00rootroot00000000000000import os import sys from pathlib import Path from subprocess import check_output from typing import Optional import mkdocs_gen_files from jinja2 import Environment, FileSystemLoader def get_help(cmd: Optional[str]) -> str: base = ["pipx"] args = base + ([cmd] if cmd else []) + ["--help"] env_patch = os.environ.copy() env_patch["PATH"] = os.pathsep.join([str(Path(sys.executable).parent)] + env_patch["PATH"].split(os.pathsep)) content = check_output(args, text=True, env=env_patch) content = content.replace(str(Path("~").expanduser()), "~") return f""" ``` {content} ``` """ params = { "install": get_help("install"), "installall": get_help("install-all"), "uninject": get_help("uninject"), "inject": get_help("inject"), "upgrade": get_help("upgrade"), "upgradeall": get_help("upgrade-all"), "upgradeshared": get_help("upgrade-shared"), "uninstall": get_help("uninstall"), "uninstallall": get_help("uninstall-all"), "reinstall": get_help("reinstall"), "reinstallall": get_help("reinstall-all"), "list": get_help("list"), "interpreter": get_help("interpreter"), "run": get_help("run"), "runpip": get_help("runpip"), "ensurepath": get_help("ensurepath"), "environment": get_help("environment"), "completions": get_help("completions"), "usage": get_help(None), } env = Environment(loader=FileSystemLoader(Path(__file__).parent / "templates")) with mkdocs_gen_files.open("docs.md", "wt") as file_handler: file_handler.write(env.get_template("docs.md").render(**params)) file_handler.write("\n") pipx-1.6.0/scripts/generate_man.py000077500000000000000000000020131462701651400171710ustar00rootroot00000000000000#!/usr/bin/env python3 import os.path import sys import textwrap from typing import cast from build_manpages.manpage import Manpage # type: ignore[import-not-found] from pipx.main import get_command_parser def main(): sys.argv[0] = "pipx" parser, _ = get_command_parser() parser.man_short_description = cast(str, parser.description).splitlines()[1] # type: ignore[attr-defined] manpage = Manpage(parser) body = str(manpage) # Avoid hardcoding build paths in manpages (and improve readability) body = body.replace(os.path.expanduser("~").replace("-", "\\-"), "~") # Add a credit section body += textwrap.dedent( """ .SH AUTHORS .IR pipx (1) was written by Chad Smith and contributors. The project can be found online at .UR https://pipx.pypa.io .UE .SH SEE ALSO .IR pip (1), .IR virtualenv (1) """ ) with open("pipx.1", "w") as f: f.write(body) if __name__ == "__main__": main() pipx-1.6.0/scripts/list_test_packages.py000077500000000000000000000123551462701651400204260ustar00rootroot00000000000000#!/usr/bin/env python3 import argparse import re import subprocess import sys import tempfile from concurrent.futures import ThreadPoolExecutor, as_completed from pathlib import Path from typing import Any, Dict, List, Set from test_packages_support import get_platform_list_path def process_command_line(argv: List[str]) -> argparse.Namespace: """Process command line invocation arguments and switches. Args: argv: list of arguments, or `None` from ``sys.argv[1:]``. Returns: argparse.Namespace: named attributes of arguments and switches """ # script_name = argv[0] argv = argv[1:] # initialize the parser object: parser = argparse.ArgumentParser( description="Create list of needed test packages for pipx tests and local pypiserver." ) # specifying nargs= puts outputs of parser in list (even if nargs=1) # required arguments parser.add_argument( "primary_package_list", help="Main packages to examine, getting list of matching distribution files and dependencies.", ) parser.add_argument("package_list_dir", help="Directory to output package distribution lists.") # switches/options: parser.add_argument("-v", "--verbose", action="store_true", help="Maximum verbosity, especially for pip operations.") return parser.parse_args(argv) def parse_package_list(package_list_file: Path) -> List[Dict[str, Any]]: output_list: List[Dict[str, Any]] = [] try: with package_list_file.open("r") as package_list_fh: for line in package_list_fh: line_parsed = re.sub(r"#.+$", "", line) if not re.search(r"\S", line_parsed): continue line_list = line_parsed.strip().split() if len(line_list) == 1: output_list.append({"spec": line_list[0]}) elif len(line_list) == 2: output_list.append({"spec": line_list[0], "no-deps": line_list[1].lower() == "true"}) else: print(f"ERROR: Unable to parse primary package list line:\n {line.strip()}") return [] except OSError: print("ERROR: File problem reading primary package list.") return [] return output_list def create_test_packages_list(package_list_dir_path: Path, primary_package_list_path: Path, verbose: bool) -> int: exit_code = 0 package_list_dir_path.mkdir(exist_ok=True) platform_package_list_path = get_platform_list_path(package_list_dir_path) primary_test_packages = parse_package_list(primary_package_list_path) if not primary_test_packages: print(f"ERROR: Problem reading {primary_package_list_path}. Exiting.", file=sys.stderr) return 1 with ThreadPoolExecutor(max_workers=12) as pool: futures = {pool.submit(download, pkg, verbose) for pkg in primary_test_packages} downloaded_list = set() for future in as_completed(futures): downloaded_list.update(future.result()) all_packages = [] for downloaded_path in downloaded_list: wheel_re = re.search(r"([^-]+)-([^-]+)-([^-]+)\-([^-]+)-([^-]+)(-[^-]+)?\.whl$", downloaded_path) src_re = re.search(r"(.+)-([^-]+)\.(?:tar.gz|zip)$", downloaded_path) if wheel_re: package_name = wheel_re.group(1) package_version = wheel_re.group(2) elif src_re: package_name = src_re.group(1) package_version = src_re.group(2) else: print(f"ERROR: cannot parse: {downloaded_path}", file=sys.stderr) continue all_packages.append(f"{package_name}=={package_version}") with platform_package_list_path.open("w") as package_list_fh: for package in sorted(all_packages): print(package, file=package_list_fh) return exit_code def download(test_package: Dict[str, str], verbose: bool) -> Set[str]: no_deps = test_package.get("no-deps", False) test_package_option_string = " (no-deps)" if no_deps else "" verbose_this_iteration = False with tempfile.TemporaryDirectory() as download_dir: cmd_list = ["pip", "download"] + (["--no-deps"] if no_deps else []) + [test_package["spec"], "-d", download_dir] if verbose: print(f"CMD: {' '.join(cmd_list)}") pip_download_process = subprocess.run(cmd_list, capture_output=True, text=True, check=False) if pip_download_process.returncode == 0: print(f"Examined {test_package['spec']}{test_package_option_string}") else: print(f"ERROR with {test_package['spec']}{test_package_option_string}", file=sys.stderr) verbose_this_iteration = True if verbose or verbose_this_iteration: print(pip_download_process.stdout) print(pip_download_process.stderr) return {i.name for i in Path(download_dir).iterdir()} def main(argv: List[str]) -> int: args = process_command_line(argv) return create_test_packages_list(Path(args.package_list_dir), Path(args.primary_package_list), args.verbose) if __name__ == "__main__": try: status = main(sys.argv) except KeyboardInterrupt: print("Stopped by Keyboard Interrupt", file=sys.stderr) status = 130 sys.exit(status) pipx-1.6.0/scripts/migrate_pipsi_to_pipx.py000077500000000000000000000035471462701651400211570ustar00rootroot00000000000000#!/usr/bin/env python3 """ Script to migrate from pipsi to pipx """ import os import subprocess import sys from pathlib import Path from shutil import which def main(): if not which("pipx"): sys.exit("pipx must be installed to migrate from pipsi to pipx") if not sys.stdout.isatty(): sys.exit("Must be run from a terminal, not a script") pipsi_home = os.environ.get("PIPSI_HOME", os.path.expanduser("~/.local/venvs/")) packages = [p.name for p in Path(pipsi_home).iterdir()] if not packages: print("No packages installed with pipsi") sys.exit(0) print("Attempting to migrate the following packages from pipsi to pipx:") for package in packages: print(f" - {package}") answer = None while answer not in ["y", "n"]: answer = input("Continue? [y/n] ") if answer == "n": sys.exit(0) error = False for package in packages: ret = subprocess.run(["pipsi", "uninstall", "--yes", package], check=False) if ret.returncode: error = True print(f"Failed to uninstall {package!r} with pipsi. Not attempting to install with pipx.") else: print(f"uninstalled {package!r} with pipsi. Now attempting to install with pipx.") ret = subprocess.run(["pipx", "install", package], check=False) if ret.returncode: error = True print(f"Failed to install {package!r} with pipx.") else: print(f"Successfully installed {package} with pipx") print(f"Done migrating {len(packages)} packages!") print("You may still need to run `pipsi uninstall pipsi` or `pip uninstall pipsi`. Refer to pipsi's documentation.") if error: print("Note: Finished with errors. Review output to manually complete migration.") if __name__ == "__main__": main() pipx-1.6.0/scripts/templates/000077500000000000000000000000001462701651400161715ustar00rootroot00000000000000pipx-1.6.0/scripts/templates/docs.md000066400000000000000000000011771462701651400174510ustar00rootroot00000000000000{{usage}} ### pipx install {{install}} ### pipx install-all {{installall}} ### pipx uninject {{uninject}} ### pipx inject {{inject}} ### pipx upgrade {{upgrade}} ### pipx upgrade-all {{upgradeall}} ### pipx upgrade-shared {{upgradeshared}} ### pipx uninstall {{uninstall}} ### pipx uninstall-all {{uninstallall}} ### pipx reinstall {{reinstall}} ### pipx reinstall-all {{reinstallall}} ### pipx list {{list}} ### pipx interpreter {{interpreter}} ### pipx run {{run}} ### pipx runpip {{runpip}} ### pipx ensurepath {{ensurepath}} ### pipx environment {{environment}} ### pipx completions {{completions}} pipx-1.6.0/scripts/test_packages_support.py000066400000000000000000000011421462701651400211540ustar00rootroot00000000000000import platform import sys from pathlib import Path PYTHON_VERSION_STR = f"{sys.version_info[0]}.{sys.version_info[1]}" # Platform logic if sys.platform == "darwin": FULL_PLATFORM = "macos" + platform.release().split(".")[0] elif sys.platform == "win32": FULL_PLATFORM = "win" else: FULL_PLATFORM = "unix" def get_platform_list_path(package_list_dir_path: Path) -> Path: return package_list_dir_path / f"{FULL_PLATFORM}-python{PYTHON_VERSION_STR}.txt" def get_platform_packages_dir_path(pipx_package_cache_path: Path) -> Path: return pipx_package_cache_path / f"{PYTHON_VERSION_STR}" pipx-1.6.0/scripts/update_package_cache.py000077500000000000000000000145601462701651400206360ustar00rootroot00000000000000#!/usr/bin/env python3 import argparse import re import subprocess import sys from concurrent.futures import ThreadPoolExecutor, as_completed from pathlib import Path from typing import List from list_test_packages import create_test_packages_list from test_packages_support import get_platform_list_path, get_platform_packages_dir_path def process_command_line(argv: List[str]) -> argparse.Namespace: """Process command line invocation arguments and switches. Args: argv: list of arguments, or `None` from ``sys.argv[1:]``. Returns: argparse.Namespace: named attributes of arguments and switches """ # script_name = argv[0] argv = argv[1:] # initialize the parser object: parser = argparse.ArgumentParser( description="Check and update as needed the pipx tests package cache " "for use with the pipx tests local pypiserver." ) # specifying nargs= puts outputs of parser in list (even if nargs=1) # required arguments parser.add_argument( "package_list_dir", help="Directory where platform- and python-specific package lists are found for pipx tests.", ) parser.add_argument( "pipx_package_cache_dir", help="Directory to store the packages distribution files.", ) # switches/options: parser.add_argument( "-c", "--check-only", action="store_true", help="Only check to see if needed packages are in PACKAGES_DIR, do not download or delete files.", ) return parser.parse_args(argv) def update_test_packages_cache(package_list_dir_path: Path, pipx_package_cache_path: Path, check_only: bool) -> int: exit_code = 0 platform_package_list_path = get_platform_list_path(package_list_dir_path) packages_dir_path = get_platform_packages_dir_path(pipx_package_cache_path) packages_dir_path.mkdir(exist_ok=True, parents=True) packages_dir_files = list(packages_dir_path.iterdir()) if not platform_package_list_path.exists(): print( f"WARNING. File {platform_package_list_path!s}\n does not exist. Creating now...", file=sys.stderr, ) create_list_returncode = create_test_packages_list( package_list_dir_path, package_list_dir_path / "primary_packages.txt", verbose=False, ) if create_list_returncode == 0: print( f"File {platform_package_list_path!s}\n" " successfully created. Please check this file in to the" " repository for future use.", file=sys.stderr, ) else: print( f"ERROR. Unable to create {platform_package_list_path!s}\n Cannot continue.\n", file=sys.stderr, ) return 1 try: platform_package_list_fh = platform_package_list_path.open("r") except OSError: print( f"ERROR. File {platform_package_list_path!s}\n is not readable. Cannot continue.\n", file=sys.stderr, ) return 1 else: platform_package_list_fh.close() print("Using the following file to specify needed package files:") print(f" {platform_package_list_path!s}") print("Ensuring the following directory contains necessary package files:") print(f" {packages_dir_path!s}") packages_dir_hits = [] packages_dir_missing = [] with platform_package_list_path.open("r") as platform_package_list_fh: for line in platform_package_list_fh: package_spec = line.strip() package_spec_re = re.search(r"^(.+)==(.+)$", package_spec) if not package_spec_re: print(f"ERROR: CANNOT PARSE {package_spec}", file=sys.stderr) exit_code = 1 continue package_name = package_spec_re.group(1) package_ver = package_spec_re.group(2) package_dist_patt = re.escape(package_name) + r"-" + re.escape(package_ver) + r"(.tar.gz|.zip|-)" matches = [ output_dir_file for output_dir_file in packages_dir_files if re.search(package_dist_patt, output_dir_file.name) ] if len(matches) == 1: packages_dir_files.remove(matches[0]) packages_dir_hits.append(matches[0]) continue elif len(matches) > 1: print(f"ERROR: more than one match for {package_spec}.", file=sys.stderr) print(f" {matches}", file=sys.stderr) exit_code = 1 continue packages_dir_missing.append(package_spec) print(f"MISSING FILES: {len(packages_dir_missing)}") print(f"EXISTING (found) FILES: {len(packages_dir_hits)}") print(f"LEFTOVER (unused) FILES: {len(packages_dir_files)}") if check_only: return 0 if len(packages_dir_missing) == 0 else 1 else: with ThreadPoolExecutor(max_workers=12) as pool: futures = {pool.submit(download, pkg, packages_dir_path) for pkg in packages_dir_missing} for future in as_completed(futures): exit_code = future.result() or exit_code for unused_file in packages_dir_files: print(f"Deleting {unused_file}...") unused_file.unlink() return exit_code def download(package_spec: str, packages_dir_path: Path) -> int: pip_download_process = subprocess.run( [ "pip", "download", "--no-deps", package_spec, "-d", str(packages_dir_path), ], capture_output=True, text=True, check=False, ) if pip_download_process.returncode == 0: print(f"Successfully downloaded {package_spec}") return 0 print(f"ERROR downloading {package_spec}", file=sys.stderr) print(pip_download_process.stdout, file=sys.stderr) print(pip_download_process.stderr, file=sys.stderr) return 1 def main(argv: List[str]) -> int: args = process_command_line(argv) return update_test_packages_cache(Path(args.package_list_dir), Path(args.pipx_package_cache_dir), args.check_only) if __name__ == "__main__": try: status = main(sys.argv) except KeyboardInterrupt: print("Stopped by Keyboard Interrupt", file=sys.stderr) status = 130 sys.exit(status) pipx-1.6.0/src/000077500000000000000000000000001462701651400132735ustar00rootroot00000000000000pipx-1.6.0/src/pipx/000077500000000000000000000000001462701651400142535ustar00rootroot00000000000000pipx-1.6.0/src/pipx/__init__.py000066400000000000000000000002361462701651400163650ustar00rootroot00000000000000import sys if sys.version_info < (3, 8, 0): sys.exit("Python 3.8 or later is required. See https://github.com/pypa/pipx for installation instructions.") pipx-1.6.0/src/pipx/__main__.py000066400000000000000000000005771462701651400163560ustar00rootroot00000000000000import os import sys if not __package__: # Running from source. Add pipx's source code to the system # path to allow direct invocation, such as: # python src/pipx --help pipx_package_source_path = os.path.dirname(os.path.dirname(__file__)) sys.path.insert(0, pipx_package_source_path) from pipx.main import cli if __name__ == "__main__": sys.exit(cli()) pipx-1.6.0/src/pipx/animate.py000066400000000000000000000071621462701651400162510ustar00rootroot00000000000000import shutil import sys from contextlib import contextmanager from threading import Event, Thread from typing import Generator, List from pipx.constants import WINDOWS from pipx.emojis import EMOJI_SUPPORT stderr_is_tty = sys.stderr.isatty() CLEAR_LINE = "\033[K" EMOJI_ANIMATION_FRAMES = ["⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾"] NONEMOJI_ANIMATION_FRAMES = ["", ".", "..", "..."] EMOJI_FRAME_PERIOD = 0.1 NONEMOJI_FRAME_PERIOD = 1 MINIMUM_COLS_ALLOW_ANIMATION = 16 if WINDOWS: import ctypes class _CursorInfo(ctypes.Structure): _fields_ = (("size", ctypes.c_int), ("visible", ctypes.c_byte)) def _env_supports_animation() -> bool: (term_cols, _) = shutil.get_terminal_size(fallback=(0, 0)) return stderr_is_tty and term_cols > MINIMUM_COLS_ALLOW_ANIMATION @contextmanager def animate(message: str, do_animation: bool, *, delay: float = 0) -> Generator[None, None, None]: if not do_animation or not _env_supports_animation(): # No animation, just a single print of message sys.stderr.write(f"{message}...\n") yield return event = Event() if EMOJI_SUPPORT: animate_at_beginning_of_line = True symbols = EMOJI_ANIMATION_FRAMES period = EMOJI_FRAME_PERIOD else: animate_at_beginning_of_line = False symbols = NONEMOJI_ANIMATION_FRAMES period = NONEMOJI_FRAME_PERIOD thread_kwargs = { "message": message, "event": event, "symbols": symbols, "delay": delay, "period": period, "animate_at_beginning_of_line": animate_at_beginning_of_line, } t = Thread(target=print_animation, kwargs=thread_kwargs) t.start() try: yield finally: event.set() clear_line() def print_animation( *, message: str, event: Event, symbols: List[str], delay: float, period: float, animate_at_beginning_of_line: bool, ) -> None: (term_cols, _) = shutil.get_terminal_size(fallback=(9999, 24)) event.wait(delay) while not event.wait(0): for s in symbols: if animate_at_beginning_of_line: max_message_len = term_cols - len(f"{s} ... ") cur_line = f"{s} {message:.{max_message_len}}" if len(message) > max_message_len: cur_line += "..." else: max_message_len = term_cols - len("... ") cur_line = f"{message:.{max_message_len}}{s}" clear_line() sys.stderr.write(cur_line) sys.stderr.flush() if event.wait(period): break # for Windows pre-ANSI-terminal-support (before Windows 10 TH2 (v1511)) # https://stackoverflow.com/a/10455937 def win_cursor(visible: bool) -> None: if sys.platform != "win32": # hello mypy return ci = _CursorInfo() handle = ctypes.windll.kernel32.GetStdHandle(-11) ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci)) ci.visible = visible ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci)) def hide_cursor() -> None: if stderr_is_tty: if WINDOWS: win_cursor(visible=False) else: sys.stderr.write("\033[?25l") sys.stderr.flush() def show_cursor() -> None: if stderr_is_tty: if WINDOWS: win_cursor(visible=True) else: sys.stderr.write("\033[?25h") sys.stderr.flush() def clear_line() -> None: """Clears current line and positions cursor at start of line""" sys.stderr.write(f"\r{CLEAR_LINE}") sys.stdout.write(f"\r{CLEAR_LINE}") pipx-1.6.0/src/pipx/colors.py000066400000000000000000000014711462701651400161310ustar00rootroot00000000000000import sys from typing import Callable try: import colorama # type: ignore[import-untyped] except ImportError: # Colorama is Windows only package colorama = None PRINT_COLOR = sys.stdout.isatty() if PRINT_COLOR and colorama: colorama.init() 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: str) -> Callable[[str], str]: def stylize_text(x: str) -> str: if PRINT_COLOR: return f"{style}{x}{c.end}" else: return x return stylize_text bold = mkcolorfunc(c.bold) red = mkcolorfunc(c.red) blue = mkcolorfunc(c.cyan) cyan = mkcolorfunc(c.blue) green = mkcolorfunc(c.green) pipx-1.6.0/src/pipx/commands/000077500000000000000000000000001462701651400160545ustar00rootroot00000000000000pipx-1.6.0/src/pipx/commands/__init__.py000066400000000000000000000021301462701651400201610ustar00rootroot00000000000000from pipx.commands.ensure_path import ensure_pipx_paths from pipx.commands.environment import environment from pipx.commands.inject import inject from pipx.commands.install import install, install_all from pipx.commands.interpreter import list_interpreters, prune_interpreters, upgrade_interpreters from pipx.commands.list_packages import list_packages from pipx.commands.pin import pin, unpin from pipx.commands.reinstall import reinstall, reinstall_all from pipx.commands.run import run from pipx.commands.run_pip import run_pip from pipx.commands.uninject import uninject from pipx.commands.uninstall import uninstall, uninstall_all from pipx.commands.upgrade import upgrade, upgrade_all, upgrade_shared __all__ = [ "upgrade", "upgrade_all", "upgrade_shared", "run", "install", "install_all", "inject", "uninject", "uninstall", "uninstall_all", "reinstall", "reinstall_all", "list_packages", "run_pip", "ensure_pipx_paths", "environment", "list_interpreters", "prune_interpreters", "pin", "unpin", "upgrade_interpreters", ] pipx-1.6.0/src/pipx/commands/common.py000066400000000000000000000414061462701651400177230ustar00rootroot00000000000000import logging import os import shlex import shutil import sys import tempfile import time from pathlib import Path from shutil import which from tempfile import TemporaryDirectory from typing import Dict, List, Optional, Set, Tuple import userpath # type: ignore[import-not-found] from packaging.utils import canonicalize_name from pipx import paths from pipx.colors import bold, red from pipx.constants import MAN_SECTIONS, WINDOWS from pipx.emojis import hazard, stars from pipx.package_specifier import parse_specifier_for_install, valid_pypi_name from pipx.pipx_metadata_file import PackageInfo from pipx.util import PipxError, mkdir, pipx_wrap, rmdir, safe_unlink from pipx.venv import Venv logger = logging.getLogger(__name__) class VenvProblems: def __init__( self, bad_venv_name: bool = False, invalid_interpreter: bool = False, missing_metadata: bool = False, not_installed: bool = False, ) -> None: self.bad_venv_name = bad_venv_name self.invalid_interpreter = invalid_interpreter self.missing_metadata = missing_metadata self.not_installed = not_installed def any_(self) -> bool: return any(self.__dict__.values()) def or_(self, venv_problems: "VenvProblems") -> None: for attribute in self.__dict__: setattr( self, attribute, getattr(self, attribute) or getattr(venv_problems, attribute), ) def expose_resources_globally( resource_type: str, local_resource_dir: Path, paths: List[Path], *, force: bool, suffix: str = "", ) -> None: for path in paths: src = path.resolve() if resource_type == "man": dest_dir = local_resource_dir / src.parent.name else: dest_dir = local_resource_dir if not dest_dir.is_dir(): mkdir(dest_dir) if not can_symlink(dest_dir): _copy_package_resource(dest_dir, path, suffix=suffix) else: _symlink_package_resource( dest_dir, path, force=force, suffix=suffix, executable=(resource_type == "app"), ) _can_symlink_cache: Dict[Path, bool] = {} def can_symlink(local_resource_dir: Path) -> bool: if not WINDOWS: # Technically, even on Unix this depends on the filesystem return True if local_resource_dir not in _can_symlink_cache: with TemporaryDirectory(dir=local_resource_dir) as d: p = Path(d) target = p / "a" target.touch() lnk = p / "b" try: lnk.symlink_to(target) _can_symlink_cache[local_resource_dir] = True except (OSError, NotImplementedError): _can_symlink_cache[local_resource_dir] = False return _can_symlink_cache[local_resource_dir] def _copy_package_resource(dest_dir: Path, path: Path, suffix: str = "") -> None: src = path.resolve() name = src.name dest = Path(dest_dir / add_suffix(name, suffix)) if not dest.parent.is_dir(): mkdir(dest.parent) if dest.exists(): logger.warning(f"{hazard} Overwriting file {dest!s} with {src!s}") safe_unlink(dest) if src.exists(): shutil.copy(src, dest) def _symlink_package_resource( dest_dir: Path, path: Path, *, force: bool, suffix: str = "", executable: bool = False, ) -> None: name_suffixed = add_suffix(path.name, suffix) symlink_path = Path(dest_dir / name_suffixed) if not symlink_path.parent.is_dir(): mkdir(symlink_path.parent) if force: logger.info(f"Force is true. Removing {symlink_path!s}.") try: symlink_path.unlink() except FileNotFoundError: pass except IsADirectoryError: rmdir(symlink_path) exists = symlink_path.exists() is_symlink = symlink_path.is_symlink() if exists: if symlink_path.samefile(path): logger.info(f"Same path {symlink_path!s} and {path!s}") else: logger.warning( pipx_wrap( f""" {hazard} File exists at {symlink_path!s} and points to {symlink_path.resolve()}, not {path!s}. Not modifying. """, subsequent_indent=" " * 4, ) ) return if is_symlink and not exists: logger.info(f"Removing existing symlink {symlink_path!s} since it pointed non-existent location") symlink_path.unlink() if executable: existing_executable_on_path = which(name_suffixed) else: existing_executable_on_path = None symlink_path.symlink_to(path) if executable and existing_executable_on_path: logger.warning( pipx_wrap( f""" {hazard} Note: {name_suffixed} was already on your PATH at {existing_executable_on_path} """, subsequent_indent=" " * 4, ) ) def venv_health_check(venv: Venv, package_name: Optional[str] = None) -> Tuple[VenvProblems, str]: venv_dir = venv.root python_path = venv.python_path.resolve() if package_name is None: package_name = venv.main_package_name if not python_path.is_file(): return ( VenvProblems(invalid_interpreter=True), f" package {red(bold(venv_dir.name))} has invalid interpreter {python_path!s}\r{hazard}", ) if not venv.package_metadata: return ( VenvProblems(missing_metadata=True), f" package {red(bold(venv_dir.name))} has missing internal pipx metadata.\r{hazard}", ) if venv_dir.name != canonicalize_name(venv_dir.name): return ( VenvProblems(bad_venv_name=True), f" package {red(bold(venv_dir.name))} needs its internal data updated.\r{hazard}", ) if venv.package_metadata[package_name].package_version == "": return ( VenvProblems(not_installed=True), f" package {red(bold(package_name))} {red('is not installed')} in the venv {venv_dir.name}\r{hazard}", ) return (VenvProblems(), "") def get_venv_summary( venv_dir: Path, *, package_name: Optional[str] = None, new_install: bool = False, include_injected: bool = False, ) -> Tuple[str, VenvProblems]: venv = Venv(venv_dir) if package_name is None: package_name = venv.main_package_name (venv_problems, warning_message) = venv_health_check(venv, package_name) if venv_problems.any_(): return (warning_message, venv_problems) package_metadata = venv.package_metadata[package_name] apps = package_metadata.apps man_pages = package_metadata.man_pages if package_metadata.include_dependencies: apps += package_metadata.apps_of_dependencies man_pages += package_metadata.man_pages_of_dependencies exposed_app_paths = get_exposed_paths_for_package( venv.bin_path, paths.ctx.bin_dir, [add_suffix(app, package_metadata.suffix) for app in apps], ) exposed_binary_names = sorted(p.name for p in exposed_app_paths) unavailable_binary_names = sorted( {add_suffix(name, package_metadata.suffix) for name in package_metadata.apps} - set(exposed_binary_names) ) exposed_man_paths = set() for man_section in MAN_SECTIONS: exposed_man_paths |= get_exposed_man_paths_for_package( venv.man_path / man_section, paths.ctx.man_dir / man_section, man_pages, ) exposed_man_pages = sorted(str(Path(p.parent.name) / p.name) for p in exposed_man_paths) unavailable_man_pages = sorted(set(package_metadata.man_pages) - set(exposed_man_pages)) # The following is to satisfy mypy that python_version is str and not # Optional[str] python_version = venv.pipx_metadata.python_version if venv.pipx_metadata.python_version is not None else "" source_interpreter = venv.pipx_metadata.source_interpreter is_standalone = ( str(source_interpreter).startswith(str(paths.ctx.standalone_python_cachedir.resolve())) if source_interpreter else False ) return ( _get_list_output( python_version, is_standalone, package_metadata.package_version, package_name, new_install, exposed_binary_names, unavailable_binary_names, exposed_man_pages, unavailable_man_pages, venv.pipx_metadata.injected_packages if include_injected else None, suffix=package_metadata.suffix, ), venv_problems, ) def get_exposed_paths_for_package( venv_resource_path: Path, local_resource_dir: Path, package_resource_names: Optional[List[str]] = None, ) -> Set[Path]: # package_binary_names is used only if local_bin_path cannot use symlinks. # It is necessary for non-symlink systems to return valid app_paths. if package_resource_names is None: package_resource_names = [] if not local_resource_dir.exists(): return set() symlinks = set() for b in local_resource_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. # We always use the stricter check on non-Windows systems. On # Windows, we use a less strict check if we don't have a symlink. is_same_file = False if can_symlink(local_resource_dir) and b.is_symlink(): is_same_file = b.resolve().parent.samefile(venv_resource_path) elif not can_symlink(local_resource_dir): is_same_file = b.name in package_resource_names if is_same_file: symlinks.add(b) except FileNotFoundError: pass return symlinks def get_exposed_man_paths_for_package( venv_man_path: Path, local_man_dir: Path, package_man_pages: Optional[List[str]] = None, ) -> Set[Path]: man_section = venv_man_path.name prefix = man_section + os.sep return get_exposed_paths_for_package( venv_man_path, local_man_dir, [ (name[len(prefix) :] if name.startswith(prefix) else name) for name in package_man_pages or [] if name.startswith(prefix) ], ) def _get_list_output( python_version: str, python_is_standalone: bool, package_version: str, package_name: str, new_install: bool, exposed_binary_names: List[str], unavailable_binary_names: List[str], exposed_man_pages: List[str], unavailable_man_pages: List[str], injected_packages: Optional[Dict[str, PackageInfo]] = None, suffix: str = "", ) -> str: output = [] suffix = f" ({bold(shlex.quote(package_name + suffix))})" if suffix else "" output.append( f" {'installed' if new_install else ''} package {bold(shlex.quote(package_name))}" f" {bold(package_version)}{suffix}, installed using {python_version}" + (" (standalone)" if python_is_standalone else "") ) if new_install and (exposed_binary_names or unavailable_binary_names): output.append(" These apps are now globally available") output.extend(f" - {name}" for name in exposed_binary_names) output.extend( f" - {red(name)} (symlink missing or pointing to unexpected location)" for name in unavailable_binary_names ) if new_install and (exposed_man_pages or unavailable_man_pages): output.append(" These manual pages are now globally available") output.extend(f" - {name}" for name in exposed_man_pages) output.extend( f" - {red(name)} (symlink missing or pointing to unexpected location)" for name in unavailable_man_pages ) if injected_packages: output.append(" Injected Packages:") output.extend(f" - {name} {injected_packages[name].package_version}" for name in injected_packages) return "\n".join(output) def package_name_from_spec(package_spec: str, python: str, *, pip_args: List[str], verbose: bool) -> str: start_time = time.time() # shortcut if valid PyPI name pypi_name = valid_pypi_name(package_spec) if pypi_name is not None: # NOTE: if pypi name and installed package name differ, this means pipx # will use the pypi name package_name = pypi_name logger.info(f"Determined package name: {package_name}") logger.info(f"Package name determined in {time.time()-start_time:.1f}s") return package_name # check syntax and clean up spec and pip_args (package_spec, pip_args) = parse_specifier_for_install(package_spec, pip_args) with tempfile.TemporaryDirectory() as temp_venv_dir: venv = Venv(Path(temp_venv_dir), python=python, verbose=verbose) venv.create_venv(venv_args=[], pip_args=[]) package_name = venv.install_package_no_deps(package_or_url=package_spec, pip_args=pip_args) logger.info(f"Package name determined in {time.time()-start_time:.1f}s") return package_name def run_post_install_actions( venv: Venv, package_name: str, local_bin_dir: Path, local_man_dir: Path, venv_dir: Path, include_dependencies: bool, *, force: bool, ) -> None: package_metadata = venv.package_metadata[package_name] display_name = f"{package_name}{package_metadata.suffix}" if ( not venv.main_package_name == package_name and venv.package_metadata[venv.main_package_name].suffix == package_metadata.suffix ): package_name = display_name if not package_metadata.apps: if not package_metadata.apps_of_dependencies: if venv.safe_to_remove(): venv.remove_venv() raise PipxError( f""" No apps associated with package {display_name} or its dependencies. If you are attempting to install a library, pipx should not be used. Consider using pip or a similar tool instead. """ ) if package_metadata.apps_of_dependencies and not include_dependencies: for ( dep, dependent_apps, ) in package_metadata.app_paths_of_dependencies.items(): print(f"Note: Dependent package '{dep}' contains {len(dependent_apps)} apps") for app in dependent_apps: print(f" - {app.name}") if venv.safe_to_remove(): venv.remove_venv() raise PipxError( f""" No apps associated with package {display_name}. Try again with '--include-deps' to include apps of dependent packages, which are listed above. If you are attempting to install a library, pipx should not be used. Consider using pip or a similar tool instead. """ ) expose_resources_globally( "app", local_bin_dir, package_metadata.app_paths, force=force, suffix=package_metadata.suffix, ) expose_resources_globally("man", local_man_dir, package_metadata.man_paths, force=force) if include_dependencies: for _, app_paths in package_metadata.app_paths_of_dependencies.items(): expose_resources_globally( "app", local_bin_dir, app_paths, force=force, suffix=package_metadata.suffix, ) for _, man_paths in package_metadata.man_paths_of_dependencies.items(): expose_resources_globally("man", local_man_dir, man_paths, force=force) package_summary, _ = get_venv_summary(venv_dir, package_name=package_name, new_install=True) print(package_summary) warn_if_not_on_path(local_bin_dir) print(f"done! {stars}", file=sys.stderr) def warn_if_not_on_path(local_bin_dir: Path) -> None: if not userpath.in_current_path(str(local_bin_dir)): logger.warning( pipx_wrap( f""" {hazard} Note: '{local_bin_dir}' is not on your PATH environment variable. These apps 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 (e.g. ~/.bashrc). """, subsequent_indent=" " * 4, ) ) def add_suffix(name: str, suffix: str) -> str: """Add suffix to app.""" app = Path(name) return f"{app.stem}{suffix}{app.suffix}" pipx-1.6.0/src/pipx/commands/ensure_path.py000066400000000000000000000115031462701651400207430ustar00rootroot00000000000000import logging import site import sys from pathlib import Path from typing import Optional, Tuple import userpath # type: ignore[import-not-found] from pipx import paths from pipx.constants import EXIT_CODE_OK, ExitCode from pipx.emojis import hazard, stars from pipx.util import pipx_wrap logger = logging.getLogger(__name__) def get_pipx_user_bin_path() -> Optional[Path]: """Returns None if pipx is not installed using `pip --user` Otherwise returns parent dir of pipx binary """ # NOTE: using this method to detect pip user-installed pipx will return # None if pipx was installed as editable using `pip install --user -e` # https://docs.python.org/3/install/index.html#inst-alt-install-user # Linux + Mac: # scripts in /bin # Windows: # scripts in /Python/Scripts # modules in /Python/site-packages pipx_bin_path = None script_path = Path(__file__).resolve() userbase_path = Path(site.getuserbase()).resolve() try: _ = script_path.relative_to(userbase_path) except ValueError: pip_user_installed = False else: pip_user_installed = True if pip_user_installed: test_paths = ( userbase_path / "bin" / "pipx", Path(site.getusersitepackages()).resolve().parent / "Scripts" / "pipx.exe", ) for test_path in test_paths: if test_path.exists(): pipx_bin_path = test_path.parent break return pipx_bin_path def ensure_path(location: Path, *, force: bool) -> Tuple[bool, bool]: """Ensure location is in user's PATH or add it to PATH. Returns True if location was added to PATH """ location_str = str(location) path_added = False need_shell_restart = userpath.need_shell_restart(location_str) in_current_path = userpath.in_current_path(location_str) if force or (not in_current_path and not need_shell_restart): path_added = userpath.append(location_str, "pipx") if not path_added: print( pipx_wrap( f"{hazard} {location_str} is not added to the PATH environment variable successfully. " f"You may need to add it to PATH manually.", subsequent_indent=" " * 4, ) ) else: print( pipx_wrap( f"Success! Added {location_str} to the PATH environment variable.", subsequent_indent=" " * 4, ) ) need_shell_restart = userpath.need_shell_restart(location_str) elif not in_current_path and need_shell_restart: print( pipx_wrap( f""" {location_str} has been been added to PATH, but you need to open a new terminal or re-login for this PATH change to take effect. Alternatively, you can source your shell's config file with e.g. 'source ~/.bashrc'. """, subsequent_indent=" " * 4, ) ) else: print(pipx_wrap(f"{location_str} is already in PATH.", subsequent_indent=" " * 4)) return (path_added, need_shell_restart) def ensure_pipx_paths(force: bool) -> ExitCode: """Returns pipx exit code.""" bin_paths = {paths.ctx.bin_dir} pipx_user_bin_path = get_pipx_user_bin_path() if pipx_user_bin_path is not None: bin_paths.add(pipx_user_bin_path) path_added = False need_shell_restart = False for bin_path in bin_paths: (path_added_current, need_shell_restart_current) = ensure_path(bin_path, force=force) path_added |= path_added_current need_shell_restart |= need_shell_restart_current print() if path_added: print( pipx_wrap( """ Consider adding shell completions for pipx. Run 'pipx completions' for instructions. """ ) + "\n" ) elif not need_shell_restart: sys.stdout.flush() logger.warning( pipx_wrap( f""" {hazard} All pipx binary directories have been added to PATH. If you are sure you want to proceed, try again with the '--force' flag. """ ) + "\n" ) if need_shell_restart: print( pipx_wrap( """ You will need to open a new terminal or re-login for the PATH changes to take effect. Alternatively, you can source your shell's config file with e.g. 'source ~/.bashrc'. """ ) + "\n" ) print(f"Otherwise pipx is ready to go! {stars}") return EXIT_CODE_OK pipx-1.6.0/src/pipx/commands/environment.py000066400000000000000000000032351462701651400207750ustar00rootroot00000000000000import os from pipx import paths from pipx.constants import EXIT_CODE_OK, ExitCode from pipx.emojis import EMOJI_SUPPORT from pipx.interpreter import DEFAULT_PYTHON from pipx.util import PipxError def environment(value: str) -> ExitCode: """Print a list of environment variables and paths used by pipx""" environment_variables = [ "PIPX_HOME", "PIPX_BIN_DIR", "PIPX_MAN_DIR", "PIPX_SHARED_LIBS", "PIPX_DEFAULT_PYTHON", "PIPX_FETCH_MISSING_PYTHON", "USE_EMOJI", ] derived_values = { "PIPX_HOME": paths.ctx.home, "PIPX_BIN_DIR": paths.ctx.bin_dir, "PIPX_MAN_DIR": paths.ctx.man_dir, "PIPX_SHARED_LIBS": paths.ctx.shared_libs, "PIPX_LOCAL_VENVS": paths.ctx.venvs, "PIPX_LOG_DIR": paths.ctx.logs, "PIPX_TRASH_DIR": paths.ctx.trash, "PIPX_VENV_CACHEDIR": paths.ctx.venv_cache, "PIPX_STANDALONE_PYTHON_CACHEDIR": paths.ctx.standalone_python_cachedir, "PIPX_DEFAULT_PYTHON": DEFAULT_PYTHON, "USE_EMOJI": str(EMOJI_SUPPORT).lower(), } if value is None: print("Environment variables (set by user):") print("") for env_variable in environment_variables: env_value = os.getenv(env_variable, "") print(f"{env_variable}={env_value}") print("") print("Derived values (computed by pipx):") print("") for env_variable in derived_values: print(f"{env_variable}={derived_values[env_variable]}") elif value in derived_values: print(derived_values[value]) else: raise PipxError("Variable not found.") return EXIT_CODE_OK pipx-1.6.0/src/pipx/commands/inject.py000066400000000000000000000121671462701651400177110ustar00rootroot00000000000000import logging import os import re import sys from pathlib import Path from typing import Generator, Iterable, List, Optional, Union from pipx import paths from pipx.colors import bold from pipx.commands.common import package_name_from_spec, run_post_install_actions from pipx.constants import EXIT_CODE_INJECT_ERROR, EXIT_CODE_OK, ExitCode from pipx.emojis import hazard, stars from pipx.util import PipxError, pipx_wrap from pipx.venv import Venv logger = logging.getLogger(__name__) COMMENT_RE = re.compile(r"(^|\s+)#.*$") def inject_dep( venv_dir: Path, package_name: Optional[str], package_spec: str, pip_args: List[str], *, verbose: bool, include_apps: bool, include_dependencies: bool, force: bool, suffix: bool = False, ) -> bool: logger.debug("Injecting package %s", package_spec) if not venv_dir.exists() or not next(venv_dir.iterdir()): raise PipxError( f""" Can't inject {package_spec!r} into nonexistent Virtual Environment {venv_dir.name!r}. Be sure to install the package first with 'pipx install {venv_dir.name}' before injecting into it. """ ) venv = Venv(venv_dir, verbose=verbose) venv.check_upgrade_shared_libs(pip_args=pip_args, verbose=verbose) if not venv.package_metadata: raise PipxError( f""" Can't inject {package_spec!r} into Virtual Environment {venv.name!r}. {venv.name!r} has missing internal pipx metadata. It was likely installed using a pipx version before 0.15.0.0. Please uninstall and install {venv.name!r}, or reinstall-all to fix. """ ) # package_spec is anything pip-installable, including package_name, vcs spec, # zip file, or tar.gz file. if package_name is None: package_name = package_name_from_spec( package_spec, os.fspath(venv.python_path), pip_args=pip_args, verbose=verbose, ) if not force and venv.has_package(package_name): logger.info("Package %s has already been injected", package_name) print( pipx_wrap( f""" {hazard} {package_name} already seems to be injected in {venv.name!r}. Not modifying existing installation in '{venv_dir}'. Pass '--force' to force installation. """ ) ) return True if suffix: venv_suffix = venv.package_metadata[venv.main_package_name].suffix else: venv_suffix = "" venv.install_package( package_name=package_name, package_or_url=package_spec, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=False, suffix=venv_suffix, ) if include_apps: run_post_install_actions( venv, package_name, paths.ctx.bin_dir, paths.ctx.man_dir, venv_dir, include_dependencies, force=force, ) print(f" injected package {bold(package_name)} into venv {bold(venv.name)}") print(f"done! {stars}", file=sys.stderr) # Any failure to install will raise PipxError, otherwise success return True def inject( venv_dir: Path, package_name: Optional[str], package_specs: Iterable[str], requirement_files: Iterable[str], pip_args: List[str], *, verbose: bool, include_apps: bool, include_dependencies: bool, force: bool, suffix: bool = False, ) -> ExitCode: """Returns pipx exit code.""" # Combined collection of package specifications packages = list(package_specs) for filename in requirement_files: packages.extend(parse_requirements(filename)) # Remove duplicates and order deterministically packages = sorted(set(packages)) if not packages: raise PipxError("No packages have been specified.") logger.info("Injecting packages: %r", packages) # Inject packages if not include_apps and include_dependencies: include_apps = True all_success = True for dep in packages: all_success &= inject_dep( venv_dir, package_name=None, package_spec=dep, pip_args=pip_args, verbose=verbose, include_apps=include_apps, include_dependencies=include_dependencies, force=force, suffix=suffix, ) # Any failure to install will raise PipxError, otherwise success return EXIT_CODE_OK if all_success else EXIT_CODE_INJECT_ERROR def parse_requirements(filename: Union[str, os.PathLike]) -> Generator[str, None, None]: """ Extract package specifications from requirements file. Return all of the non-empty lines with comments removed. """ # Based on https://github.com/pypa/pip/blob/main/src/pip/_internal/req/req_file.py with open(filename) as f: for line in f: # Strip comments and filter empty lines if pkgspec := COMMENT_RE.sub("", line).strip(): yield pkgspec pipx-1.6.0/src/pipx/commands/install.py000066400000000000000000000206631462701651400201030ustar00rootroot00000000000000import json import sys from pathlib import Path from typing import Iterator, List, Optional from pipx import commands, paths from pipx.commands.common import package_name_from_spec, run_post_install_actions from pipx.constants import ( EXIT_CODE_INSTALL_VENV_EXISTS, EXIT_CODE_OK, ExitCode, ) from pipx.emojis import sleep from pipx.interpreter import DEFAULT_PYTHON from pipx.pipx_metadata_file import PackageInfo, PipxMetadata, _json_decoder_object_hook from pipx.util import PipxError, pipx_wrap from pipx.venv import Venv, VenvContainer def install( venv_dir: Optional[Path], package_names: Optional[List[str]], package_specs: List[str], local_bin_dir: Path, local_man_dir: Path, python: Optional[str], pip_args: List[str], venv_args: List[str], verbose: bool, *, force: bool, reinstall: bool, include_dependencies: bool, preinstall_packages: Optional[List[str]], suffix: str = "", python_flag_passed=False, ) -> ExitCode: """Returns pipx exit code.""" # package_spec is anything pip-installable, including package_name, vcs spec, # zip file, or tar.gz file. python = python or DEFAULT_PYTHON package_names = package_names or [] if len(package_names) != len(package_specs): package_names = [ package_name_from_spec(package_spec, python, pip_args=pip_args, verbose=verbose) for package_spec in package_specs ] for package_name, package_spec in zip(package_names, package_specs): if venv_dir is None: venv_container = VenvContainer(paths.ctx.venvs) venv_dir = venv_container.get_venv_dir(f"{package_name}{suffix}") try: exists = venv_dir.exists() and bool(next(venv_dir.iterdir())) except StopIteration: exists = False venv = Venv(venv_dir, python=python, verbose=verbose) venv.check_upgrade_shared_libs(pip_args=pip_args, verbose=verbose) if exists: if not reinstall and force and python_flag_passed: print( pipx_wrap( f""" --python is ignored when --force is passed. If you want to reinstall {package_name} with {python}, run `pipx reinstall {package_spec} --python {python}` instead. """ ) ) if force: print(f"Installing to existing venv {venv.name!r}") pip_args = ["--force-reinstall"] + pip_args else: print( pipx_wrap( f""" {venv.name!r} already seems to be installed. Not modifying existing installation in '{venv_dir}'. Pass '--force' to force installation. """ ) ) return EXIT_CODE_INSTALL_VENV_EXISTS try: # Enable installing shared library `pip` with `pipx` override_shared = package_name == "pip" venv.create_venv(venv_args, pip_args, override_shared) for dep in preinstall_packages or []: venv.upgrade_package_no_metadata(dep, []) venv.install_package( package_name=package_name, package_or_url=package_spec, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=True, is_main_package=True, suffix=suffix, ) run_post_install_actions( venv, package_name, local_bin_dir, local_man_dir, venv_dir, include_dependencies, force=force, ) except (Exception, KeyboardInterrupt): print() venv.remove_venv() raise # Reset venv_dir to None ready to install the next package in the list venv_dir = None # Any failure to install will raise PipxError, otherwise success return EXIT_CODE_OK def extract_venv_metadata(spec_metadata_file: Path) -> Iterator[PipxMetadata]: """Extract venv metadata from spec metadata file.""" with open(spec_metadata_file) as spec_metadata_fh: try: spec_metadata_dict = json.load(spec_metadata_fh, object_hook=_json_decoder_object_hook) except json.decoder.JSONDecodeError as exc: raise PipxError("The spec metadata file is an invalid JSON file.") from exc if not ("venvs" in spec_metadata_dict and len(spec_metadata_dict["venvs"])): raise PipxError("No packages found in the spec metadata file.") venvs_metadata_dict = spec_metadata_dict["venvs"] if not isinstance(venvs_metadata_dict, dict): raise PipxError("The spec metadata file is invalid.") for package_path_name in venvs_metadata_dict: venv_dir = paths.ctx.venvs.joinpath(package_path_name) venv_metadata = PipxMetadata(venv_dir, read=False) venv_metadata.from_dict(venvs_metadata_dict[package_path_name]["metadata"]) yield venv_metadata def generate_package_spec(package_info: PackageInfo) -> str: """Generate more precise package spec from package info.""" if not package_info.package_or_url: raise PipxError(f"A package spec is not available for {package_info.package}") if package_info.package == package_info.package_or_url: return f"{package_info.package}=={package_info.package_version}" return package_info.package_or_url def get_python_interpreter( source_interpreter: Optional[Path], ) -> Optional[str]: """Get appropriate python interpreter.""" if source_interpreter is not None and source_interpreter.is_file(): return str(source_interpreter) print( pipx_wrap( f""" The exported python interpreter '{source_interpreter}' is ignored as not found. """ ) ) return None def install_all( spec_metadata_file: Path, local_bin_dir: Path, local_man_dir: Path, python: Optional[str], pip_args: List[str], venv_args: List[str], verbose: bool, *, force: bool, ) -> ExitCode: """Return pipx exit code.""" venv_container = VenvContainer(paths.ctx.venvs) failed: List[str] = [] installed: List[str] = [] for venv_metadata in extract_venv_metadata(spec_metadata_file): # Install the main package main_package = venv_metadata.main_package venv_dir = venv_container.get_venv_dir(f"{main_package.package}{main_package.suffix}") try: install( venv_dir, None, [generate_package_spec(main_package)], local_bin_dir, local_man_dir, python or get_python_interpreter(venv_metadata.source_interpreter), pip_args, venv_args, verbose, force=force, reinstall=False, include_dependencies=main_package.include_dependencies, preinstall_packages=[], suffix=main_package.suffix, ) # Install the injected packages for inject_package in venv_metadata.injected_packages.values(): commands.inject( venv_dir=venv_dir, package_name=None, package_specs=[generate_package_spec(inject_package)], requirement_files=[], pip_args=pip_args, verbose=verbose, include_apps=inject_package.include_apps, include_dependencies=inject_package.include_dependencies, force=force, suffix=inject_package.suffix == main_package.suffix, ) except PipxError as e: print(e, file=sys.stderr) failed.append(venv_dir.name) else: installed.append(venv_dir.name) if len(installed) == 0: print(f"No packages installed after running 'pipx install-all {spec_metadata_file}' {sleep}") if len(failed) > 0: raise PipxError(f"The following package(s) failed to install: {', '.join(failed)}") # Any failure to install will raise PipxError, otherwise success return EXIT_CODE_OK pipx-1.6.0/src/pipx/commands/interpreter.py000066400000000000000000000133111462701651400207700ustar00rootroot00000000000000import logging import subprocess from pathlib import Path from typing import List from packaging import version from pipx import commands, constants, paths, standalone_python from pipx.animate import animate from pipx.pipx_metadata_file import PipxMetadata from pipx.util import is_paths_relative, rmdir from pipx.venv import Venv, VenvContainer logger = logging.getLogger(__name__) def get_installed_standalone_interpreters() -> List[Path]: return [python_dir for python_dir in paths.ctx.standalone_python_cachedir.iterdir() if python_dir.is_dir()] def get_venvs_using_standalone_interpreter(venv_container: VenvContainer) -> List[Venv]: venvs: list[Venv] = [] for venv_dir in venv_container.iter_venv_dirs(): venv = Venv(venv_dir) if venv.pipx_metadata.source_interpreter: venvs.append(venv) return venvs def get_interpreter_users(interpreter: Path, venvs: List[Venv]) -> List[PipxMetadata]: return [ venv.pipx_metadata for venv in venvs if venv.pipx_metadata.source_interpreter and is_paths_relative(venv.pipx_metadata.source_interpreter, interpreter) ] def list_interpreters( venv_container: VenvContainer, ): interpreters = get_installed_standalone_interpreters() venvs = get_venvs_using_standalone_interpreter(venv_container) output: list[str] = [] output.append(f"Standalone interpreters are in {paths.ctx.standalone_python_cachedir}") for interpreter in interpreters: output.append(f"Python {interpreter.name}") used_in = get_interpreter_users(interpreter, venvs) if used_in: output.append(" Used in:") output.extend(f" - {p.main_package.package} {p.main_package.package_version}" for p in used_in) else: output.append(" Unused") print("\n".join(output)) return constants.EXIT_CODE_OK def prune_interpreters( venv_container: VenvContainer, ): interpreters = get_installed_standalone_interpreters() venvs = get_venvs_using_standalone_interpreter(venv_container) removed = [] for interpreter in interpreters: if get_interpreter_users(interpreter, venvs): continue rmdir(interpreter, safe_rm=True) removed.append(interpreter.name) if removed: print("Successfully removed:") for interpreter_name in removed: print(f" - Python {interpreter_name}") else: print("Nothing to remove") return constants.EXIT_CODE_OK def get_latest_micro_version( current_version: version.Version, latest_python_versions: List[version.Version] ) -> version.Version: for latest_python_version in latest_python_versions: if current_version.major == latest_python_version.major and current_version.minor == latest_python_version.minor: return latest_python_version return current_version def upgrade_interpreters(venv_container: VenvContainer, verbose: bool): with animate("Getting the index of the latest standalone python builds", not verbose): latest_pythons = standalone_python.list_pythons(use_cache=False) parsed_latest_python_versions = [] for latest_python_version in latest_pythons: try: parsed_latest_python_versions.append(version.parse(latest_python_version)) except version.InvalidVersion: logger.info(f"Invalid version found in latest pythons: {latest_python_version}. Skipping.") upgraded = [] for interpreter_dir in paths.ctx.standalone_python_cachedir.iterdir(): if not interpreter_dir.is_dir(): continue interpreter_python = interpreter_dir / "python.exe" if constants.WINDOWS else interpreter_dir / "bin" / "python3" interpreter_full_version = ( subprocess.run([str(interpreter_python), "--version"], stdout=subprocess.PIPE, check=True, text=True) .stdout.strip() .split()[1] ) try: parsed_interpreter_full_version = version.parse(interpreter_full_version) except version.InvalidVersion: logger.info(f"Invalid version found in interpreter at {interpreter_dir}. Skipping.") continue latest_micro_version = get_latest_micro_version(parsed_interpreter_full_version, parsed_latest_python_versions) if latest_micro_version > parsed_interpreter_full_version: standalone_python.download_python_build_standalone( f"{latest_micro_version.major}.{latest_micro_version.minor}", override=True, ) for venv_dir in venv_container.iter_venv_dirs(): venv = Venv(venv_dir) if venv.pipx_metadata.source_interpreter is not None and is_paths_relative( venv.pipx_metadata.source_interpreter, interpreter_dir ): print( f"Upgrade the interpreter of {venv.name} from {interpreter_full_version} to {latest_micro_version}" ) commands.reinstall( venv_dir=venv_dir, local_bin_dir=paths.ctx.bin_dir, local_man_dir=paths.ctx.man_dir, python=str(interpreter_python), verbose=verbose, ) upgraded.append((venv.name, interpreter_full_version, latest_micro_version)) if upgraded: print("Successfully upgraded the interpreter(s):") for venv_name, old_version, new_version in upgraded: print(f" - {venv_name}: {old_version} -> {new_version}") else: print("Nothing to upgrade") # Any failure to upgrade will raise PipxError, otherwise success return constants.EXIT_CODE_OK pipx-1.6.0/src/pipx/commands/list_packages.py000066400000000000000000000130761462701651400212460ustar00rootroot00000000000000import json import logging import sys from pathlib import Path from typing import Any, Collection, Dict, Tuple from pipx import paths from pipx.colors import bold from pipx.commands.common import VenvProblems, get_venv_summary, venv_health_check from pipx.constants import EXIT_CODE_LIST_PROBLEM, EXIT_CODE_OK, ExitCode from pipx.emojis import sleep from pipx.pipx_metadata_file import JsonEncoderHandlesPath, PipxMetadata from pipx.venv import Venv, VenvContainer logger = logging.getLogger(__name__) PIPX_SPEC_VERSION = "0.1" def get_venv_metadata_summary(venv_dir: Path) -> Tuple[PipxMetadata, VenvProblems, str]: venv = Venv(venv_dir) (venv_problems, warning_message) = venv_health_check(venv) if venv_problems.any_(): return (PipxMetadata(venv_dir, read=False), venv_problems, warning_message) return (venv.pipx_metadata, venv_problems, "") def list_short(venv_dirs: Collection[Path]) -> VenvProblems: all_venv_problems = VenvProblems() for venv_dir in venv_dirs: venv_metadata, venv_problems, warning_str = get_venv_metadata_summary(venv_dir) if venv_problems.any_(): logger.warning(warning_str) else: print( venv_metadata.main_package.package, venv_metadata.main_package.package_version, ) all_venv_problems.or_(venv_problems) return all_venv_problems def list_text(venv_dirs: Collection[Path], include_injected: bool, venv_root_dir: str) -> VenvProblems: print(f"venvs are in {bold(venv_root_dir)}") print(f"apps are exposed on your $PATH at {bold(str(paths.ctx.bin_dir))}") print(f"manual pages are exposed at {bold(str(paths.ctx.man_dir))}") all_venv_problems = VenvProblems() for venv_dir in venv_dirs: package_summary, venv_problems = get_venv_summary(venv_dir, include_injected=include_injected) if venv_problems.any_(): logger.warning(package_summary) else: print(package_summary) all_venv_problems.or_(venv_problems) return all_venv_problems def list_json(venv_dirs: Collection[Path]) -> VenvProblems: warning_messages = [] spec_metadata: Dict[str, Any] = { "pipx_spec_version": PIPX_SPEC_VERSION, "venvs": {}, } all_venv_problems = VenvProblems() for venv_dir in venv_dirs: (venv_metadata, venv_problems, warning_str) = get_venv_metadata_summary(venv_dir) all_venv_problems.or_(venv_problems) if venv_problems.any_(): warning_messages.append(warning_str) continue spec_metadata["venvs"][venv_dir.name] = {} spec_metadata["venvs"][venv_dir.name]["metadata"] = venv_metadata.to_dict() print(json.dumps(spec_metadata, indent=4, sort_keys=True, cls=JsonEncoderHandlesPath)) for warning_message in warning_messages: logger.warning(warning_message) return all_venv_problems def list_pinned(venv_dirs: Collection[Path], include_injected: bool) -> VenvProblems: all_venv_problems = VenvProblems() for venv_dir in venv_dirs: venv_metadata, venv_problems, warning_str = get_venv_metadata_summary(venv_dir) if venv_problems.any_(): logger.warning(warning_str) else: if venv_metadata.main_package.pinned: print( venv_metadata.main_package.package, venv_metadata.main_package.package_version, ) if include_injected: for pkg, info in venv_metadata.injected_packages.items(): if info.pinned: print(pkg, info.package_version, f"(injected in venv {venv_dir.name})") all_venv_problems.or_(venv_problems) return all_venv_problems def list_packages( venv_container: VenvContainer, include_injected: bool, json_format: bool, short_format: bool, pinned_only: bool, ) -> ExitCode: """Returns pipx exit code.""" venv_dirs: Collection[Path] = sorted(venv_container.iter_venv_dirs()) if not venv_dirs: print(f"nothing has been installed with pipx {sleep}", file=sys.stderr) if json_format: all_venv_problems = list_json(venv_dirs) elif short_format: all_venv_problems = list_short(venv_dirs) elif pinned_only: all_venv_problems = list_pinned(venv_dirs, include_injected) else: if not venv_dirs: return EXIT_CODE_OK all_venv_problems = list_text(venv_dirs, include_injected, str(venv_container)) if all_venv_problems.bad_venv_name: logger.warning( "\nOne or more packages contain out-of-date internal data installed from a\n" "previous pipx version and need to be updated.\n" " To fix, execute: pipx reinstall-all" ) if all_venv_problems.invalid_interpreter: logger.warning( "\nOne or more packages have a missing python interpreter.\n To fix, execute: pipx reinstall-all" ) if all_venv_problems.missing_metadata: logger.warning( "\nOne or more packages have a missing internal pipx metadata.\n" " They were likely installed using a pipx version before 0.15.0.0.\n" " Please uninstall and install these package(s) to fix." ) if all_venv_problems.not_installed: logger.warning( "\nOne or more packages are not installed properly.\n" " Please uninstall and install these package(s) to fix." ) if all_venv_problems.any_(): print("", file=sys.stderr) return EXIT_CODE_LIST_PROBLEM return EXIT_CODE_OK pipx-1.6.0/src/pipx/commands/pin.py000066400000000000000000000071051462701651400172170ustar00rootroot00000000000000import logging from pathlib import Path from typing import Sequence from pipx.colors import bold from pipx.constants import ExitCode from pipx.emojis import sleep from pipx.util import PipxError from pipx.venv import Venv logger = logging.getLogger(__name__) def _update_pin_info(venv: Venv, package_name: str, is_main_package: bool, unpin: bool) -> int: package_metadata = venv.package_metadata[package_name] venv.update_package_metadata( package_name=str(package_metadata.package), package_or_url=str(package_metadata.package_or_url), pip_args=package_metadata.pip_args, include_dependencies=package_metadata.include_dependencies, include_apps=package_metadata.include_apps, is_main_package=is_main_package, suffix=package_metadata.suffix, pinned=not unpin, ) return 1 def pin( venv_dir: Path, verbose: bool, skip: Sequence[str], injected_only: bool = False, ) -> ExitCode: venv = Venv(venv_dir, verbose=verbose) try: main_package_metadata = venv.package_metadata[venv.main_package_name] except KeyError as e: raise PipxError(f"Package {venv.name} is not installed") from e if main_package_metadata.pinned: logger.warning(f"Package {main_package_metadata.package} already pinned {sleep}") elif injected_only or skip: pinned_packages_count = 0 pinned_packages_list = [] for package_name in venv.package_metadata: if package_name == venv.main_package_name or package_name in skip: continue if venv.package_metadata[package_name].pinned: print(f"{package_name} was pinned. Not modifying.") continue pinned_packages_count += _update_pin_info(venv, package_name, is_main_package=False, unpin=False) pinned_packages_list.append(f"{package_name} {venv.package_metadata[package_name].package_version}") if pinned_packages_count != 0: print(bold(f"Pinned {pinned_packages_count} packages in venv {venv.name}")) for package in pinned_packages_list: print(" -", package) else: for package_name in venv.package_metadata: if package_name == venv.main_package_name: _update_pin_info(venv, venv.main_package_name, is_main_package=True, unpin=False) else: _update_pin_info(venv, package_name, is_main_package=False, unpin=False) return ExitCode(0) def unpin(venv_dir: Path, verbose: bool) -> ExitCode: venv = Venv(venv_dir, verbose=verbose) try: main_package_metadata = venv.package_metadata[venv.main_package_name] except KeyError as e: raise PipxError(f"Package {venv.name} is not installed") from e unpinned_packages_count = 0 unpinned_packages_list = [] for package_name in venv.package_metadata: if package_name == main_package_metadata.package and main_package_metadata.pinned: unpinned_packages_count += _update_pin_info(venv, package_name, is_main_package=True, unpin=True) elif venv.package_metadata[package_name].pinned: unpinned_packages_count += _update_pin_info(venv, package_name, is_main_package=False, unpin=True) unpinned_packages_list.append(package_name) if unpinned_packages_count != 0: print(bold(f"Unpinned {unpinned_packages_count} packages in venv {venv.name}")) for package in unpinned_packages_list: print(" -", package) else: logger.warning(f"No packages to unpin in venv {venv.name}") return ExitCode(0) pipx-1.6.0/src/pipx/commands/reinstall.py000066400000000000000000000111541462701651400204250ustar00rootroot00000000000000import sys from pathlib import Path from typing import List, Sequence from packaging.utils import canonicalize_name from pipx.commands.inject import inject_dep from pipx.commands.install import install from pipx.commands.uninstall import uninstall from pipx.constants import ( EXIT_CODE_OK, EXIT_CODE_REINSTALL_INVALID_PYTHON, EXIT_CODE_REINSTALL_VENV_NONEXISTENT, ExitCode, ) from pipx.emojis import error, sleep from pipx.util import PipxError from pipx.venv import Venv, VenvContainer def reinstall( *, venv_dir: Path, local_bin_dir: Path, local_man_dir: Path, python: str, verbose: bool, force_reinstall_shared_libs: bool = False, python_flag_passed: bool = False, ) -> ExitCode: """Returns pipx exit code.""" if not venv_dir.exists(): print(f"Nothing to reinstall for {venv_dir.name} {sleep}") return EXIT_CODE_REINSTALL_VENV_NONEXISTENT try: Path(python).relative_to(venv_dir) except ValueError: pass else: print( f"{error} Error, the python executable would be deleted!", "Change it using the --python option or PIPX_DEFAULT_PYTHON environment variable.", ) return EXIT_CODE_REINSTALL_INVALID_PYTHON venv = Venv(venv_dir, verbose=verbose) venv.check_upgrade_shared_libs( pip_args=venv.pipx_metadata.main_package.pip_args, verbose=verbose, force_upgrade=force_reinstall_shared_libs ) if venv.pipx_metadata.main_package.package_or_url is not None: package_or_url = venv.pipx_metadata.main_package.package_or_url else: package_or_url = venv.main_package_name uninstall(venv_dir, local_bin_dir, local_man_dir, verbose) # in case legacy original dir name venv_dir = venv_dir.with_name(canonicalize_name(venv_dir.name)) # install main package first install( venv_dir, [venv.main_package_name], [package_or_url], local_bin_dir, local_man_dir, python, venv.pipx_metadata.main_package.pip_args, venv.pipx_metadata.venv_args, verbose, force=True, reinstall=True, include_dependencies=venv.pipx_metadata.main_package.include_dependencies, preinstall_packages=[], suffix=venv.pipx_metadata.main_package.suffix, python_flag_passed=python_flag_passed, ) # now install injected packages for injected_name, injected_package in venv.pipx_metadata.injected_packages.items(): if injected_package.package_or_url is None: # This should never happen, but package_or_url is type # Optional[str] so mypy thinks it could be None raise PipxError(f"Internal Error injecting package {injected_package} into {venv.name}") inject_dep( venv_dir, injected_name, injected_package.package_or_url, injected_package.pip_args, verbose=verbose, include_apps=injected_package.include_apps, include_dependencies=injected_package.include_dependencies, force=True, ) # Any failure to install will raise PipxError, otherwise success return EXIT_CODE_OK def reinstall_all( venv_container: VenvContainer, local_bin_dir: Path, local_man_dir: Path, python: str, verbose: bool, *, skip: Sequence[str], python_flag_passed: bool = False, ) -> ExitCode: """Returns pipx exit code.""" failed: List[str] = [] reinstalled: List[str] = [] # iterate on all packages and reinstall them # for the first one, we also trigger # a reinstall of shared libs beforehand first_reinstall = True for venv_dir in venv_container.iter_venv_dirs(): if venv_dir.name in skip: continue try: reinstall( venv_dir=venv_dir, local_bin_dir=local_bin_dir, local_man_dir=local_man_dir, python=python, verbose=verbose, force_reinstall_shared_libs=first_reinstall, python_flag_passed=python_flag_passed, ) except PipxError as e: print(e, file=sys.stderr) failed.append(venv_dir.name) else: first_reinstall = False reinstalled.append(venv_dir.name) if len(reinstalled) == 0: print(f"No packages reinstalled after running 'pipx reinstall-all' {sleep}") if len(failed) > 0: raise PipxError(f"The following package(s) failed to reinstall: {', '.join(failed)}") # Any failure to install will raise PipxError, otherwise success return EXIT_CODE_OK pipx-1.6.0/src/pipx/commands/run.py000066400000000000000000000302611462701651400172340ustar00rootroot00000000000000import datetime import hashlib import logging import re import sys import time import urllib.parse import urllib.request from pathlib import Path from shutil import which from typing import List, NoReturn, Optional, Union from packaging.requirements import InvalidRequirement, Requirement from pipx import paths from pipx.commands.common import package_name_from_spec from pipx.constants import TEMP_VENV_EXPIRATION_THRESHOLD_DAYS, WINDOWS from pipx.emojis import hazard from pipx.util import ( PipxError, exec_app, get_pypackage_bin_path, pipx_wrap, rmdir, run_pypackage_bin, ) from pipx.venv import Venv if sys.version_info < (3, 11): import tomli as tomllib else: import tomllib logger = logging.getLogger(__name__) VENV_EXPIRED_FILENAME = "pipx_expired_venv" APP_NOT_FOUND_ERROR_MESSAGE = """\ '{app}' executable script not found in package '{package_name}'. Available executable scripts: {app_lines}""" def maybe_script_content(app: str, is_path: bool) -> Optional[Union[str, Path]]: # If the app is a script, return its content. # Return None if it should be treated as a package name. # Look for a local file first. app_path = Path(app) if app_path.is_file(): return app_path elif is_path: raise PipxError(f"The specified path {app} does not exist") # Check for a URL if urllib.parse.urlparse(app).scheme: if not app.endswith(".py"): raise PipxError( """ pipx will only execute apps from the internet directly if they end with '.py'. To run from an SVN, try pipx --spec URL BINARY """ ) logger.info("Detected url. Downloading and executing as a Python file.") return _http_get_request(app) # Otherwise, it's a package return None def run_script( content: Union[str, Path], app_args: List[str], python: str, pip_args: List[str], venv_args: List[str], verbose: bool, use_cache: bool, ) -> NoReturn: requirements = _get_requirements_from_script(content) if requirements is None: python_path = Path(python) else: # Note that the environment name is based on the identified # requirements, and *not* on the script name. This is deliberate, as # it ensures that two scripts with the same requirements can use the # same environment, which means fewer environments need to be # managed. The requirements are normalised (in # _get_requirements_from_script), so that irrelevant differences in # whitespace, and similar, don't prevent environment sharing. venv_dir = _get_temporary_venv_path(requirements, python, pip_args, venv_args) venv = Venv(venv_dir) _prepare_venv_cache(venv, None, use_cache) if venv_dir.exists(): logger.info(f"Reusing cached venv {venv_dir}") else: venv = Venv(venv_dir, python=python, verbose=verbose) venv.check_upgrade_shared_libs(pip_args=pip_args, verbose=verbose) venv.create_venv(venv_args, pip_args) venv.install_unmanaged_packages(requirements, pip_args) python_path = venv.python_path if isinstance(content, Path): exec_app([python_path, content, *app_args]) else: exec_app([python_path, "-c", content, *app_args]) def run_package( app: str, package_or_url: str, app_args: List[str], python: str, pip_args: List[str], venv_args: List[str], pypackages: bool, verbose: bool, use_cache: bool, ) -> NoReturn: if which(app): logger.warning( pipx_wrap( f""" {hazard} {app} is already on your PATH and installed at {which(app)}. Downloading and running anyway. """, subsequent_indent=" " * 4, ) ) if WINDOWS: app_filename = f"{app}.exe" logger.info(f"Assuming app is {app_filename!r} (Windows only)") else: app_filename = app pypackage_bin_path = get_pypackage_bin_path(app) if pypackage_bin_path.exists(): logger.info(f"Using app in local __pypackages__ directory at '{pypackage_bin_path}'") run_pypackage_bin(pypackage_bin_path, app_args) if pypackages: raise PipxError( f""" '--pypackages' flag was passed, but '{pypackage_bin_path}' 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 / app_filename _prepare_venv_cache(venv, bin_path, use_cache) if venv.has_app(app, app_filename): logger.info(f"Reusing cached venv {venv_dir}") venv.run_app(app, app_filename, app_args) else: logger.info(f"venv location is {venv_dir}") _download_and_run( Path(venv_dir), package_or_url, app, app_filename, app_args, python, pip_args, venv_args, use_cache, verbose, ) def run( app: str, spec: str, is_path: bool, app_args: List[str], python: str, pip_args: List[str], venv_args: List[str], pypackages: bool, verbose: bool, use_cache: bool, ) -> NoReturn: """Installs venv to temporary dir (or reuses cache), then runs app from package """ # For any package, we need to just use the name try: package_name = Requirement(app).name except InvalidRequirement: # Raw URLs to scripts are supported, too, so continue if # we can't parse this as a package package_name = app content = None if spec is not None else maybe_script_content(app, is_path) if content is not None: run_script(content, app_args, python, pip_args, venv_args, verbose, use_cache) else: package_or_url = spec if spec is not None else app run_package( package_name, package_or_url, app_args, python, pip_args, venv_args, pypackages, verbose, use_cache, ) def _download_and_run( venv_dir: Path, package_or_url: str, app: str, app_filename: str, app_args: List[str], python: str, pip_args: List[str], venv_args: List[str], use_cache: bool, verbose: bool, ) -> NoReturn: venv = Venv(venv_dir, python=python, verbose=verbose) venv.check_upgrade_shared_libs(pip_args=pip_args, verbose=verbose) if venv.pipx_metadata.main_package.package is not None: package_name = venv.pipx_metadata.main_package.package else: package_name = package_name_from_spec(package_or_url, python, pip_args=pip_args, verbose=verbose) override_shared = package_name == "pip" venv.create_venv(venv_args, pip_args, override_shared) venv.install_package( package_name=package_name, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=False, include_apps=True, is_main_package=True, ) if not venv.has_app(app, app_filename): apps = venv.pipx_metadata.main_package.apps # If there's a single app inside the package, run that by default if app == package_name and len(apps) == 1: app = apps[0] print(f"NOTE: running app {app!r} from {package_name!r}") if WINDOWS: app_filename = f"{app}.exe" logger.info(f"Assuming app is {app_filename!r} (Windows only)") else: app_filename = app else: all_apps = (f"{a} - usage: 'pipx run --spec {package_or_url} {a} [arguments?]'" for a in apps) raise PipxError( APP_NOT_FOUND_ERROR_MESSAGE.format( app=app, package_name=package_name, app_lines="\n ".join(all_apps), ), wrap_message=False, ) if not use_cache: # Let future _remove_all_expired_venvs know to remove this (venv_dir / VENV_EXPIRED_FILENAME).touch() venv.run_app(app, app_filename, app_args) def _get_temporary_venv_path(requirements: List[str], python: str, pip_args: List[str], venv_args: List[str]) -> Path: """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 app aren't relevant, but args passed to venv creation are.) """ m = hashlib.sha256() m.update("".join(requirements).encode()) m.update(python.encode()) m.update("".join(pip_args).encode()) m.update("".join(venv_args).encode()) venv_folder_name = m.hexdigest()[:15] # 15 chosen arbitrarily return Path(paths.ctx.venv_cache) / venv_folder_name def _is_temporary_venv_expired(venv_dir: Path) -> bool: 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 or (venv_dir / VENV_EXPIRED_FILENAME).exists() def _prepare_venv_cache(venv: Venv, bin_path: Optional[Path], use_cache: bool) -> None: venv_dir = venv.root if not use_cache and (bin_path is None or bin_path.exists()): logger.info(f"Removing cached venv {venv_dir!s}") rmdir(venv_dir) _remove_all_expired_venvs() def _remove_all_expired_venvs() -> None: for venv_dir in Path(paths.ctx.venv_cache).iterdir(): if _is_temporary_venv_expired(venv_dir): logger.info(f"Removing expired venv {venv_dir!s}") rmdir(venv_dir) def _http_get_request(url: str) -> str: try: res = urllib.request.urlopen(url) charset = res.headers.get_content_charset() or "utf-8" return res.read().decode(charset) except Exception as e: logger.debug("Uncaught Exception:", exc_info=True) raise PipxError(str(e)) from e # This regex comes from the inline script metadata spec INLINE_SCRIPT_METADATA = re.compile(r"(?m)^# /// (?P[a-zA-Z0-9-]+)$\s(?P(^#(| .*)$\s)+)^# ///$") def _get_requirements_from_script(content: Union[str, Path]) -> Optional[List[str]]: """ Supports inline script metadata. """ if isinstance(content, Path): content = content.read_text(encoding="utf-8") name = "script" # Windows is currently getting un-normalized line endings, so normalize content = content.replace("\r\n", "\n") matches = [m for m in INLINE_SCRIPT_METADATA.finditer(content) if m.group("type") == name] if not matches: pyproject_matches = [m for m in INLINE_SCRIPT_METADATA.finditer(content) if m.group("type") == "pyproject"] if pyproject_matches: logger.error( pipx_wrap( f""" {hazard} Using old form of requirements table. Use updated PEP 723 syntax by replacing `# /// pyproject` with `# /// script` and `run.dependencies` (or `run.requirements`) with `dependencies`. """, subsequent_indent=" " * 4, ) ) raise ValueError("Old 'pyproject' table found") return None if len(matches) > 1: raise ValueError(f"Multiple {name} blocks found") content = "".join( line[2:] if line.startswith("# ") else line[1:] for line in matches[0].group("content").splitlines(keepends=True) ) pyproject = tomllib.loads(content) requirements = [] for requirement in pyproject.get("dependencies", []): # Validate the requirement try: req = Requirement(requirement) except InvalidRequirement as e: raise PipxError(f"Invalid requirement {requirement}: {e}") from e # Use the normalised form of the requirement requirements.append(str(req)) return requirements pipx-1.6.0/src/pipx/commands/run_pip.py000066400000000000000000000010161462701651400201000ustar00rootroot00000000000000from pathlib import Path from typing import List from pipx.constants import ExitCode from pipx.util import PipxError from pipx.venv import Venv def run_pip(package: str, venv_dir: Path, pip_args: List[str], verbose: bool) -> ExitCode: """Returns pipx exit code.""" venv = Venv(venv_dir, verbose=verbose) if not venv.python_path.exists(): raise PipxError(f"venv for {package!r} was not found. Was {package!r} installed with pipx?") venv.verbose = True return venv.run_pip_get_exit_code(pip_args) pipx-1.6.0/src/pipx/commands/uninject.py000066400000000000000000000114341462701651400202500ustar00rootroot00000000000000import logging import os from pathlib import Path from typing import List, Set from packaging.utils import canonicalize_name from pipx.colors import bold from pipx.commands.uninstall import ( _get_package_bin_dir_app_paths, _get_package_man_paths, ) from pipx.constants import ( EXIT_CODE_OK, EXIT_CODE_UNINJECT_ERROR, MAN_SECTIONS, ExitCode, ) from pipx.emojis import stars from pipx.util import PipxError, pipx_wrap from pipx.venv import Venv logger = logging.getLogger(__name__) def get_include_resource_paths(package_name: str, venv: Venv, local_bin_dir: Path, local_man_dir: Path) -> Set[Path]: bin_dir_app_paths = _get_package_bin_dir_app_paths( venv, venv.package_metadata[package_name], venv.bin_path, local_bin_dir ) man_paths = set() for man_section in MAN_SECTIONS: man_paths |= _get_package_man_paths( venv, venv.package_metadata[package_name], venv.man_path / man_section, local_man_dir / man_section, ) need_to_remove = set() for bin_dir_app_path in bin_dir_app_paths: if bin_dir_app_path.name in venv.package_metadata[package_name].apps: need_to_remove.add(bin_dir_app_path) for man_path in man_paths: path = Path(man_path.parent.name) / man_path.name if str(path) in venv.package_metadata[package_name].man_pages: need_to_remove.add(path) return need_to_remove def uninject_dep( venv: Venv, package_name: str, *, local_bin_dir: Path, local_man_dir: Path, leave_deps: bool = False, ) -> bool: package_name = canonicalize_name(package_name) if package_name == venv.pipx_metadata.main_package.package: logger.warning( pipx_wrap( f""" {package_name} is the main package of {venv.root.name} venv. Use `pipx uninstall {venv.root.name}` to uninstall instead of uninject. """, subsequent_indent=" " * 4, ) ) return False if package_name not in venv.pipx_metadata.injected_packages: logger.warning(f"{package_name} is not in the {venv.root.name} venv. Skipping.") return False need_app_uninstall = venv.package_metadata[package_name].include_apps new_resource_paths = get_include_resource_paths(package_name, venv, local_bin_dir, local_man_dir) if not leave_deps: orig_not_required_packages = venv.list_installed_packages(not_required=True) logger.info(f"Original not required packages: {orig_not_required_packages}") venv.uninstall_package(package=package_name, was_injected=True) if not leave_deps: new_not_required_packages = venv.list_installed_packages(not_required=True) logger.info(f"New not required packages: {new_not_required_packages}") deps_of_uninstalled = new_not_required_packages - orig_not_required_packages if len(deps_of_uninstalled) == 0: pass else: logger.info(f"Dependencies of uninstalled package: {deps_of_uninstalled}") for dep_package_name in deps_of_uninstalled: venv.uninstall_package(package=dep_package_name, was_injected=False) deps_string = " and its dependencies" else: deps_string = "" if need_app_uninstall: for path in new_resource_paths: try: os.unlink(path) except FileNotFoundError: logger.info(f"tried to remove but couldn't find {path}") else: logger.info(f"removed file {path}") print(f"Uninjected package {bold(package_name)}{deps_string} from venv {bold(venv.root.name)} {stars}") return True def uninject( venv_dir: Path, dependencies: List[str], *, local_bin_dir: Path, local_man_dir: Path, leave_deps: bool, verbose: bool, ) -> ExitCode: """Returns pipx exit code""" if not venv_dir.exists() or not next(venv_dir.iterdir()): raise PipxError(f"Virtual environment {venv_dir.name} does not exist.") venv = Venv(venv_dir, verbose=verbose) if not venv.package_metadata: raise PipxError( f""" Can't uninject from Virtual Environment {venv_dir.name!r}. {venv_dir.name!r} has missing internal pipx metadata. It was likely installed using a pipx version before 0.15.0.0. Please uninstall and install {venv_dir.name!r} manually to fix. """ ) all_success = True for dep in dependencies: all_success &= uninject_dep( venv, dep, local_bin_dir=local_bin_dir, local_man_dir=local_man_dir, leave_deps=leave_deps, ) if all_success: return EXIT_CODE_OK else: return EXIT_CODE_UNINJECT_ERROR pipx-1.6.0/src/pipx/commands/uninstall.py000066400000000000000000000142701462701651400204430ustar00rootroot00000000000000import logging from collections.abc import Callable from pathlib import Path from shutil import which from typing import List, Optional, Set from pipx.commands.common import ( add_suffix, can_symlink, get_exposed_man_paths_for_package, get_exposed_paths_for_package, ) from pipx.constants import ( EXIT_CODE_OK, EXIT_CODE_UNINSTALL_ERROR, EXIT_CODE_UNINSTALL_VENV_NONEXISTENT, MAN_SECTIONS, ExitCode, ) from pipx.emojis import hazard, sleep, stars from pipx.pipx_metadata_file import PackageInfo from pipx.util import rmdir, safe_unlink from pipx.venv import Venv, VenvContainer from pipx.venv_inspect import VenvMetadata logger = logging.getLogger(__name__) def _venv_metadata_to_package_info( venv_metadata: VenvMetadata, package_name: str, package_or_url: str = "", pip_args: Optional[List[str]] = None, include_apps: bool = True, include_dependencies: bool = False, suffix: str = "", ) -> PackageInfo: if pip_args is None: pip_args = [] return PackageInfo( package=package_name, package_or_url=package_or_url, pip_args=pip_args, include_apps=include_apps, include_dependencies=include_dependencies, apps=venv_metadata.apps, app_paths=venv_metadata.app_paths, apps_of_dependencies=venv_metadata.apps_of_dependencies, app_paths_of_dependencies=venv_metadata.app_paths_of_dependencies, man_pages=venv_metadata.man_pages, man_paths=venv_metadata.man_paths, man_pages_of_dependencies=venv_metadata.man_pages_of_dependencies, man_paths_of_dependencies=venv_metadata.man_paths_of_dependencies, package_version=venv_metadata.package_version, suffix=suffix, ) def _get_package_bin_dir_app_paths( venv: Venv, package_info: PackageInfo, venv_bin_path: Path, local_bin_dir: Path ) -> Set[Path]: suffix = package_info.suffix apps = [] if package_info.include_apps: apps += package_info.apps if package_info.include_dependencies: apps += package_info.apps_of_dependencies return get_exposed_paths_for_package(venv_bin_path, local_bin_dir, [add_suffix(app, suffix) for app in apps]) def _get_package_man_paths(venv: Venv, package_info: PackageInfo, venv_man_path: Path, local_man_dir: Path) -> Set[Path]: man_pages = [] if package_info.include_apps: man_pages += package_info.man_pages if package_info.include_dependencies: man_pages += package_info.man_pages_of_dependencies return get_exposed_man_paths_for_package(venv_man_path, local_man_dir, man_pages) def _get_venv_resource_paths( resource_type: str, venv: Venv, venv_resource_path: Path, local_resource_dir: Path ) -> Set[Path]: resource_paths = set() assert resource_type in ("app", "man"), "invalid resource type" get_package_resource_paths: Callable[[Venv, PackageInfo, Path, Path], Set[Path]] get_package_resource_paths = { "app": _get_package_bin_dir_app_paths, "man": _get_package_man_paths, }[resource_type] if venv.pipx_metadata.main_package.package is not None: # Valid metadata for venv for package_info in venv.package_metadata.values(): resource_paths |= get_package_resource_paths(venv, package_info, venv_resource_path, local_resource_dir) elif venv.python_path.is_file(): # No metadata from pipx_metadata.json, but valid python interpreter. # In pre-metadata-pipx venv.root.name is name of main package # In pre-metadata-pipx there is no suffix # We make the conservative assumptions: no injected packages, # not include_dependencies. Other PackageInfo fields are irrelevant # here. venv_metadata = venv.get_venv_metadata_for_package(venv.root.name, set()) main_package_info = _venv_metadata_to_package_info(venv_metadata, venv.root.name) resource_paths = get_package_resource_paths(venv, main_package_info, venv_resource_path, local_resource_dir) else: # No metadata and no valid python interpreter. # We'll take our best guess on what to uninstall here based on symlink # location for symlink-capable systems. # The heuristic here is any symlink in ~/.local/bin pointing to # .local/share/pipx/venvs/VENV_NAME/{bin,Scripts} should be uninstalled. # For non-symlink systems we give up and return an empty set. if not local_resource_dir.is_dir() or not can_symlink(local_resource_dir): return set() resource_paths = get_exposed_paths_for_package(venv_resource_path, local_resource_dir) return resource_paths def uninstall(venv_dir: Path, local_bin_dir: Path, local_man_dir: Path, verbose: bool) -> ExitCode: """Uninstall entire venv_dir, including main package and all injected packages. Returns pipx exit code. """ if not venv_dir.exists(): print(f"Nothing to uninstall for {venv_dir.name} {sleep}") app = which(venv_dir.name) if app: print(f"{hazard} Note: '{app}' still exists on your system and is on your PATH") return EXIT_CODE_UNINSTALL_VENV_NONEXISTENT venv = Venv(venv_dir, verbose=verbose) bin_dir_app_paths = _get_venv_resource_paths("app", venv, venv.bin_path, local_bin_dir) man_dir_paths = set() for man_section in MAN_SECTIONS: man_dir_paths |= _get_venv_resource_paths("man", venv, venv.man_path / man_section, local_man_dir / man_section) for path in bin_dir_app_paths | man_dir_paths: try: safe_unlink(path) except FileNotFoundError: logger.info(f"tried to remove but couldn't find {path}") else: logger.info(f"removed file {path}") rmdir(venv_dir) print(f"uninstalled {venv.name}! {stars}") return EXIT_CODE_OK def uninstall_all( venv_container: VenvContainer, local_bin_dir: Path, local_man_dir: Path, verbose: bool, ) -> ExitCode: """Returns pipx exit code.""" all_success = True for venv_dir in venv_container.iter_venv_dirs(): return_val = uninstall(venv_dir, local_bin_dir, local_man_dir, verbose) all_success &= return_val == 0 return EXIT_CODE_OK if all_success else EXIT_CODE_UNINSTALL_ERROR pipx-1.6.0/src/pipx/commands/upgrade.py000066400000000000000000000211311462701651400200530ustar00rootroot00000000000000import logging import os import sys from pathlib import Path from typing import Dict, List, Optional, Sequence from pipx import commands, paths from pipx.colors import bold, red from pipx.commands.common import expose_resources_globally from pipx.constants import EXIT_CODE_OK, ExitCode from pipx.emojis import sleep from pipx.package_specifier import parse_specifier_for_upgrade from pipx.util import PipxError, pipx_wrap from pipx.venv import Venv, VenvContainer logger = logging.getLogger(__name__) def _upgrade_package( venv: Venv, package_name: str, pip_args: List[str], is_main_package: bool, force: bool, upgrading_all: bool, ) -> int: """Returns 1 if package version changed, 0 if same version""" package_metadata = venv.package_metadata[package_name] if package_metadata.package_or_url is None: raise PipxError(f"Internal Error: package {package_name} has corrupt pipx metadata.") elif package_metadata.pinned: if package_metadata.package != venv.main_package_name: logger.warning( f"Not upgrading pinned package {package_metadata.package} in venv {venv.name}. " f"Run `pipx unpin {venv.name}` to unpin it." ) else: logger.warning(f"Not upgrading pinned package {venv.name}. Run `pipx unpin {venv.name}` to unpin it.") return 0 package_or_url = parse_specifier_for_upgrade(package_metadata.package_or_url) old_version = package_metadata.package_version venv.upgrade_package( package_name, package_or_url, pip_args, include_dependencies=package_metadata.include_dependencies, include_apps=package_metadata.include_apps, is_main_package=is_main_package, suffix=package_metadata.suffix, ) package_metadata = venv.package_metadata[package_name] display_name = f"{package_metadata.package}{package_metadata.suffix}" new_version = package_metadata.package_version if package_metadata.include_apps: expose_resources_globally( "app", paths.ctx.bin_dir, package_metadata.app_paths, force=force, suffix=package_metadata.suffix, ) expose_resources_globally("man", paths.ctx.man_dir, package_metadata.man_paths, force=force) if package_metadata.include_dependencies: for _, app_paths in package_metadata.app_paths_of_dependencies.items(): expose_resources_globally( "app", paths.ctx.bin_dir, app_paths, force=force, suffix=package_metadata.suffix, ) for _, man_paths in package_metadata.man_paths_of_dependencies.items(): expose_resources_globally("man", paths.ctx.man_dir, man_paths, force=force) if old_version == new_version: if upgrading_all: pass else: print( pipx_wrap( f""" {display_name} is already at latest version {old_version} (location: {venv.root!s}) """ ) ) return 0 else: print( pipx_wrap( f""" upgraded package {display_name} from {old_version} to {new_version} (location: {venv.root!s}) """ ) ) return 1 def _upgrade_venv( venv_dir: Path, pip_args: List[str], verbose: bool, *, include_injected: bool, upgrading_all: bool, force: bool, install: bool = False, venv_args: Optional[List[str]] = None, python: Optional[str] = None, python_flag_passed: bool = False, ) -> int: """Return number of packages with changed versions.""" if not venv_dir.is_dir(): if install: if venv_args is None: venv_args = [] commands.install( venv_dir=None, venv_args=venv_args, package_names=None, package_specs=[str(venv_dir).split(os.path.sep)[-1]], local_bin_dir=paths.ctx.bin_dir, local_man_dir=paths.ctx.man_dir, python=python, pip_args=pip_args, verbose=verbose, force=force, reinstall=False, include_dependencies=False, preinstall_packages=None, python_flag_passed=python_flag_passed, ) return 0 else: raise PipxError( f""" Package is not installed. Expected to find {venv_dir!s}, but it does not exist. """ ) if venv_args and not install: logger.info("Ignoring " + ", ".join(venv_args) + " as not combined with --install") if python and not install: logger.info("Ignoring --python as not combined with --install") venv = Venv(venv_dir, verbose=verbose) venv.check_upgrade_shared_libs(pip_args=pip_args, verbose=verbose) if not venv.package_metadata: raise PipxError( f"Not upgrading {red(bold(venv_dir.name))}. It has missing internal pipx metadata.\n" f"It was likely installed using a pipx version before 0.15.0.0.\n" f"Please uninstall and install this package to fix.", wrap_message=False, ) # Upgrade shared libraries (pip, setuptools and wheel) venv.upgrade_packaging_libraries(pip_args) versions_updated = 0 package_name = venv.main_package_name versions_updated += _upgrade_package( venv, package_name, pip_args, is_main_package=True, force=force, upgrading_all=upgrading_all, ) if include_injected: for package_name in venv.package_metadata: if package_name == venv.main_package_name: continue versions_updated += _upgrade_package( venv, package_name, pip_args, is_main_package=False, force=force, upgrading_all=upgrading_all, ) return versions_updated def upgrade( venv_dirs: Dict[str, Path], python: Optional[str], pip_args: List[str], venv_args: List[str], verbose: bool, *, include_injected: bool, force: bool, install: bool, python_flag_passed: bool = False, ) -> ExitCode: """Return pipx exit code.""" for venv_dir in venv_dirs.values(): _ = _upgrade_venv( venv_dir, pip_args, verbose, include_injected=include_injected, upgrading_all=False, force=force, install=install, venv_args=venv_args, python=python, python_flag_passed=python_flag_passed, ) # Any error in upgrade will raise PipxError (e.g. from venv.upgrade_package()) return EXIT_CODE_OK def upgrade_all( venv_container: VenvContainer, verbose: bool, *, pip_args: List[str], include_injected: bool, skip: Sequence[str], force: bool, python_flag_passed: bool = False, ) -> ExitCode: """Return pipx exit code.""" failed: List[str] = [] upgraded: List[str] = [] for venv_dir in venv_container.iter_venv_dirs(): venv = Venv(venv_dir, verbose=verbose) venv.check_upgrade_shared_libs(pip_args=pip_args, verbose=verbose) if venv_dir.name in skip or "--editable" in venv.pipx_metadata.main_package.pip_args: continue try: _upgrade_venv( venv_dir, venv.pipx_metadata.main_package.pip_args, verbose=verbose, include_injected=include_injected, upgrading_all=True, force=force, python_flag_passed=python_flag_passed, ) except PipxError as e: print(e, file=sys.stderr) failed.append(venv_dir.name) else: upgraded.append(venv_dir.name) if len(upgraded) == 0: print(f"No packages upgraded after running 'pipx upgrade-all' {sleep}") if len(failed) > 0: raise PipxError(f"The following package(s) failed to upgrade: {','.join(failed)}") # Any failure to install will raise PipxError, otherwise success return EXIT_CODE_OK def upgrade_shared( verbose: bool, pip_args: List[str], ) -> ExitCode: """Return pipx exit code.""" from pipx.shared_libs import shared_libs shared_libs.upgrade(verbose=verbose, pip_args=pip_args, raises=True) return EXIT_CODE_OK pipx-1.6.0/src/pipx/constants.py000066400000000000000000000044231462701651400166440ustar00rootroot00000000000000import os import platform import sysconfig from textwrap import dedent from typing import NewType PIPX_SHARED_PTH = "pipx_shared.pth" TEMP_VENV_EXPIRATION_THRESHOLD_DAYS = 14 MINIMUM_PYTHON_VERSION = "3.8" MAN_SECTIONS = ["man%d" % i for i in range(1, 10)] FETCH_MISSING_PYTHON = os.environ.get("PIPX_FETCH_MISSING_PYTHON", False) ExitCode = NewType("ExitCode", int) # pipx shell exit codes EXIT_CODE_OK = ExitCode(0) EXIT_CODE_INJECT_ERROR = ExitCode(1) EXIT_CODE_UNINJECT_ERROR = ExitCode(1) EXIT_CODE_INSTALL_VENV_EXISTS = ExitCode(0) EXIT_CODE_LIST_PROBLEM = ExitCode(1) EXIT_CODE_UNINSTALL_VENV_NONEXISTENT = ExitCode(1) EXIT_CODE_UNINSTALL_ERROR = ExitCode(1) EXIT_CODE_REINSTALL_VENV_NONEXISTENT = ExitCode(1) EXIT_CODE_REINSTALL_INVALID_PYTHON = ExitCode(1) EXIT_CODE_SPECIFIED_PYTHON_EXECUTABLE_NOT_FOUND = ExitCode(1) def is_windows() -> bool: return platform.system() == "Windows" def is_macos() -> bool: return platform.system() == "Darwin" def is_linux() -> bool: return platform.system() == "Linux" def is_mingw() -> bool: return sysconfig.get_platform().startswith("mingw") WINDOWS: bool = is_windows() MACOS: bool = is_macos() LINUX: bool = is_linux() MINGW: bool = is_mingw() completion_instructions = dedent( """ If you encountered register-python-argcomplete command not found error, or if you are using zipapp, run pipx install argcomplete before running any of the following commands. Add the appropriate command to your shell's config file so that it is run on startup. You will likely have to restart or re-login for the autocompletion to start working. bash: eval "$(register-python-argcomplete pipx)" zsh: To activate completions in zsh, first make sure compinit is marked for autoload and run autoload: autoload -U compinit && compinit Afterwards you can enable completions for pipx: eval "$(register-python-argcomplete pipx)" NOTE: If your version of argcomplete is earlier than v3, you may need to have bashcompinit enabled in zsh by running: autoload -U bashcompinit bashcompinit tcsh: eval `register-python-argcomplete --shell tcsh pipx` fish: # Not required to be in the config file, only run once register-python-argcomplete --shell fish pipx >~/.config/fish/completions/pipx.fish """ ) pipx-1.6.0/src/pipx/emojis.py000066400000000000000000000015111462701651400161110ustar00rootroot00000000000000import os import sys def strtobool(val: str) -> bool: val = val.lower() if val in ("y", "yes", "t", "true", "on", "1"): return True elif val in ("n", "no", "f", "false", "off", "0"): return False else: return False def use_emojis() -> bool: # All emojis that pipx might possibly use emoji_test_str = "✨🌟⚠️đź´âŁ·âŁŻâŁźâˇżâ˘żâŁ»âŁ˝âŁľ" try: emoji_test_str.encode(sys.stderr.encoding) platform_emoji_support = True except UnicodeEncodeError: platform_emoji_support = False return strtobool(str(os.getenv("USE_EMOJI", platform_emoji_support))) EMOJI_SUPPORT = use_emojis() if EMOJI_SUPPORT: stars = "✨ 🌟 ✨" hazard = "⚠️" error = "â›”" sleep = "đź´" else: stars = "" hazard = "" error = "" sleep = "" pipx-1.6.0/src/pipx/interpreter.py000066400000000000000000000146541462701651400172020ustar00rootroot00000000000000import logging import os import shutil import subprocess import sys from pathlib import Path from typing import Optional from packaging import version from pipx.constants import FETCH_MISSING_PYTHON, WINDOWS from pipx.standalone_python import download_python_build_standalone from pipx.util import PipxError logger = logging.getLogger(__name__) def has_venv() -> bool: try: import venv # noqa: F401 except ImportError: return False return True class InterpreterResolutionError(PipxError): def __init__(self, source: str, version: str, wrap_message: bool = True): self.source = source self.version = version potentially_path = "/" in version potentially_pylauncher = "python" not in version and not potentially_path message = ( f"No executable for the provided Python version '{version}' found in {source}." " Please make sure the provided version is " ) if source == "py launcher": message += "listed when running `py --list`." if source == "PATH": message += "on your PATH or the file path is valid. " if potentially_path: message += "The provided version looks like a path, but no executable was found there." if potentially_pylauncher: message += ( "The provided version looks like a version, " "but both the python command and the Python Launcher were not found on PATH." ) if source == "the python-build-standalone project": message += "listed in https://github.com/indygreg/python-build-standalone/releases/latest." super().__init__(message, wrap_message) def find_unix_command_python(python_version: str) -> Optional[str]: try: parsed_python_version = version.parse(python_version) except version.InvalidVersion: logger.info(f"Invalid Python version: {python_version}") return None if ( parsed_python_version.epoch != 0 or parsed_python_version.is_devrelease or parsed_python_version.is_postrelease or parsed_python_version.is_prerelease ): logger.info(f"Unsupported Python version: {python_version}") return None # Python command could be `python3` or `python3.x` without micro version component python_command = f"python{'.'.join(python_version.split('.')[:2])}" python_path = shutil.which(python_command) if not python_path: logger.info(f"Command `{python_command}` was not found on the system") return None if parsed_python_version.micro != 0: logger.warning( f"The command '{python_command}' located at '{python_path}' will be used. " f"It may not match the specified version {python_version} at the micro/patch level." ) return python_path def find_python_interpreter(python_version: str, fetch_missing_python: bool = False) -> str: if Path(python_version).is_file() or shutil.which(python_version): return python_version if not WINDOWS: python_unix_command = find_unix_command_python(python_version) if python_unix_command: return python_unix_command try: py_executable = find_py_launcher_python(python_version) if py_executable: return py_executable except (subprocess.CalledProcessError, FileNotFoundError) as e: raise InterpreterResolutionError(source="py launcher", version=python_version) from e if fetch_missing_python or FETCH_MISSING_PYTHON: try: return download_python_build_standalone(python_version) except PipxError as e: raise InterpreterResolutionError(source="the python-build-standalone project", version=python_version) from e raise InterpreterResolutionError(source="PATH", version=python_version) # The following code was copied from https://github.com/uranusjr/pipx-standalone # which uses the same technique to build a completely standalone pipx # distribution. # # If we are running under the Windows embeddable distribution, # venv isn't available (and we probably don't want to use the # embeddable distribution as our applications' base Python anyway) # so we try to locate the system Python and use that instead. def find_py_launcher_python(python_version: Optional[str] = None) -> Optional[str]: py = shutil.which("py") if py and python_version: python_semver = python_version if python_version.startswith("python"): logger.warning( "Removing `python` from the start of the version, as pylauncher just expects the semantic version" ) python_semver = python_semver.lstrip("python") py = subprocess.run( [py, f"-{python_semver}", "-c", "import sys; print(sys.executable)"], capture_output=True, text=True, check=True, ).stdout.strip() return py def _find_default_windows_python() -> str: if has_venv(): return sys.executable python = find_py_launcher_python() or shutil.which("python") if python is None: raise PipxError("No suitable Python found") # If the path contains "WindowsApps", it's the store python if "WindowsApps" not in python: return python # Special treatment to detect Windows Store stub. # https://twitter.com/zooba/status/1212454929379581952 proc = subprocess.run([python, "-V"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=False) if proc.returncode != 0: # Cover the 9009 return code pre-emptively. raise PipxError("No suitable Python found") if not proc.stdout.strip(): # A real Python should print version, Windows Store stub won't. raise PipxError("No suitable Python found") return python # This executable seems to work. def _get_sys_executable() -> str: if WINDOWS: return _find_default_windows_python() else: return str(Path(sys.executable).resolve()) def _get_absolute_python_interpreter(env_python: str) -> str: which_python = shutil.which(env_python) if not which_python: raise PipxError(f"Default python interpreter '{env_python}' is invalid.") return which_python env_default_python = os.environ.get("PIPX_DEFAULT_PYTHON") if not env_default_python: DEFAULT_PYTHON = _get_sys_executable() else: DEFAULT_PYTHON = _get_absolute_python_interpreter(env_default_python) pipx-1.6.0/src/pipx/main.py000066400000000000000000001215761462701651400155650ustar00rootroot00000000000000# PYTHON_ARGCOMPLETE_OK """The command line interface to pipx""" import argparse import logging import logging.config import os import re import shlex import sys import textwrap import time import urllib.parse from pathlib import Path from typing import Any, Callable, Dict, List, Optional, Tuple import argcomplete import platformdirs from packaging.utils import canonicalize_name from pipx import commands, constants, paths from pipx.animate import hide_cursor, show_cursor from pipx.colors import bold, green from pipx.constants import ( EXIT_CODE_OK, EXIT_CODE_SPECIFIED_PYTHON_EXECUTABLE_NOT_FOUND, MINIMUM_PYTHON_VERSION, WINDOWS, ExitCode, ) from pipx.emojis import hazard from pipx.interpreter import ( DEFAULT_PYTHON, InterpreterResolutionError, find_python_interpreter, ) from pipx.util import PipxError, mkdir, pipx_wrap, rmdir from pipx.venv import VenvContainer from pipx.version import version as __version__ logger = logging.getLogger(__name__) VenvCompleter = Callable[[str], List[str]] def print_version() -> None: print(__version__) def prog_name() -> str: try: prog = os.path.basename(sys.argv[0]) if prog == "__main__.py": return f"{sys.executable} -m pipx" else: return prog except Exception: pass return "pipx" 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 apps from Python packages. Binaries can either be installed globally into isolated Virtual Environments or run directly in a temporary Virtual Environment. Virtual Environment location is {paths.ctx.venvs!s}. Symlinks to apps are placed in {paths.ctx.bin_dir!s}. Symlinks to manual pages are placed in {paths.ctx.man_dir!s}. """ ) PIPX_DESCRIPTION += pipx_wrap( """ optional environment variables: PIPX_HOME Overrides default pipx location. Virtual Environments will be installed to $PIPX_HOME/venvs. PIPX_BIN_DIR Overrides location of app installations. Apps are symlinked or copied here. PIPX_MAN_DIR Overrides location of manual pages installations. Manual pages are symlinked or copied here. PIPX_DEFAULT_PYTHON Overrides default python used for commands. USE_EMOJI Overrides emoji behavior. Default value varies based on platform. """, subsequent_indent=" " * 24, # match the indent of argparse options keep_newlines=True, ) DOC_DEFAULT_PYTHON = os.getenv("PIPX__DOC_DEFAULT_PYTHON", DEFAULT_PYTHON) INSTALL_DESCRIPTION = textwrap.dedent( f""" The install command is the preferred way to globally install apps from python packages on your system. It creates an isolated virtual environment for the package, then ensures the package's apps are accessible on your $PATH. The package's manual pages installed in share/man/man[1-9] can be viewed with man on an operating system where it is available and the path in the environment variable `PIPX_MAN_DIR` (default: {paths.DEFAULT_PIPX_MAN_DIR}) is in the man search path ($MANPATH). The result: apps 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_SPEC ... pipx install --python PYTHON PACKAGE_SPEC pipx install VCS_URL pipx install ./LOCAL_PATH pipx install ZIP_FILE pipx install TAR_GZ_FILE The PACKAGE_SPEC argument is passed directly to `pip install`. The default virtual environment location is {paths.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 app location is {paths.DEFAULT_PIPX_BIN_DIR} and can be overridden by setting the environment variable `PIPX_BIN_DIR`. The default manual pages location is {paths.DEFAULT_PIPX_MAN_DIR} and can be overridden by setting the environment variable `PIPX_MAN_DIR`. The default python executable used to install a package is {DOC_DEFAULT_PYTHON} and can be overridden by setting the environment variable `PIPX_DEFAULT_PYTHON`. """ ) class LineWrapRawTextHelpFormatter(argparse.RawDescriptionHelpFormatter): def _split_lines(self, text: str, width: int) -> List[str]: text = self._whitespace_matcher.sub(" ", text).strip() return textwrap.wrap(text, width) class InstalledVenvsCompleter: def __init__(self, venv_container: VenvContainer) -> None: self.packages = [str(p.name) for p in sorted(venv_container.iter_venv_dirs())] def use(self, prefix: str, **kwargs: Any) -> List[str]: return [f"{prefix}{x[len(prefix):]}" for x in self.packages if x.startswith(canonicalize_name(prefix))] def get_pip_args(parsed_args: Dict[str, str]) -> List[str]: pip_args: List[str] = [] if parsed_args.get("index_url"): pip_args += ["--index-url", parsed_args["index_url"]] if parsed_args.get("pip_args"): pip_args += shlex.split(parsed_args.get("pip_args", ""), posix=not WINDOWS) # make sure --editable is last because it needs to be right before # package specification if parsed_args.get("editable"): pip_args += ["--editable"] return pip_args def get_venv_args(parsed_args: Dict[str, str]) -> List[str]: venv_args: List[str] = [] if parsed_args.get("system_site_packages"): venv_args += ["--system-site-packages"] return venv_args def package_is_url(package: str, raise_error: bool = True) -> bool: url_parse_package = urllib.parse.urlparse(package) if url_parse_package.scheme and url_parse_package.netloc: if not raise_error: return True raise PipxError("Package cannot be a URL. A valid package name should be passed instead.") return False def package_is_path(package: str): if os.path.sep in package: raise PipxError( pipx_wrap( f""" Error: '{package}' looks like a path. Expected the name of an installed package. """ ) ) def run_pipx_command(args: argparse.Namespace, subparsers: Dict[str, argparse.ArgumentParser]) -> ExitCode: # noqa: C901 verbose = args.verbose if "verbose" in args else False if not constants.WINDOWS and args.is_global: paths.ctx.make_global() pip_args = get_pip_args(vars(args)) venv_args = get_venv_args(vars(args)) venv_container = VenvContainer(paths.ctx.venvs) if "package" in args: package = args.package package_is_url(package) package_is_path(package) if "spec" in args and args.spec is not None: if package_is_url(args.spec, raise_error=False): if "#egg=" not in args.spec: args.spec = args.spec + f"#egg={package}" venv_dir = venv_container.get_venv_dir(package) logger.info(f"Virtual Environment location is {venv_dir}") if "packages" in args: for package in args.packages: package_is_url(package) package_is_path(package) venv_dirs = {package: venv_container.get_venv_dir(package) for package in args.packages} venv_dirs_msg = "\n".join(f"- {key} : {value}" for key, value in venv_dirs.items()) logger.info(f"Virtual Environment locations are:\n{venv_dirs_msg}") if "skip" in args: skip_list = [canonicalize_name(x) for x in args.skip] python_flag_passed = False if "python" in args: python_flag_passed = bool(args.python) fetch_missing_python = args.fetch_missing_python try: interpreter = find_python_interpreter( args.python or DEFAULT_PYTHON, fetch_missing_python=fetch_missing_python ) args.python = interpreter except InterpreterResolutionError as e: logger.debug("Failed to resolve interpreter:", exc_info=True) print( pipx_wrap( f"{hazard} {e}", subsequent_indent=" " * 4, ) ) return EXIT_CODE_SPECIFIED_PYTHON_EXECUTABLE_NOT_FOUND if args.command == "run": commands.run( args.app_with_args[0], args.spec, args.path, args.app_with_args[1:], args.python, pip_args, venv_args, args.pypackages, verbose, not args.no_cache, ) # We should never reach here because run() is NoReturn. return ExitCode(1) elif args.command == "install": return commands.install( None, None, args.package_spec, paths.ctx.bin_dir, paths.ctx.man_dir, args.python, pip_args, venv_args, verbose, force=args.force, reinstall=False, include_dependencies=args.include_deps, preinstall_packages=args.preinstall, suffix=args.suffix, python_flag_passed=python_flag_passed, ) elif args.command == "install-all": return commands.install_all( args.spec_metadata_file, paths.ctx.bin_dir, paths.ctx.man_dir, args.python, pip_args, venv_args, verbose, force=args.force, ) elif args.command == "inject": return commands.inject( venv_dir, None, args.dependencies, args.requirements, pip_args, verbose=verbose, include_apps=args.include_apps, include_dependencies=args.include_deps, force=args.force, suffix=args.with_suffix, ) elif args.command == "uninject": return commands.uninject( venv_dir, args.dependencies, local_bin_dir=paths.ctx.bin_dir, local_man_dir=paths.ctx.man_dir, leave_deps=args.leave_deps, verbose=verbose, ) elif args.command == "upgrade": return commands.upgrade( venv_dirs, args.python, pip_args, venv_args, verbose, include_injected=args.include_injected, force=args.force, install=args.install, python_flag_passed=python_flag_passed, ) elif args.command == "upgrade-all": return commands.upgrade_all( venv_container, verbose, include_injected=args.include_injected, skip=skip_list, force=args.force, pip_args=pip_args, python_flag_passed=python_flag_passed, ) elif args.command == "upgrade-shared": return commands.upgrade_shared( verbose, pip_args, ) elif args.command == "list": return commands.list_packages( venv_container, args.include_injected, args.json, args.short, args.pinned, ) elif args.command == "interpreter": if args.interpreter_command == "list": return commands.list_interpreters(venv_container) elif args.interpreter_command == "prune": return commands.prune_interpreters(venv_container) elif args.interpreter_command == "upgrade": return commands.upgrade_interpreters(venv_container, verbose) elif args.interpreter_command is None: subparsers["interpreter"].print_help() return EXIT_CODE_OK else: raise PipxError(f"Unknown interpreter command {args.interpreter_command}") elif args.command == "pin": return commands.pin(venv_dir, verbose, skip_list, args.injected_only) elif args.command == "unpin": return commands.unpin(venv_dir, verbose) elif args.command == "uninstall": return commands.uninstall(venv_dir, paths.ctx.bin_dir, paths.ctx.man_dir, verbose) elif args.command == "uninstall-all": return commands.uninstall_all( venv_container, paths.ctx.bin_dir, paths.ctx.man_dir, verbose, ) elif args.command == "reinstall": return commands.reinstall( venv_dir=venv_dir, local_bin_dir=paths.ctx.bin_dir, local_man_dir=paths.ctx.man_dir, python=args.python, verbose=verbose, python_flag_passed=python_flag_passed, ) elif args.command == "reinstall-all": return commands.reinstall_all( venv_container, paths.ctx.bin_dir, paths.ctx.man_dir, args.python, verbose, skip=skip_list, python_flag_passed=python_flag_passed, ) elif args.command == "runpip": if not venv_dir: raise PipxError("Developer error: venv_dir is not defined.") return commands.run_pip(package, venv_dir, args.pipargs, args.verbose) elif args.command == "ensurepath": try: return commands.ensure_pipx_paths(force=args.force) except Exception as e: logger.debug("Uncaught Exception:", exc_info=True) raise PipxError(str(e), wrap_message=False) from None elif args.command == "completions": print(constants.completion_instructions) return ExitCode(0) elif args.command == "environment": return commands.environment(value=args.value) else: raise PipxError(f"Unknown command {args.command}") def add_pip_venv_args(parser: argparse.ArgumentParser) -> None: 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_dependencies(parser: argparse.ArgumentParser) -> None: parser.add_argument("--include-deps", help="Include apps of dependent packages", action="store_true") def add_python_options(parser: argparse.ArgumentParser) -> None: parser.add_argument( "--python", help=( "Python to install with. Possible values can be the executable name (python3.11), " "the version of an available system Python or to pass to py launcher (3.11), " f"or the full path to the executable. Requires Python {MINIMUM_PYTHON_VERSION} or above." ), ) parser.add_argument( "--fetch-missing-python", action="store_true", help=( "Whether to fetch a standalone python build from GitHub if the specified python version is not found locally on the system." ), ) def _add_install(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "install", help="Install a package", formatter_class=LineWrapRawTextHelpFormatter, description=INSTALL_DESCRIPTION, parents=[shared_parser], ) p.add_argument("package_spec", help="package name(s) or pip installation spec(s)", nargs="+") add_include_dependencies(p) p.add_argument( "--force", "-f", action="store_true", help="Modify existing virtual environment and files in PIPX_BIN_DIR and PIPX_MAN_DIR", ) p.add_argument( "--suffix", default="", help=( "Optional suffix for virtual environment and executable names. " "NOTE: The suffix feature is experimental and subject to change." ), ) add_python_options(p) p.add_argument( "--preinstall", action="append", help=( "Optional package to be installed into the Virtual Environment before " "installing the main package. Use this flag multiple times if you want to preinstall multiple packages." ), ) add_pip_venv_args(p) def _add_install_all(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "install-all", help="Install all packages", formatter_class=LineWrapRawTextHelpFormatter, description="Installs all the packages according to spec metadata file.", parents=[shared_parser], ) p.add_argument("spec_metadata_file", help="Spec metadata file generated from pipx list --json") p.add_argument( "--force", "-f", action="store_true", help="Modify existing virtual environment and files in PIPX_BIN_DIR and PIPX_MAN_DIR", ) add_python_options(p) add_pip_venv_args(p) def _add_inject(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "inject", help="Install packages into an existing Virtual Environment", description="Installs packages to an existing pipx-managed virtual environment.", parents=[shared_parser], ) p.add_argument( "package", help="Name of the existing pipx-managed Virtual Environment to inject into", ).completer = venv_completer p.add_argument( "dependencies", nargs="*", help="the packages to inject into the Virtual Environment--either package name or pip package spec", ) p.add_argument( "-r", "--requirement", dest="requirements", action="append", default=[], metavar="file", help=( "file containing the packages to inject into the Virtual Environment--" "one package name or pip package spec per line. " "May be specified multiple times." ), ) p.add_argument( "--include-apps", action="store_true", help="Add apps from the injected packages onto your PATH and expose their manual pages", ) p.add_argument( "--include-deps", help="Include apps of dependent packages. Implies --include-apps", action="store_true", ) add_pip_venv_args(p) p.add_argument( "--force", "-f", action="store_true", help="Modify existing virtual environment and files in PIPX_BIN_DIR and PIPX_MAN_DIR", ) p.add_argument( "--with-suffix", action="store_true", help="Add the suffix (if given) of the Virtual Environment to the packages to inject", ) def _add_uninject(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser): p = subparsers.add_parser( "uninject", help="Uninstall injected packages from an existing Virtual Environment", description="Uninstalls injected packages from an existing pipx-managed virtual environment.", parents=[shared_parser], ) p.add_argument( "package", help="Name of the existing pipx-managed Virtual Environment to inject into", ).completer = venv_completer p.add_argument( "dependencies", nargs="+", help="the package names to uninject from the Virtual Environment", ) p.add_argument( "--leave-deps", action="store_true", help="Only uninstall the main injected package but leave its dependencies installed.", ) def _add_pin(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "pin", description="Pin the specified package to prevent it from being upgraded", parents=[shared_parser], ) p.add_argument("package", help="Installed package to pin") p.add_argument( "--injected-only", action="store_true", help=( "Pin injected packages in venv only, so that they will not be upgraded during upgrade operations. " "Note that this should not be passed if you wish to pin both main package and injected packages." ), ) p.add_argument( "--skip", nargs="+", default=[], help="Skip these packages. Implies `--injected-only`.", ) def _add_unpin(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "unpin", description="Unpin the specified package and all injected packages in its venv to allow them to be upgraded", parents=[shared_parser], ) p.add_argument("package", help="Installed package to unpin") def _add_upgrade(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "upgrade", help="Upgrade a package", description="Upgrade package(s) in pipx-managed Virtual Environment(s) by running 'pip install --upgrade PACKAGE'", parents=[shared_parser], ) p.add_argument("packages", help="package names(s) to upgrade", nargs="+").completer = venv_completer p.add_argument( "--include-injected", action="store_true", help="Also upgrade packages injected into the main app's environment", ) p.add_argument( "--force", "-f", action="store_true", help="Modify existing virtual environment and files in PIPX_BIN_DIR and PIPX_MAN_DIR", ) add_pip_venv_args(p) p.add_argument( "--install", action="store_true", help="Install package spec if missing", ) add_python_options(p) def _add_upgrade_all(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: 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'", parents=[shared_parser], ) p.add_argument( "--include-injected", action="store_true", help="Also upgrade packages injected into the main app's environment", ) p.add_argument("--skip", nargs="+", default=[], help="skip these packages") p.add_argument( "--force", "-f", action="store_true", help="Modify existing virtual environment and files in PIPX_BIN_DIR and PIPX_MAN_DIR", ) def _add_upgrade_shared(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "upgrade-shared", help="Upgrade shared libraries.", description="Upgrade shared libraries.", parents=[shared_parser], ) p.add_argument( "--pip-args", help="Arbitrary pip arguments to pass directly to pip install/upgrade commands", ) def _add_uninstall(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "uninstall", help="Uninstall a package", description="Uninstalls a pipx-managed Virtual Environment by deleting it and any files that point to its apps.", parents=[shared_parser], ) p.add_argument("package").completer = venv_completer def _add_uninstall_all(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: subparsers.add_parser( "uninstall-all", help="Uninstall all packages", description="Uninstall all pipx-managed packages", parents=[shared_parser], ) def _add_reinstall(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "reinstall", formatter_class=LineWrapRawTextHelpFormatter, help="Reinstall a package", description=textwrap.dedent( """ Reinstalls a package. Package is uninstalled, then installed with pipx install PACKAGE with the same options used in the original install of PACKAGE. """ ), parents=[shared_parser], ) p.add_argument("package").completer = venv_completer add_python_options(p) def _add_reinstall_all(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "reinstall-all", formatter_class=LineWrapRawTextHelpFormatter, help="Reinstall all packages", description=textwrap.dedent( """ Reinstalls all packages. Packages are uninstalled, then installed with pipx install PACKAGE with the same options used in the original install of PACKAGE. This is useful if you upgraded to a new version of Python and want all your packages to use the latest as well. """ ), parents=[shared_parser], ) add_python_options(p) p.add_argument("--skip", nargs="+", default=[], help="skip these packages") def _add_list(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "list", help="List installed packages", description="List packages and apps installed with pipx", parents=[shared_parser], ) p.add_argument( "--include-injected", action="store_true", help="Show packages injected into the main app's environment", ) g = p.add_mutually_exclusive_group() g.add_argument("--json", action="store_true", help="Output rich data in json format.") g.add_argument("--short", action="store_true", help="List packages only.") g.add_argument( "--pinned", action="store_true", help="List pinned packages only. Pass --include-injected at the same time to list injected packages that were pinned.", ) g.add_argument("--skip-maintenance", action="store_true", help="(deprecated) No-op") def _add_interpreter( subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser ) -> argparse.ArgumentParser: p: argparse.ArgumentParser = subparsers.add_parser( "interpreter", help="Interact with interpreters managed by pipx", description="Interact with interpreters managed by pipx", parents=[shared_parser], ) s = p.add_subparsers( title="subcommands", description="Get help for commands with pipx interpreter COMMAND --help", dest="interpreter_command", ) s.add_parser("list", help="List available interpreters", description="List available interpreters") s.add_parser("prune", help="Prune unused interpreters", description="Prune unused interpreters") s.add_parser( "upgrade", help="Upgrade installed interpreters to the latest available micro/patch version", description="Upgrade installed interpreters to the latest available micro/patch version", ) return p def _add_run(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "run", formatter_class=LineWrapRawTextHelpFormatter, help=( "Download the latest version of a package to a temporary virtual environment, " "then run an app from it. Also compatible with local `__pypackages__` " "directory (experimental)." ), description=textwrap.dedent( f""" Download the latest version of a package to a temporary virtual environment, then run an app from it. The environment will be cached and re-used for up to {constants.TEMP_VENV_EXPIRATION_THRESHOLD_DAYS} days. This means subsequent calls to 'run' for the same package will be faster since they can reuse the cached Virtual Environment. In support of PEP 582 'run' will use apps found in a local __pypackages__ directory, if present. Please note that this behavior is experimental, and acts as a companion tool to pythonloc. It may be modified or removed in the future. See https://github.com/cs01/pythonloc. """ ), parents=[shared_parser], ) p.add_argument( "--no-cache", action="store_true", help="Do not reuse cached virtual environment if it exists", ) p.add_argument( "app_with_args", metavar="app ...", nargs=argparse.REMAINDER, help="app/package name and any arguments to be passed to it", default=[], ) p.add_argument("--path", action="store_true", help="Interpret app name as a local path") p.add_argument( "--pypackages", action="store_true", help="Require app to be run from local __pypackages__ directory", ) p.add_argument("--spec", help=SPEC_HELP) add_python_options(p) add_pip_venv_args(p) p.set_defaults(subparser=p) # modify usage text to show required app argument p.usage = re.sub(r"^usage: ", "", p.format_usage()) # add a double-dash to usage text to show requirement before app p.usage = re.sub(r"\.\.\.", "app ...", p.usage) def _add_runpip(subparsers, venv_completer: VenvCompleter, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "runpip", help="Run pip in an existing pipx-managed Virtual Environment", description="Run pip in an existing pipx-managed Virtual Environment", parents=[shared_parser], ) p.add_argument( "package", help="Name of the existing pipx-managed Virtual Environment to run pip in", ).completer = venv_completer p.add_argument( "pipargs", nargs=argparse.REMAINDER, default=[], help="Arguments to forward to pip command", ) def _add_ensurepath(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "ensurepath", help=("Ensure directories necessary for pipx operation are in your PATH environment variable."), description=( "Ensure directory where pipx stores apps is in your " "PATH environment variable. Also if pipx was installed via " "`pip install --user`, ensure pipx itself is in your PATH. " "Note that running this may modify " "your shell's configuration file(s) such as '~/.bashrc'." ), parents=[shared_parser], ) p.add_argument( "--force", "-f", action="store_true", help=( "Add text to your shell's config file even if it looks like your " "PATH already contains paths to pipx and pipx-install apps." ), ) def _add_environment(subparsers: argparse._SubParsersAction, shared_parser: argparse.ArgumentParser) -> None: p = subparsers.add_parser( "environment", formatter_class=LineWrapRawTextHelpFormatter, help="Print a list of environment variables and paths used by pipx.", description=textwrap.dedent( """ Prints the names and current values of environment variables used by pipx, followed by internal pipx variables which are derived from the environment variables and platform specific default values. Available variables: PIPX_HOME, PIPX_BIN_DIR, PIPX_MAN_DIR, PIPX_SHARED_LIBS, PIPX_LOCAL_VENVS, PIPX_LOG_DIR, PIPX_TRASH_DIR, PIPX_VENV_CACHEDIR, PIPX_DEFAULT_PYTHON, USE_EMOJI """ ), parents=[shared_parser], ) p.add_argument("--value", "-V", metavar="VARIABLE", help="Print the value of the variable.") def get_command_parser() -> Tuple[argparse.ArgumentParser, Dict[str, argparse.ArgumentParser]]: venv_container = VenvContainer(paths.ctx.venvs) completer_venvs = InstalledVenvsCompleter(venv_container) shared_parser = argparse.ArgumentParser(add_help=False) shared_parser.add_argument( "--quiet", "-q", action="count", default=0, help=( "Give less output. May be used multiple times corresponding to the" " ERROR and CRITICAL logging levels. The count maxes out at 2." ), ) shared_parser.add_argument( "--verbose", "-v", action="count", default=0, help=( "Give more output. May be used multiple times corresponding to the" " INFO, DEBUG and NOTSET logging levels. The count maxes out at 3." ), ) if not constants.WINDOWS: shared_parser.add_argument( "--global", action="store_true", dest="is_global", help="Perform action globally for all users.", ) parser = argparse.ArgumentParser( prog=prog_name(), formatter_class=LineWrapRawTextHelpFormatter, description=PIPX_DESCRIPTION, parents=[shared_parser], ) parser.man_short_description = PIPX_DESCRIPTION.splitlines()[1] # type: ignore[attr-defined] subparsers = parser.add_subparsers(dest="command", description="Get help for commands with pipx COMMAND --help") subparsers_with_subcommands = {} _add_install(subparsers, shared_parser) _add_install_all(subparsers, shared_parser) _add_uninject(subparsers, completer_venvs.use, shared_parser) _add_inject(subparsers, completer_venvs.use, shared_parser) _add_pin(subparsers, completer_venvs.use, shared_parser) _add_unpin(subparsers, completer_venvs.use, shared_parser) _add_upgrade(subparsers, completer_venvs.use, shared_parser) _add_upgrade_all(subparsers, shared_parser) _add_upgrade_shared(subparsers, shared_parser) _add_uninstall(subparsers, completer_venvs.use, shared_parser) _add_uninstall_all(subparsers, shared_parser) _add_reinstall(subparsers, completer_venvs.use, shared_parser) _add_reinstall_all(subparsers, shared_parser) _add_list(subparsers, shared_parser) subparsers_with_subcommands["interpreter"] = _add_interpreter(subparsers, shared_parser) _add_run(subparsers, shared_parser) _add_runpip(subparsers, completer_venvs.use, shared_parser) _add_ensurepath(subparsers, shared_parser) _add_environment(subparsers, shared_parser) parser.add_argument("--version", action="store_true", help="Print version and exit") subparsers.add_parser( "completions", help="Print instructions on enabling shell completions for pipx", description="Print instructions on enabling shell completions for pipx", parents=[shared_parser], ) return parser, subparsers_with_subcommands def delete_oldest_logs(file_list: List[Path], keep_number: int) -> None: file_list = sorted(file_list) if len(file_list) > keep_number: for existing_file in file_list[:-keep_number]: try: existing_file.unlink() except FileNotFoundError: pass def _setup_log_file(pipx_log_dir: Optional[Path] = None) -> Path: max_logs = 10 pipx_log_dir = pipx_log_dir or paths.ctx.logs # don't use utils.mkdir, to prevent emission of log message pipx_log_dir.mkdir(parents=True, exist_ok=True) delete_oldest_logs(list(pipx_log_dir.glob("cmd_*[0-9].log")), max_logs) delete_oldest_logs(list(pipx_log_dir.glob("cmd_*_pip_errors.log")), max_logs) datetime_str = time.strftime("%Y-%m-%d_%H.%M.%S") log_file = pipx_log_dir / f"cmd_{datetime_str}.log" counter = 1 while log_file.exists() and counter < 10: log_file = pipx_log_dir / f"cmd_{datetime_str}_{counter}.log" counter += 1 log_file.touch() return log_file def setup_log_file() -> Path: try: return _setup_log_file() except PermissionError: return _setup_log_file(platformdirs.user_log_path("pipx")) def setup_logging(verbose: int) -> None: pipx_str = bold(green("pipx >")) if sys.stdout.isatty() else "pipx >" paths.ctx.log_file = setup_log_file() # Determine logging level, a value between 0 and 50 level_number = min(max(0, logging.WARNING - 10 * verbose), 50) level = logging.getLevelName(level_number) # "incremental" is False so previous pytest tests don't accumulate handlers logging_config = { "version": 1, "formatters": { "stream_nonverbose": { "class": "logging.Formatter", "format": "{message}", "style": "{", }, "stream_verbose": { "class": "logging.Formatter", "format": pipx_str + "({funcName}:{lineno}): {message}", "style": "{", }, "file": { "class": "logging.Formatter", "format": "{relativeCreated: >8.1f}ms ({funcName}:{lineno}): {message}", "style": "{", }, }, "handlers": { "stream": { "class": "logging.StreamHandler", "formatter": "stream_verbose" if verbose else "stream_nonverbose", "level": level, }, "file": { "class": "logging.FileHandler", "formatter": "file", "filename": str(paths.ctx.log_file), "encoding": "utf-8", "level": "DEBUG", }, }, "loggers": {"pipx": {"handlers": ["stream", "file"], "level": "DEBUG"}}, "incremental": False, } logging.config.dictConfig(logging_config) def setup(args: argparse.Namespace) -> None: if "version" in args and args.version: print_version() sys.exit(0) verbose = args.verbose - args.quiet setup_logging(verbose) logger.debug(f"{time.strftime('%Y-%m-%d %H:%M:%S')}") logger.debug(f"{' '.join(sys.argv)}") logger.info(f"pipx version is {__version__}") logger.info(f"Default python interpreter is '{DEFAULT_PYTHON}'") mkdir(paths.ctx.venvs) mkdir(paths.ctx.bin_dir) mkdir(paths.ctx.man_dir) mkdir(paths.ctx.venv_cache) mkdir(paths.ctx.standalone_python_cachedir) for cachedir in [ paths.ctx.venv_cache, paths.ctx.standalone_python_cachedir, ]: cachedir_tag = cachedir / "CACHEDIR.TAG" if not cachedir_tag.exists(): logger.debug("Adding CACHEDIR.TAG to cache directory") signature = ( "Signature: 8a477f597d28d172789f06886806bc55\n" "# This file is a cache directory tag created by pipx.\n" "# For information about cache directory tags, see:\n" "# https://bford.info/cachedir/\n" ) with open(cachedir_tag, "w") as file: file.write(signature) rmdir(paths.ctx.trash, False) old_pipx_venv_location = paths.ctx.venvs / "pipx-app" if old_pipx_venv_location.exists(): logger.warning( pipx_wrap( f""" {hazard} A virtual environment for pipx was detected at {old_pipx_venv_location!s}. The 'pipx-app' package has been renamed back to 'pipx' (https://github.com/pypa/pipx/issues/82). """, subsequent_indent=" " * 4, ) ) def check_args(parsed_pipx_args: argparse.Namespace) -> None: if parsed_pipx_args.command == "run": # we manually discard a first -- because using nargs=argparse.REMAINDER # will not do it automatically if parsed_pipx_args.app_with_args and parsed_pipx_args.app_with_args[0] == "--": parsed_pipx_args.app_with_args.pop(0) # since we would like app to be required but not in a separate argparse # add_argument, we implement our own missing required arg error if not parsed_pipx_args.app_with_args: parsed_pipx_args.subparser.error("the following arguments are required: app") def cli() -> ExitCode: """Entry point from command line""" try: hide_cursor() parser, subparsers = get_command_parser() argcomplete.autocomplete(parser) parsed_pipx_args = parser.parse_args() setup(parsed_pipx_args) check_args(parsed_pipx_args) if not parsed_pipx_args.command: parser.print_help() return ExitCode(1) return run_pipx_command(parsed_pipx_args, subparsers) except PipxError as e: print(str(e), file=sys.stderr) logger.debug(f"PipxError: {e}", exc_info=True) return ExitCode(1) except KeyboardInterrupt: return ExitCode(1) except Exception: logger.debug("Uncaught Exception:", exc_info=True) raise finally: logger.debug("pipx finished.") show_cursor() if __name__ == "__main__": sys.exit(cli()) pipx-1.6.0/src/pipx/package_specifier.py000066400000000000000000000206441462701651400202570ustar00rootroot00000000000000# Valid package specifiers for pipx: # PEP508-compliant # git+ # # # # import logging import re import urllib.parse from dataclasses import dataclass from pathlib import Path from typing import List, Optional, Set, Tuple from packaging.requirements import InvalidRequirement, Requirement from packaging.specifiers import SpecifierSet from packaging.utils import canonicalize_name from pipx.emojis import hazard from pipx.util import PipxError, pipx_wrap logger = logging.getLogger(__name__) ARCHIVE_EXTENSIONS = (".whl", ".tar.gz", ".zip") @dataclass(frozen=True) class ParsedPackage: valid_pep508: Optional[Requirement] valid_url: Optional[str] valid_local_path: Optional[str] def _split_path_extras(package_spec: str) -> Tuple[str, str]: """Returns (path, extras_string)""" package_spec_extras_re = re.search(r"(.+)(\[.+\])", package_spec) if package_spec_extras_re: return (package_spec_extras_re.group(1), package_spec_extras_re.group(2)) else: return (package_spec, "") def _check_package_path(package_path: str) -> Tuple[Path, bool]: pkg_path = Path(package_path) pkg_path_exists = pkg_path.exists() return (pkg_path, pkg_path_exists) def _parse_specifier(package_spec: str) -> ParsedPackage: """Parse package_spec as would be given to pipx""" # If package_spec is valid pypi name, pip will always treat it as a # pypi package, not checking for local path. # We replicate pypi precedence here (only non-valid-pypi names # initiate check for local path, e.g. './package-name') valid_pep508 = None valid_url = None valid_local_path = None try: package_req = Requirement(package_spec) except InvalidRequirement: # not a valid PEP508 package specification pass else: # valid PEP508 package specification valid_pep508 = package_req if valid_pep508 and package_req.name.endswith(ARCHIVE_EXTENSIONS): # It might be a local archive (package_path, package_path_exists) = _check_package_path(package_req.name) if package_path_exists: valid_local_path = str(package_path.resolve()) else: raise PipxError(f"{package_path} does not exist") # If this looks like a URL, treat it as such. if not valid_pep508: parsed_url = urllib.parse.urlsplit(package_spec) if parsed_url.scheme and parsed_url.netloc: valid_url = package_spec # Treat the input as a local path if it does not look like a PEP 508 # specifier nor a URL. In this case we want to split out the extra part. if not valid_pep508 and not valid_url: (package_path_str, package_extras_str) = _split_path_extras(package_spec) (package_path, package_path_exists) = _check_package_path(package_path_str) if package_path_exists: valid_local_path = str(package_path.resolve()) + package_extras_str if not valid_pep508 and not valid_url and not valid_local_path: raise PipxError(f"Unable to parse package spec: {package_spec}") if valid_pep508 and valid_local_path: # It is a valid local path without "./" # Use valid_local_path valid_pep508 = None return ParsedPackage( valid_pep508=valid_pep508, valid_url=valid_url, valid_local_path=valid_local_path, ) def package_or_url_from_pep508(requirement: Requirement, remove_version_specifiers: bool = False) -> str: requirement.marker = None requirement.name = canonicalize_name(requirement.name) if remove_version_specifiers: requirement.specifier = SpecifierSet("") return str(requirement) def _parsed_package_to_package_or_url(parsed_package: ParsedPackage, remove_version_specifiers: bool) -> str: if parsed_package.valid_pep508 is not None: if parsed_package.valid_pep508.marker is not None: logger.warning( pipx_wrap( f""" {hazard} Ignoring environment markers ({parsed_package.valid_pep508.marker}) in package specification. Use pipx options to specify this type of information. """, subsequent_indent=" " * 4, ) ) package_or_url = package_or_url_from_pep508( parsed_package.valid_pep508, remove_version_specifiers=remove_version_specifiers, ) elif parsed_package.valid_url is not None: package_or_url = parsed_package.valid_url elif parsed_package.valid_local_path is not None: package_or_url = parsed_package.valid_local_path logger.info(f"cleaned package spec: {package_or_url}") return package_or_url def parse_specifier_for_install(package_spec: str, pip_args: List[str]) -> Tuple[str, List[str]]: """Return package_or_url and pip_args suitable for pip install Specifically: * Strip any markers (e.g. python_version > "3.4") * Ensure --editable is removed for any package_spec not a local path * Convert local paths to absolute paths """ parsed_package = _parse_specifier(package_spec) package_or_url = _parsed_package_to_package_or_url(parsed_package, remove_version_specifiers=False) if "--editable" in pip_args and not parsed_package.valid_local_path: logger.warning( pipx_wrap( f""" {hazard} Ignoring --editable install option. pipx disallows it for anything but a local path, to avoid having to create a new src/ directory. """, subsequent_indent=" " * 4, ) ) pip_args.remove("--editable") return (package_or_url, pip_args) def parse_specifier_for_metadata(package_spec: str) -> str: """Return package_or_url suitable for pipx metadata Specifically: * Strip any markers (e.g. python_version > 3.4) * Convert local paths to absolute paths """ parsed_package = _parse_specifier(package_spec) return _parsed_package_to_package_or_url(parsed_package, remove_version_specifiers=False) def parse_specifier_for_upgrade(package_spec: str) -> str: """Return package_or_url suitable for pip upgrade Specifically: * Strip any version specifiers (e.g. package == 1.5.4) * Strip any markers (e.g. python_version > 3.4) * Convert local paths to absolute paths """ parsed_package = _parse_specifier(package_spec) return _parsed_package_to_package_or_url(parsed_package, remove_version_specifiers=True) def get_extras(package_spec: str) -> Set[str]: parsed_package = _parse_specifier(package_spec) if parsed_package.valid_pep508 and parsed_package.valid_pep508.extras is not None: return parsed_package.valid_pep508.extras elif parsed_package.valid_local_path: (_, package_extras_str) = _split_path_extras(parsed_package.valid_local_path) return Requirement("notapackage" + package_extras_str).extras return set() def valid_pypi_name(package_spec: str) -> Optional[str]: try: package_req = Requirement(package_spec) except InvalidRequirement: # not a valid PEP508 package specification return None if package_req.url or package_req.name.endswith(ARCHIVE_EXTENSIONS): # package name supplied by user might not match package found in URL, # also if package name ends with archive extension, it might be a local archive file, # so force package name determination the long way return None return canonicalize_name(package_req.name) def fix_package_name(package_or_url: str, package_name: str) -> str: try: package_req = Requirement(package_or_url) except InvalidRequirement: # not a valid PEP508 package specification return package_or_url if package_req.name.endswith(ARCHIVE_EXTENSIONS): return str(package_req) if canonicalize_name(package_req.name) != canonicalize_name(package_name): logger.warning( pipx_wrap( f""" {hazard} Name supplied in package specifier was {package_req.name!r} but package found has name {package_name!r}. Using {package_name!r}. """, subsequent_indent=" " * 4, ) ) package_req.name = package_name return str(package_req) pipx-1.6.0/src/pipx/paths.py000066400000000000000000000120171462701651400157450ustar00rootroot00000000000000import logging import os from pathlib import Path from typing import List, Optional, Union from platformdirs import user_cache_path, user_data_path, user_log_path from pipx.constants import LINUX, WINDOWS from pipx.emojis import hazard from pipx.util import pipx_wrap if LINUX: DEFAULT_PIPX_HOME = user_data_path("pipx") FALLBACK_PIPX_HOMES = [Path.home() / ".local/pipx"] elif WINDOWS: DEFAULT_PIPX_HOME = Path.home() / "pipx" FALLBACK_PIPX_HOMES = [Path.home() / ".local/pipx", user_data_path("pipx")] else: DEFAULT_PIPX_HOME = Path.home() / ".local/pipx" FALLBACK_PIPX_HOMES = [user_data_path("pipx")] DEFAULT_PIPX_BIN_DIR = Path.home() / ".local/bin" DEFAULT_PIPX_MAN_DIR = Path.home() / ".local/share/man" DEFAULT_PIPX_GLOBAL_HOME = "/opt/pipx" DEFAULT_PIPX_GLOBAL_BIN_DIR = "/usr/local/bin" DEFAULT_PIPX_GLOBAL_MAN_DIR = "/usr/local/share/man" logger = logging.getLogger(__name__) def get_expanded_environ(env_name: str) -> Optional[Path]: val = os.environ.get(env_name) if val is not None: return Path(val).expanduser().resolve() return val class _PathContext: _base_home: Optional[Union[Path, str]] = get_expanded_environ("PIPX_HOME") _base_bin: Optional[Union[Path, str]] = get_expanded_environ("PIPX_BIN_DIR") _base_man: Optional[Union[Path, str]] = get_expanded_environ("PIPX_MAN_DIR") _base_shared_libs: Optional[Union[Path, str]] = get_expanded_environ("PIPX_SHARED_LIBS") _fallback_homes: List[Path] = FALLBACK_PIPX_HOMES _fallback_home: Optional[Path] = next(iter([fallback for fallback in _fallback_homes if fallback.exists()]), None) _home_exists: bool = _base_home is not None or any(fallback.exists() for fallback in _fallback_homes) log_file: Optional[Path] = None @property def venvs(self) -> Path: return self.home / "venvs" @property def logs(self) -> Path: if self._home_exists or not LINUX: return self.home / "logs" return user_log_path("pipx") @property def trash(self) -> Path: if self._home_exists: return self.home / ".trash" return self.home / "trash" @property def venv_cache(self) -> Path: if self._home_exists or not LINUX: return self.home / ".cache" return user_cache_path("pipx") @property def bin_dir(self) -> Path: return Path(self._base_bin or DEFAULT_PIPX_BIN_DIR).resolve() @property def man_dir(self) -> Path: return Path(self._base_man or DEFAULT_PIPX_MAN_DIR).resolve() @property def home(self) -> Path: if self._base_home: home = Path(self._base_home) elif self._fallback_home: home = self._fallback_home else: home = Path(DEFAULT_PIPX_HOME) return home.resolve() @property def shared_libs(self) -> Path: return Path(self._base_shared_libs or self.home / "shared").resolve() def make_local(self) -> None: self._base_home = get_expanded_environ("PIPX_HOME") self._base_bin = get_expanded_environ("PIPX_BIN_DIR") self._base_man = get_expanded_environ("PIPX_MAN_DIR") self._home_exists = self._base_home is not None or any(fallback.exists() for fallback in self._fallback_homes) def make_global(self) -> None: self._base_home = get_expanded_environ("PIPX_GLOBAL_HOME") or DEFAULT_PIPX_GLOBAL_HOME self._base_bin = get_expanded_environ("PIPX_GLOBAL_BIN_DIR") or DEFAULT_PIPX_GLOBAL_BIN_DIR self._base_man = get_expanded_environ("PIPX_GLOBAL_MAN_DIR") or DEFAULT_PIPX_GLOBAL_MAN_DIR self._home_exists = self._base_home is not None or any(fallback.exists() for fallback in self._fallback_homes) @property def standalone_python_cachedir(self) -> Path: return self.home / "py" def log_warnings(self): if " " in str(self.home): logger.warning( pipx_wrap( ( f"{hazard} Found a space in the home path. We heavily discourage this, due to " "multiple incompatibilities. Please check our docs for more information on this, " "as well as some pointers on how to migrate to a different home path." ), subsequent_indent=" " * 4, ) ) fallback_home_exists = self._fallback_home is not None and self._fallback_home.exists() specific_home_exists = self.home != self._fallback_home if fallback_home_exists and specific_home_exists: logger.info( pipx_wrap( ( f"Both a specific pipx home folder ({self.home}) and the fallback " f"pipx home folder ({self._fallback_home}) exist. If you are done migrating from the" "fallback to the new location, it is safe to delete the fallback location." ), subsequent_indent=" " * 4, ) ) ctx = _PathContext() ctx.log_warnings() pipx-1.6.0/src/pipx/pipx_metadata_file.py000066400000000000000000000160651462701651400204540ustar00rootroot00000000000000import json import logging from dataclasses import asdict, dataclass, field from pathlib import Path from typing import Any, Dict, List, Optional, Union from pipx.emojis import hazard from pipx.util import PipxError, pipx_wrap logger = logging.getLogger(__name__) PIPX_INFO_FILENAME = "pipx_metadata.json" class JsonEncoderHandlesPath(json.JSONEncoder): def default(self, obj: Any) -> Any: # only handles what json.JSONEncoder doesn't understand by default if isinstance(obj, Path): return {"__type__": "Path", "__Path__": str(obj)} return super().default(obj) def _json_decoder_object_hook(json_dict: Dict[str, Any]) -> Union[Dict[str, Any], Path]: if json_dict.get("__type__") == "Path" and "__Path__" in json_dict: return Path(json_dict["__Path__"]) return json_dict @dataclass(frozen=True) class PackageInfo: package: Optional[str] package_or_url: Optional[str] pip_args: List[str] include_dependencies: bool include_apps: bool apps: List[str] app_paths: List[Path] apps_of_dependencies: List[str] app_paths_of_dependencies: Dict[str, List[Path]] package_version: str man_pages: List[str] = field(default_factory=list) man_paths: List[Path] = field(default_factory=list) man_pages_of_dependencies: List[str] = field(default_factory=list) man_paths_of_dependencies: Dict[str, List[Path]] = field(default_factory=dict) suffix: str = "" pinned: bool = False class PipxMetadata: # Only change this if file format changes # V0.1 -> original version # V0.2 -> Improve handling of suffixes # V0.3 -> Add man pages fields # V0.4 -> Add source interpreter # V0.5 -> Add pinned __METADATA_VERSION__: str = "0.5" def __init__(self, venv_dir: Path, read: bool = True): self.venv_dir = venv_dir # We init this instance with reasonable fallback defaults for all # members, EXCEPT for those we cannot know: # self.main_package.package=None # self.main_package.package_or_url=None # self.python_version=None self.main_package = PackageInfo( package=None, package_or_url=None, pip_args=[], include_dependencies=False, include_apps=True, # always True for main_package apps=[], app_paths=[], apps_of_dependencies=[], app_paths_of_dependencies={}, man_pages=[], man_paths=[], man_pages_of_dependencies=[], man_paths_of_dependencies={}, package_version="", ) self.python_version: Optional[str] = None self.source_interpreter: Optional[Path] = None self.venv_args: List[str] = [] self.injected_packages: Dict[str, PackageInfo] = {} if read: self.read() def to_dict(self) -> Dict[str, Any]: return { "main_package": asdict(self.main_package), "python_version": self.python_version, "source_interpreter": self.source_interpreter, "venv_args": self.venv_args, "injected_packages": {name: asdict(data) for (name, data) in self.injected_packages.items()}, "pipx_metadata_version": self.__METADATA_VERSION__, } def _convert_legacy_metadata(self, metadata_dict: Dict[str, Any]) -> Dict[str, Any]: if metadata_dict["pipx_metadata_version"] in (self.__METADATA_VERSION__): pass elif metadata_dict["pipx_metadata_version"] == "0.4": metadata_dict["pinned"] = False elif metadata_dict["pipx_metadata_version"] in ("0.2", "0.3"): metadata_dict["source_interpreter"] = None elif metadata_dict["pipx_metadata_version"] == "0.1": main_package_data = metadata_dict["main_package"] if main_package_data["package"] != self.venv_dir.name: # handle older suffixed packages gracefully main_package_data["suffix"] = self.venv_dir.name.replace(main_package_data["package"], "") metadata_dict["source_interpreter"] = None else: raise PipxError( f""" {self.venv_dir.name}: Unknown metadata version {metadata_dict['pipx_metadata_version']}. Perhaps it was installed with a later version of pipx. """ ) return metadata_dict def from_dict(self, input_dict: Dict[str, Any]) -> None: input_dict = self._convert_legacy_metadata(input_dict) self.main_package = PackageInfo(**input_dict["main_package"]) self.python_version = input_dict["python_version"] self.source_interpreter = ( Path(input_dict["source_interpreter"]) if input_dict.get("source_interpreter") else None ) self.venv_args = input_dict["venv_args"] self.injected_packages = { f"{name}{data.get('suffix', '')}": PackageInfo(**data) for (name, data) in input_dict["injected_packages"].items() } def _validate_before_write(self) -> None: if ( self.main_package.package is None or self.main_package.package_or_url is None or not self.main_package.include_apps ): logger.debug(f"PipxMetadata corrupt:\n{self.to_dict()}") raise PipxError("Internal Error: PipxMetadata is corrupt, cannot write.") def write(self) -> None: self._validate_before_write() try: with open(self.venv_dir / PIPX_INFO_FILENAME, "w", encoding="utf-8") as pipx_metadata_fh: json.dump( self.to_dict(), pipx_metadata_fh, indent=4, sort_keys=True, cls=JsonEncoderHandlesPath, ) except OSError: logger.warning( pipx_wrap( f""" {hazard} Unable to write {PIPX_INFO_FILENAME} to {self.venv_dir}. This may cause future pipx operations involving {self.venv_dir.name} to fail or behave incorrectly. """, subsequent_indent=" " * 4, ) ) def read(self, verbose: bool = False) -> None: try: with open(self.venv_dir / PIPX_INFO_FILENAME, "rb") as pipx_metadata_fh: self.from_dict(json.load(pipx_metadata_fh, object_hook=_json_decoder_object_hook)) except OSError: # Reset self if problem reading if verbose: logger.warning( pipx_wrap( f""" {hazard} Unable to read {PIPX_INFO_FILENAME} in {self.venv_dir}. This may cause this or future pipx operations involving {self.venv_dir.name} to fail or behave incorrectly. """, subsequent_indent=" " * 4, ) ) return pipx-1.6.0/src/pipx/shared_libs.py000066400000000000000000000112371462701651400171100ustar00rootroot00000000000000import datetime import logging import time from pathlib import Path from typing import List, Optional from pipx import paths from pipx.animate import animate from pipx.constants import WINDOWS from pipx.interpreter import DEFAULT_PYTHON from pipx.util import ( get_site_packages, get_venv_paths, run_subprocess, subprocess_post_check, ) logger = logging.getLogger(__name__) SHARED_LIBS_MAX_AGE_SEC = datetime.timedelta(days=30).total_seconds() class _SharedLibs: def __init__(self) -> None: self.root = paths.ctx.shared_libs self.bin_path, self.python_path, self.man_path = get_venv_paths(self.root) self.pip_path = self.bin_path / ("pip" if not WINDOWS else "pip.exe") # i.e. bin_path is ~/.local/share/pipx/shared/bin # i.e. python_path is ~/.local/share/pipx/shared/python self._site_packages: Optional[Path] = None self.has_been_updated_this_run = False self.has_been_logged_this_run = False @property def site_packages(self) -> Path: if self._site_packages is None: self._site_packages = get_site_packages(self.python_path) return self._site_packages def create(self, pip_args: List[str], verbose: bool = False) -> None: if not self.is_valid: with animate("creating shared libraries", not verbose): create_process = run_subprocess( [DEFAULT_PYTHON, "-m", "venv", "--clear", self.root], run_dir=str(self.root) ) subprocess_post_check(create_process) # Recompute these paths, as they might resolve differently now, see comment in get_venv_paths self.bin_path, self.python_path, self.man_path = get_venv_paths(self.root) # ignore installed packages to ensure no unexpected patches from the OS vendor # are used pip_args = pip_args or [] pip_args.append("--force-reinstall") self.upgrade(pip_args=pip_args, verbose=verbose, raises=True) @property def is_valid(self) -> bool: if self.python_path.is_file(): check_pip = "import importlib.util; print(importlib.util.find_spec('pip'))" out = run_subprocess( [self.python_path, "-c", check_pip], capture_stderr=False, log_cmd_str="", ).stdout.strip() return self.pip_path.is_file() and out != "None" else: return False @property def needs_upgrade(self) -> bool: if self.has_been_updated_this_run: return False if not self.pip_path.is_file(): return True now = time.time() time_since_last_update_sec = now - self.pip_path.stat().st_mtime if not self.has_been_logged_this_run: logger.info( f"Time since last upgrade of shared libs, in seconds: {time_since_last_update_sec:.0f}. " f"Upgrade will be run by pipx if greater than {SHARED_LIBS_MAX_AGE_SEC:.0f}." ) self.has_been_logged_this_run = True return time_since_last_update_sec > SHARED_LIBS_MAX_AGE_SEC def upgrade(self, *, pip_args: List[str], verbose: bool = False, raises: bool = False) -> None: if not self.is_valid: self.create(verbose=verbose, pip_args=pip_args) return # Don't try to upgrade multiple times per run if self.has_been_updated_this_run: logger.info(f"Already upgraded libraries in {self.root}") return if pip_args is None: pip_args = [] logger.info(f"Upgrading shared libraries in {self.root}") ignored_args = ["--editable"] _pip_args = [arg for arg in pip_args if arg not in ignored_args] if not verbose: _pip_args.append("-q") try: with animate("upgrading shared libraries", not verbose): upgrade_process = run_subprocess( [ self.python_path, "-m", "pip", "--no-input", "--disable-pip-version-check", "install", *_pip_args, "--upgrade", "pip >= 23.1", ] ) subprocess_post_check(upgrade_process) self.has_been_updated_this_run = True self.pip_path.touch() except Exception: logger.error("Failed to upgrade shared libraries", exc_info=not raises) if raises: raise shared_libs = _SharedLibs() pipx-1.6.0/src/pipx/standalone_python.py000066400000000000000000000165771462701651400203760ustar00rootroot00000000000000import datetime import hashlib import json import logging import platform import re import shutil import tarfile import tempfile import urllib.error from functools import partial from pathlib import Path from typing import Any, Dict, List from urllib.request import urlopen from pipx import constants, paths from pipx.animate import animate from pipx.util import PipxError logger = logging.getLogger(__name__) # Much of the code in this module is adapted with extreme gratitude from # https://github.com/tusharsadhwani/yen/blob/main/src/yen/github.py MACHINE_SUFFIX: Dict[str, Dict[str, Any]] = { "Darwin": { "arm64": "aarch64-apple-darwin-install_only.tar.gz", "x86_64": "x86_64-apple-darwin-install_only.tar.gz", }, "Linux": { "aarch64": { "glibc": "aarch64-unknown-linux-gnu-install_only.tar.gz", # musl doesn't exist }, "x86_64": { "glibc": "x86_64-unknown-linux-gnu-install_only.tar.gz", "musl": "x86_64-unknown-linux-musl-install_only.tar.gz", }, }, "Windows": {"AMD64": "x86_64-pc-windows-msvc-shared-install_only.tar.gz"}, } GITHUB_API_URL = "https://api.github.com/repos/indygreg/python-build-standalone/releases/latest" PYTHON_VERSION_REGEX = re.compile(r"cpython-(\d+\.\d+\.\d+)") def download_python_build_standalone(python_version: str, override: bool = False): """When all other python executable resolutions have failed, attempt to download and use an appropriate python build from https://github.com/indygreg/python-build-standalone and unpack it into the pipx shared directory.""" # python_version can be a bare version number like "3.9" or a "binary name" like python3.10 # we'll convert it to a bare version number python_version = re.sub(r"[c]?python", "", python_version) install_dir = paths.ctx.standalone_python_cachedir / python_version installed_python = install_dir / "python.exe" if constants.WINDOWS else install_dir / "bin" / "python3" if override: if install_dir.exists(): shutil.rmtree(install_dir) else: if installed_python.exists(): return str(installed_python) if install_dir.exists(): logger.warning(f"A previous attempt to install python {python_version} failed. Retrying.") shutil.rmtree(install_dir) full_version, download_link = resolve_python_version(python_version) with tempfile.TemporaryDirectory() as tempdir: archive = Path(tempdir) / f"python-{full_version}.tar.gz" download_dir = Path(tempdir) / "download" # download the python build gz _download(full_version, download_link, archive) # unpack the python build _unpack(full_version, download_link, archive, download_dir) # the python installation we want is nested in the tarball # under a directory named 'python'. We move it to the install # directory extracted_dir = download_dir / "python" shutil.move(extracted_dir, install_dir) return str(installed_python) def _download(full_version: str, download_link: str, archive: Path): with animate(f"Downloading python {full_version} build", True): try: # python standalone builds are typically ~32MB in size. to avoid # ballooning memory usage, we read the file in chunks with urlopen(download_link) as response, open(archive, "wb") as file_handle: for data in iter(partial(response.read, 32768), b""): file_handle.write(data) except urllib.error.URLError as e: raise PipxError(f"Unable to download python {full_version} build.") from e def _unpack(full_version, download_link, archive: Path, download_dir: Path): with animate(f"Unpacking python {full_version} build", True): # Calculate checksum with open(archive, "rb") as python_zip: checksum = hashlib.sha256(python_zip.read()).hexdigest() # Validate checksum checksum_link = download_link + ".sha256" expected_checksum = urlopen(checksum_link).read().decode().rstrip("\n") if checksum != expected_checksum: raise PipxError( f"Checksum mismatch for python {full_version} build. Expected {expected_checksum}, got {checksum}." ) with tarfile.open(archive, mode="r:gz") as tar: tar.extractall(download_dir) def get_or_update_index(use_cache: bool = True): """Get or update the index of available python builds from the python-build-standalone repository.""" index_file = paths.ctx.standalone_python_cachedir / "index.json" if use_cache and index_file.exists(): index = json.loads(index_file.read_text()) # update index after 30 days fetched = datetime.datetime.fromtimestamp(index["fetched"]) if datetime.datetime.now() - fetched > datetime.timedelta(days=30): index = {} else: index = {} if not index: releases = get_latest_python_releases() index = {"fetched": datetime.datetime.now().timestamp(), "releases": releases} # update index index_file.write_text(json.dumps(index)) return index def get_latest_python_releases() -> List[str]: """Returns the list of python download links from the latest github release.""" try: with urlopen(GITHUB_API_URL) as response: release_data = json.load(response) except urllib.error.URLError as e: # raise raise PipxError(f"Unable to fetch python-build-standalone release data (from {GITHUB_API_URL}).") from e return [asset["browser_download_url"] for asset in release_data["assets"]] def list_pythons(use_cache: bool = True) -> Dict[str, str]: """Returns available python versions for your machine and their download links.""" system, machine = platform.system(), platform.machine() download_link_suffix = MACHINE_SUFFIX[system][machine] # linux suffixes are nested under glibc or musl builds if system == "Linux": # fallback to musl if libc version is not found libc_version = platform.libc_ver()[0] or "musl" download_link_suffix = download_link_suffix[libc_version] python_releases = get_or_update_index(use_cache)["releases"] available_python_links = [link for link in python_releases if link.endswith(download_link_suffix)] python_versions: dict[str, str] = {} for link in available_python_links: match = PYTHON_VERSION_REGEX.search(link) if match is None: logger.warning(f"Could not parse python version from link {link}. Skipping.") continue python_version = match[1] python_versions[python_version] = link return { version: python_versions[version] for version in sorted( python_versions, # sort by semver key=lambda version: [int(k) for k in version.split(".")], reverse=True, ) } def resolve_python_version(requested_version: str): pythons = list_pythons() requested_release = requested_version.split(".") for full_version, download_link in pythons.items(): standalone_release = full_version.split(".") if requested_release == standalone_release[: len(requested_release)]: return full_version, download_link raise PipxError(f"Unable to acquire a standalone python build matching {requested_version}.") pipx-1.6.0/src/pipx/util.py000066400000000000000000000356251462701651400156150ustar00rootroot00000000000000import logging import os import random import re import shutil import string import subprocess import sys import textwrap from dataclasses import dataclass from pathlib import Path from typing import ( Any, Dict, List, NoReturn, Optional, Pattern, Sequence, Tuple, Union, ) from pipx import paths from pipx.animate import show_cursor from pipx.constants import MINGW, WINDOWS logger = logging.getLogger(__name__) class PipxError(Exception): def __init__(self, message: str, wrap_message: bool = True): if wrap_message: super().__init__(pipx_wrap(message)) else: super().__init__(message) @dataclass(frozen=True) class RelevantSearch: pattern: Pattern[str] category: str def _get_trash_file(path: Path) -> Path: if not paths.ctx.trash.is_dir(): paths.ctx.trash.mkdir() prefix = "".join(random.choices(string.ascii_lowercase, k=8)) return paths.ctx.trash / f"{prefix}.{path.name}" def rmdir(path: Path, safe_rm: bool = True) -> None: if not path.is_dir(): return logger.info(f"removing directory {path}") # Windows doesn't let us delete or overwrite files that are being run # But it does let us rename/move it. To get around this issue, we can move # the file to a temporary folder (to be deleted at a later time) # So, if safe_rm is True, we ignore any errors and move the file to the trash with below code shutil.rmtree(path, ignore_errors=safe_rm) # move it to be deleted later if it still exists if path.is_dir(): if safe_rm: logger.warning(f"Failed to delete {path}. Will move it to a temp folder to delete later.") path.rename(_get_trash_file(path)) else: logger.warning(f"Failed to delete {path}. You may need to delete it manually.") def mkdir(path: Path) -> None: if path.is_dir(): return logger.info(f"creating directory {path}") path.mkdir(parents=True, exist_ok=True) def safe_unlink(file: Path) -> None: # Windows doesn't let us delete or overwrite files that are being run # But it does let us rename/move it. To get around this issue, we can move # the file to a temporary folder (to be deleted at a later time) if not file.is_file(): return try: file.unlink() except PermissionError: file.rename(_get_trash_file(file)) def get_pypackage_bin_path(binary_name: str) -> Path: return ( Path("__pypackages__") / (str(sys.version_info.major) + "." + str(sys.version_info.minor)) / "lib" / "bin" / binary_name ) def run_pypackage_bin(bin_path: Path, args: List[str]) -> NoReturn: exec_app( [str(bin_path.resolve())] + args, extra_python_paths=[".", str(bin_path.parent.parent)], ) if WINDOWS: def get_venv_paths(root: Path) -> Tuple[Path, Path, Path]: # Make sure to use the real root path. This matters especially on Windows when using the packaged app # (Microsoft Store) version of Python, which uses path redirection for sandboxing. # See https://github.com/pypa/pipx/issues/1164 root = root.resolve() bin_path = root / "Scripts" if not MINGW else root / "bin" python_path = bin_path / "python.exe" man_path = root / "share" / "man" return bin_path, python_path, man_path else: def get_venv_paths(root: Path) -> Tuple[Path, Path, Path]: bin_path = root / "bin" python_path = bin_path / "python" man_path = root / "share" / "man" return bin_path, python_path, man_path def get_site_packages(python: Path) -> Path: output = run_subprocess( [python, "-c", "import sysconfig; print(sysconfig.get_path('purelib'))"], capture_stderr=False, ).stdout path = Path(output.strip()) path.mkdir(parents=True, exist_ok=True) return path def _fix_subprocess_env(env: Dict[str, str]) -> Dict[str, str]: # Remove PYTHONPATH because some platforms (macOS with Homebrew) add pipx # directories to it, and can make it appear to venvs as though pipx # dependencies are in the venv path (#233) # Remove __PYVENV_LAUNCHER__ because it can cause the wrong python binary # to be used (#334) env_blocklist = ["PYTHONPATH", "__PYVENV_LAUNCHER__"] for env_to_remove in env_blocklist: env.pop(env_to_remove, None) env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1" # Make sure that Python writes output in UTF-8 env["PYTHONIOENCODING"] = "utf-8" env["PYTHONLEGACYWINDOWSSTDIO"] = "utf-8" # Make sure we install package to venv, not userbase dir env["PIP_USER"] = "0" return env def run_subprocess( cmd: Sequence[Union[str, Path]], capture_stdout: bool = True, capture_stderr: bool = True, log_cmd_str: Optional[str] = None, log_stdout: bool = True, log_stderr: bool = True, run_dir: Optional[str] = None, ) -> "subprocess.CompletedProcess[str]": """Run arbitrary command as subprocess, capturing stderr and stout""" env = dict(os.environ) env = _fix_subprocess_env(env) if log_cmd_str is None: log_cmd_str = " ".join(str(c) for c in cmd) logger.info(f"running {log_cmd_str}") if run_dir: os.makedirs(run_dir, exist_ok=True) # windows cannot take Path objects, only strings cmd_str_list = [str(c) for c in cmd] # TODO: Switch to using `-P` / PYTHONSAFEPATH instead of running in # separate directory in Python 3.11 completed_process = subprocess.run( cmd_str_list, env=env, stdout=subprocess.PIPE if capture_stdout else None, stderr=subprocess.PIPE if capture_stderr else None, encoding="utf-8", text=True, check=False, cwd=run_dir, ) if capture_stdout and log_stdout: logger.debug(f"stdout: {completed_process.stdout}".rstrip()) if capture_stderr and log_stderr: logger.debug(f"stderr: {completed_process.stderr}".rstrip()) logger.debug(f"returncode: {completed_process.returncode}") return completed_process def subprocess_post_check(completed_process: "subprocess.CompletedProcess[str]", raise_error: bool = True) -> None: if completed_process.returncode: if completed_process.stdout is not None: print(completed_process.stdout, file=sys.stdout, end="") if completed_process.stderr is not None: print(completed_process.stderr, file=sys.stderr, end="") if raise_error: raise PipxError(f"{' '.join([str(x) for x in completed_process.args])!r} failed") else: logger.info(f"{' '.join(completed_process.args)!r} failed") def dedup_ordered(input_list: List[Tuple[str, Any]]) -> List[Tuple[str, Any]]: output_list = [] seen = set() for x in input_list: if x[0] not in seen: output_list.append(x) seen.add(x[0]) return output_list def analyze_pip_output(pip_stdout: str, pip_stderr: str) -> None: r"""Extract useful errors from pip output of failed install Print the module that failed to build Print some of the most relevant errors from the pip output Example pip stderr line for each "relevant" type: not_found Package cairo was not found in the pkg-config search path. src/common.h:34:10: fatal error: 'stdio.h' file not found The headers or library files could not be found for zlib, no_such unable to execute 'gcc': No such file or directory build\test1.c(2): fatal error C1083: Cannot open include file: 'cpuid.h': No such file ... exception_error Exception: Unable to find OpenSSL >= 1.0 headers. (Looked here: ... fatal_error LINK : fatal error LNK1104: cannot open file 'kernel32.lib' conflict_ ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/... error_ error: can't copy 'lib\ansible\module_utils\ansible_release.py': doesn't exist ... build\test1.c(4): error C2146: syntax error: missing ';' before identifier 'x' """ max_relevant_errors = 10 failed_build_stdout: List[str] = [] last_collecting_dep: Optional[str] = None # for any useful information in stdout, `pip install` must be run without # the -q option for line in pip_stdout.split("\n"): failed_match = re.search(r"Failed to build\s+(\S.+)$", line) collecting_match = re.search(r"^\s*Collecting\s+(\S+)", line) if failed_match: failed_build_stdout = failed_match.group(1).strip().split() if collecting_match: last_collecting_dep = collecting_match.group(1) # In order of most useful to least useful relevant_searches = [ RelevantSearch(re.compile(r"not (?:be )?found", re.I), "not_found"), RelevantSearch(re.compile(r"no such", re.I), "no_such"), RelevantSearch(re.compile(r"(Exception|Error):\s*\S+"), "exception_error"), RelevantSearch(re.compile(r"fatal error", re.I), "fatal_error"), RelevantSearch(re.compile(r"conflict", re.I), "conflict_"), RelevantSearch( re.compile( r"error:" r"(?!.+Command errored out)" r"(?!.+failed building wheel for)" r"(?!.+could not build wheels? for)" r"(?!.+failed to build one or more wheels)" r".+[^:]$", re.I, ), "error_", ), ] failed_stderr_patt = re.compile(r"Failed to build\s+(?!one or more packages)(\S+)") relevants_saved = [] failed_build_stderr = set() for line in pip_stderr.split("\n"): failed_build_match = failed_stderr_patt.search(line) if failed_build_match: failed_build_stderr.add(failed_build_match.group(1)) for relevant_search in relevant_searches: if relevant_search.pattern.search(line): relevants_saved.append((line.strip(), relevant_search.category)) break if failed_build_stdout: failed_to_build_str = "\n ".join(failed_build_stdout) plural_str = "s" if len(failed_build_stdout) > 1 else "" print("", file=sys.stderr) logger.error(f"pip failed to build package{plural_str}:\n {failed_to_build_str}") elif failed_build_stderr: failed_to_build_str = "\n ".join(failed_build_stderr) plural_str = "s" if len(failed_build_stderr) > 1 else "" print("", file=sys.stderr) logger.error(f"pip seemed to fail to build package{plural_str}:\n {failed_to_build_str}") elif last_collecting_dep is not None: print("", file=sys.stderr) logger.error(f"pip seemed to fail to build package:\n {last_collecting_dep}") relevants_saved = dedup_ordered(relevants_saved) if relevants_saved: print("\nSome possibly relevant errors from pip install:", file=sys.stderr) print_categories = [x.category for x in relevant_searches] relevants_saved_filtered = relevants_saved.copy() while (len(print_categories) > 1) and (len(relevants_saved_filtered) > max_relevant_errors): print_categories.pop(-1) relevants_saved_filtered = [x for x in relevants_saved if x[1] in print_categories] for relevant_saved in relevants_saved_filtered: print(f" {relevant_saved[0]}", file=sys.stderr) def subprocess_post_check_handle_pip_error( completed_process: "subprocess.CompletedProcess[str]", ) -> None: if completed_process.returncode: logger.info(f"{' '.join(completed_process.args)!r} failed") # Save STDOUT and STDERR to file in pipx/logs/ if paths.ctx.log_file is None: raise PipxError("Pipx internal error: No log_file present.") pip_error_file = paths.ctx.log_file.parent / (paths.ctx.log_file.stem + "_pip_errors.log") with pip_error_file.open("a", encoding="utf-8") as pip_error_fh: print("PIP STDOUT", file=pip_error_fh) print("----------", file=pip_error_fh) if completed_process.stdout is not None: print(completed_process.stdout, file=pip_error_fh, end="") print("\nPIP STDERR", file=pip_error_fh) print("----------", file=pip_error_fh) if completed_process.stderr is not None: print(completed_process.stderr, file=pip_error_fh, end="") logger.error(f"Fatal error from pip prevented installation. Full pip output in file:\n {pip_error_file}") analyze_pip_output(completed_process.stdout, completed_process.stderr) def exec_app( cmd: Sequence[Union[str, Path]], env: Optional[Dict[str, str]] = None, extra_python_paths: Optional[List[str]] = None, ) -> NoReturn: """Run command, do not return POSIX: replace current process with command using os.exec*() Windows: Use subprocess and sys.exit() to run command """ if env is None: env = dict(os.environ) env = _fix_subprocess_env(env) if extra_python_paths is not None: env["PYTHONPATH"] = os.path.pathsep.join( extra_python_paths + (os.getenv("PYTHONPATH", "").split(os.path.pathsep) if os.getenv("PYTHONPATH") else []) ) # make sure we show cursor again before handing over control show_cursor() logger.info("exec_app: " + " ".join([str(c) for c in cmd])) if WINDOWS: sys.exit( subprocess.run( cmd, env=env, stdout=None, stderr=None, encoding="utf-8", text=True, check=False, ).returncode ) else: os.execvpe(str(cmd[0]), [str(x) for x in cmd], env) def full_package_description(package_name: str, package_spec: str) -> str: if package_name == package_spec: return package_name else: return f"{package_name} from spec {package_spec!r}" def pipx_wrap(text: str, subsequent_indent: str = "", keep_newlines: bool = False) -> str: """Dedent, strip, wrap to shell width. Don't break on hyphens, only spaces""" minimum_width = 40 width = max(shutil.get_terminal_size((80, 40)).columns, minimum_width) - 2 text = textwrap.dedent(text).strip() if keep_newlines: return "\n".join( [ textwrap.fill( line, width=width, subsequent_indent=subsequent_indent, break_on_hyphens=False, ) for line in text.splitlines() ] ) else: return textwrap.fill( text, width=width, subsequent_indent=subsequent_indent, break_on_hyphens=False, ) def is_paths_relative(path: Path, parent: Path): # Can be replaced with path.is_relative_to() if support for python3.8 is dropped try: path.resolve().relative_to(parent.resolve()) except ValueError: return False return True pipx-1.6.0/src/pipx/venv.py000066400000000000000000000465621462701651400156200ustar00rootroot00000000000000import json import logging import re import shutil import time from pathlib import Path from subprocess import CompletedProcess from typing import Dict, Generator, List, NoReturn, Optional, Set try: from importlib.metadata import Distribution, EntryPoint except ImportError: from importlib_metadata import Distribution, EntryPoint # type: ignore[import-not-found,no-redef] from packaging.utils import canonicalize_name from pipx.animate import animate from pipx.constants import PIPX_SHARED_PTH, ExitCode from pipx.emojis import hazard from pipx.interpreter import DEFAULT_PYTHON from pipx.package_specifier import ( fix_package_name, get_extras, parse_specifier_for_install, parse_specifier_for_metadata, ) from pipx.pipx_metadata_file import PackageInfo, PipxMetadata from pipx.shared_libs import shared_libs from pipx.util import ( PipxError, exec_app, full_package_description, get_site_packages, get_venv_paths, pipx_wrap, rmdir, run_subprocess, subprocess_post_check, subprocess_post_check_handle_pip_error, ) from pipx.venv_inspect import VenvMetadata, inspect_venv logger = logging.getLogger(__name__) _entry_point_value_pattern = re.compile( r""" ^(?P[\w.]+)\s* (:\s*(?P[\w.]+))?\s* (?P\[.*\])?\s*$ """, re.VERBOSE, ) class VenvContainer: """A collection of venvs managed by pipx.""" def __init__(self, root: Path): self._root = root def __repr__(self) -> str: return f"VenvContainer({str(self._root)!r})" def __str__(self) -> str: return str(self._root) def iter_venv_dirs(self) -> Generator[Path, None, None]: """Iterate venv directories in this container.""" if not self._root.is_dir(): return for entry in self._root.iterdir(): if not entry.is_dir(): continue yield entry def get_venv_dir(self, package_name: str) -> Path: """Return the expected venv path for given `package_name`.""" return self._root.joinpath(canonicalize_name(package_name)) 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, self.python_path, self.man_path = get_venv_paths(self.root) self.pipx_metadata = PipxMetadata(venv_dir=path) self.verbose = verbose self.do_animation = not verbose try: self._existing = self.root.exists() and bool(next(self.root.iterdir())) except StopIteration: self._existing = False def check_upgrade_shared_libs(self, verbose: bool, pip_args: List[str], force_upgrade: bool = False): """ If necessary, run maintenance tasks to keep the shared libs up-to-date. This can trigger `pip install`/`pip install --upgrade` operations, so we expect the caller to provide sensible `pip_args` ( provided by the user in the current CLI call or retrieved from the metadata of a previous installation) """ if self._existing and self.uses_shared_libs: if shared_libs.is_valid: if force_upgrade or shared_libs.needs_upgrade: shared_libs.upgrade(verbose=verbose, pip_args=pip_args) else: shared_libs.create(verbose=verbose, pip_args=pip_args) if not shared_libs.is_valid: raise PipxError( pipx_wrap( f""" Error: pipx's shared venv {shared_libs.root} is invalid and needs re-installation. To fix this, install or reinstall a package. For example: """ ) + f"\n pipx install {self.root.name} --force", wrap_message=False, ) @property def name(self) -> str: if self.pipx_metadata.main_package.package is not None: venv_name = f"{self.pipx_metadata.main_package.package}{self.pipx_metadata.main_package.suffix}" else: venv_name = self.root.name return venv_name @property def uses_shared_libs(self) -> bool: if self._existing: pth_files = self.root.glob("**/" + PIPX_SHARED_PTH) return next(pth_files, None) is not None else: # always use shared libs when creating a new venv return True @property def package_metadata(self) -> Dict[str, PackageInfo]: return_dict = self.pipx_metadata.injected_packages.copy() if self.pipx_metadata.main_package.package is not None: return_dict[self.pipx_metadata.main_package.package] = self.pipx_metadata.main_package return return_dict @property def main_package_name(self) -> str: if self.pipx_metadata.main_package.package is None: # This is OK, because if no metadata, we are pipx < v0.15.0.0 and # venv_name==main_package_name return self.root.name else: return self.pipx_metadata.main_package.package def create_venv(self, venv_args: List[str], pip_args: List[str], override_shared: bool = False) -> None: """ override_shared -- Override installing shared libraries to the pipx shared directory (default False) """ logger.info("Creating virtual environment") with animate("creating virtual environment", self.do_animation): cmd = [self.python, "-m", "venv"] if not override_shared: cmd.append("--without-pip") venv_process = run_subprocess(cmd + venv_args + [str(self.root)], run_dir=str(self.root)) subprocess_post_check(venv_process) shared_libs.create(verbose=self.verbose, pip_args=pip_args) if not override_shared: pipx_pth = get_site_packages(self.python_path) / PIPX_SHARED_PTH # write path pointing to the shared libs site-packages directory # example pipx_pth location: # ~/.local/share/pipx/venvs/black/lib/python3.8/site-packages/pipx_shared.pth # example shared_libs.site_packages location: # ~/.local/share/pipx/shared/lib/python3.6/site-packages # # https://docs.python.org/3/library/site.html # A path configuration file is a file whose name has the form 'name.pth'. # its contents are additional items (one per line) to be added to sys.path pipx_pth.write_text(f"{shared_libs.site_packages}\n", encoding="utf-8") self.pipx_metadata.venv_args = venv_args self.pipx_metadata.python_version = self.get_python_version() source_interpreter = shutil.which(self.python) if source_interpreter: self.pipx_metadata.source_interpreter = Path(source_interpreter) def safe_to_remove(self) -> bool: return not self._existing def remove_venv(self) -> None: if self.safe_to_remove(): rmdir(self.root) else: logger.warning( pipx_wrap( f""" {hazard} Not removing existing venv {self.root} because it was not created in this session """, subsequent_indent=" " * 4, ) ) def upgrade_packaging_libraries(self, pip_args: List[str]) -> None: if self.uses_shared_libs: shared_libs.upgrade(pip_args=pip_args, verbose=self.verbose) else: # TODO: setuptools and wheel? Original code didn't bother # but shared libs code does. self.upgrade_package_no_metadata("pip", pip_args) def uninstall_package(self, package: str, was_injected: bool = False): try: logger.info("Uninstalling %s", package) with animate(f"uninstalling {package}", self.do_animation): cmd = ["uninstall", "-y"] + [package] self._run_pip(cmd) except PipxError as e: logger.info(e) raise PipxError(f"Error uninstalling {package}.") from None if was_injected: self.pipx_metadata.injected_packages.pop(package) self.pipx_metadata.write() def install_package( self, package_name: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", ) -> None: # package_name in package specifier can mismatch URL due to user error package_or_url = fix_package_name(package_or_url, package_name) # check syntax and clean up spec and pip_args (package_or_url, pip_args) = parse_specifier_for_install(package_or_url, pip_args) logger.info("Installing %s", package_descr := full_package_description(package_name, package_or_url)) with animate(f"installing {package_descr}", self.do_animation): # do not use -q with `pip install` so subprocess_post_check_pip_errors # has more information to analyze in case of failure. cmd = [ str(self.python_path), "-m", "pip", "--no-input", "install", *pip_args, package_or_url, ] # no logging because any errors will be specially logged by # subprocess_post_check_handle_pip_error() pip_process = run_subprocess(cmd, log_stdout=False, log_stderr=False, run_dir=str(self.root)) subprocess_post_check_handle_pip_error(pip_process) if pip_process.returncode: raise PipxError(f"Error installing {full_package_description(package_name, package_or_url)}.") self.update_package_metadata( package_name=package_name, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, suffix=suffix, ) # Verify package installed ok if self.package_metadata[package_name].package_version is None: raise PipxError( f"Unable to install " f"{full_package_description(package_name, package_or_url)}.\n" f"Check the name or spec for errors, and verify that it can " f"be installed with pip.", wrap_message=False, ) def install_unmanaged_packages(self, requirements: List[str], pip_args: List[str]) -> None: """Install packages in the venv, but do not record them in the metadata.""" # Note: We want to install everything at once, as that lets # pip resolve conflicts correctly. logger.info("Installing %s", package_descr := ", ".join(requirements)) with animate(f"installing {package_descr}", self.do_animation): # do not use -q with `pip install` so subprocess_post_check_pip_errors # has more information to analyze in case of failure. cmd = [ str(self.python_path), "-m", "pip", "--no-input", "install", *pip_args, *requirements, ] # no logging because any errors will be specially logged by # subprocess_post_check_handle_pip_error() pip_process = run_subprocess(cmd, log_stdout=False, log_stderr=False, run_dir=str(self.root)) subprocess_post_check_handle_pip_error(pip_process) if pip_process.returncode: raise PipxError(f"Error installing {', '.join(requirements)}.") def install_package_no_deps(self, package_or_url: str, pip_args: List[str]) -> str: with animate(f"determining package name from {package_or_url!r}", self.do_animation): old_package_set = self.list_installed_packages() cmd = [ "--no-input", "install", "--no-dependencies", *pip_args, package_or_url, ] pip_process = self._run_pip(cmd) subprocess_post_check(pip_process, raise_error=False) if pip_process.returncode: raise PipxError( f""" Cannot determine package name from spec {package_or_url!r}. Check package spec for errors. """ ) installed_packages = self.list_installed_packages() - old_package_set if len(installed_packages) == 1: package_name = installed_packages.pop() logger.info(f"Determined package name: {package_name}") else: logger.info(f"old_package_set = {old_package_set}") logger.info(f"install_packages = {installed_packages}") raise PipxError( f""" Cannot determine package name from spec {package_or_url!r}. Check package spec for errors. """ ) return package_name def get_venv_metadata_for_package(self, package_name: str, package_extras: Set[str]) -> VenvMetadata: data_start = time.time() venv_metadata = inspect_venv(package_name, package_extras, self.bin_path, self.python_path, self.man_path) logger.info(f"get_venv_metadata_for_package: {1e3*(time.time()-data_start):.0f}ms") return venv_metadata def update_package_metadata( self, package_name: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", pinned: bool = False, ) -> None: venv_package_metadata = self.get_venv_metadata_for_package(package_name, get_extras(package_or_url)) package_info = PackageInfo( package=package_name, package_or_url=parse_specifier_for_metadata(package_or_url), pip_args=pip_args, include_apps=include_apps, include_dependencies=include_dependencies, apps=venv_package_metadata.apps, app_paths=venv_package_metadata.app_paths, apps_of_dependencies=venv_package_metadata.apps_of_dependencies, app_paths_of_dependencies=venv_package_metadata.app_paths_of_dependencies, man_pages=venv_package_metadata.man_pages, man_paths=venv_package_metadata.man_paths, man_pages_of_dependencies=venv_package_metadata.man_pages_of_dependencies, man_paths_of_dependencies=venv_package_metadata.man_paths_of_dependencies, package_version=venv_package_metadata.package_version, suffix=suffix, pinned=pinned, ) if is_main_package: self.pipx_metadata.main_package = package_info else: self.pipx_metadata.injected_packages[package_name] = package_info self.pipx_metadata.write() def get_python_version(self) -> str: return run_subprocess([str(self.python_path), "--version"]).stdout.strip() def list_installed_packages(self, not_required=False) -> Set[str]: cmd_run = run_subprocess( [str(self.python_path), "-m", "pip", "list", "--format=json"] + (["--not-required"] if not_required else []) ) pip_list = json.loads(cmd_run.stdout.strip()) return {x["name"] for x in pip_list} def _find_entry_point(self, app: str) -> Optional[EntryPoint]: if not self.python_path.exists(): return None dists = Distribution.discover(name=self.main_package_name, path=[str(get_site_packages(self.python_path))]) for dist in dists: for ep in dist.entry_points: if ep.group == "pipx.run": if ep.name == app: return ep # Try to infer app name from dist's metadata if given # local path if Path(app).exists() and dist.metadata["Name"] == ep.name: return ep return None def run_app(self, app: str, filename: str, app_args: List[str]) -> NoReturn: entry_point = self._find_entry_point(app) # No [pipx.run] entry point; default to run console script. if entry_point is None: exec_app([str(self.bin_path / filename)] + app_args) # Evaluate and execute the entry point. # TODO: After dropping support for Python < 3.9, use # "entry_point.module" and "entry_point.attr" instead. match = _entry_point_value_pattern.match(entry_point.value) assert match is not None, "invalid entry point" logger.info("Using discovered entry point for 'pipx run'") module, attr = match.group("module", "attr") code = f"import sys, {module}\nsys.argv[0] = {entry_point.name!r}\nsys.exit({module}.{attr}())\n" exec_app([str(self.python_path), "-c", code] + app_args) def has_app(self, app: str, filename: str) -> bool: if self._find_entry_point(app) is not None: return True return (self.bin_path / filename).is_file() def has_package(self, package_name: str) -> bool: return bool(list(Distribution.discover(name=package_name, path=[str(get_site_packages(self.python_path))]))) def upgrade_package_no_metadata(self, package_name: str, pip_args: List[str]) -> None: logger.info("Upgrading %s", package_descr := full_package_description(package_name, package_name)) with animate(f"upgrading {package_descr}", self.do_animation): pip_process = self._run_pip(["--no-input", "install"] + pip_args + ["--upgrade", package_name]) subprocess_post_check(pip_process) def upgrade_package( self, package_name: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", ) -> None: logger.info("Upgrading %s", package_descr := full_package_description(package_name, package_or_url)) with animate(f"upgrading {package_descr}", self.do_animation): pip_process = self._run_pip(["--no-input", "install"] + pip_args + ["--upgrade", package_or_url]) subprocess_post_check(pip_process) self.update_package_metadata( package_name=package_name, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, suffix=suffix, ) def _run_pip(self, cmd: List[str]) -> "CompletedProcess[str]": cmd = [str(self.python_path), "-m", "pip"] + cmd if not self.verbose: cmd.append("-q") return run_subprocess(cmd, run_dir=str(self.root)) def run_pip_get_exit_code(self, cmd: List[str]) -> ExitCode: cmd = [str(self.python_path), "-m", "pip"] + cmd if not self.verbose: cmd.append("-q") returncode = run_subprocess(cmd, capture_stdout=False, capture_stderr=False).returncode if returncode: cmd_str = " ".join(str(c) for c in cmd) logger.error(f"{cmd_str!r} failed") return ExitCode(returncode) pipx-1.6.0/src/pipx/venv_inspect.py000066400000000000000000000277231462701651400173430ustar00rootroot00000000000000import json import logging import textwrap from pathlib import Path from typing import Collection, Dict, List, NamedTuple, Optional, Set, Tuple from packaging.requirements import Requirement from packaging.utils import canonicalize_name try: from importlib import metadata except ImportError: import importlib_metadata as metadata # type: ignore[import-not-found,no-redef] from pipx.constants import MAN_SECTIONS, WINDOWS from pipx.util import PipxError, run_subprocess logger = logging.getLogger(__name__) class VenvInspectInformation(NamedTuple): distributions: Collection[metadata.Distribution] env: Dict[str, str] bin_path: Path man_path: Path class VenvMetadata(NamedTuple): apps: List[str] app_paths: List[Path] apps_of_dependencies: List[str] app_paths_of_dependencies: Dict[str, List[Path]] man_pages: List[str] man_paths: List[Path] man_pages_of_dependencies: List[str] man_paths_of_dependencies: Dict[str, List[Path]] package_version: str python_version: str def get_dist(package: str, distributions: Collection[metadata.Distribution]) -> Optional[metadata.Distribution]: """Find matching distribution in the canonicalized sense.""" for dist in distributions: if canonicalize_name(dist.metadata["name"]) == canonicalize_name(package): return dist return None def get_package_dependencies(dist: metadata.Distribution, extras: Set[str], env: Dict[str, str]) -> List[Requirement]: eval_env = env.copy() # Add an empty extra to enable evaluation of non-extra markers if not extras: extras.add("") dependencies = [] for req in map(Requirement, dist.requires or []): if not req.marker: dependencies.append(req) else: for extra in extras: eval_env["extra"] = extra if req.marker.evaluate(eval_env): dependencies.append(req) break return dependencies def get_apps_from_entry_points(dist: metadata.Distribution, bin_path: Path): app_names = set() sections = {"console_scripts", "gui_scripts"} # "entry_points" entry in setup.py are found here for ep in dist.entry_points: if ep.group not in sections: continue if (bin_path / ep.name).exists(): app_names.add(ep.name) if WINDOWS and (bin_path / (ep.name + ".exe")).exists(): # WINDOWS adds .exe to entry_point name app_names.add(ep.name + ".exe") return app_names def get_resources_from_dist_files(dist: metadata.Distribution, bin_path: Path, man_path: Path): app_names = set() man_names = set() # search installed files # "scripts" entry in setup.py is found here (test w/ awscli) for path in dist.files or []: # vast speedup by ignoring all paths not above distribution root dir # (venv/bin or venv/Scripts is above distribution root) if Path(path).parts[0] != "..": continue dist_file_path = Path(str(dist.locate_file(path))) try: if dist_file_path.parent.samefile(bin_path): app_names.add(path.name) if dist_file_path.parent.name in MAN_SECTIONS and dist_file_path.parent.parent.samefile(man_path): man_names.add(str(Path(dist_file_path.parent.name) / path.name)) except FileNotFoundError: pass return app_names, man_names def get_resources_from_inst_files(dist: metadata.Distribution, bin_path: Path, man_path: Path): app_names = set() man_names = set() # not sure what is found here inst_files = dist.read_text("installed-files.txt") or "" for line in inst_files.splitlines(): entry = line.split(",")[0] inst_file_path = Path(str(dist.locate_file(entry))).resolve() try: if inst_file_path.parent.samefile(bin_path): app_names.add(inst_file_path.name) if inst_file_path.parent.name in MAN_SECTIONS and inst_file_path.parent.parent.samefile(man_path): man_names.add(str(Path(inst_file_path.parent.name) / inst_file_path.name)) except FileNotFoundError: pass return app_names, man_names def get_resources(dist: metadata.Distribution, bin_path: Path, man_path: Path) -> Tuple[List[str], List[str]]: app_names = set() man_names = set() app_names_ep = get_apps_from_entry_points(dist, bin_path) app_names_df, man_names_df = get_resources_from_dist_files(dist, bin_path, man_path) app_names_if, man_names_if = get_resources_from_inst_files(dist, bin_path, man_path) app_names = app_names_ep | app_names_df | app_names_if man_names = man_names_df | man_names_if return sorted(app_names), sorted(man_names) def _dfs_package_resources( dist: metadata.Distribution, package_req: Requirement, venv_inspect_info: VenvInspectInformation, app_paths_of_dependencies: Dict[str, List[Path]], man_paths_of_dependencies: Dict[str, List[Path]], dep_visited: Optional[Dict[str, bool]] = None, ) -> Tuple[Dict[str, List[Path]], Dict[str, List[Path]]]: if dep_visited is None: # Initialize: we have already visited root dep_visited = {canonicalize_name(package_req.name): True} dependencies = get_package_dependencies(dist, package_req.extras, venv_inspect_info.env) for dep_req in dependencies: dep_name = canonicalize_name(dep_req.name) if dep_name in dep_visited: # avoid infinite recursion, avoid duplicates in info continue dep_dist = get_dist(dep_req.name, venv_inspect_info.distributions) if dep_dist is None: raise PipxError(f"Pipx Internal Error: cannot find package {dep_req.name!r} metadata.") app_names, man_names = get_resources(dep_dist, venv_inspect_info.bin_path, venv_inspect_info.man_path) if app_names: app_paths_of_dependencies[dep_name] = [venv_inspect_info.bin_path / name for name in app_names] if man_names: man_paths_of_dependencies[dep_name] = [venv_inspect_info.man_path / name for name in man_names] # recursively search for more dep_visited[dep_name] = True app_paths_of_dependencies, man_paths_of_dependencies = _dfs_package_resources( dep_dist, dep_req, venv_inspect_info, app_paths_of_dependencies, man_paths_of_dependencies, dep_visited, ) return app_paths_of_dependencies, man_paths_of_dependencies def _windows_extra_app_paths(app_paths: List[Path]) -> List[Path]: # In Windows, editable package have additional files starting with the # same name that are required to be in the same dir to run the app # Add "*-script.py", "*.exe.manifest" only to app_paths to make # execution work; do not add them to apps to ensure they are not listed app_paths_output = app_paths.copy() for app_path in app_paths: win_app_path = app_path.parent / (app_path.stem + "-script.py") if win_app_path.exists(): app_paths_output.append(win_app_path) win_app_path = app_path.parent / (app_path.stem + ".exe.manifest") if win_app_path.exists(): app_paths_output.append(win_app_path) return app_paths_output def fetch_info_in_venv(venv_python_path: Path) -> Tuple[List[str], Dict[str, str], str]: command_str = textwrap.dedent( """ import json import os import platform import sys impl_ver = sys.implementation.version implementation_version = "{0.major}.{0.minor}.{0.micro}".format(impl_ver) if impl_ver.releaselevel != "final": implementation_version = "{}{}{}".format( implementation_version, impl_ver.releaselevel[0], impl_ver.serial, ) sys_path = sys.path try: sys_path.remove("") except ValueError: pass print( json.dumps( { "sys_path": sys_path, "python_version": "{0.major}.{0.minor}.{0.micro}".format(sys.version_info), "environment": { "implementation_name": sys.implementation.name, "implementation_version": implementation_version, "os_name": os.name, "platform_machine": platform.machine(), "platform_release": platform.release(), "platform_system": platform.system(), "platform_version": platform.version(), "python_full_version": platform.python_version(), "platform_python_implementation": platform.python_implementation(), "python_version": ".".join(platform.python_version_tuple()[:2]), "sys_platform": sys.platform, }, } ) ) """ ) venv_info = json.loads( run_subprocess( [venv_python_path, "-c", command_str], capture_stderr=False, log_cmd_str="", ).stdout ) return ( venv_info["sys_path"], venv_info["environment"], f"Python {venv_info['python_version']}", ) def inspect_venv( root_package_name: str, root_package_extras: Set[str], venv_bin_path: Path, venv_python_path: Path, venv_man_path: Path, ) -> VenvMetadata: app_paths_of_dependencies: Dict[str, List[Path]] = {} apps_of_dependencies: List[str] = [] man_paths_of_dependencies: Dict[str, List[Path]] = {} man_pages_of_dependencies: List[str] = [] root_req = Requirement(root_package_name) root_req.extras = root_package_extras (venv_sys_path, venv_env, venv_python_version) = fetch_info_in_venv(venv_python_path) # Collect the generator created from metadata.distributions() # (see `itertools.chain.from_iterable`) into a tuple because we # need to iterate over it multiple times in `_dfs_package_apps`. # Tuple is chosen over a list because the program only iterate over # the distributions and never modify it. distributions = tuple(metadata.distributions(path=venv_sys_path)) venv_inspect_info = VenvInspectInformation( bin_path=venv_bin_path, man_path=venv_man_path, env=venv_env, distributions=distributions, ) root_dist = get_dist(root_req.name, venv_inspect_info.distributions) if root_dist is None: raise PipxError(f"Pipx Internal Error: cannot find package {root_req.name!r} metadata.") app_paths_of_dependencies, man_paths_of_dependencies = _dfs_package_resources( root_dist, root_req, venv_inspect_info, app_paths_of_dependencies, man_paths_of_dependencies, ) apps, man_pages = get_resources(root_dist, venv_bin_path, venv_man_path) app_paths = [venv_bin_path / app for app in apps] man_paths = [venv_man_path / man_page for man_page in man_pages] if WINDOWS: app_paths = _windows_extra_app_paths(app_paths) for dep in app_paths_of_dependencies: apps_of_dependencies += [dep_path.name for dep_path in app_paths_of_dependencies[dep]] if WINDOWS: app_paths_of_dependencies[dep] = _windows_extra_app_paths(app_paths_of_dependencies[dep]) for dep in man_paths_of_dependencies: man_pages_of_dependencies += [ str(Path(dep_path.parent.name) / dep_path.name) for dep_path in man_paths_of_dependencies[dep] ] return VenvMetadata( apps=apps, app_paths=app_paths, apps_of_dependencies=apps_of_dependencies, app_paths_of_dependencies=app_paths_of_dependencies, man_pages=man_pages, man_paths=man_paths, man_pages_of_dependencies=man_pages_of_dependencies, man_paths_of_dependencies=man_paths_of_dependencies, package_version=root_dist.version, python_version=venv_python_version, ) pipx-1.6.0/src/pipx/version.pyi000066400000000000000000000003621462701651400164640ustar00rootroot00000000000000version: str version_tuple: tuple[int, int, int, str, str] | tuple[int, int, int] # Note that newer versions of setuptools_scm also add __version__, but we are # not forcing new versions of setuptools_scm, so only these imports are allowed. pipx-1.6.0/testdata/000077500000000000000000000000001462701651400143155ustar00rootroot00000000000000pipx-1.6.0/testdata/empty_project/000077500000000000000000000000001462701651400172015ustar00rootroot00000000000000pipx-1.6.0/testdata/empty_project/README.md000066400000000000000000000000441462701651400204560ustar00rootroot00000000000000Empty project used for testing only pipx-1.6.0/testdata/empty_project/empty_project/000077500000000000000000000000001462701651400220655ustar00rootroot00000000000000pipx-1.6.0/testdata/empty_project/empty_project/__init__.py000066400000000000000000000000001462701651400241640ustar00rootroot00000000000000pipx-1.6.0/testdata/empty_project/empty_project/main.py000066400000000000000000000000751462701651400233650ustar00rootroot00000000000000def main(): pass if __name__ == "__main__": main() pipx-1.6.0/testdata/empty_project/pyproject.toml000066400000000000000000000012311462701651400221120ustar00rootroot00000000000000[build-system] build-backend = "setuptools.build_meta" requires = [ "setuptools", ] [project] name = "empty-project" version = "0.1.0" description = "Empty Python Project" authors = [ { name = "My Name", email = "me@example.com" }, ] requires-python = ">=3.8" classifiers = [ "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] scripts.empty-project = "empty_project.main:cli" entry-points."pipx.run".empty-project = "empty_project.main:cli" pipx-1.6.0/testdata/pipx_metadata_multiple_errors.json000066400000000000000000000042231462701651400233400ustar00rootroot00000000000000{ "pipx_spec_version": "0.1", "venvs": { "dotenv": { "metadata": { "injected_packages": {}, "main_package": { "app_paths": [ ], "app_paths_of_dependencies": {}, "apps": [ ], "apps_of_dependencies": [], "include_apps": true, "include_dependencies": false, "man_pages": [], "man_pages_of_dependencies": [], "man_paths": [], "man_paths_of_dependencies": {}, "package": "dotenv", "package_or_url": "dotenv", "package_version": "0.0.5", "pip_args": [], "suffix": "" }, "pipx_metadata_version": "0.4", "python_version": "Python 3.10.12", "source_interpreter": { }, "venv_args": [] } }, "weblate": { "metadata": { "injected_packages": {}, "main_package": { "app_paths": [ ], "app_paths_of_dependencies": {}, "apps": [ ], "apps_of_dependencies": [], "include_apps": true, "include_dependencies": false, "man_pages": [ ], "man_pages_of_dependencies": [], "man_paths": [ ], "man_paths_of_dependencies": {}, "package": "weblate", "package_or_url": "weblate", "package_version": "4.3.1", "pip_args": [], "suffix": "" }, "pipx_metadata_version": "0.4", "python_version": "Python 3.10.12", "source_interpreter": { }, "venv_args": [] } } } } pipx-1.6.0/testdata/standalone_python_index_20240107.json000066400000000000000000002624311462701651400231170ustar00rootroot00000000000000{"fetched": 1713356788.130173, "releases": ["https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.10.13%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.8.18%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.9.18%2B20240107-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240107/SHA256SUMS"]} pipx-1.6.0/testdata/standalone_python_index_20240224.json000066400000000000000000002625741462701651400231270ustar00rootroot00000000000000{"fetched": 1713360361.758339, "releases": ["https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.10.13%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.11.8%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.12.2%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.8.18%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-i686-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-ppc64le-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-s390x-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-apple-darwin-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-shared-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-static-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-pc-windows-msvc-static-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v2-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-pgo%2Blto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-gnu-pgo-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v3-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-gnu-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-debug-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-install_only.tar.gz.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-lto-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-x86_64_v4-unknown-linux-musl-noopt-full.tar.zst.sha256", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/SHA256SUMS", "https://github.com/indygreg/python-build-standalone/releases/download/20240224/xz-5.2.12.tar.gz"]} pipx-1.6.0/testdata/test_package_specifier/000077500000000000000000000000001462701651400210005ustar00rootroot00000000000000pipx-1.6.0/testdata/test_package_specifier/local_extras/000077500000000000000000000000001462701651400234605ustar00rootroot00000000000000pipx-1.6.0/testdata/test_package_specifier/local_extras/repeatme/000077500000000000000000000000001462701651400252625ustar00rootroot00000000000000pipx-1.6.0/testdata/test_package_specifier/local_extras/repeatme/__init__.py000066400000000000000000000000001462701651400273610ustar00rootroot00000000000000pipx-1.6.0/testdata/test_package_specifier/local_extras/repeatme/main.py000066400000000000000000000004321462701651400265570ustar00rootroot00000000000000import sys try: import pycowsay.main has_pycowsay = True except ImportError: has_pycowsay = False def main(): print(f"You said:\n {' '.join(sys.argv[1:])}") if has_pycowsay: print() print("In cow, you said:") pycowsay.main.main() pipx-1.6.0/testdata/test_package_specifier/local_extras/setup.py000066400000000000000000000004071462701651400251730ustar00rootroot00000000000000from setuptools import setup setup( name="repeatme", version=0.1, description="Repeat arguments.", packages=["repeatme"], extras_require={"cow": ["pycowsay==0.0.0.2"]}, entry_points={"console_scripts": ["repeatme=repeatme.main:main"]}, ) pipx-1.6.0/testdata/tests_packages/000077500000000000000000000000001462701651400173155ustar00rootroot00000000000000pipx-1.6.0/testdata/tests_packages/README.md000066400000000000000000000024041462701651400205740ustar00rootroot00000000000000# Introduction `primary_packages.txt` is the master list, containing all packages installed or injected in the pipx tests `tests`. Platform-specific list files listing both these primary packages and their dependencies are generated from it. These platform-specific list files are used to populate the directory `.pipx_tests/package_cache`. # Generating the platform-specific lists from the master list Using the Github Workflow * Make sure that the file in this directory `primary_packages.txt` is up to date for every package & version that is installed or injected in the tests. * Manually activate the Github workflow: Create tests package lists for offline tests * Download the artifact `lists` and put the files from it into this directory. Or to locally generate these lists, on the target platform execute: * `nox -s create_test_package_list` # Updating / Populating the directory `.pipx_tests/package_cache` before running the tests Pre-populating this directory allows the pipx `tests` to run completely offline. Nox instructions * execute `nox -s refresh_packages_cache` Or manually execute from the top-level pipx repo directory: * `mkdir -p .pipx_tests/package_cache` * `python3 scripts/update_package_cache.py testdata/tests_packages .pipx_tests/package_cache` pipx-1.6.0/testdata/tests_packages/macos23-python3.12.txt000066400000000000000000000220711462701651400231520ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 appnope==0.1.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 awscli==1.18.168 backcall==0.2.0 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.21.2 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.23.0 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jedi==0.19.1 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyobjc==10.2 pyobjc_core==10.2 pyobjc_framework_AVFoundation==10.2 pyobjc_framework_AVKit==10.2 pyobjc_framework_AVRouting==10.2 pyobjc_framework_Accessibility==10.2 pyobjc_framework_Accounts==10.2 pyobjc_framework_AdServices==10.2 pyobjc_framework_AdSupport==10.2 pyobjc_framework_AddressBook==10.2 pyobjc_framework_AppTrackingTransparency==10.2 pyobjc_framework_AppleScriptKit==10.2 pyobjc_framework_AppleScriptObjC==10.2 pyobjc_framework_ApplicationServices==10.2 pyobjc_framework_AudioVideoBridging==10.2 pyobjc_framework_AuthenticationServices==10.2 pyobjc_framework_AutomaticAssessmentConfiguration==10.2 pyobjc_framework_Automator==10.2 pyobjc_framework_BackgroundAssets==10.2 pyobjc_framework_BrowserEngineKit==10.2 pyobjc_framework_BusinessChat==10.2 pyobjc_framework_CFNetwork==10.2 pyobjc_framework_CalendarStore==10.2 pyobjc_framework_CallKit==10.2 pyobjc_framework_Cinematic==10.2 pyobjc_framework_ClassKit==10.2 pyobjc_framework_CloudKit==10.2 pyobjc_framework_Cocoa==10.2 pyobjc_framework_Collaboration==10.2 pyobjc_framework_ColorSync==10.2 pyobjc_framework_Contacts==10.2 pyobjc_framework_ContactsUI==10.2 pyobjc_framework_CoreAudio==10.2 pyobjc_framework_CoreAudioKit==10.2 pyobjc_framework_CoreBluetooth==10.2 pyobjc_framework_CoreData==10.2 pyobjc_framework_CoreHaptics==10.2 pyobjc_framework_CoreLocation==10.2 pyobjc_framework_CoreMIDI==10.2 pyobjc_framework_CoreML==10.2 pyobjc_framework_CoreMedia==10.2 pyobjc_framework_CoreMediaIO==10.2 pyobjc_framework_CoreMotion==10.2 pyobjc_framework_CoreServices==10.2 pyobjc_framework_CoreSpotlight==10.2 pyobjc_framework_CoreText==10.2 pyobjc_framework_CoreWLAN==10.2 pyobjc_framework_CryptoTokenKit==10.2 pyobjc_framework_DVDPlayback==10.2 pyobjc_framework_DataDetection==10.2 pyobjc_framework_DeviceCheck==10.2 pyobjc_framework_DictionaryServices==10.2 pyobjc_framework_DiscRecording==10.2 pyobjc_framework_DiscRecordingUI==10.2 pyobjc_framework_DiskArbitration==10.2 pyobjc_framework_EventKit==10.2 pyobjc_framework_ExceptionHandling==10.2 pyobjc_framework_ExecutionPolicy==10.2 pyobjc_framework_ExtensionKit==10.2 pyobjc_framework_ExternalAccessory==10.2 pyobjc_framework_FSEvents==10.2 pyobjc_framework_FileProvider==10.2 pyobjc_framework_FileProviderUI==10.2 pyobjc_framework_FinderSync==10.2 pyobjc_framework_GameCenter==10.2 pyobjc_framework_GameController==10.2 pyobjc_framework_GameKit==10.2 pyobjc_framework_GameplayKit==10.2 pyobjc_framework_HealthKit==10.2 pyobjc_framework_IOBluetooth==10.2 pyobjc_framework_IOBluetoothUI==10.2 pyobjc_framework_IOSurface==10.2 pyobjc_framework_ImageCaptureCore==10.2 pyobjc_framework_InputMethodKit==10.2 pyobjc_framework_InstallerPlugins==10.2 pyobjc_framework_InstantMessage==10.2 pyobjc_framework_Intents==10.2 pyobjc_framework_IntentsUI==10.2 pyobjc_framework_KernelManagement==10.2 pyobjc_framework_LatentSemanticMapping==10.2 pyobjc_framework_LaunchServices==10.2 pyobjc_framework_LinkPresentation==10.2 pyobjc_framework_LocalAuthentication==10.2 pyobjc_framework_LocalAuthenticationEmbeddedUI==10.2 pyobjc_framework_MLCompute==10.2 pyobjc_framework_MailKit==10.2 pyobjc_framework_MapKit==10.2 pyobjc_framework_MediaAccessibility==10.2 pyobjc_framework_MediaLibrary==10.2 pyobjc_framework_MediaPlayer==10.2 pyobjc_framework_MediaToolbox==10.2 pyobjc_framework_Metal==10.2 pyobjc_framework_MetalFX==10.2 pyobjc_framework_MetalKit==10.2 pyobjc_framework_MetalPerformanceShaders==10.2 pyobjc_framework_MetalPerformanceShadersGraph==10.2 pyobjc_framework_MetricKit==10.2 pyobjc_framework_ModelIO==10.2 pyobjc_framework_MultipeerConnectivity==10.2 pyobjc_framework_NaturalLanguage==10.2 pyobjc_framework_NetFS==10.2 pyobjc_framework_Network==10.2 pyobjc_framework_NetworkExtension==10.2 pyobjc_framework_NotificationCenter==10.2 pyobjc_framework_OSAKit==10.2 pyobjc_framework_OSLog==10.2 pyobjc_framework_OpenDirectory==10.2 pyobjc_framework_PHASE==10.2 pyobjc_framework_PassKit==10.2 pyobjc_framework_PencilKit==10.2 pyobjc_framework_Photos==10.2 pyobjc_framework_PhotosUI==10.2 pyobjc_framework_PreferencePanes==10.2 pyobjc_framework_PushKit==10.2 pyobjc_framework_Quartz==10.2 pyobjc_framework_QuickLookThumbnailing==10.2 pyobjc_framework_ReplayKit==10.2 pyobjc_framework_SafariServices==10.2 pyobjc_framework_SafetyKit==10.2 pyobjc_framework_SceneKit==10.2 pyobjc_framework_ScreenCaptureKit==10.2 pyobjc_framework_ScreenSaver==10.2 pyobjc_framework_ScreenTime==10.2 pyobjc_framework_ScriptingBridge==10.2 pyobjc_framework_SearchKit==10.2 pyobjc_framework_Security==10.2 pyobjc_framework_SecurityFoundation==10.2 pyobjc_framework_SecurityInterface==10.2 pyobjc_framework_SensitiveContentAnalysis==10.2 pyobjc_framework_ServiceManagement==10.2 pyobjc_framework_SharedWithYou==10.2 pyobjc_framework_SharedWithYouCore==10.2 pyobjc_framework_ShazamKit==10.2 pyobjc_framework_Social==10.2 pyobjc_framework_SoundAnalysis==10.2 pyobjc_framework_Speech==10.2 pyobjc_framework_SpriteKit==10.2 pyobjc_framework_StoreKit==10.2 pyobjc_framework_Symbols==10.2 pyobjc_framework_SyncServices==10.2 pyobjc_framework_SystemConfiguration==10.2 pyobjc_framework_SystemExtensions==10.2 pyobjc_framework_ThreadNetwork==10.2 pyobjc_framework_UniformTypeIdentifiers==10.2 pyobjc_framework_UserNotifications==10.2 pyobjc_framework_UserNotificationsUI==10.2 pyobjc_framework_VideoSubscriberAccount==10.2 pyobjc_framework_VideoToolbox==10.2 pyobjc_framework_Virtualization==10.2 pyobjc_framework_Vision==10.2 pyobjc_framework_WebKit==10.2 pyobjc_framework_iTunesLibrary==10.2 pyobjc_framework_libdispatch==10.2 pyobjc_framework_libxpc==10.2 pyparsing==3.1.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 richxerox==1.0.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/testdata/tests_packages/primary_packages.txt000066400000000000000000000012571462701651400234040ustar00rootroot00000000000000# Modify this list if the packages pipx installs in 'tests' changes # Comments ignored after # # Space-separated values on same row. # spec no-deps Cython # in 'setup_requires' of jupyter dep pywinpty on Win ansible==6.7.0 awscli==1.18.168 black==22.8.0 black==22.10.0 cloudtoken==2.1.0 ipython==7.16.1 isort==5.6.4 jaraco-clipboard==2.0.1 zest-releaser==9.1.2 jupyter==1.0.0 kaggle==1.6.11 nox==2022.1.7 nox[tox_to_nox]==2023.4.22 pbr==5.6.0 pip==23.3.2 pip==24.0 pip pycowsay==0.0.0.2 pygdbmi==0.10.0.0 pylint pylint==3.0.4 setuptools-scm setuptools>=41.0 shell-functools==0.3.0 tox tox-ini-fmt==0.5.0 weblate==4.3.1 True # expected fail in tests wheel pipx-1.6.0/testdata/tests_packages/unix-python3.10.txt000066400000000000000000000073561462701651400226750ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 SecretStorage==3.3.3 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 awscli==1.18.168 backcall==0.2.0 backports.tarfile==1.1.1 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.21.2 exceptiongroup==1.2.1 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.23.0 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jedi==0.19.1 jeepney==0.8.0 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyparsing==3.1.2 pyperclip==1.8.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomli==2.0.1 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/testdata/tests_packages/unix-python3.11.txt000066400000000000000000000073131462701651400226670ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 SecretStorage==3.3.3 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 awscli==1.18.168 backcall==0.2.0 backports.tarfile==1.1.1 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.21.2 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.23.0 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jedi==0.19.1 jeepney==0.8.0 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyparsing==3.1.2 pyperclip==1.8.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/testdata/tests_packages/unix-python3.12.txt000066400000000000000000000072621462701651400226730ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 SecretStorage==3.3.3 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 awscli==1.18.168 backcall==0.2.0 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.21.2 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.23.0 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jedi==0.19.1 jeepney==0.8.0 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyparsing==3.1.2 pyperclip==1.8.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/testdata/tests_packages/unix-python3.8.txt000066400000000000000000000075041462701651400226170ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 SecretStorage==3.3.3 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 awscli==1.18.168 backcall==0.2.0 backports.tarfile==1.1.1 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.20.1 exceptiongroup==1.2.1 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 importlib_resources==6.4.0 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.12.3 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jedi==0.19.1 jeepney==0.8.0 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 pkgutil_resolve_name==1.3.10 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyparsing==3.1.2 pyperclip==1.8.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pytz==2024.1 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomli==2.0.1 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==1.26.18 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/testdata/tests_packages/unix-python3.9.txt000066400000000000000000000073771462701651400226300ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 SecretStorage==3.3.3 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 awscli==1.18.168 backcall==0.2.0 backports.tarfile==1.1.1 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.21.2 exceptiongroup==1.2.1 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.18.1 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jedi==0.19.1 jeepney==0.8.0 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyparsing==3.1.2 pyperclip==1.8.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomli==2.0.1 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==1.26.18 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/testdata/tests_packages/win-python3.12.txt000066400000000000000000000100761462701651400225020ustar00rootroot00000000000000Babel==2.14.0 Cython==3.0.10 Flask==1.1.4 Jinja2==2.11.3 Jinja2==3.1.3 MarkupSafe==2.1.5 PyYAML==5.3.1 PyYAML==6.0.1 QtPy==2.4.1 Send2Trash==1.8.3 Weblate==4.3.1 Werkzeug==1.0.1 ansible==6.7.0 ansible_core==2.13.13 anyio==4.3.0 appdirs==1.4.4 argcomplete==1.12.3 argcomplete==3.3.0 argon2_cffi==23.1.0 argon2_cffi_bindings==21.2.0 arrow==1.3.0 astroid==3.0.3 astroid==3.1.0 asttokens==2.4.1 async_lru==2.0.4 attrs==23.2.0 autocommand==2.2.2 awscli==1.18.168 backcall==0.2.0 beautifulsoup4==4.12.3 black==22.10.0 black==22.8.0 bleach==6.1.0 boto3==1.34.92 botocore==1.19.8 botocore==1.34.92 build==1.2.1 cachetools==5.3.3 certifi==2024.2.2 cffi==1.16.0 chardet==5.2.0 charset_normalizer==3.3.2 click==7.1.2 click==8.1.7 cloudtoken==2.1.0 cmarkgfm==2024.1.14 colorama==0.4.3 colorama==0.4.6 colorlog==6.8.2 comm==0.2.2 cryptography==42.0.5 debugpy==1.8.1 decorator==5.1.1 deepdiff==5.8.1 defusedxml==0.7.1 delegator.py==0.1.1 dill==0.3.8 distlib==0.3.8 docutils==0.15.2 docutils==0.21.2 executing==2.0.1 fastjsonschema==2.19.1 filelock==3.13.4 fqdn==1.5.1 h11==0.14.0 halo==0.0.31 httpcore==1.0.5 httpx==0.27.0 idna==3.7 ifaddr==0.1.7 importlib_metadata==7.1.0 inflect==7.2.1 iniconfig==2.0.0 ipykernel==6.29.4 ipython==7.16.1 ipython==8.23.0 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 isort==5.6.4 itsdangerous==1.1.0 jaraco.classes==3.4.0 jaraco.clipboard==2.0.1 jaraco.collections==5.0.1 jaraco.context==5.3.0 jaraco.functools==4.0.1 jaraco.structures==2.2.0 jaraco.text==3.12.0 jaraco.ui==2.3.0 jaraco.windows==5.8.0 jedi==0.19.1 jmespath==0.10.0 jmespath==1.0.1 json5==0.9.25 jsonpointer==2.4 jsonschema==4.21.1 jsonschema_specifications==2023.12.1 jupyter==1.0.0 jupyter_client==8.6.1 jupyter_console==6.6.3 jupyter_core==5.7.2 jupyter_events==0.10.0 jupyter_lsp==2.2.5 jupyter_server==2.14.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.6 jupyterlab_pygments==0.3.0 jupyterlab_server==2.27.1 jupyterlab_widgets==3.0.10 kaggle==1.6.11 keyring==21.8.0 keyring==25.1.0 log_symbols==0.0.14 lxml==4.9.4 markdown_it_py==3.0.0 matplotlib_inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.0.2 more_itertools==10.2.0 mypy_extensions==1.0.0 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.4 nest_asyncio==1.6.0 nh3==0.2.17 notebook==7.1.3 notebook_shim==0.2.4 nox==2022.1.7 nox==2023.4.22 ordered_set==4.1.0 overrides==7.7.0 packaging==20.9 packaging==24.0 pandocfilters==1.5.1 parso==0.8.4 path==16.14.0 pathspec==0.12.1 pbr==5.6.0 pexpect==4.9.0 pickleshare==0.7.5 pip==23.3.2 pip==24.0 pkginfo==1.10.0 platformdirs==4.2.1 pluggy==1.5.0 prometheus_client==0.20.0 prompt_toolkit==3.0.43 psutil==5.9.8 ptyprocess==0.7.0 pure_eval==0.2.2 py==1.11.0 pyasn1==0.6.0 pycowsay==0.0.0.2 pycparser==2.22 pygdbmi==0.10.0.0 pygments==2.17.2 pylint==3.0.4 pylint==3.1.0 pyparsing==3.1.2 pyproject_api==1.6.1 pyproject_hooks==1.0.0 pytest==8.1.1 python_dateutil==2.9.0.post0 python_json_logger==2.0.7 python_slugify==8.0.4 pywin32==306 pywin32_ctypes==0.2.2 pywinpty==2.0.13 pyzmq==26.0.2 qtconsole==5.5.1 readme_renderer==43.0 referencing==0.35.0 requests==2.31.0 requests_toolbelt==1.0.0 resolvelib==0.8.1 rfc3339_validator==0.1.4 rfc3986==2.0.0 rfc3986_validator==0.1.1 rich==13.7.1 rpds_py==0.18.0 rsa==4.5 ruamel.yaml.clib==0.2.8 ruamel.yaml==0.17.40 s3transfer==0.10.1 s3transfer==0.3.7 setuptools==69.5.1 setuptools_scm==8.0.4 shell-functools==0.3.0 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 spinners==0.0.24 stack_data==0.6.3 termcolor==2.4.0 terminado==0.18.1 text_unidecode==1.3 tinycss2==1.3.0 tomlkit==0.12.4 tornado==6.4 tox==3.28.0 tox==4.14.2 tox_ini_fmt==0.5.0 tqdm==4.66.2 traitlets==5.14.3 twine==5.0.0 typeguard==4.2.1 types_python_dateutil==2.9.0.20240316 typing_extensions==4.11.0 uri_template==1.3.0 urllib3==1.25.11 urllib3==2.2.1 virtualenv==20.26.0 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket_client==1.8.0 wheel==0.43.0 widgetsnbextension==4.0.10 xdg==5.1.1 zest.releaser==9.1.2 zipp==3.18.1 pipx-1.6.0/tests/000077500000000000000000000000001462701651400136465ustar00rootroot00000000000000pipx-1.6.0/tests/conftest.py000066400000000000000000000204371462701651400160530ustar00rootroot00000000000000import json import os import shutil import socket import subprocess import sys from contextlib import closing from http import HTTPStatus from pathlib import Path from typing import Iterator from urllib.error import HTTPError, URLError from urllib.request import urlopen import pytest # type: ignore[import-not-found] from helpers import WIN from pipx import commands, interpreter, paths, shared_libs, standalone_python, venv PIPX_TESTS_DIR = Path(".pipx_tests") PIPX_TESTS_PACKAGE_LIST_DIR = Path("testdata/tests_packages") @pytest.fixture(scope="session") def root() -> Path: return Path(__file__).parents[1] @pytest.fixture() def mocked_github_api(monkeypatch, root): """ Fixture to replace the github index with a local copy, to prevent unit tests from exceeding github's API request limit. """ with open(root / "testdata" / "standalone_python_index_20240107.json") as f: index = json.load(f) monkeypatch.setattr(standalone_python, "get_or_update_index", lambda _: index) def pytest_addoption(parser): parser.addoption( "--all-packages", action="store_true", dest="all_packages", default=False, help="Run only the long, slow tests installing the maximum list of packages.", ) parser.addoption( "--net-pypiserver", action="store_true", dest="net_pypiserver", default=False, help="Start local pypi server and use in tests.", ) def pytest_configure(config): markexpr = getattr(config.option, "markexpr", "") if config.option.all_packages: new_markexpr = (f"{markexpr} or " if markexpr else "") + "all_packages" else: new_markexpr = (f"{markexpr} and " if markexpr else "") + "not all_packages" config.option.markexpr = new_markexpr def pipx_temp_env_helper(pipx_shared_dir, tmp_path, monkeypatch, request, utils_temp_dir, pypi): home_dir = Path(tmp_path) / "subdir" / "pipxhome" bin_dir = Path(tmp_path) / "otherdir" / "pipxbindir" man_dir = Path(tmp_path) / "otherdir" / "pipxmandir" global_home_dir = Path(tmp_path) / "global" / "pipxhome" global_bin_dir = Path(tmp_path) / "global_otherdir" / "pipxbindir" global_man_dir = Path(tmp_path) / "global_otherdir" / "pipxmandir" # Patch in test specific base paths monkeypatch.setattr(paths.ctx, "_base_shared_libs", pipx_shared_dir) monkeypatch.setattr(paths.ctx, "_base_home", home_dir) monkeypatch.setattr(paths.ctx, "_base_bin", bin_dir) monkeypatch.setattr(paths.ctx, "_base_man", man_dir) # Patch the default global paths so developers don't contaminate their own systems monkeypatch.setattr(paths, "DEFAULT_PIPX_GLOBAL_BIN_DIR", global_bin_dir) monkeypatch.setattr(paths, "DEFAULT_PIPX_GLOBAL_HOME", global_home_dir) monkeypatch.setattr(paths, "DEFAULT_PIPX_GLOBAL_MAN_DIR", global_man_dir) monkeypatch.setattr(shared_libs, "shared_libs", shared_libs._SharedLibs()) monkeypatch.setattr(venv, "shared_libs", shared_libs.shared_libs) monkeypatch.setattr(interpreter, "DEFAULT_PYTHON", sys.executable) if "PIPX_DEFAULT_PYTHON" in os.environ: monkeypatch.delenv("PIPX_DEFAULT_PYTHON") # macOS needs /usr/bin in PATH to compile certain packages, but # applications in /usr/bin cause test_install.py tests to raise warnings # which make tests fail (e.g. on Github ansible apps exist in /usr/bin) monkeypatch.setenv("PATH_ORIG", str(paths.ctx.bin_dir) + os.pathsep + os.environ["PATH"]) monkeypatch.setenv("PATH_TEST", str(paths.ctx.bin_dir)) monkeypatch.setenv("PATH", str(paths.ctx.bin_dir) + os.pathsep + str(utils_temp_dir)) # On Windows, monkeypatch pipx.commands.common._can_symlink_cache to # indicate that paths.ctx.bin_dir and paths.ctx.man_dir # cannot use symlinks, even if we're running as administrator and # symlinks are actually possible. if WIN: monkeypatch.setitem(commands.common._can_symlink_cache, paths.ctx.bin_dir, False) monkeypatch.setitem(commands.common._can_symlink_cache, paths.ctx.man_dir, False) if not request.config.option.net_pypiserver: # IMPORTANT: use 127.0.0.1 not localhost # Using localhost on Windows creates enormous slowdowns # (for some reason--perhaps IPV6/IPV4 tries, timeouts?) monkeypatch.setenv("PIP_INDEX_URL", pypi) @pytest.fixture(scope="session", autouse=True) def pipx_local_pypiserver(request, root: Path, tmp_path_factory) -> Iterator[str]: """Starts local pypiserver once per session unless --net-pypiserver was passed to pytest""" if request.config.option.net_pypiserver: # need both yield and return because other codepath has both yield "" return pipx_cache_dir = root / PIPX_TESTS_DIR / "package_cache" check_test_packages_cmd = [ sys.executable, "scripts/update_package_cache.py", "--check-only", str(PIPX_TESTS_PACKAGE_LIST_DIR), str(pipx_cache_dir), ] update_test_packages_cmd = [ sys.executable, "scripts/update_package_cache.py", str(PIPX_TESTS_PACKAGE_LIST_DIR), str(pipx_cache_dir), ] check_test_packages_process = subprocess.run(check_test_packages_cmd, check=False, cwd=root) if check_test_packages_process.returncode != 0: raise Exception( f"Directory {pipx_cache_dir!s} does not contain all " "package distribution files necessary to run pipx tests. Please " "run the following command to populate it: " f"{' '.join(update_test_packages_cmd)}" ) def find_free_port(): with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: s.bind(("", 0)) return s.getsockname()[1] server_log = tmp_path_factory.mktemp("log") / "pypiserver.log" if server_log.exists(): server_log.unlink() port = find_free_port() os.environ["NO_PROXY"] = "127.0.0.1" cache = str(pipx_cache_dir / f"{sys.version_info[0]}.{sys.version_info[1]}") server = str(Path(sys.executable).parent / "pypi-server") cmd = [server, "run", "--verbose", "--disable-fallback", "--host", "127.0.0.1", "--port", str(port), cache] cmd += ["--log-file", str(server_log)] pypiserver_process = subprocess.Popen(cmd, cwd=root) url = f"http://127.0.0.1:{port}/simple/" while True: try: with urlopen(url) as response: if response.code == HTTPStatus.OK: break except (URLError, HTTPError): continue yield url pypiserver_process.terminate() @pytest.fixture(scope="session") def pipx_session_shared_dir(tmp_path_factory): """Makes a temporary pipx shared libs directory only once per session""" return tmp_path_factory.mktemp("session_shareddir") @pytest.fixture(scope="session") def utils_temp_dir(tmp_path_factory): tmp_path = tmp_path_factory.mktemp("session_utilstempdir") utils = ["git"] for util in utils: at_path = shutil.which(util) assert at_path is not None util_path = Path(at_path) try: (tmp_path / util_path.name).symlink_to(util_path) except FileExistsError: pass return tmp_path @pytest.fixture def pipx_temp_env(tmp_path, monkeypatch, pipx_session_shared_dir, request, utils_temp_dir, pipx_local_pypiserver): """Sets up temporary paths for pipx to install into. Shared libs are setup once per session, all other pipx dirs, constants are recreated for every test function. Also adds environment variables as necessary to make pip installations seamless. """ pipx_temp_env_helper(pipx_session_shared_dir, tmp_path, monkeypatch, request, utils_temp_dir, pipx_local_pypiserver) yield paths.ctx.make_local() @pytest.fixture def pipx_ultra_temp_env(tmp_path, monkeypatch, request, utils_temp_dir, pipx_local_pypiserver): """Sets up temporary paths for pipx to install into. Fully temporary environment, every test function starts as if pipx has never been run before, including empty shared libs directory. Also adds environment variables as necessary to make pip installations seamless. """ shared_dir = Path(tmp_path) / "shareddir" pipx_temp_env_helper(shared_dir, tmp_path, monkeypatch, request, utils_temp_dir, pipx_local_pypiserver) yield paths.ctx.make_local() pipx-1.6.0/tests/helpers.py000066400000000000000000000173551462701651400156750ustar00rootroot00000000000000import json import os import re import sys from dataclasses import replace from pathlib import Path from typing import Any, Dict, List, Optional from unittest import mock import pytest # type: ignore[import-not-found] from packaging.utils import canonicalize_name from package_info import PKG from pipx import constants, main, paths, pipx_metadata_file, util WIN = sys.platform.startswith("win") PIPX_METADATA_LEGACY_VERSIONS = [None, "0.1", "0.2", "0.3"] MOCK_PIPXMETADATA_0_1: Dict[str, Any] = { "main_package": None, "python_version": None, "venv_args": [], "injected_packages": {}, "pipx_metadata_version": "0.1", } MOCK_PIPXMETADATA_0_2: Dict[str, Any] = { "main_package": None, "python_version": None, "venv_args": [], "injected_packages": {}, "pipx_metadata_version": "0.2", } MOCK_PIPXMETADATA_0_3: Dict[str, Any] = { "main_package": None, "python_version": None, "venv_args": [], "injected_packages": {}, "pipx_metadata_version": "0.3", "man_pages": [], "man_paths": [], "man_pages_of_dependencies": [], "man_paths_of_dependencies": {}, } MOCK_PACKAGE_INFO_0_1: Dict[str, Any] = { "package": None, "package_or_url": None, "pip_args": [], "include_dependencies": False, "include_apps": True, "apps": [], "app_paths": [], "apps_of_dependencies": [], "app_paths_of_dependencies": {}, "package_version": "", } MOCK_PACKAGE_INFO_0_2: Dict[str, Any] = { "package": None, "package_or_url": None, "pip_args": [], "include_dependencies": False, "include_apps": True, "apps": [], "app_paths": [], "apps_of_dependencies": [], "app_paths_of_dependencies": {}, "package_version": "", "suffix": "", } def app_name(app: str) -> str: return f"{app}.exe" if WIN else app def run_pipx_cli(pipx_args: List[str]) -> int: with mock.patch.object(sys, "argv", ["pipx"] + pipx_args): return main.cli() def unwrap_log_text(log_text: str): """Remove line-break + indent space from log messages Captured log lines always start with the 'severity' so if a line starts with any spaces assume it is due to an indented pipx wrapped message. """ return re.sub(r"\n\s+", " ", log_text) def _mock_legacy_package_info(modern_package_info: Dict[str, Any], metadata_version: str) -> Dict[str, Any]: if metadata_version in ["0.2", "0.3"]: mock_package_info_template = MOCK_PACKAGE_INFO_0_2 elif metadata_version == "0.1": mock_package_info_template = MOCK_PACKAGE_INFO_0_1 else: raise Exception(f"Internal Test Error: Unknown metadata_version={metadata_version}") mock_package_info = {} for key in mock_package_info_template: mock_package_info[key] = modern_package_info[key] return mock_package_info def mock_legacy_venv(venv_name: str, metadata_version: Optional[str] = None) -> None: """Convert a venv installed with the most recent pipx to look like one with a previous metadata version. metadata_version=None refers to no metadata file (pipx pre-0.15.0.0) """ venv_dir = Path(paths.ctx.venvs) / canonicalize_name(venv_name) if metadata_version == "0.4": # Current metadata version, do nothing return elif metadata_version == "0.3": mock_pipx_metadata_template = MOCK_PIPXMETADATA_0_3 elif metadata_version == "0.2": mock_pipx_metadata_template = MOCK_PIPXMETADATA_0_2 elif metadata_version == "0.1": mock_pipx_metadata_template = MOCK_PIPXMETADATA_0_1 elif metadata_version is None: # No metadata os.remove(venv_dir / "pipx_metadata.json") return else: raise Exception(f"Internal Test Error: Unknown metadata_version={metadata_version}") modern_metadata = pipx_metadata_file.PipxMetadata(venv_dir).to_dict() # Convert to mock old metadata mock_pipx_metadata: dict[str, Any] = {} for key in mock_pipx_metadata_template: if key == "main_package": mock_pipx_metadata[key] = _mock_legacy_package_info(modern_metadata[key], metadata_version=metadata_version) if key == "injected_packages": mock_pipx_metadata[key] = {} for injected in modern_metadata[key]: mock_pipx_metadata[key][injected] = _mock_legacy_package_info( modern_metadata[key][injected], metadata_version=metadata_version ) else: mock_pipx_metadata[key] = modern_metadata.get(key) mock_pipx_metadata["pipx_metadata_version"] = mock_pipx_metadata_template["pipx_metadata_version"] # replicate pipx_metadata_file.PipxMetadata.write() with open(venv_dir / "pipx_metadata.json", "w") as pipx_metadata_fh: json.dump( mock_pipx_metadata, pipx_metadata_fh, indent=4, sort_keys=True, cls=pipx_metadata_file.JsonEncoderHandlesPath, ) def create_package_info_ref(venv_name, package_name, pipx_venvs_dir, **field_overrides): """Create reference PackageInfo to check against Overridable fields to be used in field_overrides: pip_args (default: []) include_apps (default: True) include_dependencies (default: False) app_paths_of_dependencies (default: {}) """ venv_bin_dir = "Scripts" if constants.WINDOWS else "bin" return pipx_metadata_file.PackageInfo( package=package_name, package_or_url=PKG[package_name]["spec"], pip_args=field_overrides.get("pip_args", []), include_apps=field_overrides.get("include_apps", True), include_dependencies=field_overrides.get("include_dependencies", False), apps=PKG[package_name]["apps"], app_paths=[pipx_venvs_dir / venv_name / venv_bin_dir / app for app in PKG[package_name]["apps"]], apps_of_dependencies=PKG[package_name]["apps_of_dependencies"], app_paths_of_dependencies=field_overrides.get("app_paths_of_dependencies", {}), man_pages=PKG[package_name].get("man_pages", []), man_paths=[ pipx_venvs_dir / venv_name / "share" / "man" / man_page for man_page in PKG[package_name].get("man_pages", []) ], man_pages_of_dependencies=PKG[package_name].get("man_pages_of_dependencies", []), man_paths_of_dependencies=field_overrides.get("man_paths_of_dependencies", {}), package_version=PKG[package_name]["spec"].split("==")[-1], ) def assert_package_metadata(test_metadata, ref_metadata): # only compare sorted versions of apps, app_paths so order is not important assert test_metadata.package_version != "" assert isinstance(test_metadata.apps, list) assert isinstance(test_metadata.app_paths, list) test_metadata_replaced = replace( test_metadata, apps=sorted(test_metadata.apps), app_paths=sorted(test_metadata.app_paths), apps_of_dependencies=sorted(test_metadata.apps_of_dependencies), app_paths_of_dependencies={key: sorted(value) for key, value in test_metadata.app_paths_of_dependencies.items()}, ) ref_metadata_replaced = replace( ref_metadata, apps=sorted(ref_metadata.apps), app_paths=sorted(ref_metadata.app_paths), apps_of_dependencies=sorted(ref_metadata.apps_of_dependencies), app_paths_of_dependencies={key: sorted(value) for key, value in ref_metadata.app_paths_of_dependencies.items()}, ) assert test_metadata_replaced == ref_metadata_replaced def remove_venv_interpreter(venv_name): _, venv_python_path, _ = util.get_venv_paths(paths.ctx.venvs / venv_name) assert venv_python_path.is_file() venv_python_path.unlink() assert not venv_python_path.is_file() skip_if_windows = pytest.mark.skipif(sys.platform.startswith("win"), reason="This behavior is undefined on Windows") pipx-1.6.0/tests/package_info.py000066400000000000000000000675021462701651400166400ustar00rootroot00000000000000import sys from pathlib import Path from typing import Any, Dict WIN = sys.platform.startswith("win") def _exe_if_win(apps): return [f"{app}.exe" if WIN else app for app in apps] # Versions of all packages possibly used in our tests # Only apply _exe_if_win to entry_points, NOT scripts PKG: Dict[str, Dict[str, Any]] = { "ansible": { "spec": "ansible==6.7.0", "apps": [ "ansible", "ansible-config", "ansible-connection", "ansible-console", "ansible-doc", "ansible-galaxy", "ansible-inventory", "ansible-playbook", "ansible-pull", "ansible-test", "ansible-vault", ], "apps_of_dependencies": [], }, "awscli": { "spec": "awscli==1.18.168", "apps": [ "aws", "aws.cmd", "aws_bash_completer", "aws_completer", "aws_zsh_completer.sh", ], "apps_of_dependencies": _exe_if_win( [ "pyrsa-decrypt", # rsa EXE "pyrsa-encrypt", # rsa EXE "pyrsa-keygen", # rsa EXE "pyrsa-priv2pub", # rsa EXE "pyrsa-sign", # rsa EXE "pyrsa-verify", # rsa EXE ] ) + [ "jp.py", # jmespath.py NO_EXE "rst2html.py", # docutils NO_EXE "rst2html4.py", # docutils NO_EXE "rst2html5.py", # docutils NO_EXE "rst2latex.py", # docutils NO_EXE "rst2man.py", # docutils NO_EXE "rst2odt.py", # docutils NO_EXE "rst2odt_prepstyles.py", # docutils NO_EXE "rst2pseudoxml.py", # docutils NO_EXE "rst2s5.py", # docutils NO_EXE "rst2xetex.py", # docutils NO_EXE "rst2xml.py", # docutils NO_EXE "rstpep2html.py", # docutils NO_EXE ], }, "b2": { "spec": "b2==3.12.0", "apps": _exe_if_win(["b2"]), "apps_of_dependencies": _exe_if_win(["docutils", "rst2ansi", "tabulate", "tqdm", "normalizer"]) + [ "activate-global-python-argcomplete", "python-argcomplete-check-easy-install-script", "register-python-argcomplete", "rst2html4.py", "rst2html5.py", "rst2html.py", "rst2latex.py", "rst2man.py", "rst2odt_prepstyles.py", "rst2odt.py", "rst2pseudoxml.py", "rst2s5.py", "rst2xetex.py", "rst2xml.py", "rstpep2html.py", ], }, "beancount": { "spec": "beancount==2.3.6", "apps": _exe_if_win( [ "bean-bake", "bean-check", "bean-doctor", "bean-example", "bean-extract", "bean-file", "bean-format", "bean-identify", "bean-price", "bean-query", "bean-report", "bean-sql", "bean-web", "treeify", "upload-to-sheets", ] ), "apps_of_dependencies": _exe_if_win( [ "chardetect", # chardet EXE "py.test", # pytest EXE "pyrsa-decrypt", # rsa EXE "pyrsa-encrypt", # rsa EXE "pyrsa-keygen", # rsa EXE "pyrsa-priv2pub", # rsa EXE "pyrsa-sign", # rsa EXE "pyrsa-verify", # rsa EXE "pytest", # pytest EXE "normalizer", "py.test", ] ) + ["bottle.py", "dumppdf.py", "latin2ascii.py", "pdf2txt.py"], # bottle NO_EXE }, "beets": { "spec": "beets==1.4.9", "apps": _exe_if_win(["beet"]), "apps_of_dependencies": _exe_if_win( [ "mid3cp", "mid3iconv", "mid3v2", "moggsplit", "mutagen-inspect", "mutagen-pony", "unidecode", # unidecode EXE ] ), "man_pages": [], "man_pages_of_dependencies": [ str(Path("man1") / "mutagen-pony.1"), str(Path("man1") / "mutagen-inspect.1"), str(Path("man1") / "moggsplit.1"), str(Path("man1") / "mid3v2.1"), str(Path("man1") / "mid3iconv.1"), str(Path("man1") / "mid3cp.1"), ], }, "black": { "spec": "black==22.8.0", "apps": _exe_if_win(["black", "blackd"]), "apps_of_dependencies": [], }, "cactus": { "spec": "cactus==3.3.3", "apps": _exe_if_win(["cactus"]), "apps_of_dependencies": _exe_if_win(["keyring", "markdown2"]) + [ "asadmin", "bundle_image", "cfadmin", "cq", "cwutil", "django-admin.py", "dynamodb_dump", "dynamodb_load", "elbadmin", "fetch_file", "glacier", "instance_events", "keyring", "kill_instance", "launch_instance", "list_instances", "lss3", "mturk", "pyami_sendmail", "route53", "s3put", "sdbadmin", "taskadmin", ], }, "chert": { "spec": "chert==19.1.0", "apps": _exe_if_win(["chert"]), "apps_of_dependencies": _exe_if_win(["ashes", "markdown_py"]) + ["ashes.py"], }, "cloudtoken": { "spec": "cloudtoken==2.1.0", "apps": ["awstoken", "cloudtoken", "cloudtoken.app", "cloudtoken_proxy.sh"], "apps_of_dependencies": _exe_if_win(["flask", "keyring", "normalizer"]) + ["jp.py"], }, "coala": { "spec": "coala==0.11.0", "apps": _exe_if_win(["coala", "coala-ci", "coala-delete-orig", "coala-format", "coala-json"]), "apps_of_dependencies": _exe_if_win(["normalizer", "pygmentize"]) + ["unidiff"], }, "cookiecutter": { "spec": "cookiecutter==2.4.0", "apps": _exe_if_win(["cookiecutter"]), "apps_of_dependencies": _exe_if_win(["chardetect", "normalizer", "markdown-it", "pygmentize", "slugify"]), }, "cython": { "spec": "cython==0.29.21", "apps": _exe_if_win(["cygdb", "cython", "cythonize"]), "apps_of_dependencies": [], }, "datasette": { "spec": "datasette==0.50.2", "apps": _exe_if_win(["datasette"]), "apps_of_dependencies": _exe_if_win(["httpx", "hupper", "uvicorn"]) + ["pint-convert"], }, "diffoscope": { "spec": "diffoscope==154", "apps": _exe_if_win(["diffoscope"]), "apps_of_dependencies": [], }, "doc2dash": { "spec": "doc2dash==3.0.0", "apps": _exe_if_win(["doc2dash"]), "apps_of_dependencies": _exe_if_win( ["markdown-it", "pygmentize"] # pygments EXE ), }, "doitlive": { "spec": "doitlive==4.3.0", "apps": _exe_if_win(["doitlive"]), "apps_of_dependencies": [], }, "gdbgui": { "spec": "gdbgui==0.14.0.1", "apps": _exe_if_win(["gdbgui"]), "apps_of_dependencies": _exe_if_win(["flask", "pygmentize"]), }, "gns3-gui": { "spec": "gns3-gui==2.2.15", "apps": _exe_if_win(["gns3"]), "apps_of_dependencies": _exe_if_win(["distro", "jsonschema"]), }, "grow": { "spec": "grow==1.0.0a10", "apps": ["grow"], "apps_of_dependencies": _exe_if_win( [ "chardetect", # chardet EXE "gen_protorpc", # EXE "html2text", # html2text EXE "markdown_py", # Markdwon EXE "pybabel", # babel EXE "pygmentize", # pygments EXE "pyrsa-decrypt", # rsa EXE "pyrsa-encrypt", # rsa EXE "pyrsa-keygen", # rsa EXE "pyrsa-priv2pub", # rsa EXE "pyrsa-sign", # rsa EXE "pyrsa-verify", # rsa EXE "slugify", # python_slugify EXE "watchmedo", # watchdog EXE ] ), }, "guake": { "spec": "guake==3.7.0", "apps": _exe_if_win(["guake", "guake-toggle"]), "apps_of_dependencies": _exe_if_win(["pbr"]), }, "gunicorn": { "spec": "gunicorn==20.0.4", "apps": _exe_if_win(["gunicorn"]), "apps_of_dependencies": [], }, "howdoi": { "spec": "howdoi==2.0.20", "apps": _exe_if_win(["howdoi"]), "apps_of_dependencies": _exe_if_win(["markdown-it", "keep", "normalizer", "pygmentize"]), }, "httpie": { "spec": "httpie==3.2.2", "apps": _exe_if_win(["http", "httpie", "https"]), "apps_of_dependencies": _exe_if_win(["markdown-it", "normalizer", "pygmentize"]), "man_pages": [ str(Path("man1") / "http.1"), str(Path("man1") / "httpie.1"), str(Path("man1") / "https.1"), ], "man_pages_of_dependencies": [], }, "hyde": { "spec": "hyde==0.8.9", "apps": _exe_if_win(["hyde"]), "apps_of_dependencies": _exe_if_win(["markdown_py", "pygmentize"]) + ["smartypants"], }, "ipython": { "spec": "ipython==7.16.1", "apps": _exe_if_win(["iptest", "iptest3", "ipython", "ipython3"]), "apps_of_dependencies": _exe_if_win(["pygmentize"]), # pygments EXE "man_pages": [str(Path("man1") / "ipython.1.gz")], "man_pages_of_dependencies": [], }, "isort": { "spec": "isort==5.6.4", "apps": _exe_if_win(["isort"]), "apps_of_dependencies": [], }, "zest-releaser": { "spec": "zest.releaser==9.1.2", "apps": _exe_if_win( [ "addchangelogentry", "bumpversion", "fullrelease", "lasttagdiff", "lasttaglog", "longtest", "postrelease", "prerelease", "release", ] ), "apps_of_dependencies": _exe_if_win( [ "markdown-it", "normalizer", "twine", "pkginfo", "pyproject-build", "docutils", "pygmentize", "keyring", ] ) + [ "rst2html.py", "rst2html4.py", "rst2html5.py", "rst2latex.py", "rst2man.py", "rst2odt.py", "rst2odt_prepstyles.py", "rst2pseudoxml.py", "rst2s5.py", "rst2xetex.py", "rst2xml.py", "rstpep2html.py", ], }, "jupyter": { "spec": "jupyter==1.0.0", "apps": [], "apps_of_dependencies": _exe_if_win( [ "iptest", # EXE "iptest3", # EXE "ipython", # EXE "ipython3", # EXE "jsonschema", # jsonschema EXE "jupyter", # EXE "jupyter-bundlerextension", # EXE "jupyter-console", # EXE "jupyter-kernel", # EXE "jupyter-kernelspec", # EXE "jupyter-migrate", # EXE "jupyter-nbconvert", # EXE "jupyter-nbextension", # EXE "jupyter-notebook", # EXE "jupyter-qtconsole", # EXE "jupyter-run", # EXE "jupyter-serverextension", # EXE "jupyter-troubleshoot", # EXE "jupyter-trust", # EXE "pygmentize", # pygments EXE ] ), }, "kaggle": { "spec": "kaggle==1.6.11", "apps": _exe_if_win(["kaggle"]), "apps_of_dependencies": list(set(_exe_if_win(["slugify", "normalizer", "tqdm"]))), }, "kibitzr": { "spec": "kibitzr==7.0.5", "apps": _exe_if_win(["kibitzr"]), "apps_of_dependencies": _exe_if_win(["doesitcache", "httpx", "normalizer"]), }, "klaus": { "spec": "klaus==1.5.2", "apps": ["klaus"], "apps_of_dependencies": _exe_if_win(["dulwich", "flask", "pygmentize"]) + ["dul-receive-pack", "dul-upload-pack"], }, "kolibri": { "spec": "kolibri==0.14.3", "apps": _exe_if_win(["kolibri"]), "apps_of_dependencies": [], }, "lektor": { "spec": "Lektor==3.3.10", "apps": _exe_if_win(["lektor"]), "apps_of_dependencies": _exe_if_win(["filetype", "flask", "pybabel", "normalizer", "slugify", "watchmedo"]) + ["EXIF.py"], }, "localstack": { "spec": "localstack==0.12.1", "apps": ["localstack", "localstack.bat"], "apps_of_dependencies": _exe_if_win( [ "dotenv", "markdown-it", "pbr", "pygmentize", "pyrsa-decrypt", "pyrsa-encrypt", "pyrsa-keygen", "pyrsa-priv2pub", "pyrsa-sign", "pyrsa-verify", "pysemver", "pytail", "tabulate", "normalizer", ] ) + ["get_objgraph", "jp.py", "localstack-supervisor", "undill"], }, "mackup": { "spec": "mackup==0.8.29", "apps": _exe_if_win(["mackup"]), "apps_of_dependencies": [], }, # ONLY FOR mac, linux "magic-wormhole": { "spec": "magic-wormhole==0.13.0", "apps": _exe_if_win(["wormhole"]), "apps_of_dependencies": _exe_if_win( [ "automat-visualize", # EXE "cftp", # EXE "ckeygen", # EXE "conch", # EXE "mailmail", # EXE "pyhtmlizer", # EXE "tkconch", # EXE "tqdm", # tqdm EXE "trial", # EXE "twist", # EXE "twistd", # EXE "wamp", # EXE "xbrnetwork", # EXE "xbrnetwork-ui", # EXE ] ) + (["pywin32_postinstall.py", "pywin32_testall.py"] if WIN else []), }, "mayan-edms": { "spec": "mayan-edms==3.5.2", "apps": ["mayan-edms.py"], "apps_of_dependencies": _exe_if_win( [ "celery", # EXE "chardetect", # chardet EXE "django-admin", # EXE "gunicorn", # EXE "jsonschema", # jsonschema EXE "sqlformat", # sqlparse EXE "swagger-flex", # EXE "update-tld-names", # # EXE ] ) + ["django-admin.py", "jsonpointer"], }, "mkdocs": { "spec": "mkdocs==1.1.2", "apps": _exe_if_win(["mkdocs"]), "apps_of_dependencies": _exe_if_win( [ "livereload", # EXE "futurize", # future EXE "pasteurize", # future EXE "nltk", # EXE "tqdm", # tqdm EXE "markdown_py", # Markdwon EXE ] ), }, "mycli": { "spec": "mycli==1.22.2", "apps": _exe_if_win(["mycli"]), "apps_of_dependencies": _exe_if_win(["pygmentize", "sqlformat", "tabulate"]), }, "nikola": { "spec": "nikola==8.2.4", "apps": _exe_if_win(["nikola"]), "apps_of_dependencies": _exe_if_win( [ "docutils", "doit", # EXE "mako-render", # mako EXE "markdown_py", # Markdwon EXE "natsort", # EXE "pybabel", # babel EXE "pygmentize", # pygments EXE "unidecode", # unidecode EXE "normalizer", ] ) + [ "rst2html.py", # docutils NO_EXE "rst2html4.py", # docutils NO_EXE "rst2html5.py", # docutils NO_EXE "rst2latex.py", # docutils NO_EXE "rst2man.py", # docutils NO_EXE "rst2odt.py", # docutils NO_EXE "rst2odt_prepstyles.py", # docutils NO_EXE "rst2pseudoxml.py", # docutils NO_EXE "rst2s5.py", # docutils NO_EXE "rst2xetex.py", # docutils NO_EXE "rst2xml.py", # docutils NO_EXE "rstpep2html.py", # docutils NO_EXE ], "man_pages": [str(Path("man1") / "nikola.1.gz")], "man_pages_of_dependencies": [], }, "nox": { "spec": "nox==2023.4.22", "apps": _exe_if_win(["nox", "tox-to-nox"]), "apps_of_dependencies": _exe_if_win(["virtualenv"]) + [ "activate-global-python-argcomplete", "python-argcomplete-check-easy-install-script", "register-python-argcomplete", ], # from argcomplete }, "pbr": {"spec": "pbr==5.6.0", "apps": _exe_if_win(["pbr"])}, "pelican": { "spec": "pelican==4.8.0", "apps": _exe_if_win( [ "pelican", "pelican-import", "pelican-plugins", "pelican-quickstart", "pelican-themes", ] ), "apps_of_dependencies": _exe_if_win(["docutils", "markdown-it", "pygmentize", "unidecode"]) + [ "rst2html.py", # docutils NO_EXE "rst2html4.py", # docutils NO_EXE "rst2html5.py", # docutils NO_EXE "rst2latex.py", # docutils NO_EXE "rst2man.py", # docutils NO_EXE "rst2odt.py", # docutils NO_EXE "rst2odt_prepstyles.py", # docutils NO_EXE "rst2pseudoxml.py", # docutils NO_EXE "rst2s5.py", # docutils NO_EXE "rst2xetex.py", # docutils NO_EXE "rst2xml.py", # docutils NO_EXE "rstpep2html.py", # docutils NO_EXE ], }, "platformio": { "spec": "platformio==6.1.11", "apps": _exe_if_win(["pio", "piodebuggdb", "platformio"]), "apps_of_dependencies": _exe_if_win( [ "async-json-rpc-server", "pyserial-miniterm", "pyserial-ports", "tabulate", "uvicorn", "normalizer", ] ) + ["bottle.py", "readelf.py"], }, "ppci": { "spec": "ppci==0.5.8", "apps": _exe_if_win( [ "ppci-archive", "ppci-asm", "ppci-build", "ppci-c3c", "ppci-cc", "ppci-dbg", "ppci-disasm", "ppci-hexdump", "ppci-hexutil", "ppci-java", "ppci-ld", "ppci-llc", "ppci-mkuimage", "ppci-objcopy", "ppci-objdump", "ppci-ocaml", "ppci-opt", "ppci-pascal", "ppci-pedump", "ppci-pycompile", "ppci-readelf", "ppci-wabt", "ppci-wasm2wat", "ppci-wasmcompile", "ppci-wat2wasm", "ppci-yacc", ] ), "apps_of_dependencies": [], }, "prosopopee": { "spec": "prosopopee==1.1.3", "apps": _exe_if_win(["prosopopee"]), "apps_of_dependencies": _exe_if_win(["futurize", "pasteurize", "pybabel"]), }, "ptpython": { "spec": "ptpython==3.0.7", "apps": _exe_if_win( [ "ptipython", "ptipython3", "ptipython3.8", "ptpython", "ptpython3", "ptpython3.8", ] ), "apps_of_dependencies": _exe_if_win(["pygmentize"]), # pygments EXE }, "pycowsay": { "spec": "pycowsay==0.0.0.2", "apps": _exe_if_win(["pycowsay"]), "apps_of_dependencies": [], "man_pages": [str(Path("man6") / "pycowsay.6")], "man_pages_of_dependencies": [], }, "pygdbmi": {"spec": "pygdbmi==0.10.0.0", "apps": [], "apps_of_dependencies": []}, "pylint": { "spec": "pylint==3.0.4", "apps": _exe_if_win(["pylint", "pylint-config", "pyreverse", "symilar"]), "apps_of_dependencies": _exe_if_win(["isort", "isort-identify-imports"]) + ["get_gprof", "get_objgraph", "undill"], }, "retext": { "spec": "ReText==8.0.1", "apps": _exe_if_win(["retext"]), "apps_of_dependencies": _exe_if_win( [ "docutils", "markdown_py", # Markdwon EXE "pygmentize", # pygments EXE "pylupdate6", # EXE "pyuic6", # EXE "chardetect", ] ) + [ "rst2html.py", # docutils NO_EXE "rst2html4.py", # docutils NO_EXE "rst2html5.py", # docutils NO_EXE "rst2latex.py", # docutils NO_EXE "rst2man.py", # docutils NO_EXE "rst2odt.py", # docutils NO_EXE "rst2odt_prepstyles.py", # docutils NO_EXE "rst2pseudoxml.py", # docutils NO_EXE "rst2s5.py", # docutils NO_EXE "rst2xetex.py", # docutils NO_EXE "rst2xml.py", # docutils NO_EXE "rstpep2html.py", # docutils NO_EXE ], }, "robotframework": { "spec": "robotframework==3.2.2", "apps": _exe_if_win(["rebot", "robot"]), "apps_of_dependencies": [], }, "shell-functools": { "spec": "shell-functools==0.3.0", "apps": [ "filter", "foldl", "foldl1", "ft-functions", "map", "sort_by", "take_while", ], "apps_of_dependencies": [], }, "speedtest-cli": { "spec": "speedtest-cli==2.1.2", "apps": _exe_if_win(["speedtest", "speedtest-cli"]), "apps_of_dependencies": [], }, "sphinx": { "spec": "Sphinx==7.2.6", "apps": _exe_if_win(["sphinx-apidoc", "sphinx-autogen", "sphinx-build", "sphinx-quickstart"]), "apps_of_dependencies": _exe_if_win(["docutils", "pybabel", "normalizer", "pygmentize"]) + [ "rst2html.py", # docutils NO_EXE "rst2html4.py", # docutils NO_EXE "rst2html5.py", # docutils NO_EXE "rst2latex.py", # docutils NO_EXE "rst2man.py", # docutils NO_EXE "rst2odt.py", # docutils NO_EXE "rst2odt_prepstyles.py", # docutils NO_EXE "rst2pseudoxml.py", # docutils NO_EXE "rst2s5.py", # docutils NO_EXE "rst2xetex.py", # docutils NO_EXE "rst2xml.py", # docutils NO_EXE "rstpep2html.py", # docutils NO_EXE ], }, "sqlmap": { "spec": "sqlmap==1.4.10", "apps": _exe_if_win(["sqlmap"]), "apps_of_dependencies": [], }, "streamlink": { "spec": "streamlink==6.3.1", "apps": _exe_if_win(["streamlink"] + (["streamlinkw"] if WIN else [])), "apps_of_dependencies": _exe_if_win(["normalizer", "wsdump"]), "man_pages": [str(Path("man1") / "streamlink.1")], "man_pages_of_dependencies": [], }, "taguette": { "spec": "taguette==0.9.2", "apps": _exe_if_win(["taguette"]), "apps_of_dependencies": _exe_if_win(["alembic", "mako-render"]) + ["vba_extract.py"], }, "term2048": { "spec": "term2048==0.2.7", "apps": _exe_if_win(["term2048"]), "apps_of_dependencies": [], }, "tox-ini-fmt": { "spec": "tox-ini-fmt==0.5.0", "apps": _exe_if_win(["tox-ini-fmt"]), "apps_of_dependencies": _exe_if_win(["py.test", "pytest"]), # pytest EXE }, "visidata": { "spec": "visidata==2.0.1", "apps": _exe_if_win(["visidata"]) + ["vd"], "apps_of_dependencies": [], "man_pages": [str(Path("man1") / "vd.1")], "man_pages_of_dependencies": [], }, "vulture": { "spec": "vulture==2.1", "apps": _exe_if_win(["vulture"]), "apps_of_dependencies": [], }, "weblate": { "spec": "Weblate==4.3.1", "apps": _exe_if_win(["weblate"]), "apps_of_dependencies": _exe_if_win( # TODO: check if _exe_if_win (can't install) [ "borg", "borgfs", "build_firefox.sh", "build_tmdb", "buildxpi.py", "celery", "chardetect", # chardet EXE "csv2po", "csv2tbx", "cygdb", "cython", "cythonize", "django-admin", "django-admin.py", # NO_EXE "flatxml2po", "get_moz_enUS.py", "html2po", "html2text", # html2text EXE "ical2po", "idml2po", "ini2po", "json2po", "jsonschema", # jsonschema EXE "junitmsgfmt", "misaka", "moz2po", "mozlang2po", "odf2xliff", "oo2po", "oo2xliff", "php2po", "phppo2pypo", "po2csv", "po2flatxml", "po2html", "po2ical", "po2idml", "po2ini", "po2json", "po2moz", "po2mozlang", "po2oo", "po2php", "po2prop", "po2rc", "po2resx", "po2sub", "po2symb", "po2tiki", "po2tmx", "po2ts", "po2txt", "po2web2py", "po2wordfast", "po2xliff", "po2yaml", "poclean", "pocommentclean", "pocompendium", "pocompile", "poconflicts", "pocount", "podebug", "pofilter", "pogrep", "pomerge", "pomigrate2", "popuretext", "poreencode", "porestructure", "posegment", "posplit", "poswap", "pot2po", "poterminology", "pretranslate", "prop2po", "pydiff", "pypo2phppo", "rc2po", "resx2po", "sqlformat", # sqlparse EXE "sub2po", "symb2po", "tbx2po", "tiki2po", "tmserver", "ts2po", "txt2po", "web2py2po", "weblate-discover", "xliff2odf", "xliff2oo", "xliff2po", "yaml2po", ] ), }, "youtube-dl": { "spec": "youtube-dl==2020.9.20", "apps": _exe_if_win(["youtube-dl"]), "apps_of_dependencies": [], "man_pages": [str(Path("man1") / "youtube-dl.1")], "man_pages_of_dependencies": [], }, "zeo": { "spec": "ZEO==5.2.2", "apps": _exe_if_win(["runzeo", "zeo-nagios", "zeoctl", "zeopack"]), "apps_of_dependencies": _exe_if_win( [ "fsdump", "fsoids", "fsrefs", "fstail", "repozo", "zconfig", "zconfig_schema2html", "zdaemon", ] ), }, } pipx-1.6.0/tests/test_animate.py000066400000000000000000000107671462701651400167100ustar00rootroot00000000000000import time import pytest # type: ignore[import-not-found] import pipx.animate from pipx.animate import ( CLEAR_LINE, EMOJI_ANIMATION_FRAMES, EMOJI_FRAME_PERIOD, NONEMOJI_ANIMATION_FRAMES, NONEMOJI_FRAME_PERIOD, ) # 40-char test_string counts columns e.g.: "0204060810 ... 363840" TEST_STRING_40_CHAR = "".join([f"{x:02}" for x in range(2, 41, 2)]) def check_animate_output( capsys, test_string, frame_strings, frame_period, frames_to_test, extra_animate_time=0.4, extra_after_thread_time=0.1, ): # github workflow history (2020-07-27): # extra_animate_time <= 0.3 failed on macos # extra_after_thread_time <= 0.0 failed on macos expected_string = "".join(frame_strings) chars_to_test = 1 + len("".join(frame_strings[:frames_to_test])) with pipx.animate.animate(test_string, do_animation=True): time.sleep(frame_period * (frames_to_test - 1) + extra_animate_time) # Wait before capturing stderr to ensure animate thread is finished # and to capture all its characters. time.sleep(extra_after_thread_time) captured = capsys.readouterr() print("check_animate_output() Test Debug Output:") if len(captured.err) < chars_to_test: print("Not enough captured characters--Likely need to increase extra_animate_time") print(f"captured characters: {len(captured.err)}") print(f"chars_to_test: {chars_to_test}") for i in range(0, chars_to_test, 40): i_end = min(i + 40, chars_to_test) print(f"expected_string[{i}:{i_end}]: {expected_string[i:i_end]!r}") print(f"captured.err[{i}:{i_end}] : {captured.err[i:i_end]!r}") assert captured.err[:chars_to_test] == expected_string[:chars_to_test] def test_delay_suppresses_output(capsys, monkeypatch): monkeypatch.setattr(pipx.animate, "stderr_is_tty", True) monkeypatch.setenv("COLUMNS", "80") test_string = "asdf" with pipx.animate.animate(test_string, do_animation=True, delay=0.9): time.sleep(0.5) captured = capsys.readouterr() assert test_string not in captured.err @pytest.mark.parametrize( "env_columns,expected_frame_message", [ (45, f"{TEST_STRING_40_CHAR:.{45-6}}..."), (46, f"{TEST_STRING_40_CHAR}"), (47, f"{TEST_STRING_40_CHAR}"), ], ) def test_line_lengths_emoji(capsys, monkeypatch, env_columns, expected_frame_message): # EMOJI_SUPPORT and stderr_is_tty is set only at import animate.py # since we are already after that, we must override both here monkeypatch.setattr(pipx.animate, "stderr_is_tty", True) monkeypatch.setattr(pipx.animate, "EMOJI_SUPPORT", True) monkeypatch.setenv("COLUMNS", str(env_columns)) frames_to_test = 4 frame_strings = [f"\r{CLEAR_LINE}{x} {expected_frame_message}" for x in EMOJI_ANIMATION_FRAMES] check_animate_output(capsys, TEST_STRING_40_CHAR, frame_strings, EMOJI_FRAME_PERIOD, frames_to_test) @pytest.mark.parametrize( "env_columns,expected_frame_message", [ (43, f"{TEST_STRING_40_CHAR:.{43-4}}"), (44, f"{TEST_STRING_40_CHAR}"), (45, f"{TEST_STRING_40_CHAR}"), ], ) def test_line_lengths_no_emoji(capsys, monkeypatch, env_columns, expected_frame_message): # EMOJI_SUPPORT and stderr_is_tty is set only at import animate.py # since we are already after that, we must override both here monkeypatch.setattr(pipx.animate, "stderr_is_tty", True) monkeypatch.setattr(pipx.animate, "EMOJI_SUPPORT", False) monkeypatch.setenv("COLUMNS", str(env_columns)) frames_to_test = 2 frame_strings = [f"\r{CLEAR_LINE}{expected_frame_message}{x}" for x in NONEMOJI_ANIMATION_FRAMES] check_animate_output( capsys, TEST_STRING_40_CHAR, frame_strings, NONEMOJI_FRAME_PERIOD, frames_to_test, ) @pytest.mark.parametrize("env_columns,stderr_is_tty", [(0, True), (8, True), (16, True), (17, False)]) def test_env_no_animate(capsys, monkeypatch, env_columns, stderr_is_tty): monkeypatch.setattr(pipx.animate, "stderr_is_tty", stderr_is_tty) monkeypatch.setenv("COLUMNS", str(env_columns)) frames_to_test = 4 expected_string = f"{TEST_STRING_40_CHAR}...\n" extra_animate_time = 0.4 extra_after_thread_time = 0.1 with pipx.animate.animate(TEST_STRING_40_CHAR, do_animation=True): time.sleep(EMOJI_FRAME_PERIOD * (frames_to_test - 1) + extra_animate_time) time.sleep(extra_after_thread_time) captured = capsys.readouterr() assert captured.out == "" assert captured.err == expected_string pipx-1.6.0/tests/test_completions.py000066400000000000000000000003171462701651400176140ustar00rootroot00000000000000from helpers import run_pipx_cli def test_cli(monkeypatch, capsys): assert not run_pipx_cli(["completions"]) captured = capsys.readouterr() assert "Add the appropriate command" in captured.out pipx-1.6.0/tests/test_emojis.py000066400000000000000000000026631462701651400165540ustar00rootroot00000000000000import sys from io import BytesIO, TextIOWrapper from unittest import mock import pytest # type: ignore[import-not-found] from pipx.emojis import use_emojis @pytest.mark.parametrize( "USE_EMOJI, encoding, expected", [ # utf-8 (None, "utf-8", True), ("", "utf-8", False), ("0", "utf-8", False), ("1", "utf-8", True), ("true", "utf-8", True), ("tru", "utf-8", False), # codespell:ignore tru ("True", "utf-8", True), ("false", "utf-8", False), # latin_1 (alias: iso-8859-1) (None, "latin_1", False), ("", "latin_1", False), ("0", "latin_1", False), ("1", "latin_1", True), ("true", "latin_1", True), ("tru", "latin_1", False), # codespell:ignore tru ("True", "latin_1", True), ("false", "latin_1", False), # cp1252 (None, "cp1252", False), ("", "cp1252", False), ("0", "cp1252", False), ("1", "cp1252", True), ("true", "cp1252", True), ("tru", "cp1252", False), # codespell:ignore tru ("True", "cp1252", True), ("false", "cp1252", False), ], ) def test_use_emojis(monkeypatch, USE_EMOJI, encoding, expected): with mock.patch.object(sys, "stderr", TextIOWrapper(BytesIO(), encoding=encoding)): if USE_EMOJI is not None: monkeypatch.setenv("USE_EMOJI", USE_EMOJI) assert use_emojis() is expected pipx-1.6.0/tests/test_environment.py000066400000000000000000000063251462701651400176310ustar00rootroot00000000000000import fnmatch from pathlib import Path from helpers import run_pipx_cli, skip_if_windows from pipx.paths import get_expanded_environ def test_cli(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["environment"]) captured = capsys.readouterr() assert fnmatch.fnmatch(captured.out, "*PIPX_HOME=*subdir/pipxhome*") assert fnmatch.fnmatch(captured.out, "*PIPX_BIN_DIR=*otherdir/pipxbindir*") assert fnmatch.fnmatch(captured.out, "*PIPX_MAN_DIR=*otherdir/pipxmandir*") assert "PIPX_SHARED_LIBS" in captured.out assert fnmatch.fnmatch(captured.out, "*PIPX_LOCAL_VENVS=*subdir/pipxhome/venvs*") assert fnmatch.fnmatch(captured.out, "*PIPX_LOG_DIR=*subdir/pipxhome/logs*") assert fnmatch.fnmatch(captured.out, "*PIPX_TRASH_DIR=*subdir/pipxhome/.trash*") assert fnmatch.fnmatch(captured.out, "*PIPX_VENV_CACHEDIR=*subdir/pipxhome/.cache*") # Checking just for the sake of completeness assert "PIPX_DEFAULT_PYTHON" in captured.out assert "USE_EMOJI" in captured.out assert "Environment variables (set by user):" in captured.out def test_cli_with_args(monkeypatch, capsys): assert not run_pipx_cli(["environment", "--value", "PIPX_HOME"]) assert not run_pipx_cli(["environment", "--value", "PIPX_BIN_DIR"]) assert not run_pipx_cli(["environment", "--value", "PIPX_MAN_DIR"]) assert not run_pipx_cli(["environment", "--value", "PIPX_SHARED_LIBS"]) assert not run_pipx_cli(["environment", "--value", "PIPX_LOCAL_VENVS"]) assert not run_pipx_cli(["environment", "--value", "PIPX_LOG_DIR"]) assert not run_pipx_cli(["environment", "--value", "PIPX_TRASH_DIR"]) assert not run_pipx_cli(["environment", "--value", "PIPX_VENV_CACHEDIR"]) assert not run_pipx_cli(["environment", "--value", "PIPX_DEFAULT_PYTHON"]) assert not run_pipx_cli(["environment", "--value", "USE_EMOJI"]) assert run_pipx_cli(["environment", "--value", "SSS"]) captured = capsys.readouterr() assert "Variable not found." in captured.err def test_resolve_user_dir_in_env_paths(monkeypatch): monkeypatch.setenv("TEST_DIR", "~/test") home = Path.home() env_dir = get_expanded_environ("TEST_DIR") assert "~" not in str(env_dir) assert env_dir == home / "test" env_dir = get_expanded_environ("THIS_SHOULD_NOT_EXIST") assert env_dir is None @skip_if_windows def test_cli_global(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["environment", "--global"]) captured = capsys.readouterr() assert fnmatch.fnmatch(captured.out, "*PIPX_HOME=*global/pipxhome*") assert fnmatch.fnmatch(captured.out, "*PIPX_BIN_DIR=*global_otherdir/pipxbindir*") assert fnmatch.fnmatch(captured.out, "*PIPX_MAN_DIR=*global_otherdir/pipxmandir*") assert "PIPX_SHARED_LIBS" in captured.out assert fnmatch.fnmatch(captured.out, "*PIPX_LOCAL_VENVS=*global/pipxhome/venvs*") assert fnmatch.fnmatch(captured.out, "*PIPX_LOG_DIR=*global/pipxhome/logs*") assert fnmatch.fnmatch(captured.out, "*PIPX_TRASH_DIR=*global/pipxhome/.trash*") assert fnmatch.fnmatch(captured.out, "*PIPX_VENV_CACHEDIR=*global/pipxhome/.cache*") # Checking just for the sake of completeness assert "PIPX_DEFAULT_PYTHON" in captured.out assert "USE_EMOJI" in captured.out pipx-1.6.0/tests/test_inject.py000066400000000000000000000101021462701651400165250ustar00rootroot00000000000000import logging import re import textwrap import pytest # type: ignore[import-not-found] from helpers import PIPX_METADATA_LEGACY_VERSIONS, mock_legacy_venv, run_pipx_cli, skip_if_windows from package_info import PKG # Note that this also checks that packages used in other tests can be injected individually @pytest.mark.parametrize( "pkg_spec,", [ PKG["black"]["spec"], PKG["nox"]["spec"], PKG["pylint"]["spec"], PKG["ipython"]["spec"], "jaraco.clipboard==2.0.1", # tricky character ], ) def test_inject_single_package(pipx_temp_env, capsys, caplog, pkg_spec): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["inject", "pycowsay", pkg_spec]) # Check arguments have been parsed correctly assert f"Injecting packages: {[pkg_spec]!r}" in caplog.text # Check it's actually being installed and into correct venv captured = capsys.readouterr() injected = re.findall(r"injected package (.+?) into venv pycowsay", captured.out) pkg_name = pkg_spec.split("=", 1)[0].replace(".", "-") # assuming spec is always of the form == assert set(injected) == {pkg_name} @skip_if_windows def test_inject_simple_global(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "--global", "pycowsay"]) assert not run_pipx_cli(["inject", "--global", "pycowsay", PKG["black"]["spec"]]) @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_inject_simple_legacy_venv(pipx_temp_env, capsys, metadata_version): assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) if metadata_version is not None: assert not run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"]]) else: # no metadata in venv should result in PipxError with message assert run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"]]) assert "Please uninstall and install" in capsys.readouterr().err @pytest.mark.parametrize("with_suffix,", [(False,), (True,)]) def test_inject_include_apps(pipx_temp_env, capsys, with_suffix): install_args = [] suffix = "" if with_suffix: suffix = "_x" install_args = [f"--suffix={suffix}"] assert not run_pipx_cli(["install", "pycowsay", *install_args]) assert not run_pipx_cli(["inject", f"pycowsay{suffix}", PKG["black"]["spec"], "--include-deps"]) if suffix: assert run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"], "--include-deps"]) assert not run_pipx_cli(["inject", f"pycowsay{suffix}", PKG["black"]["spec"], "--include-deps"]) @pytest.mark.parametrize( "with_packages,", [ (), # no extra packages ("black",), # duplicate from requirements file ("ipython",), # additional package ], ) def test_inject_with_req_file(pipx_temp_env, capsys, caplog, tmp_path, with_packages): caplog.set_level(logging.INFO) req_file = tmp_path / "inject-requirements.txt" req_file.write_text( textwrap.dedent( f""" {PKG["black"]["spec"]} # a comment inline {PKG["nox"]["spec"]} {PKG["pylint"]["spec"]} # comment on separate line """ ).strip() ) assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli( ["inject", "pycowsay", *(PKG[pkg]["spec"] for pkg in with_packages), "--requirement", str(req_file)] ) packages = [ ("black", PKG["black"]["spec"]), ("nox", PKG["nox"]["spec"]), ("pylint", PKG["pylint"]["spec"]), ] packages.extend((pkg, PKG[pkg]["spec"]) for pkg in with_packages) packages = sorted(set(packages)) # Check arguments and files have been parsed correctly assert f"Injecting packages: {[p for _, p in packages]!r}" in caplog.text # Check they're actually being installed and into correct venv captured = capsys.readouterr() injected = re.findall(r"injected package (.+?) into venv pycowsay", captured.out) assert set(injected) == {pkg for pkg, _ in packages} pipx-1.6.0/tests/test_install.py000066400000000000000000000415621462701651400167350ustar00rootroot00000000000000import os import re import subprocess import sys from pathlib import Path from unittest import mock import pytest # type: ignore[import-not-found] from helpers import app_name, run_pipx_cli, skip_if_windows, unwrap_log_text from package_info import PKG from pipx import paths, shared_libs TEST_DATA_PATH = "./testdata/test_package_specifier" def test_help_text(monkeypatch, capsys): mock_exit = mock.Mock(side_effect=ValueError("raised in test to exit early")) with mock.patch.object(sys, "exit", mock_exit), pytest.raises(ValueError, match="raised in test to exit early"): run_pipx_cli(["install", "--help"]) captured = capsys.readouterr() assert "apps you can run from anywhere" in captured.out def install_packages(capsys, pipx_temp_env, caplog, packages, package_names=()): if len(package_names) != len(packages): package_names = packages run_pipx_cli(["install", *packages, "--verbose"]) captured = capsys.readouterr() for package_name in package_names: assert f"installed package {package_name}" in captured.out if not sys.platform.startswith("win"): # TODO assert on windows too # https://github.com/pypa/pipx/issues/217 assert "symlink missing or pointing to unexpected location" not in captured.out assert "not modifying" not in captured.out assert "is not on your PATH environment variable" not in captured.out assert "⚠️" not in caplog.text assert "WARNING" not in caplog.text @pytest.mark.parametrize( "package_name, package_spec", [("pycowsay", "pycowsay"), ("black", PKG["black"]["spec"])], ) def test_install_easy_packages(capsys, pipx_temp_env, caplog, package_name, package_spec): install_packages(capsys, pipx_temp_env, caplog, [package_spec], [package_name]) def test_install_easy_multiple_packages(capsys, pipx_temp_env, caplog): install_packages( capsys, pipx_temp_env, caplog, ["pycowsay", PKG["black"]["spec"]], ["pycowsay", "black"], ) @pytest.mark.parametrize( "package_name, package_spec", [("pycowsay", "pycowsay"), ("black", PKG["black"]["spec"])], ) @skip_if_windows def test_install_easy_packages_globally(capsys, pipx_temp_env, caplog, package_name, package_spec): install_packages(capsys, pipx_temp_env, caplog, [package_spec], [package_name]) @pytest.mark.parametrize( "package_name, package_spec", [ ("cloudtoken", PKG["cloudtoken"]["spec"]), ("awscli", PKG["awscli"]["spec"]), ("ansible", PKG["ansible"]["spec"]), ("shell-functools", PKG["shell-functools"]["spec"]), ], ) def test_install_tricky_packages(capsys, pipx_temp_env, caplog, package_name, package_spec): if os.getenv("FAST"): pytest.skip("skipping slow tests") if sys.platform.startswith("win") and package_name == "ansible": pytest.skip("Ansible is not installable on Windows") install_packages(capsys, pipx_temp_env, caplog, [package_spec], [package_name]) def test_install_tricky_multiple_packages(capsys, pipx_temp_env, caplog): if os.getenv("FAST"): pytest.skip("skipping slow tests") packages = ["cloudtoken", "awscli", "shell-functools"] package_specs = [PKG[package]["spec"] for package in packages] install_packages(capsys, pipx_temp_env, caplog, package_specs, packages) @pytest.mark.parametrize( "package_name, package_spec", [ ("pycowsay", "git+https://github.com/cs01/pycowsay.git@master"), ("pylint", PKG["pylint"]["spec"]), ("nox", "https://github.com/wntrblm/nox/archive/2022.1.7.zip"), ], ) def test_install_package_specs(capsys, pipx_temp_env, caplog, package_name, package_spec): install_packages(capsys, pipx_temp_env, caplog, [package_spec], [package_name]) def test_force_install(pipx_temp_env, capsys): run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() # print(captured.out) assert "installed package" in captured.out run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert "installed package" not in captured.out assert "'pycowsay' already seems to be installed" in captured.out run_pipx_cli(["install", "pycowsay", "--force"]) captured = capsys.readouterr() assert "Installing to existing venv" in captured.out def test_install_no_packages_found(pipx_temp_env, capsys): run_pipx_cli(["install", PKG["pygdbmi"]["spec"]]) captured = capsys.readouterr() assert "No apps associated with package pygdbmi" in captured.err def test_install_same_package_twice_no_force(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert "'pycowsay' already seems to be installed. Not modifying existing installation" in captured.out def test_include_deps(pipx_temp_env, capsys): assert run_pipx_cli(["install", PKG["jupyter"]["spec"]]) == 1 assert not run_pipx_cli(["install", PKG["jupyter"]["spec"], "--include-deps"]) @pytest.mark.parametrize( "package_name, package_spec", [ ("zest-releaser", PKG["zest-releaser"]["spec"]), ("tox-ini-fmt", PKG["tox-ini-fmt"]["spec"]), ], ) def test_name_tricky_characters(caplog, capsys, pipx_temp_env, package_name, package_spec): install_packages(capsys, pipx_temp_env, caplog, [package_spec], [package_name]) def test_extra(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "nox[tox_to_nox]==2023.4.22", "--include-deps"]) captured = capsys.readouterr() assert f"- {app_name('tox')}\n" in captured.out def test_install_local_extra(pipx_temp_env, capsys, monkeypatch, root): assert not run_pipx_cli(["install", str(root / f"{TEST_DATA_PATH}/local_extras[cow]"), "--include-deps"]) captured = capsys.readouterr() assert f"- {app_name('pycowsay')}\n" in captured.out assert f"- {Path('man6/pycowsay.6')}\n" in captured.out def test_path_warning(pipx_temp_env, capsys, monkeypatch, caplog): assert not run_pipx_cli(["install", "pycowsay"]) assert "is not on your PATH environment variable" not in unwrap_log_text(caplog.text) monkeypatch.setenv("PATH", "") assert not run_pipx_cli(["install", "pycowsay", "--force"]) assert "is not on your PATH environment variable" in unwrap_log_text(caplog.text) @skip_if_windows def test_existing_symlink_points_to_existing_wrong_location_warning(pipx_temp_env, caplog, capsys): paths.ctx.bin_dir.mkdir(exist_ok=True, parents=True) (paths.ctx.bin_dir / "pycowsay").symlink_to(os.devnull) assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert "File exists at" in unwrap_log_text(caplog.text) assert "symlink missing or pointing to unexpected location" in captured.out # bin dir was on path, so the warning should NOT appear (even though the symlink # pointed to the wrong location) assert "is not on your PATH environment variable" not in captured.err @skip_if_windows def test_existing_man_page_symlink_points_to_existing_wrong_location_warning(pipx_temp_env, caplog, capsys): (paths.ctx.man_dir / "man6").mkdir(exist_ok=True, parents=True) (paths.ctx.man_dir / "man6" / "pycowsay.6").symlink_to(os.devnull) assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert "File exists at" in unwrap_log_text(caplog.text) assert "symlink missing or pointing to unexpected location" in captured.out @skip_if_windows def test_existing_symlink_points_to_nothing(pipx_temp_env, capsys): paths.ctx.bin_dir.mkdir(exist_ok=True, parents=True) (paths.ctx.bin_dir / "pycowsay").symlink_to("/asdf/jkl") assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() # pipx should realize the symlink points to nothing and replace it, # so no warning should be present assert "symlink missing or pointing to unexpected location" not in captured.out @skip_if_windows def test_existing_man_page_symlink_points_to_nothing(pipx_temp_env, capsys): (paths.ctx.man_dir / "man6").mkdir(exist_ok=True, parents=True) (paths.ctx.man_dir / "man6" / "pycowsay.6").symlink_to("/asdf/jkl") assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() # pipx should realize the symlink points to nothing and replace it, # so no warning should be present assert "symlink missing or pointing to unexpected location" not in captured.out def test_pip_args_forwarded_to_shared_libs(pipx_ultra_temp_env, capsys, caplog): # strategy: # 1. start from an empty env to ensure the next command would trigger a shared lib update assert shared_libs.shared_libs.needs_upgrade # 2. install any package with --no-index # and check that the shared library update phase fails return_code = run_pipx_cli(["install", "--verbose", "--pip-args=--no-index", "pycowsay"]) assert "Upgrading shared libraries in" in caplog.text captured = capsys.readouterr() assert return_code != 0 assert "ERROR: Could not find a version that satisfies the requirement pip" in captured.err assert "Failed to upgrade shared libraries" in caplog.text def test_pip_args_forwarded_to_package_name_determination(pipx_temp_env, capsys): assert run_pipx_cli( [ "install", # use a valid spec and invalid pip args "https://github.com/psf/black/archive/22.8.0.zip", "--verbose", "--pip-args='--asdf'", ] ) captured = capsys.readouterr() assert "Cannot determine package name from spec" in captured.err def test_pip_args_with_windows_path(pipx_temp_env, capsys): if not sys.platform.startswith("win"): pytest.skip("Test pip arguments with Windows path on Windows only.") assert run_pipx_cli( [ "install", "pycowsay", "--verbose", "--pip-args='--no-index --find-links=D:\\TEST\\DIR'", ] ) captured = capsys.readouterr() assert r"D:\\TEST\\DIR" in captured.err def test_install_suffix(pipx_temp_env, capsys): name = "pbr" suffix = "_a" assert not run_pipx_cli(["install", PKG[name]["spec"], f"--suffix={suffix}"]) captured = capsys.readouterr() name_a = app_name(f"{name}{suffix}") assert f"- {name_a}" in captured.out suffix = "_b" assert not run_pipx_cli(["install", PKG[name]["spec"], f"--suffix={suffix}"]) captured = capsys.readouterr() name_b = app_name(f"{name}{suffix}") assert f"- {name_b}" in captured.out assert (paths.ctx.bin_dir / name_a).exists() assert (paths.ctx.bin_dir / name_b).exists() def test_man_page_install(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert f"- {Path('man6/pycowsay.6')}" in captured.out assert (paths.ctx.man_dir / "man6" / "pycowsay.6").exists() def test_install_pip_failure(pipx_temp_env, capsys): assert run_pipx_cli(["install", "weblate==4.3.1", "--verbose"]) captured = capsys.readouterr() assert "Fatal error from pip" in captured.err pip_log_file_match = re.search(r"Full pip output in file:\s+(\S.+)$", captured.err, re.MULTILINE) assert pip_log_file_match assert Path(pip_log_file_match[1]).exists() assert re.search(r"pip (failed|seemed to fail) to build package", captured.err) def test_install_local_archive(pipx_temp_env, monkeypatch, capsys, root): monkeypatch.chdir(root / TEST_DATA_PATH / "local_extras") subprocess.run([sys.executable, "-m", "pip", "wheel", "."], check=True) assert not run_pipx_cli(["install", "repeatme-0.1-py3-none-any.whl"]) captured = capsys.readouterr() assert f"- {app_name('repeatme')}\n" in captured.out def test_force_install_changes(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "https://github.com/wntrblm/nox/archive/2022.1.7.zip"]) captured = capsys.readouterr() assert "2022.1.7" in captured.out assert not run_pipx_cli(["install", "nox", "--force"]) captured = capsys.readouterr() assert "2022.1.7" not in captured.out def test_force_install_changes_editable(pipx_temp_env, root, capsys): empty_project_path_as_string = (root / "testdata" / "empty_project").as_posix() assert not run_pipx_cli(["install", "--editable", empty_project_path_as_string]) captured = capsys.readouterr() assert "empty-project" in captured.out assert not run_pipx_cli(["install", "--editable", empty_project_path_as_string, "--force"]) captured = capsys.readouterr() assert "Installing to existing venv 'empty-project'" in captured.out def test_preinstall(pipx_temp_env, caplog): assert not run_pipx_cli(["install", "--preinstall", "black", "nox"]) assert "black" in caplog.text def test_preinstall_multiple(pipx_temp_env, caplog): assert not run_pipx_cli(["install", "--preinstall", "chardet", "--preinstall", "colorama", "nox"]) assert "chardet" in caplog.text assert "colorama" in caplog.text def test_preinstall_specific_version(pipx_temp_env, caplog): assert not run_pipx_cli(["install", "--preinstall", "black==22.8.0", "nox"]) assert "black==22.8.0" in caplog.text @pytest.mark.xfail def test_do_not_wait_for_input(pipx_temp_env, pipx_session_shared_dir, monkeypatch): monkeypatch.setenv("PIP_INDEX_URL", "http://127.0.0.1:8080/simple") run_pipx_cli(["install", "pycowsay"]) def test_passed_python_and_force_flag_warning(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "black"]) assert not run_pipx_cli(["install", "--python", sys.executable, "--force", "black"]) captured = capsys.readouterr() assert "--python is ignored when --force is passed." in captured.out assert not run_pipx_cli(["install", "black", "--force"]) captured = capsys.readouterr() assert ( "--python is ignored when --force is passed." not in captured.out ), "Should only print warning if both flags present" assert not run_pipx_cli(["install", "pycowsay", "--force"]) captured = capsys.readouterr() assert ( "--python is ignored when --force is passed." not in captured.out ), "Should not print warning if package does not exist yet" @pytest.mark.parametrize( "python_version", ["3.0", "3.1"], ) def test_install_fetch_missing_python_invalid(capsys, python_version): assert run_pipx_cli(["install", "--python", python_version, "--fetch-missing-python", "pycowsay"]) captured = capsys.readouterr() assert f"No executable for the provided Python version '{python_version}' found" in captured.out def test_install_run_in_separate_directory(caplog, capsys, pipx_temp_env, monkeypatch, tmp_path): monkeypatch.chdir(tmp_path) f = Path("argparse.py") f.touch() install_packages(capsys, pipx_temp_env, caplog, ["pycowsay"], ["pycowsay"]) @skip_if_windows @pytest.mark.parametrize( "python_version", [ str(sys.version_info.major), f"{sys.version_info.major}.{sys.version_info.minor}", f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}", ], ) def test_install_python_command_version(pipx_temp_env, monkeypatch, capsys, python_version): monkeypatch.setenv("PATH", os.getenv("PATH_ORIG")) assert not run_pipx_cli(["install", "--python", python_version, "--verbose", "pycowsay"]) captured = capsys.readouterr() assert python_version in captured.out @skip_if_windows def test_install_python_command_version_invalid(pipx_temp_env, capsys): python_version = "3.x" assert run_pipx_cli(["install", "--python", python_version, "--verbose", "pycowsay"]) captured = capsys.readouterr() assert f"Invalid Python version: {python_version}" in captured.err @skip_if_windows def test_install_python_command_version_unsupported(pipx_temp_env, capsys): python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}.dev" assert run_pipx_cli(["install", "--python", python_version, "--verbose", "pycowsay"]) captured = capsys.readouterr() assert f"Unsupported Python version: {python_version}" in captured.err @skip_if_windows def test_install_python_command_version_missing(pipx_temp_env, monkeypatch, capsys): monkeypatch.setenv("PATH", os.getenv("PATH_ORIG")) python_version = f"{sys.version_info.major + 99}.{sys.version_info.minor}" assert run_pipx_cli(["install", "--python", python_version, "--verbose", "pycowsay"]) captured = capsys.readouterr() assert f"Command `python{python_version}` was not found" in captured.err @skip_if_windows def test_install_python_command_version_micro_mismatch(pipx_temp_env, monkeypatch, capsys): monkeypatch.setenv("PATH", os.getenv("PATH_ORIG")) python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro + 1}" assert not run_pipx_cli(["install", "--python", python_version, "--verbose", "pycowsay"]) captured = capsys.readouterr() assert f"It may not match the specified version {python_version} at the micro/patch level" in captured.err pipx-1.6.0/tests/test_install_all.py000066400000000000000000000025531462701651400175620ustar00rootroot00000000000000from pathlib import Path from helpers import run_pipx_cli from pipx import paths def test_install_all(pipx_temp_env, tmp_path, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["install", "black"]) _ = capsys.readouterr() assert not run_pipx_cli(["list", "--json"]) captured = capsys.readouterr() pipx_list_path = Path(tmp_path) / "pipx_list.json" with open(pipx_list_path, "w") as pipx_list_fh: pipx_list_fh.write(captured.out) assert not run_pipx_cli(["install-all", str(pipx_list_path)]) captured = capsys.readouterr() assert "black" in captured.out assert "pycowsay" in captured.out def test_install_all_multiple_errors(pipx_temp_env, root, capsys): pipx_metadata_path = root / "testdata" / "pipx_metadata_multiple_errors.json" assert run_pipx_cli(["install-all", str(pipx_metadata_path)]) captured = capsys.readouterr() assert "The following package(s) failed to install: dotenv, weblate" in captured.err assert f"No packages installed after running 'pipx install-all {pipx_metadata_path}'" in captured.out if paths.ctx.log_file: with open(paths.ctx.log_file.parent / (paths.ctx.log_file.stem + "_pip_errors.log")) as log_fh: log_contents = log_fh.read() assert "dotenv" in log_contents assert "weblate" in log_contents pipx-1.6.0/tests/test_install_all_packages.py000066400000000000000000000441231462701651400214170ustar00rootroot00000000000000""" This module uses the pytest infrastructure to produce reports on a large list of packages. It verifies installation with and without an intact system PATH. It also generates report summaries and error reports files. Test pytest outcomes: PASS - if no pip errors, and no pipx issues, and package apps verified all installed correctly XFAIL - if there is a pip error, i.e. an installation problem out of pipx's control FAIL - if there is no pip error, but there is a problem due to pipx, including a pipx error or warning, incorrect list of installed apps, etc. """ import io import os import re import subprocess import sys import textwrap import time from datetime import datetime, timedelta from pathlib import Path from typing import List, Optional, Tuple import pytest # type: ignore[import-not-found] from helpers import run_pipx_cli from package_info import PKG REPORTS_DIR = "./reports" REPORT_FILENAME_ROOT = "all_packages" PACKAGE_NAME_LIST = [ "ansible", "awscli", "b2", "beancount", "beets", "black", "cactus", "chert", "cloudtoken", "coala", "cookiecutter", "cython", "datasette", "diffoscope", "doc2dash", "doitlive", "gdbgui", "gns3-gui", "grow", "guake", "gunicorn", "howdoi", "httpie", "hyde", "ipython", "isort", "zest-releaser", "kaggle", "kibitzr", "klaus", "kolibri", "lektor", "localstack", "mackup", "magic-wormhole", "mayan-edms", "mkdocs", "mycli", "nikola", "nox", "pelican", "platformio", "ppci", "prosopopee", "ptpython", "pycowsay", "pylint", "retext", "robotframework", "shell-functools", "speedtest-cli", "sphinx", "sqlmap", "streamlink", "taguette", "term2048", "tox-ini-fmt", "visidata", "vulture", "weblate", "youtube-dl", "zeo", ] class PackageData: def __init__(self): self.package_name: str = "" self.package_spec: str = "" self.clear_elapsed_time: Optional[float] = None self.clear_pip_pass: Optional[bool] = None self.clear_pipx_pass: Optional[bool] = None self.sys_elapsed_time: Optional[float] = None self.sys_pip_pass: Optional[bool] = None self.sys_pipx_pass: Optional[bool] = None self.overall_pass: Optional[bool] = None @property def clear_pip_pf_str(self) -> str: return self._get_pass_fail_str("clear_pip_pass") @property def clear_pipx_pf_str(self) -> str: return self._get_pass_fail_str("clear_pipx_pass") @property def sys_pip_pf_str(self) -> str: return self._get_pass_fail_str("sys_pip_pass") @property def sys_pipx_pf_str(self) -> str: return self._get_pass_fail_str("sys_pipx_pass") @property def overall_pf_str(self) -> str: return self._get_pass_fail_str("overall_pass") def _get_pass_fail_str(self, test_attr: str) -> str: if getattr(self, test_attr) is not None: return "PASS" if getattr(self, test_attr) else "FAIL" else: return "" class ModuleGlobalsData: def __init__(self): self.errors_path = Path(".") self.install_data: List[PackageData] = [] self.py_version_display = "Python {0.major}.{0.minor}.{0.micro}".format(sys.version_info) self.py_version_short = "{0.major}.{0.minor}".format(sys.version_info) self.report_path = Path(".") self.sys_platform = sys.platform self.test_class = "" self.test_start = datetime.now() self.test_end = datetime.now() # default, must be set later def reset(self, test_class: str = "") -> None: self.errors_path = Path(".") self.install_data = [] self.report_path = Path(".") self.test_class = test_class self.test_start = datetime.now() @pytest.fixture(scope="module") def module_globals() -> ModuleGlobalsData: return ModuleGlobalsData() def pip_cache_purge() -> None: subprocess.run([sys.executable, "-m", "pip", "cache", "purge"], check=True) def write_report_legend(report_legend_path: Path) -> None: with report_legend_path.open("w", encoding="utf-8") as report_legend_fh: print( textwrap.dedent( """ LEGEND =========== cleared_PATH = PATH used for pipx tests with only pipx bin dir and nothing else sys_PATH = Normal system PATH with all default directories included overall = PASS or FAIL for complete end-to-end pipx install, PASS if no errors or warnings and all the proper apps were installed and linked pip = PASS or FAIL sub-category based only if pip inside of pipx installs package with/without error pipx = PASS or FAIL sub-category based on the non-pip parts of pipx, including whether any errors or warnings are present, and if all the proper apps were installed and linked """ ).strip(), file=report_legend_fh, ) def format_report_table_header(module_globals: ModuleGlobalsData) -> str: header_string = "\n\n" header_string += "=" * 79 + "\n" header_string += f"{module_globals.sys_platform:16}" header_string += f"{module_globals.py_version_display:16}" header_string += f"{module_globals.test_start.strftime('%Y-%m-%d %H:%M:%S')}\n\n" header_string += f"{'package_spec':24}{'overall':12}{'cleared_PATH':24}" header_string += f"{'system_PATH':24}\n" header_string += f"{'':24}{'':12}{'pip':8}{'pipx':8}{'time':8}" header_string += f"{'pip':8}{'pipx':8}{'time':8}\n" header_string += "-" * 79 return header_string def format_report_table_row(package_data: PackageData) -> str: clear_install_time = f"{package_data.clear_elapsed_time:>3.0f}s" if package_data.sys_elapsed_time is not None: sys_install_time = f"{package_data.sys_elapsed_time:>3.0f}s" else: sys_install_time = "" return ( f"{package_data.package_spec:24}{package_data.overall_pf_str:12}" f"{package_data.clear_pip_pf_str:8}{package_data.clear_pipx_pf_str:8}" f"{clear_install_time:8}" f"{package_data.sys_pip_pf_str:8}{package_data.sys_pipx_pf_str:8}" f"{sys_install_time:8}" ) def format_report_table_footer(module_globals: ModuleGlobalsData) -> str: fail_list = [] prebuild_list = [] footer_string = "\nSummary\n" footer_string += "-" * 79 + "\n" for package_data in module_globals.install_data: clear_pip_pass = package_data.clear_pip_pass clear_pipx_pass = package_data.clear_pipx_pass sys_pip_pass = package_data.sys_pip_pass sys_pipx_pass = package_data.sys_pipx_pass if clear_pip_pass and clear_pipx_pass: continue elif not clear_pip_pass and sys_pip_pass and sys_pipx_pass: prebuild_list.append(package_data.package_spec) else: fail_list.append(package_data.package_spec) if fail_list: footer_string += "FAILS:\n" for failed_package_spec in sorted(fail_list, key=str.lower): footer_string += f" {failed_package_spec}\n" if prebuild_list: footer_string += "Needs prebuilt wheel:\n" for prebuild_package_spec in sorted(prebuild_list, key=str.lower): footer_string += f" {prebuild_package_spec}\n" dt_string = module_globals.test_end.strftime("%Y-%m-%d %H:%M:%S") el_datetime = module_globals.test_end - module_globals.test_start el_datetime = el_datetime - timedelta(microseconds=el_datetime.microseconds) footer_string += f"\nFinished {dt_string}\n" footer_string += f"Elapsed: {el_datetime}" return footer_string def verify_installed_resources( resource_type: str, captured_outerr, package_name: str, test_error_fh: io.StringIO, deps: bool = False, ) -> bool: resource_name = {"app": "apps", "man": "man_pages"}[resource_type] resource_name_long = {"app": "apps", "man": "manual pages"}[resource_type] package_resources = PKG[package_name][resource_name].copy() if deps: package_resources += PKG[package_name][f"{resource_name}_of_dependencies"] if len(package_resources) == 0: return True reported_resources_re = re.search( r"These " + resource_name_long + r" are now globally available\n((?: - [^\n]+\n)*)", captured_outerr.out, re.DOTALL, ) if reported_resources_re: reported_resources = [x.strip()[2:] for x in reported_resources_re.group(1).strip().split("\n")] if set(reported_resources) != set(package_resources): resource_success = False print("verify_install: REPORTED APPS DO NOT MATCH PACKAGE", file=test_error_fh) print( f"pipx reported %s: {reported_resources}" % resource_name, file=test_error_fh, ) print( f" true package %s: {package_resources}" % resource_name, file=test_error_fh, ) else: resource_success = True else: resource_success = False print("verify_install: APPS TESTING ERROR", file=test_error_fh) return resource_success def verify_post_install( pipx_exit_code: int, captured_outerr, caplog, package_name: str, test_error_fh: io.StringIO, using_clear_path: bool, deps: bool = False, ) -> Tuple[bool, Optional[bool], Optional[Path]]: pip_error_file = None caplog_problem = False install_success = f"installed package {package_name}" in captured_outerr.out for record in caplog.records: if "⚠️" in record.message or "WARNING" in record.message: if using_clear_path or "was already on your PATH" not in record.message: caplog_problem = True print("verify_install: WARNING IN CAPLOG:", file=test_error_fh) print(record.message, file=test_error_fh) if "Fatal error from pip prevented installation" in record.message: pip_error_file_re = re.search(r"pip output in file:\s+(\S.+)$", record.message) if pip_error_file_re: pip_error_file = Path(pip_error_file_re.group(1)) if install_success and PKG[package_name].get("apps", None) is not None: app_success = verify_installed_resources("app", captured_outerr, package_name, test_error_fh, deps=deps) else: app_success = True if install_success and ( PKG[package_name].get("man_pages", None) is not None or PKG[package_name].get("man_pages_of_dependencies", None) is not None ): man_success = verify_installed_resources("man", captured_outerr, package_name, test_error_fh, deps=deps) else: man_success = True pip_pass = not ((pipx_exit_code != 0) and f"Error installing {package_name}" in captured_outerr.err) pipx_pass: Optional[bool] if pip_pass: pipx_pass = install_success and not caplog_problem and app_success and man_success else: pipx_pass = None return pip_pass, pipx_pass, pip_error_file def print_error_report( module_globals: ModuleGlobalsData, command_captured, test_error_fh: io.StringIO, package_spec: str, test_type: str, pip_error_file: Optional[Path], ) -> None: with module_globals.errors_path.open("a", encoding="utf-8") as errors_fh: print("\n\n", file=errors_fh) print("=" * 79, file=errors_fh) print( f"{package_spec:24}{test_type:16}{module_globals.sys_platform:16}{module_globals.py_version_display}", file=errors_fh, ) print("\nSTDOUT:", file=errors_fh) print("-" * 76, file=errors_fh) print(command_captured.out, end="", file=errors_fh) print("\nSTDERR:", file=errors_fh) print("-" * 76, file=errors_fh) print(command_captured.err, end="", file=errors_fh) if pip_error_file is not None: print("\nPIP ERROR LOG FILE:", file=errors_fh) print("-" * 76, file=errors_fh) with pip_error_file.open("r") as pip_error_fh: print(pip_error_fh.read(), end="", file=errors_fh) print("\n\nTEST WARNINGS / ERRORS:", file=errors_fh) print("-" * 76, file=errors_fh) print(test_error_fh.getvalue(), end="", file=errors_fh) def install_and_verify( capsys: pytest.CaptureFixture, caplog, monkeypatch, module_globals: ModuleGlobalsData, using_clear_path: bool, package_data: PackageData, deps: bool, ) -> Tuple[bool, Optional[bool], float]: _ = capsys.readouterr() caplog.clear() test_error_fh = io.StringIO() monkeypatch.setenv("PATH", os.getenv("PATH_TEST" if using_clear_path else "PATH_ORIG")) start_time = time.time() pipx_exit_code = run_pipx_cli( ["install", package_data.package_spec, "--verbose"] + (["--include-deps"] if deps else []) ) elapsed_time = time.time() - start_time captured = capsys.readouterr() pip_pass, pipx_pass, pip_error_file = verify_post_install( pipx_exit_code, captured, caplog, package_data.package_name, test_error_fh, using_clear_path=using_clear_path, deps=deps, ) if not pip_pass or not pipx_pass: print_error_report( module_globals, captured, test_error_fh, package_data.package_spec, "clear PATH" if using_clear_path else "sys PATH", pip_error_file, ) return pip_pass, pipx_pass, elapsed_time def install_package_both_paths( monkeypatch, capsys: pytest.CaptureFixture, caplog, module_globals: ModuleGlobalsData, pipx_temp_env, package_name: str, deps: bool = False, ) -> bool: package_data = PackageData() module_globals.install_data.append(package_data) package_data.package_name = package_name package_data.package_spec = PKG[package_name]["spec"] ( package_data.clear_pip_pass, package_data.clear_pipx_pass, package_data.clear_elapsed_time, ) = install_and_verify( capsys, caplog, monkeypatch, module_globals, using_clear_path=True, package_data=package_data, deps=deps, ) if not package_data.clear_pip_pass: # if we fail to install due to pip install error, try again with # full system path ( package_data.sys_pip_pass, package_data.sys_pipx_pass, package_data.sys_elapsed_time, ) = install_and_verify( capsys, caplog, monkeypatch, module_globals, using_clear_path=False, package_data=package_data, deps=deps, ) package_data.overall_pass = bool( (package_data.clear_pip_pass and package_data.clear_pipx_pass) or (package_data.sys_pip_pass and package_data.sys_pipx_pass) ) with module_globals.report_path.open("a", encoding="utf-8") as report_fh: print(format_report_table_row(package_data), file=report_fh, flush=True) if not package_data.clear_pip_pass and not package_data.sys_pip_pass: # Use xfail to specify error that is from a pip installation problem pytest.xfail("pip installation error") return package_data.overall_pass # use class scope to start and finish at end of all parametrized tests @pytest.fixture(scope="class") def start_end_test_class(module_globals: ModuleGlobalsData, request): reports_path = Path(REPORTS_DIR) reports_path.mkdir(exist_ok=True, parents=True) module_globals.reset() module_globals.test_class = getattr(request.cls, "test_class", "unknown") report_filename = ( f"{REPORT_FILENAME_ROOT}_" f"{module_globals.test_class}_" f"report_" f"{module_globals.sys_platform}_" f"{module_globals.py_version_short}_" f"{module_globals.test_start.strftime('%Y%m%d')}.txt" ) errors_filename = ( f"{REPORT_FILENAME_ROOT}_" f"{module_globals.test_class}_" f"errors_" f"{module_globals.sys_platform}_" f"{module_globals.py_version_short}_" f"{module_globals.test_start.strftime('%Y%m%d')}.txt" ) module_globals.report_path = reports_path / report_filename module_globals.errors_path = reports_path / errors_filename write_report_legend(reports_path / f"{REPORT_FILENAME_ROOT}_report_legend.txt") with module_globals.report_path.open("a", encoding="utf-8") as report_fh: print(format_report_table_header(module_globals), file=report_fh) yield module_globals.test_end = datetime.now() with module_globals.report_path.open("a", encoding="utf-8") as report_fh: print(format_report_table_footer(module_globals), file=report_fh) class TestAllPackagesNoDeps: test_class = "nodeps" @pytest.mark.parametrize("package_name", PACKAGE_NAME_LIST) @pytest.mark.all_packages def test_all_packages( self, monkeypatch, capsys: pytest.CaptureFixture, caplog, module_globals: ModuleGlobalsData, start_end_test_class, pipx_temp_env, package_name: str, ): pip_cache_purge() assert install_package_both_paths( monkeypatch, capsys, caplog, module_globals, pipx_temp_env, package_name, deps=False, ) class TestAllPackagesDeps: test_class = "deps" @pytest.mark.parametrize("package_name", PACKAGE_NAME_LIST) @pytest.mark.all_packages def test_deps_all_packages( self, monkeypatch, capsys: pytest.CaptureFixture, caplog, module_globals: ModuleGlobalsData, start_end_test_class, pipx_temp_env, package_name: str, ): pip_cache_purge() assert install_package_both_paths( monkeypatch, capsys, caplog, module_globals, pipx_temp_env, package_name, deps=True, ) pipx-1.6.0/tests/test_interpreter.py000066400000000000000000000152671462701651400176350ustar00rootroot00000000000000import shutil import subprocess import sys from unittest.mock import Mock import pytest # type: ignore[import-not-found] import pipx.interpreter import pipx.paths import pipx.standalone_python from pipx.constants import WINDOWS from pipx.interpreter import ( InterpreterResolutionError, _find_default_windows_python, _get_absolute_python_interpreter, find_python_interpreter, ) from pipx.util import PipxError original_which = shutil.which @pytest.mark.skipif(not sys.platform.startswith("win"), reason="Looks for Python.exe") @pytest.mark.parametrize("venv", [True, False]) def test_windows_python_with_version(monkeypatch, venv): def which(name): if name == "py": return "py" return original_which(name) major = sys.version_info.major minor = sys.version_info.minor monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: venv) monkeypatch.setattr(shutil, "which", which) python_path = find_python_interpreter(f"{major}.{minor}") assert python_path is not None assert f"{major}.{minor}" in python_path or f"{major}{minor}" in python_path assert python_path.endswith("python.exe") @pytest.mark.skipif(not sys.platform.startswith("win"), reason="Looks for Python.exe") @pytest.mark.parametrize("venv", [True, False]) def test_windows_python_with_python_and_version(monkeypatch, venv): def which(name): if name == "py": return "py" return original_which(name) major = sys.version_info.major minor = sys.version_info.minor monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: venv) monkeypatch.setattr(shutil, "which", which) python_path = find_python_interpreter(f"python{major}.{minor}") assert python_path is not None assert f"{major}.{minor}" in python_path or f"{major}{minor}" in python_path assert python_path.endswith("python.exe") @pytest.mark.skipif(not sys.platform.startswith("win"), reason="Looks for Python.exe") @pytest.mark.parametrize("venv", [True, False]) def test_windows_python_with_python_and_unavailable_version(monkeypatch, venv): def which(name): if name == "py": return "py" return original_which(name) major = sys.version_info.major + 99 minor = sys.version_info.minor monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: venv) monkeypatch.setattr(shutil, "which", which) with pytest.raises(InterpreterResolutionError) as e: find_python_interpreter(f"python{major}.{minor}") assert "py --list" in str(e) def test_windows_python_no_version_with_venv(monkeypatch): monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: True) assert _find_default_windows_python() == sys.executable def test_windows_python_no_version_no_venv_with_py(monkeypatch): def which(name): return "py" monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: False) monkeypatch.setattr(shutil, "which", which) assert _find_default_windows_python() == "py" def test_windows_python_no_version_no_venv_python_present(monkeypatch): def which(name): if name == "python": return "python" # Note: returns False for "py" monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: False) monkeypatch.setattr(shutil, "which", which) assert _find_default_windows_python() == "python" def test_windows_python_no_version_no_venv_no_python(monkeypatch): def which(name): return None monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: False) monkeypatch.setattr(shutil, "which", which) with pytest.raises(PipxError): _find_default_windows_python() # Test the checks for the store Python. def test_windows_python_no_venv_store_python(monkeypatch): def which(name): if name == "python": return "WindowsApps" class dummy_runner: def __init__(self, rc, out): self.rc = rc self.out = out def __call__(self, *args, **kw): ret = Mock() ret.returncode = self.rc ret.stdout = self.out return ret monkeypatch.setattr(pipx.interpreter, "has_venv", lambda: False) monkeypatch.setattr(shutil, "which", which) # Store version stub gives return code 9009 monkeypatch.setattr(subprocess, "run", dummy_runner(9009, "")) with pytest.raises(PipxError): _find_default_windows_python() # Even if it doesn't, it returns no output monkeypatch.setattr(subprocess, "run", dummy_runner(0, "")) with pytest.raises(PipxError): _find_default_windows_python() # If it *does* pass the tests, we use it as it's not the stub monkeypatch.setattr(subprocess, "run", dummy_runner(0, "3.8")) assert _find_default_windows_python() == "WindowsApps" def test_bad_env_python(monkeypatch): with pytest.raises(PipxError): _get_absolute_python_interpreter("bad_python") def test_good_env_python(monkeypatch, capsys): good_exec = _get_absolute_python_interpreter(sys.executable) assert good_exec == sys.executable def test_find_python_interpreter_by_path(monkeypatch): interpreter_path = sys.executable assert interpreter_path == find_python_interpreter(interpreter_path) def test_find_python_interpreter_by_version(monkeypatch): major = sys.version_info.major minor = sys.version_info.minor python_path = find_python_interpreter(f"python{major}.{minor}") assert python_path == f"python{major}.{minor}" or f"Python\\{major}.{minor}" in python_path def test_find_python_interpreter_by_wrong_path_raises(monkeypatch): interpreter_path = sys.executable + "99" with pytest.raises(InterpreterResolutionError) as e: find_python_interpreter(interpreter_path) assert "like a path" in str(e) def test_find_python_interpreter_missing_on_path_raises(monkeypatch): interpreter = "1.1" with pytest.raises(InterpreterResolutionError) as e: find_python_interpreter(interpreter) assert "Python Launcher" in str(e) assert "on your PATH" in str(e) def test_fetch_missing_python(monkeypatch, mocked_github_api): def which(name): return None monkeypatch.setattr(shutil, "which", which) major = sys.version_info.major minor = sys.version_info.minor target_python = f"{major}.{minor}" python_path = find_python_interpreter(target_python, fetch_missing_python=True) assert python_path is not None assert target_python in python_path assert str(pipx.paths.ctx.standalone_python_cachedir) in python_path if WINDOWS: assert python_path.endswith("python.exe") else: assert python_path.endswith("python3") subprocess.run([python_path, "-c", "import sys; print(sys.executable)"], check=True) pipx-1.6.0/tests/test_list.py000066400000000000000000000205541462701651400162400ustar00rootroot00000000000000import json import os import re import shutil import sys import time import pytest # type: ignore[import-not-found] from helpers import ( PIPX_METADATA_LEGACY_VERSIONS, app_name, assert_package_metadata, create_package_info_ref, mock_legacy_venv, remove_venv_interpreter, run_pipx_cli, skip_if_windows, ) from package_info import PKG from pipx import constants, paths, shared_libs from pipx.pipx_metadata_file import PackageInfo, _json_decoder_object_hook def test_cli(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["list"]) captured = capsys.readouterr() assert "nothing has been installed with pipx" in captured.err @skip_if_windows def test_cli_global(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert "installed package" in captured.out assert not run_pipx_cli(["list", "--global"]) captured = capsys.readouterr() assert "nothing has been installed with pipx" in captured.err def test_missing_interpreter(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["list"]) captured = capsys.readouterr() assert "package pycowsay has invalid interpreter" not in captured.err remove_venv_interpreter("pycowsay") assert run_pipx_cli(["list"]) captured = capsys.readouterr() assert "package pycowsay has invalid interpreter" in captured.err def test_list_suffix(pipx_temp_env, monkeypatch, capsys): suffix = "_x" assert not run_pipx_cli(["install", "pycowsay", f"--suffix={suffix}"]) assert not run_pipx_cli(["list"]) captured = capsys.readouterr() assert f"package pycowsay 0.0.0.2 (pycowsay{suffix})," in captured.out @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_list_legacy_venv(pipx_temp_env, monkeypatch, capsys, metadata_version): assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) if metadata_version is None: assert run_pipx_cli(["list"]) captured = capsys.readouterr() assert "package pycowsay has missing internal pipx metadata" in captured.err else: assert not run_pipx_cli(["list"]) captured = capsys.readouterr() assert "package pycowsay 0.0.0.2," in captured.out @pytest.mark.parametrize("metadata_version", ["0.1"]) def test_list_suffix_legacy_venv(pipx_temp_env, monkeypatch, capsys, metadata_version): suffix = "_x" assert not run_pipx_cli(["install", "pycowsay", f"--suffix={suffix}"]) mock_legacy_venv(f"pycowsay{suffix}", metadata_version=metadata_version) assert not run_pipx_cli(["list"]) captured = capsys.readouterr() assert f"package pycowsay 0.0.0.2 (pycowsay{suffix})," in captured.out def test_list_json(pipx_temp_env, capsys): pipx_venvs_dir = paths.ctx.home / "venvs" venv_bin_dir = "Scripts" if constants.WINDOWS else "bin" assert not run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) assert not run_pipx_cli(["inject", "pylint", PKG["black"]["spec"]]) captured = capsys.readouterr() assert not run_pipx_cli(["list", "--json"]) captured = capsys.readouterr() assert not re.search(r"\S", captured.err) json_parsed = json.loads(captured.out, object_hook=_json_decoder_object_hook) # raises error if not valid json assert sorted(json_parsed["venvs"].keys()) == ["pycowsay", "pylint"] # pycowsay venv pycowsay_package_ref = create_package_info_ref("pycowsay", "pycowsay", pipx_venvs_dir) assert_package_metadata( PackageInfo(**json_parsed["venvs"]["pycowsay"]["metadata"]["main_package"]), pycowsay_package_ref, ) assert json_parsed["venvs"]["pycowsay"]["metadata"]["injected_packages"] == {} # pylint venv pylint_package_ref = create_package_info_ref( "pylint", "pylint", pipx_venvs_dir, **{ "app_paths_of_dependencies": { "dill": [ pipx_venvs_dir / "pylint" / venv_bin_dir / "get_gprof", pipx_venvs_dir / "pylint" / venv_bin_dir / "get_objgraph", pipx_venvs_dir / "pylint" / venv_bin_dir / "undill", ], "isort": [ pipx_venvs_dir / "pylint" / venv_bin_dir / app_name("isort"), pipx_venvs_dir / "pylint" / venv_bin_dir / app_name("isort-identify-imports"), ], } }, ) assert_package_metadata( PackageInfo(**json_parsed["venvs"]["pylint"]["metadata"]["main_package"]), pylint_package_ref, ) assert sorted(json_parsed["venvs"]["pylint"]["metadata"]["injected_packages"].keys()) == ["black"] black_package_ref = create_package_info_ref("pylint", "black", pipx_venvs_dir, include_apps=False) assert_package_metadata( PackageInfo(**json_parsed["venvs"]["pylint"]["metadata"]["injected_packages"]["black"]), black_package_ref, ) def test_list_short(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) captured = capsys.readouterr() assert not run_pipx_cli(["list", "--short"]) captured = capsys.readouterr() assert "pycowsay 0.0.0.2" in captured.out assert "pylint 3.0.4" in captured.out def test_list_standalone_interpreter(pipx_temp_env, monkeypatch, mocked_github_api, capsys): def which(name): return None monkeypatch.setattr(shutil, "which", which) major = sys.version_info.major minor = sys.version_info.minor target_python = f"{major}.{minor}" assert not run_pipx_cli( [ "install", "--fetch-missing-python", "--python", target_python, PKG["pycowsay"]["spec"], ] ) captured = capsys.readouterr() assert not run_pipx_cli(["list"]) captured = capsys.readouterr() assert "standalone" in captured.out def test_list_does_not_trigger_maintenance(pipx_temp_env, caplog): assert not run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) now = time.time() shared_libs.shared_libs.create(verbose=True, pip_args=[]) shared_libs.shared_libs.has_been_updated_this_run = False access_time = now # this can be anything os.utime( shared_libs.shared_libs.pip_path, (access_time, -shared_libs.SHARED_LIBS_MAX_AGE_SEC - 5 * 60 + now), ) assert shared_libs.shared_libs.needs_upgrade run_pipx_cli(["list"]) assert not shared_libs.shared_libs.has_been_updated_this_run assert shared_libs.shared_libs.needs_upgrade # same test with --skip-maintenance, which is a no-op # we expect the same result, along with a warning os.utime( shared_libs.shared_libs.pip_path, (access_time, -shared_libs.SHARED_LIBS_MAX_AGE_SEC - 5 * 60 + now), ) shared_libs.shared_libs.has_been_updated_this_run = False assert shared_libs.shared_libs.needs_upgrade run_pipx_cli(["list", "--skip-maintenance"]) assert not shared_libs.shared_libs.has_been_updated_this_run assert shared_libs.shared_libs.needs_upgrade def test_list_pinned_packages(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) assert not run_pipx_cli(["install", PKG["black"]["spec"]]) captured = capsys.readouterr() assert not run_pipx_cli(["pin", "black"]) assert not run_pipx_cli(["list", "--pinned"]) captured = capsys.readouterr() assert "black 22.8.0" in captured.out assert "pycowsay 0.0.0.2" not in captured.out def test_list_pinned_packages_include_injected(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", PKG["pylint"]["spec"], PKG["nox"]["spec"]]) assert not run_pipx_cli(["inject", "pylint", PKG["black"]["spec"]]) assert not run_pipx_cli(["pin", "pylint"]) assert not run_pipx_cli(["pin", "nox"]) captured = capsys.readouterr() assert not run_pipx_cli(["list", "--pinned", "--include-injected"]) captured = capsys.readouterr() assert "nox 2023.4.22" in captured.out assert "pylint 3.0.4" in captured.out assert "black 22.8.0 (injected in venv pylint)" in captured.out pipx-1.6.0/tests/test_main.py000066400000000000000000000026511462701651400162070ustar00rootroot00000000000000import sys from unittest import mock import pytest # type: ignore[import-not-found] from helpers import run_pipx_cli from pipx import main def test_help_text(monkeypatch, capsys): mock_exit = mock.Mock(side_effect=ValueError("raised in test to exit early")) with mock.patch.object(sys, "exit", mock_exit), pytest.raises(ValueError, match="raised in test to exit early"): assert not run_pipx_cli(["--help"]) captured = capsys.readouterr() assert "usage: pipx" in captured.out def test_version(monkeypatch, capsys): mock_exit = mock.Mock(side_effect=ValueError("raised in test to exit early")) with mock.patch.object(sys, "exit", mock_exit), pytest.raises(ValueError, match="raised in test to exit early"): assert not run_pipx_cli(["--version"]) captured = capsys.readouterr() mock_exit.assert_called_with(0) assert main.__version__ in captured.out.strip() @pytest.mark.parametrize( ("argv", "executable", "expected"), [ ("/usr/bin/pipx", "", "pipx"), ("__main__.py", "/usr/bin/python", "/usr/bin/python -m pipx"), ], ) def test_prog_name(monkeypatch, argv, executable, expected): monkeypatch.setattr("pipx.main.sys.argv", [argv]) monkeypatch.setattr("pipx.main.sys.executable", executable) assert main.prog_name() == expected def test_limit_verbosity(): assert not run_pipx_cli(["list", "-qqq"]) assert not run_pipx_cli(["list", "-vvvv"]) pipx-1.6.0/tests/test_package_specifier.py000066400000000000000000000225051462701651400207070ustar00rootroot00000000000000from pathlib import Path import pytest # type: ignore[import-not-found] from pipx.package_specifier import ( fix_package_name, parse_specifier_for_install, parse_specifier_for_metadata, parse_specifier_for_upgrade, valid_pypi_name, ) from pipx.util import PipxError TEST_DATA_PATH = "./testdata/test_package_specifier" @pytest.mark.parametrize( "package_spec_in,package_name_out", [ ("Black", "black"), ("https://github.com/ambv/black/archive/18.9b0.zip", None), ("black @ https://github.com/ambv/black/archive/18.9b0.zip", None), ("black-18.9b0-py36-none-any.whl", None), ("black-18.9b0.tar.gz", None), ], ) def test_valid_pypi_name(package_spec_in, package_name_out): assert valid_pypi_name(package_spec_in) == package_name_out @pytest.mark.parametrize( "package_spec_in,package_name,package_spec_out", [ ( "https://github.com/ambv/black/archive/18.9b0.zip", "black", "https://github.com/ambv/black/archive/18.9b0.zip", ), ( "nox@https://github.com/ambv/black/archive/18.9b0.zip", "black", "black@ https://github.com/ambv/black/archive/18.9b0.zip", ), ( "nox[extra]@https://github.com/ambv/black/archive/18.9b0.zip", "black", "black[extra]@ https://github.com/ambv/black/archive/18.9b0.zip", ), ], ) def test_fix_package_name(package_spec_in, package_name, package_spec_out): assert fix_package_name(package_spec_in, package_name) == package_spec_out _ROOT = Path(__file__).parents[1] @pytest.mark.parametrize( "package_spec_in,package_or_url_correct,valid_spec", [ ("pipx", "pipx", True), ("PiPx_stylized.name", "pipx-stylized-name", True), ("pipx==0.15.0", "pipx==0.15.0", True), ("pipx>=0.15.0", "pipx>=0.15.0", True), ("pipx<=0.15.0", "pipx<=0.15.0", True), ('pipx;python_version>="3.6"', "pipx", True), ('pipx==0.15.0;python_version>="3.6"', "pipx==0.15.0", True), ("pipx[extra1]", "pipx[extra1]", True), ("pipx[extra1, extra2]", "pipx[extra1,extra2]", True), ("src/pipx", str((_ROOT / "src" / "pipx").resolve()), True), ( "git+https://github.com/cs01/nox.git@5ea70723e9e6", "git+https://github.com/cs01/nox.git@5ea70723e9e6", True, ), ( "nox@git+https://github.com/cs01/nox.git@5ea70723e9e6", "nox@ git+https://github.com/cs01/nox.git@5ea70723e9e6", True, ), ( "https://github.com/ambv/black/archive/18.9b0.zip", "https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( "black@https://github.com/ambv/black/archive/18.9b0.zip", "black@ https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( "black @ https://github.com/ambv/black/archive/18.9b0.zip", "black@ https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( "black[extra] @ https://github.com/ambv/black/archive/18.9b0.zip", "black[extra]@ https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( 'my-project[cli] @ git+ssh://git@bitbucket.org/my-company/myproject.git ; python_version<"3.8"', "my-project[cli]@ git+ssh://git@bitbucket.org/my-company/myproject.git", True, ), ("path/doesnt/exist", "non-existent-path", False), ( "https:/github.com/ambv/black/archive/18.9b0.zip", "URL-syntax-error-slash", False, ), ], ) def test_parse_specifier_for_metadata(package_spec_in, package_or_url_correct, valid_spec, monkeypatch, root): monkeypatch.chdir(root) if valid_spec: package_or_url = parse_specifier_for_metadata(package_spec_in) assert package_or_url == package_or_url_correct else: # print package_spec_in for info in case no error is raised print(f"package_spec_in = {package_spec_in}") with pytest.raises(PipxError, match=r"^Unable to parse package spec"): package_or_url = parse_specifier_for_metadata(package_spec_in) @pytest.mark.parametrize( "package_spec_in,package_or_url_correct,valid_spec", [ ("pipx", "pipx", True), ("PiPx_stylized.name", "pipx-stylized-name", True), ("pipx==0.15.0", "pipx", True), ("pipx>=0.15.0", "pipx", True), ("pipx<=0.15.0", "pipx", True), ('pipx;python_version>="3.6"', "pipx", True), ('pipx==0.15.0;python_version>="3.6"', "pipx", True), ("pipx[extra1]", "pipx[extra1]", True), ("pipx[extra1, extra2]", "pipx[extra1,extra2]", True), ("src/pipx", str((_ROOT / "src" / "pipx").resolve()), True), ( "git+https://github.com/cs01/nox.git@5ea70723e9e6", "git+https://github.com/cs01/nox.git@5ea70723e9e6", True, ), ( "nox@git+https://github.com/cs01/nox.git@5ea70723e9e6", "nox@ git+https://github.com/cs01/nox.git@5ea70723e9e6", True, ), ( "https://github.com/ambv/black/archive/18.9b0.zip", "https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( "black@https://github.com/ambv/black/archive/18.9b0.zip", "black@ https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( "black @ https://github.com/ambv/black/archive/18.9b0.zip", "black@ https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( "black[extra] @ https://github.com/ambv/black/archive/18.9b0.zip", "black[extra]@ https://github.com/ambv/black/archive/18.9b0.zip", True, ), ( 'my-project[cli] @ git+ssh://git@bitbucket.org/my-company/myproject.git ; python_version<"3.8"', "my-project[cli]@ git+ssh://git@bitbucket.org/my-company/myproject.git", True, ), ("path/doesnt/exist", "non-existent-path", False), ( "https:/github.com/ambv/black/archive/18.9b0.zip", "URL-syntax-error-slash", False, ), ], ) def test_parse_specifier_for_upgrade(package_spec_in, package_or_url_correct, valid_spec, monkeypatch, root): monkeypatch.chdir(root) if valid_spec: package_or_url = parse_specifier_for_upgrade(package_spec_in) assert package_or_url == package_or_url_correct else: # print package_spec_in for info in case no error is raised print(f"package_spec_in = {package_spec_in}") with pytest.raises(PipxError, match=r"^Unable to parse package spec"): package_or_url = parse_specifier_for_upgrade(package_spec_in) @pytest.mark.parametrize( "package_spec_in,pip_args_in,package_spec_expected,pip_args_expected,warning_str", [ ('pipx==0.15.0;python_version>="3.6"', [], "pipx==0.15.0", [], None), ("pipx==0.15.0", ["--editable"], "pipx==0.15.0", [], "Ignoring --editable"), ( 'pipx==0.15.0;python_version>="3.6"', [], "pipx==0.15.0", [], 'Ignoring environment markers (python_version >= "3.6") in package', ), ( "pipx==0.15.0", ["--no-cache-dir", "--editable"], "pipx==0.15.0", ["--no-cache-dir"], "Ignoring --editable", ), ( "git+https://github.com/cs01/nox.git@5ea70723e9e6", ["--editable"], "git+https://github.com/cs01/nox.git@5ea70723e9e6", [], "Ignoring --editable", ), ( "https://github.com/ambv/black/archive/18.9b0.zip", ["--editable"], "https://github.com/ambv/black/archive/18.9b0.zip", [], "Ignoring --editable", ), ( "src/pipx", ["--editable"], str(Path("src/pipx").resolve()), ["--editable"], None, ), ( TEST_DATA_PATH + "/local_extras", [], str(Path(TEST_DATA_PATH + "/local_extras").resolve), [], None, ), ( TEST_DATA_PATH + "/local_extras[cow]", [], str(Path(TEST_DATA_PATH + "/local_extras").resolve) + "[cow]", [], None, ), ( TEST_DATA_PATH + "/local_extras", ["--editable"], str(Path(TEST_DATA_PATH + "/local_extras").resolve), ["--editable"], None, ), ( TEST_DATA_PATH + "/local_extras[cow]", ["--editable"], str(Path(TEST_DATA_PATH + "/local_extras").resolve) + "[cow]", ["--editable"], None, ), ], ) def test_parse_specifier_for_install( caplog, package_spec_in, pip_args_in, package_spec_expected, pip_args_expected, warning_str, monkeypatch, root, ): monkeypatch.chdir(root) [package_or_url_out, pip_args_out] = parse_specifier_for_install(package_spec_in, pip_args_in) if warning_str is not None: assert warning_str in caplog.text pipx-1.6.0/tests/test_pin.py000066400000000000000000000042541462701651400160520ustar00rootroot00000000000000from helpers import run_pipx_cli from package_info import PKG def test_pin(capsys, pipx_temp_env, caplog): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["pin", "pycowsay"]) assert not run_pipx_cli(["upgrade", "pycowsay"]) assert "Not upgrading pinned package pycowsay" in caplog.text def test_pin_with_suffix(capsys, pipx_temp_env, caplog): assert not run_pipx_cli(["install", PKG["black"]["spec"], "--suffix", "@1"]) assert not run_pipx_cli(["pin", "black@1"]) assert not run_pipx_cli(["upgrade", "black@1"]) assert "Not upgrading pinned package black@1" in caplog.text def test_pin_warning(capsys, pipx_temp_env, caplog): assert not run_pipx_cli(["install", PKG["nox"]["spec"]]) assert not run_pipx_cli(["pin", "nox"]) assert not run_pipx_cli(["pin", "nox"]) assert "Package nox already pinned đź´" in caplog.text def test_pin_not_installed_package(capsys, pipx_temp_env): assert run_pipx_cli(["pin", "abc"]) captured = capsys.readouterr() assert "Package abc is not installed" in captured.err def test_pin_injected_packages_only(capsys, pipx_temp_env, caplog): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["inject", "pycowsay", "black", PKG["pylint"]["spec"]]) assert not run_pipx_cli(["pin", "pycowsay", "--injected-only"]) captured = capsys.readouterr() assert "Pinned 2 packages in venv pycowsay" in captured.out assert "black" in captured.out assert "pylint" in captured.out assert not run_pipx_cli(["upgrade", "pycowsay", "--include-injected"]) assert "Not upgrading pinned package black in venv pycowsay" in caplog.text assert "Not upgrading pinned package pylint in venv pycowsay" in caplog.text def test_pin_injected_packages_with_skip(capsys, pipx_temp_env): assert not run_pipx_cli(["install", "black"]) assert not run_pipx_cli(["inject", "black", PKG["pylint"]["spec"], PKG["isort"]["spec"]]) _ = capsys.readouterr() assert not run_pipx_cli(["pin", "black", "--injected-only", "--skip", "isort"]) captured = capsys.readouterr() assert "pylint" in captured.out assert "isort" not in captured.out pipx-1.6.0/tests/test_pipx_metadata_file.py000066400000000000000000000075561462701651400211130ustar00rootroot00000000000000import sys from dataclasses import replace from pathlib import Path import pytest # type: ignore[import-not-found] from helpers import assert_package_metadata, create_package_info_ref, run_pipx_cli from package_info import PKG from pipx import paths from pipx.pipx_metadata_file import PackageInfo, PipxMetadata from pipx.util import PipxError TEST_PACKAGE1 = PackageInfo( package="test_package", package_or_url="test_package_url", pip_args=[], include_apps=True, include_dependencies=False, apps=["testapp"], app_paths=[Path("/usr/bin")], apps_of_dependencies=["dep1"], app_paths_of_dependencies={"dep1": [Path("bin")]}, man_pages=[str(Path("man1/testapp.1"))], man_pages_of_dependencies=[str(Path("man1/dep1.1"))], man_paths_of_dependencies={"dep1": [Path("man1/dep1.1")]}, package_version="0.1.2", ) TEST_PACKAGE2 = PackageInfo( package="inj_package", package_or_url="inj_package_url", pip_args=["-e"], include_apps=True, include_dependencies=False, apps=["injapp"], app_paths=[Path("/usr/bin")], apps_of_dependencies=["dep2"], app_paths_of_dependencies={"dep2": [Path("bin")]}, man_pages=[str(Path("man1/injapp.1"))], man_pages_of_dependencies=[str(Path("man1/dep2.1"))], man_paths_of_dependencies={"dep2": [Path("man1/dep2.1")]}, package_version="6.7.8", ) def test_pipx_metadata_file_create(tmp_path): venv_dir = tmp_path / TEST_PACKAGE1.package venv_dir.mkdir() pipx_metadata = PipxMetadata(venv_dir) pipx_metadata.main_package = TEST_PACKAGE1 pipx_metadata.python_version = "3.4.5" pipx_metadata.source_interpreter = Path(sys.executable) pipx_metadata.venv_args = ["--system-site-packages"] pipx_metadata.injected_packages = {"injected": TEST_PACKAGE2} pipx_metadata.write() pipx_metadata2 = PipxMetadata(venv_dir) for attribute in [ "venv_dir", "main_package", "python_version", "venv_args", "injected_packages", ]: assert getattr(pipx_metadata, attribute) == getattr(pipx_metadata2, attribute) @pytest.mark.parametrize( "test_package", [ replace(TEST_PACKAGE1, include_apps=False), replace(TEST_PACKAGE1, package=None), replace(TEST_PACKAGE1, package_or_url=None), ], ) def test_pipx_metadata_file_validation(tmp_path, test_package): venv_dir = tmp_path / "venv" venv_dir.mkdir() pipx_metadata = PipxMetadata(venv_dir) pipx_metadata.main_package = test_package pipx_metadata.python_version = "3.4.5" pipx_metadata.source_interpreter = Path(sys.executable) pipx_metadata.venv_args = ["--system-site-packages"] pipx_metadata.injected_packages = {} with pytest.raises(PipxError): pipx_metadata.write() def test_package_install(monkeypatch, tmp_path, pipx_temp_env): pipx_venvs_dir = paths.ctx.home / "venvs" run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) assert (pipx_venvs_dir / "pycowsay" / "pipx_metadata.json").is_file() pipx_metadata = PipxMetadata(pipx_venvs_dir / "pycowsay") pycowsay_package_ref = create_package_info_ref("pycowsay", "pycowsay", pipx_venvs_dir) assert_package_metadata(pipx_metadata.main_package, pycowsay_package_ref) assert pipx_metadata.injected_packages == {} def test_package_inject(monkeypatch, tmp_path, pipx_temp_env): pipx_venvs_dir = paths.ctx.home / "venvs" run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"]]) assert (pipx_venvs_dir / "pycowsay" / "pipx_metadata.json").is_file() pipx_metadata = PipxMetadata(pipx_venvs_dir / "pycowsay") assert pipx_metadata.injected_packages.keys() == {"black"} black_package_ref = create_package_info_ref("pycowsay", "black", pipx_venvs_dir, include_apps=False) assert_package_metadata(pipx_metadata.injected_packages["black"], black_package_ref) pipx-1.6.0/tests/test_reinstall.py000066400000000000000000000050601462701651400172550ustar00rootroot00000000000000import sys import pytest # type: ignore[import-not-found] from helpers import PIPX_METADATA_LEGACY_VERSIONS, mock_legacy_venv, run_pipx_cli, skip_if_windows def test_reinstall(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["reinstall", "--python", sys.executable, "pycowsay"]) @skip_if_windows def test_reinstall_global(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "--global", "pycowsay"]) assert not run_pipx_cli(["reinstall", "--global", "--python", sys.executable, "pycowsay"]) def test_reinstall_nonexistent(pipx_temp_env, capsys): assert run_pipx_cli(["reinstall", "--python", sys.executable, "nonexistent"]) assert "Nothing to reinstall for nonexistent" in capsys.readouterr().out @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_reinstall_legacy_venv(pipx_temp_env, capsys, metadata_version): assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) assert not run_pipx_cli(["reinstall", "--python", sys.executable, "pycowsay"]) def test_reinstall_suffix(pipx_temp_env, capsys): suffix = "_x" assert not run_pipx_cli(["install", "pycowsay", f"--suffix={suffix}"]) assert not run_pipx_cli(["reinstall", "--python", sys.executable, f"pycowsay{suffix}"]) @pytest.mark.parametrize("metadata_version", ["0.1"]) def test_reinstall_suffix_legacy_venv(pipx_temp_env, capsys, metadata_version): suffix = "_x" assert not run_pipx_cli(["install", "pycowsay", f"--suffix={suffix}"]) mock_legacy_venv(f"pycowsay{suffix}", metadata_version=metadata_version) assert not run_pipx_cli(["reinstall", "--python", sys.executable, f"pycowsay{suffix}"]) def test_reinstall_specifier(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pylint==3.0.4"]) # clear capsys before reinstall captured = capsys.readouterr() assert not run_pipx_cli(["reinstall", "--python", sys.executable, "pylint"]) captured = capsys.readouterr() assert "installed package pylint 3.0.4" in captured.out def test_reinstall_with_path(pipx_temp_env, capsys, tmp_path): path = tmp_path / "some" / "path" assert run_pipx_cli(["reinstall", str(path)]) captured = capsys.readouterr() assert "Expected the name of an installed package" in captured.err.replace("\n", " ") assert run_pipx_cli(["reinstall", str(path.resolve())]) captured = capsys.readouterr() assert "Expected the name of an installed package" in captured.err.replace("\n", " ") pipx-1.6.0/tests/test_reinstall_all.py000066400000000000000000000035071462701651400201110ustar00rootroot00000000000000import sys import pytest # type: ignore[import-not-found] from helpers import PIPX_METADATA_LEGACY_VERSIONS, mock_legacy_venv, run_pipx_cli from pipx import shared_libs def test_reinstall_all(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["reinstall-all", "--python", sys.executable]) def test_reinstall_all_none(pipx_temp_env, capsys): assert not run_pipx_cli(["reinstall-all"]) captured = capsys.readouterr() assert "No packages reinstalled after running 'pipx reinstall-all'" in captured.out @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_reinstall_all_legacy_venv(pipx_temp_env, capsys, metadata_version): assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) assert not run_pipx_cli(["reinstall-all", "--python", sys.executable]) def test_reinstall_all_suffix(pipx_temp_env, capsys): suffix = "_x" assert not run_pipx_cli(["install", "pycowsay", f"--suffix={suffix}"]) assert not run_pipx_cli(["reinstall-all", "--python", sys.executable]) @pytest.mark.parametrize("metadata_version", ["0.1"]) def test_reinstall_all_suffix_legacy_venv(pipx_temp_env, capsys, metadata_version): suffix = "_x" assert not run_pipx_cli(["install", "pycowsay", f"--suffix={suffix}"]) mock_legacy_venv(f"pycowsay{suffix}", metadata_version=metadata_version) assert not run_pipx_cli(["reinstall-all", "--python", sys.executable]) def test_reinstall_all_triggers_shared_libs_upgrade(pipx_temp_env, caplog, capsys): assert not run_pipx_cli(["install", "pycowsay"]) shared_libs.shared_libs.has_been_updated_this_run = False caplog.clear() assert not run_pipx_cli(["reinstall-all"]) assert "Upgrading shared libraries in" in caplog.text pipx-1.6.0/tests/test_run.py000066400000000000000000000337551462701651400161000ustar00rootroot00000000000000import logging import os import subprocess import sys import textwrap from pathlib import Path from unittest import mock import pytest # type: ignore[import-not-found] import pipx.main import pipx.util from helpers import run_pipx_cli from package_info import PKG from pipx import paths, shared_libs def test_help_text(pipx_temp_env, monkeypatch, capsys): mock_exit = mock.Mock(side_effect=ValueError("raised in test to exit early")) with mock.patch.object(sys, "exit", mock_exit), pytest.raises(ValueError, match="raised in test to exit early"): run_pipx_cli(["run", "--help"]) captured = capsys.readouterr() assert "Download the latest version of a package" in captured.out def execvpe_mock(cmd_path, cmd_args, env): return_code = subprocess.run( [str(x) for x in cmd_args], env=env, capture_output=False, encoding="utf-8", text=True, check=False, ).returncode sys.exit(return_code) def run_pipx_cli_exit(pipx_cmd_list, assert_exit=None): with pytest.raises(SystemExit) as sys_exit: run_pipx_cli(pipx_cmd_list) if assert_exit is not None: assert sys_exit.type == SystemExit assert sys_exit.value.code == assert_exit @pytest.mark.parametrize("package_name", ["pycowsay", "pycowsay==0.0.0.2", "pycowsay>=0.0.0.2"]) @mock.patch("os.execvpe", new=execvpe_mock) def test_simple_run(pipx_temp_env, monkeypatch, capsys, package_name): run_pipx_cli_exit(["run", package_name, "--help"]) captured = capsys.readouterr() assert "Download the latest version of a package" not in captured.out @mock.patch("os.execvpe", new=execvpe_mock) def test_cache(pipx_temp_env, monkeypatch, capsys, caplog): run_pipx_cli_exit(["run", "pycowsay", "cowsay", "args"]) caplog.set_level(logging.DEBUG) run_pipx_cli_exit(["run", "--verbose", "pycowsay", "cowsay", "args"], assert_exit=0) assert "Reusing cached venv" in caplog.text run_pipx_cli_exit(["run", "--no-cache", "pycowsay", "cowsay", "args"]) assert "Removing cached venv" in caplog.text @mock.patch("os.execvpe", new=execvpe_mock) def test_cachedir_tag(pipx_ultra_temp_env, monkeypatch, capsys, caplog): tag_path = paths.ctx.venv_cache / "CACHEDIR.TAG" assert not tag_path.exists() # Run pipx to create tag caplog.set_level(logging.DEBUG) run_pipx_cli_exit(["run", "pycowsay", "cowsay", "args"]) assert "Adding CACHEDIR.TAG to cache directory" in caplog.text assert tag_path.exists() caplog.clear() # Run pipx again to verify the tag file is not recreated run_pipx_cli_exit(["run", "pycowsay", "cowsay", "args"]) assert "Adding CACHEDIR.TAG to cache directory" not in caplog.text assert tag_path.exists() # Verify the tag file starts with the required signature. with tag_path.open("r") as tag_file: assert tag_file.read().startswith("Signature: 8a477f597d28d172789f06886806bc55") @mock.patch("os.execvpe", new=execvpe_mock) def test_run_script_from_internet(pipx_temp_env, capsys): run_pipx_cli_exit( [ "run", "https://gist.githubusercontent.com/cs01/" "fa721a17a326e551ede048c5088f9e0f/raw/" "6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py", ], assert_exit=0, ) @pytest.mark.parametrize( "input_run_args,expected_app_with_args", [ (["--", "pycowsay", "--", "hello"], ["pycowsay", "--", "hello"]), (["--", "pycowsay", "--", "--", "hello"], ["pycowsay", "--", "--", "hello"]), (["--", "pycowsay", "hello", "--"], ["pycowsay", "hello", "--"]), (["--", "pycowsay", "hello", "--", "--"], ["pycowsay", "hello", "--", "--"]), (["--", "pycowsay", "--"], ["pycowsay", "--"]), (["--", "pycowsay", "--", "--"], ["pycowsay", "--", "--"]), (["pycowsay", "--", "hello"], ["pycowsay", "--", "hello"]), (["pycowsay", "--", "--", "hello"], ["pycowsay", "--", "--", "hello"]), (["pycowsay", "hello", "--"], ["pycowsay", "hello", "--"]), (["pycowsay", "hello", "--", "--"], ["pycowsay", "hello", "--", "--"]), (["pycowsay", "--"], ["pycowsay", "--"]), (["pycowsay", "--", "--"], ["pycowsay", "--", "--"]), (["--", "--", "pycowsay", "--"], ["--", "pycowsay", "--"]), ], ) def test_appargs_doubledash(pipx_temp_env, capsys, monkeypatch, input_run_args, expected_app_with_args): parser, _ = pipx.main.get_command_parser() monkeypatch.setattr(sys, "argv", ["pipx", "run"] + input_run_args) parsed_pipx_args = parser.parse_args() pipx.main.check_args(parsed_pipx_args) assert parsed_pipx_args.app_with_args == expected_app_with_args def test_run_ensure_null_pythonpath(): env = os.environ.copy() env["PYTHONPATH"] = "test" assert ( "None" in subprocess.run( [ sys.executable, "-m", "pipx", "run", "ipython", "-c", "import os; print(os.environ.get('PYTHONPATH'))", ], env=env, capture_output=True, text=True, check=True, ).stdout ) # packages listed roughly in order of increasing test duration @pytest.mark.parametrize( "package, package_or_url, app_appargs, skip_win", [ ("pycowsay", "pycowsay", ["pycowsay", "hello"], False), ("shell-functools", PKG["shell-functools"]["spec"], ["filter", "--help"], True), ("black", PKG["black"]["spec"], ["black", "--help"], False), ("pylint", PKG["pylint"]["spec"], ["pylint", "--help"], False), ("kaggle", PKG["kaggle"]["spec"], ["kaggle", "--help"], False), ("ipython", PKG["ipython"]["spec"], ["ipython", "--version"], False), ("cloudtoken", PKG["cloudtoken"]["spec"], ["cloudtoken", "--help"], True), ("awscli", PKG["awscli"]["spec"], ["aws", "--help"], True), # ("ansible", PKG["ansible"]["spec"], ["ansible", "--help"]), # takes too long ], ) @mock.patch("os.execvpe", new=execvpe_mock) def test_package_determination(caplog, pipx_temp_env, package, package_or_url, app_appargs, skip_win): if sys.platform.startswith("win") and skip_win: # Skip packages with 'scripts' in setup.py that don't work on Windows pytest.skip() caplog.set_level(logging.INFO) run_pipx_cli_exit(["run", "--verbose", "--spec", package_or_url, "--"] + app_appargs) assert "Cannot determine package name" not in caplog.text assert f"Determined package name: {package}" in caplog.text @mock.patch("os.execvpe", new=execvpe_mock) def test_run_without_requirements(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" test_str = "Hello, world!" script.write_text( textwrap.dedent( f""" from pathlib import Path Path({str(out)!r}).write_text({test_str!r}) """ ).strip() ) run_pipx_cli_exit(["run", script.as_uri()]) assert out.read_text() == test_str @mock.patch("os.execvpe", new=execvpe_mock) def test_run_with_requirements(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" script.write_text( textwrap.dedent( f""" # /// script # dependencies = ["requests==2.31.0"] # /// # Check requests can be imported import requests # Check dependencies of requests can be imported import certifi # Check the installed version from pathlib import Path Path({str(out)!r}).write_text(requests.__version__) """ ).strip(), encoding="utf-8", ) run_pipx_cli_exit(["run", script.as_uri()]) assert out.read_text() == "2.31.0" @mock.patch("os.execvpe", new=execvpe_mock) def test_run_with_requirements_old(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" script.write_text( textwrap.dedent( f""" # /// pyproject # run.requirements = ["requests==2.31.0"] # /// # Check requests can be imported import requests # Check dependencies of requests can be imported import certifi # Check the installed version from pathlib import Path Path({str(out)!r}).write_text(requests.__version__) """ ).strip(), encoding="utf-8", ) with pytest.raises(ValueError): run_pipx_cli_exit(["run", script.as_uri()]) @mock.patch("os.execvpe", new=execvpe_mock) def test_run_correct_traceback(capfd, pipx_temp_env, tmp_path): script = tmp_path / "test.py" script.write_text( textwrap.dedent( """ raise RuntimeError("Should fail") """ ).strip() ) with pytest.raises(SystemExit): run_pipx_cli(["run", str(script)]) captured = capfd.readouterr() assert "test.py" in captured.err @mock.patch("os.execvpe", new=execvpe_mock) def test_run_with_args(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" script.write_text( textwrap.dedent( f""" import sys from pathlib import Path Path({str(out)!r}).write_text(str(int(sys.argv[1]) + 1)) """ ).strip() ) run_pipx_cli_exit(["run", script.as_uri(), "1"]) assert out.read_text() == "2" @mock.patch("os.execvpe", new=execvpe_mock) def test_run_with_requirements_and_args(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" script.write_text( textwrap.dedent( f""" # /// script # dependencies = ["packaging"] # /// import packaging import sys from pathlib import Path Path({str(out)!r}).write_text(str(int(sys.argv[1]) + 1)) """ ).strip() ) run_pipx_cli_exit(["run", script.as_uri(), "1"]) assert out.read_text() == "2" def test_pip_args_forwarded_to_shared_libs(pipx_ultra_temp_env, capsys, caplog): # strategy: # 1. start from an empty env to ensure the next command would trigger a shared lib update assert shared_libs.shared_libs.needs_upgrade # 2. install any package with --no-index # and check that the shared library update phase fails return_code = run_pipx_cli(["run", "--verbose", "--pip-args=--no-index", "pycowsay", "hello"]) assert "Upgrading shared libraries in" in caplog.text captured = capsys.readouterr() assert return_code != 0 assert "ERROR: Could not find a version that satisfies the requirement pip" in captured.err assert "Failed to upgrade shared libraries" in caplog.text @mock.patch("os.execvpe", new=execvpe_mock) def test_run_with_invalid_requirement(capsys, pipx_temp_env, tmp_path): script = tmp_path / "test.py" script.write_text( textwrap.dedent( """ # /// script # dependencies = ["this is an invalid requirement"] # /// print() """ ).strip() ) ret = run_pipx_cli(["run", script.as_uri()]) assert ret == 1 captured = capsys.readouterr() assert "Invalid requirement this is an invalid requirement" in captured.err @mock.patch("os.execvpe", new=execvpe_mock) def test_run_script_by_absolute_name(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" test_str = "Hello, world!" script.write_text( textwrap.dedent( f""" from pathlib import Path Path({str(out)!r}).write_text({test_str!r}) """ ).strip() ) run_pipx_cli_exit(["run", "--path", str(script)]) assert out.read_text() == test_str @mock.patch("os.execvpe", new=execvpe_mock) def test_run_script_by_relative_name(caplog, pipx_temp_env, monkeypatch, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" test_str = "Hello, world!" script.write_text( textwrap.dedent( f""" from pathlib import Path Path({str(out)!r}).write_text({test_str!r}) """ ).strip() ) with monkeypatch.context() as m: m.chdir(tmp_path) run_pipx_cli_exit(["run", "test.py"]) assert out.read_text() == test_str @pytest.mark.skipif(not sys.platform.startswith("win"), reason="uses windows version format") @mock.patch("os.execvpe", new=execvpe_mock) def test_run_with_windows_python_version(caplog, pipx_temp_env, tmp_path): script = tmp_path / "test.py" out = tmp_path / "output.txt" script.write_text( textwrap.dedent( f""" import sys from pathlib import Path Path({str(out)!r}).write_text(sys.version) """ ).strip() ) run_pipx_cli_exit(["run", script.as_uri(), "--python", "3.12"]) assert "3.12" in out.read_text() @mock.patch("os.execvpe", new=execvpe_mock) def test_run_verify_script_name_provided(pipx_temp_env, capsys, tmpdir): tmpdir.mkdir("black") run_pipx_cli_exit(["run", "black"]) captured = capsys.readouterr() assert "black" in captured.err @mock.patch("os.execvpe", new=execvpe_mock) def test_run_shared_lib_as_app(pipx_temp_env, monkeypatch, capfd): run_pipx_cli_exit(["run", "pip", "--help"]) captured = capfd.readouterr() assert "pip [options]" in captured.out @mock.patch("os.execvpe", new=execvpe_mock) def test_run_local_path_entry_point(pipx_temp_env, caplog, root): empty_project_path = (Path("testdata") / "empty_project").as_posix() os.chdir(root) caplog.set_level(logging.INFO) run_pipx_cli_exit(["run", empty_project_path]) assert "Using discovered entry point for 'pipx run'" in caplog.text pipx-1.6.0/tests/test_runpip.py000066400000000000000000000006621462701651400166000ustar00rootroot00000000000000from helpers import run_pipx_cli, skip_if_windows def test_runpip(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["runpip", "pycowsay", "list"]) @skip_if_windows def test_runpip_global(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["install", "--global", "pycowsay"]) assert not run_pipx_cli(["runpip", "--global", "pycowsay", "list"]) pipx-1.6.0/tests/test_shared_libs.py000066400000000000000000000013541462701651400175410ustar00rootroot00000000000000import os import time import pytest # type: ignore[import-not-found] from pipx import shared_libs @pytest.mark.parametrize( "mtime_minus_now,needs_upgrade", [ (-shared_libs.SHARED_LIBS_MAX_AGE_SEC - 5 * 60, True), (-shared_libs.SHARED_LIBS_MAX_AGE_SEC + 5 * 60, False), ], ) def test_auto_update_shared_libs(capsys, pipx_ultra_temp_env, mtime_minus_now, needs_upgrade): now = time.time() shared_libs.shared_libs.create(verbose=True, pip_args=[]) shared_libs.shared_libs.has_been_updated_this_run = False access_time = now # this can be anything os.utime(shared_libs.shared_libs.pip_path, (access_time, mtime_minus_now + now)) assert shared_libs.shared_libs.needs_upgrade is needs_upgrade pipx-1.6.0/tests/test_standalone_interpreter.py000066400000000000000000000100711462701651400220310ustar00rootroot00000000000000import json import shutil import sys from helpers import ( run_pipx_cli, ) from package_info import PKG from pipx import standalone_python MAJOR_PYTHON_VERSION = sys.version_info.major MINOR_PYTHON_VERSION = sys.version_info.minor TARGET_PYTHON_VERSION = f"{MAJOR_PYTHON_VERSION}.{MINOR_PYTHON_VERSION}" original_which = shutil.which def mock_which(name): if name == TARGET_PYTHON_VERSION: return None return original_which(name) def test_list_no_standalone_interpreters(pipx_temp_env, monkeypatch, capsys): assert not run_pipx_cli(["interpreter", "list"]) captured = capsys.readouterr() assert "Standalone interpreters" in captured.out assert len(captured.out.splitlines()) == 1 def test_list_used_standalone_interpreters(pipx_temp_env, monkeypatch, mocked_github_api, capsys): monkeypatch.setattr(shutil, "which", mock_which) assert not run_pipx_cli( [ "install", "--fetch-missing-python", "--python", TARGET_PYTHON_VERSION, PKG["pycowsay"]["spec"], ] ) capsys.readouterr() assert not run_pipx_cli(["interpreter", "list"]) captured = capsys.readouterr() assert TARGET_PYTHON_VERSION in captured.out assert "pycowsay" in captured.out def test_list_unused_standalone_interpreters(pipx_temp_env, monkeypatch, mocked_github_api, capsys): monkeypatch.setattr(shutil, "which", mock_which) assert not run_pipx_cli( [ "install", "--fetch-missing-python", "--python", TARGET_PYTHON_VERSION, PKG["pycowsay"]["spec"], ] ) assert not run_pipx_cli(["uninstall", "pycowsay"]) capsys.readouterr() assert not run_pipx_cli(["interpreter", "list"]) captured = capsys.readouterr() assert TARGET_PYTHON_VERSION in captured.out assert "pycowsay" not in captured.out assert "Unused" in captured.out def test_prune_unused_standalone_interpreters(pipx_temp_env, monkeypatch, mocked_github_api, capsys): monkeypatch.setattr(shutil, "which", mock_which) assert not run_pipx_cli( [ "install", "--fetch-missing-python", "--python", TARGET_PYTHON_VERSION, PKG["pycowsay"]["spec"], ] ) capsys.readouterr() assert not run_pipx_cli(["interpreter", "prune"]) captured = capsys.readouterr() assert "Nothing to remove" in captured.out assert not run_pipx_cli(["uninstall", "pycowsay"]) capsys.readouterr() assert not run_pipx_cli(["interpreter", "prune"]) captured = capsys.readouterr() assert "Successfully removed:" in captured.out assert f"- Python {TARGET_PYTHON_VERSION}" in captured.out assert not run_pipx_cli(["interpreter", "list"]) captured = capsys.readouterr() assert "Standalone interpreters" in captured.out assert len(captured.out.splitlines()) == 1 assert not run_pipx_cli(["interpreter", "prune"]) captured = capsys.readouterr() assert "Nothing to remove" in captured.out def test_upgrade_standalone_interpreter(pipx_temp_env, root, monkeypatch, capsys): monkeypatch.setattr(shutil, "which", mock_which) with open(root / "testdata" / "standalone_python_index_20240107.json") as f: new_index = json.load(f) monkeypatch.setattr(standalone_python, "get_or_update_index", lambda _: new_index) assert not run_pipx_cli( [ "install", "--fetch-missing-python", "--python", TARGET_PYTHON_VERSION, PKG["pycowsay"]["spec"], ] ) with open(root / "testdata" / "standalone_python_index_20240224.json") as f: new_index = json.load(f) monkeypatch.setattr(standalone_python, "get_or_update_index", lambda _: new_index) assert not run_pipx_cli(["interpreter", "upgrade"]) def test_upgrade_standalone_interpreter_nothing_to_upgrade(pipx_temp_env, capsys, mocked_github_api): assert not run_pipx_cli(["interpreter", "upgrade"]) captured = capsys.readouterr() assert "Nothing to upgrade" in captured.out pipx-1.6.0/tests/test_uninject.py000066400000000000000000000035401462701651400171000ustar00rootroot00000000000000from helpers import run_pipx_cli, skip_if_windows from package_info import PKG def test_uninject_simple(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"]]) assert not run_pipx_cli(["uninject", "pycowsay", "black"]) captured = capsys.readouterr() assert "Uninjected package black" in captured.out assert not run_pipx_cli(["list", "--include-injected"]) captured = capsys.readouterr() assert "black" not in captured.out @skip_if_windows def test_uninject_simple_global(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "--global", "pycowsay"]) assert not run_pipx_cli(["inject", "--global", "pycowsay", PKG["black"]["spec"]]) assert not run_pipx_cli(["uninject", "--global", "pycowsay", "black"]) captured = capsys.readouterr() assert "Uninjected package black" in captured.out assert not run_pipx_cli(["list", "--global", "--include-injected"]) captured = capsys.readouterr() assert "black" not in captured.out def test_uninject_with_include_apps(pipx_temp_env, capsys, caplog): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"], "--include-deps", "--include-apps"]) assert not run_pipx_cli(["uninject", "pycowsay", "black", "--verbose"]) assert "removed file" in caplog.text def test_uninject_leave_deps(pipx_temp_env, capsys, caplog): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["inject", "pycowsay", PKG["black"]["spec"]]) assert not run_pipx_cli(["uninject", "pycowsay", "black", "--leave-deps", "--verbose"]) captured = capsys.readouterr() assert "Uninjected package black from venv pycowsay" in captured.out assert "Dependencies of uninstalled package:" not in caplog.text pipx-1.6.0/tests/test_uninstall.py000066400000000000000000000161241462701651400172740ustar00rootroot00000000000000import sys import pytest # type: ignore[import-not-found] from helpers import ( PIPX_METADATA_LEGACY_VERSIONS, app_name, mock_legacy_venv, remove_venv_interpreter, run_pipx_cli, skip_if_windows, ) from package_info import PKG from pipx import paths def file_or_symlink(filepath): # Returns True for file or broken symlink or non-broken symlink # Returns False for no file and no symlink # filepath.exists() returns True for regular file or non-broken symlink # filepath.exists() returns False for no regular file or broken symlink # filepath.is_symlink() returns True for broken or non-broken symlink return filepath.exists() or filepath.is_symlink() def test_uninstall(pipx_temp_env): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["uninstall", "pycowsay"]) @skip_if_windows def test_uninstall_global(pipx_temp_env): assert not run_pipx_cli(["install", "--global", "pycowsay"]) assert not run_pipx_cli(["uninstall", "--global", "pycowsay"]) def test_uninstall_circular_deps(pipx_temp_env): assert not run_pipx_cli(["install", PKG["cloudtoken"]["spec"]]) assert not run_pipx_cli(["uninstall", "cloudtoken"]) @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_uninstall_legacy_venv(pipx_temp_env, metadata_version): executable_path = paths.ctx.bin_dir / app_name("pycowsay") assert not run_pipx_cli(["install", "pycowsay"]) assert executable_path.exists() mock_legacy_venv("pycowsay", metadata_version=metadata_version) assert not run_pipx_cli(["uninstall", "pycowsay"]) assert not file_or_symlink(executable_path) def test_uninstall_suffix(pipx_temp_env): name = "pbr" suffix = "_a" executable_path = paths.ctx.bin_dir / app_name(f"{name}{suffix}") assert not run_pipx_cli(["install", PKG[name]["spec"], f"--suffix={suffix}"]) assert executable_path.exists() assert not run_pipx_cli(["uninstall", f"{name}{suffix}"]) assert not file_or_symlink(executable_path) def test_uninstall_man_page(pipx_temp_env): man_page_path = paths.ctx.man_dir / "man6" / "pycowsay.6" assert not run_pipx_cli(["install", "pycowsay"]) assert man_page_path.exists() assert not run_pipx_cli(["uninstall", "pycowsay"]) assert not file_or_symlink(man_page_path) def test_uninstall_injected(pipx_temp_env): pycowsay_app_paths = [paths.ctx.bin_dir / app for app in PKG["pycowsay"]["apps"]] pycowsay_man_page_paths = [paths.ctx.man_dir / man_page for man_page in PKG["pycowsay"]["man_pages"]] pylint_app_paths = [paths.ctx.bin_dir / app for app in PKG["pylint"]["apps"]] app_paths = pycowsay_app_paths + pylint_app_paths man_page_paths = pycowsay_man_page_paths assert not run_pipx_cli(["install", PKG["pycowsay"]["spec"]]) assert not run_pipx_cli(["inject", "--include-apps", "pycowsay", PKG["pylint"]["spec"]]) for app_path in app_paths: assert app_path.exists() for man_page_path in man_page_paths: assert man_page_path.exists() assert not run_pipx_cli(["uninstall", "pycowsay"]) for app_path in app_paths: assert not file_or_symlink(app_path) for man_page_path in man_page_paths: assert not file_or_symlink(man_page_path) @pytest.mark.parametrize("metadata_version", ["0.1"]) def test_uninstall_suffix_legacy_venv(pipx_temp_env, metadata_version): name = "pbr" # legacy uninstall on Windows only works with "canonical name characters" # in suffix suffix = "-a" executable_path = paths.ctx.bin_dir / app_name(f"{name}{suffix}") assert not run_pipx_cli(["install", PKG[name]["spec"], f"--suffix={suffix}"]) mock_legacy_venv(f"{name}{suffix}", metadata_version=metadata_version) assert executable_path.exists() assert not run_pipx_cli(["uninstall", f"{name}{suffix}"]) assert not file_or_symlink(executable_path) @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_uninstall_with_missing_interpreter(pipx_temp_env, metadata_version): executable_path = paths.ctx.bin_dir / app_name("pycowsay") assert not run_pipx_cli(["install", "pycowsay"]) assert executable_path.exists() mock_legacy_venv("pycowsay", metadata_version=metadata_version) remove_venv_interpreter("pycowsay") assert not run_pipx_cli(["uninstall", "pycowsay"]) # On Windows we cannot remove app binaries if no metadata and no python if not (sys.platform.startswith("win") and metadata_version is None): assert not file_or_symlink(executable_path) @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_uninstall_proper_dep_behavior(pipx_temp_env, metadata_version): # isort is a dependency of pylint. Make sure that uninstalling pylint # does not also uninstall isort app in LOCAL_BIN_DIR isort_app_paths = [paths.ctx.bin_dir / app for app in PKG["isort"]["apps"]] pylint_app_paths = [paths.ctx.bin_dir / app for app in PKG["pylint"]["apps"]] assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) assert not run_pipx_cli(["install", PKG["isort"]["spec"]]) mock_legacy_venv("pylint", metadata_version=metadata_version) mock_legacy_venv("isort", metadata_version=metadata_version) for pylint_app_path in pylint_app_paths: assert pylint_app_path.exists() for isort_app_path in isort_app_paths: assert isort_app_path.exists() assert not run_pipx_cli(["uninstall", "pylint"]) for pylint_app_path in pylint_app_paths: assert not file_or_symlink(pylint_app_path) # THIS is what we're making sure is true: for isort_app_path in isort_app_paths: assert isort_app_path.exists() @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_uninstall_proper_dep_behavior_missing_interpreter(pipx_temp_env, metadata_version): # isort is a dependency of pylint. Make sure that uninstalling pylint # does not also uninstall isort app in LOCAL_BIN_DIR isort_app_paths = [paths.ctx.bin_dir / app for app in PKG["isort"]["apps"]] pylint_app_paths = [paths.ctx.bin_dir / app for app in PKG["pylint"]["apps"]] assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) assert not run_pipx_cli(["install", PKG["isort"]["spec"]]) mock_legacy_venv("pylint", metadata_version=metadata_version) mock_legacy_venv("isort", metadata_version=metadata_version) remove_venv_interpreter("pylint") remove_venv_interpreter("isort") for pylint_app_path in pylint_app_paths: assert pylint_app_path.exists() for isort_app_path in isort_app_paths: assert isort_app_path.exists() assert not run_pipx_cli(["uninstall", "pylint"]) # Do not check the following on Windows without metadata, we do not # remove bin dir links by design for missing interpreter in that case if not (sys.platform.startswith("win") and metadata_version is None): for pylint_app_path in pylint_app_paths: assert not file_or_symlink(pylint_app_path) # THIS is what we're making sure is true: for isort_app_path in isort_app_paths: assert isort_app_path.exists() pipx-1.6.0/tests/test_uninstall_all.py000066400000000000000000000011331462701651400201160ustar00rootroot00000000000000import pytest # type: ignore[import-not-found] from helpers import PIPX_METADATA_LEGACY_VERSIONS, mock_legacy_venv, run_pipx_cli def test_uninstall_all(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["uninstall-all"]) @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_uninstall_all_legacy_venv(pipx_temp_env, capsys, metadata_version): assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) assert not run_pipx_cli(["uninstall-all"]) pipx-1.6.0/tests/test_unpin.py000066400000000000000000000033771462701651400164220ustar00rootroot00000000000000from helpers import run_pipx_cli from package_info import PKG def test_unpin(capsys, pipx_temp_env, caplog): assert not run_pipx_cli(["install", PKG["nox"]["spec"]]) assert not run_pipx_cli(["pin", "nox"]) assert not run_pipx_cli(["unpin", "nox"]) assert not run_pipx_cli(["upgrade", "nox"]) captured = capsys.readouterr() assert "nox is already at latest version" in captured.out def test_unpin_with_suffix(capsys, pipx_temp_env): assert not run_pipx_cli(["install", PKG["black"]["spec"], "--suffix", "@1"]) assert not run_pipx_cli(["pin", "black@1"]) assert not run_pipx_cli(["unpin", "black@1"]) captured = capsys.readouterr() assert "Unpinned 1 packages in venv black@1" in captured.out assert not run_pipx_cli(["upgrade", "black@1"]) captured = capsys.readouterr() assert "upgraded package black@1 from 22.8.0 to 22.10.0" in captured.out def test_unpin_warning(capsys, pipx_temp_env, caplog): assert not run_pipx_cli(["install", PKG["nox"]["spec"]]) assert not run_pipx_cli(["pin", "nox"]) assert not run_pipx_cli(["unpin", "nox"]) assert not run_pipx_cli(["unpin", "nox"]) assert "No packages to unpin in venv nox" in caplog.text def test_unpin_not_installed_package(capsys, pipx_temp_env): assert run_pipx_cli(["unpin", "abc"]) captured = capsys.readouterr() assert "Package abc is not installed" in captured.err def test_unpin_injected_packages(capsys, pipx_temp_env): assert not run_pipx_cli(["install", "black"]) assert not run_pipx_cli(["inject", "black", "nox", "pylint"]) assert not run_pipx_cli(["pin", "black"]) assert not run_pipx_cli(["unpin", "black"]) captured = capsys.readouterr() assert "Unpinned 3 packages in venv black" in captured.out pipx-1.6.0/tests/test_upgrade.py000066400000000000000000000112201462701651400167020ustar00rootroot00000000000000import pytest # type: ignore[import-not-found] from helpers import PIPX_METADATA_LEGACY_VERSIONS, mock_legacy_venv, run_pipx_cli, skip_if_windows from package_info import PKG def test_upgrade(pipx_temp_env, capsys): assert run_pipx_cli(["upgrade", "pycowsay"]) captured = capsys.readouterr() assert "Package is not installed" in captured.err assert not run_pipx_cli(["install", "pycowsay"]) captured = capsys.readouterr() assert "installed package pycowsay" in captured.out assert not run_pipx_cli(["upgrade", "pycowsay"]) captured = capsys.readouterr() assert "pycowsay is already at latest version" in captured.out @skip_if_windows def test_upgrade_global(pipx_temp_env, capsys): assert run_pipx_cli(["upgrade", "--global", "pycowsay"]) captured = capsys.readouterr() assert "Package is not installed" in captured.err assert not run_pipx_cli(["install", "--global", "pycowsay"]) captured = capsys.readouterr() assert "installed package pycowsay" in captured.out assert not run_pipx_cli(["upgrade", "--global", "pycowsay"]) captured = capsys.readouterr() assert "pycowsay is already at latest version" in captured.out @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_upgrade_legacy_venv(pipx_temp_env, capsys, metadata_version): assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) captured = capsys.readouterr() if metadata_version is None: assert run_pipx_cli(["upgrade", "pycowsay"]) captured = capsys.readouterr() assert "Not upgrading pycowsay. It has missing internal pipx metadata." in captured.err else: assert not run_pipx_cli(["upgrade", "pycowsay"]) captured = capsys.readouterr() def test_upgrade_suffix(pipx_temp_env, capsys): name = "pycowsay" suffix = "_a" assert not run_pipx_cli(["install", name, f"--suffix={suffix}"]) assert run_pipx_cli(["upgrade", f"{name}"]) assert not run_pipx_cli(["upgrade", f"{name}{suffix}"]) @pytest.mark.parametrize("metadata_version", ["0.1"]) def test_upgrade_suffix_legacy_venv(pipx_temp_env, capsys, metadata_version): name = "pycowsay" suffix = "_a" assert not run_pipx_cli(["install", name, f"--suffix={suffix}"]) mock_legacy_venv(f"{name}{suffix}", metadata_version=metadata_version) assert run_pipx_cli(["upgrade", f"{name}"]) assert not run_pipx_cli(["upgrade", f"{name}{suffix}"]) def test_upgrade_specifier(pipx_temp_env, capsys): name = "pylint" pkg_spec = PKG[name]["spec"] initial_version = pkg_spec.split("==")[-1] assert not run_pipx_cli(["install", f"{pkg_spec}"]) assert not run_pipx_cli(["upgrade", f"{name}"]) captured = capsys.readouterr() assert f"upgraded package {name} from {initial_version} to" in captured.out def test_upgrade_include_injected(pipx_temp_env, capsys): assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) assert not run_pipx_cli(["inject", "pylint", PKG["black"]["spec"]]) captured = capsys.readouterr() assert not run_pipx_cli(["upgrade", "--include-injected", "pylint"]) captured = capsys.readouterr() assert "upgraded package pylint" in captured.out assert "upgraded package black" in captured.out def test_upgrade_no_include_injected(pipx_temp_env, capsys): assert not run_pipx_cli(["install", PKG["pylint"]["spec"]]) assert not run_pipx_cli(["inject", "pylint", PKG["black"]["spec"]]) captured = capsys.readouterr() assert not run_pipx_cli(["upgrade", "pylint"]) captured = capsys.readouterr() assert "upgraded package pylint" in captured.out assert "upgraded package black" not in captured.out def test_upgrade_install_missing(pipx_temp_env, capsys): assert not run_pipx_cli(["upgrade", "pycowsay", "--install"]) captured = capsys.readouterr() assert "installed package pycowsay" in captured.out def test_upgrade_multiple(pipx_temp_env, capsys): name = "pylint" pkg_spec = PKG[name]["spec"] initial_version = pkg_spec.split("==")[-1] assert not run_pipx_cli(["install", pkg_spec]) assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["upgrade", name, "pycowsay"]) captured = capsys.readouterr() assert f"upgraded package {name} from {initial_version} to" in captured.out assert "pycowsay is already at latest version" in captured.out def test_upgrade_absolute_path(pipx_temp_env, capsys, root): assert run_pipx_cli(["upgrade", "--verbose", str((root / "testdata" / "empty_project").resolve())]) captured = capsys.readouterr() assert "Package cannot be a URL" not in captured.err pipx-1.6.0/tests/test_upgrade_all.py000066400000000000000000000021411462701651400175340ustar00rootroot00000000000000import pytest # type: ignore[import-not-found] from helpers import PIPX_METADATA_LEGACY_VERSIONS, mock_legacy_venv, run_pipx_cli def test_upgrade_all(pipx_temp_env, capsys): assert run_pipx_cli(["upgrade", "pycowsay"]) assert not run_pipx_cli(["install", "pycowsay"]) assert not run_pipx_cli(["upgrade-all"]) def test_upgrade_all_none(pipx_temp_env, capsys): assert not run_pipx_cli(["upgrade-all"]) captured = capsys.readouterr() assert "No packages upgraded after running 'pipx upgrade-all'" in captured.out @pytest.mark.parametrize("metadata_version", PIPX_METADATA_LEGACY_VERSIONS) def test_upgrade_all_legacy_venv(pipx_temp_env, capsys, caplog, metadata_version): assert run_pipx_cli(["upgrade", "pycowsay"]) assert not run_pipx_cli(["install", "pycowsay"]) mock_legacy_venv("pycowsay", metadata_version=metadata_version) if metadata_version is None: capsys.readouterr() assert run_pipx_cli(["upgrade-all"]) assert "The following package(s) failed to upgrade: pycowsay" in caplog.text else: assert not run_pipx_cli(["upgrade-all"]) pipx-1.6.0/tests/test_upgrade_shared.py000066400000000000000000000054011462701651400202340ustar00rootroot00000000000000import subprocess import pytest # type: ignore[import-not-found] from helpers import run_pipx_cli @pytest.fixture def shared_libs(pipx_ultra_temp_env): # local import to get the shared_libs object patched by fixtures from pipx.shared_libs import shared_libs as _shared_libs yield _shared_libs def test_upgrade_shared(shared_libs, capsys, caplog): assert shared_libs.has_been_updated_this_run is False assert shared_libs.is_valid is False assert run_pipx_cli(["upgrade-shared", "-v"]) == 0 captured = capsys.readouterr() assert "creating shared libraries" in captured.err assert "upgrading shared libraries" in captured.err assert "Upgrading shared libraries in" in caplog.text assert "Already upgraded libraries in" not in caplog.text assert shared_libs.has_been_updated_this_run is True assert shared_libs.is_valid is True shared_libs.has_been_updated_this_run = False assert run_pipx_cli(["upgrade-shared", "-v"]) == 0 captured = capsys.readouterr() assert "creating shared libraries" not in captured.err assert "upgrading shared libraries" in captured.err assert "Upgrading shared libraries in" in caplog.text assert "Already upgraded libraries in" not in caplog.text assert shared_libs.has_been_updated_this_run is True assert run_pipx_cli(["upgrade-shared", "-v"]) == 0 assert "Already upgraded libraries in" in caplog.text def test_upgrade_shared_pip_args(shared_libs, capsys, caplog): assert shared_libs.has_been_updated_this_run is False assert shared_libs.is_valid is False assert run_pipx_cli(["upgrade-shared", "-v", "--pip-args='--no-index'"]) == 1 captured = capsys.readouterr() assert "creating shared libraries" in captured.err assert "upgrading shared libraries" in captured.err assert "Upgrading shared libraries in" in caplog.text assert "Already upgraded libraries in" not in caplog.text assert shared_libs.has_been_updated_this_run is False assert shared_libs.is_valid is True def test_upgrade_shared_pin_pip(shared_libs): def pip_version(): cmd = "from importlib.metadata import version; print(version('pip'))" ret = subprocess.run([shared_libs.python_path, "-c", cmd], check=True, capture_output=True, text=True) return ret.stdout.strip() assert shared_libs.has_been_updated_this_run is False assert shared_libs.is_valid is False assert run_pipx_cli(["upgrade-shared", "-v", "--pip-args=pip==24.0"]) == 0 assert shared_libs.is_valid is True assert pip_version() == "24.0" shared_libs.has_been_updated_this_run = False # reset for next run assert run_pipx_cli(["upgrade-shared", "-v", "--pip-args=pip==23.3.2"]) == 0 assert shared_libs.is_valid is True assert pip_version() == "23.3.2"