pex-1.1.14/0000755000076500000240000000000012743552145013213 5ustar kwilsonstaff00000000000000pex-1.1.14/CHANGES.rst0000644000076500000240000005574012743540453015027 0ustar kwilsonstaff00000000000000Release Notes ============= 1.1.14 ------ * Repair Executor error handling for other classes of IOError/OSError. (#292) `#292 `_ * Fix bdist_pex --pex-args. (#285) `#285 `_ * Inherit user site with --inherit-path. (#284) `#284 `_ 1.1.13 ------ * Repair passing of stdio kwargs to PEX.run(). (#288) `#288 `_ 1.1.12 ------ * Fix bdist_pex interpreter cache directory. (#286) `#286 `_ * Normalize and edify subprocess execution. (#255) `#255 `_ * Don't ignore exit codes when using setuptools entry points. (#280) `#280 `_ `Fixes #137 `_ 1.1.11 ------ * Update cache dir when bdist_pex.run is called directly. `#278 `_ `Fixes #274 `_ 1.1.10 ------ * Improve failure modes for os.rename() as used in distribution caching. `#271 `_ `Fixes #265 `_ 1.1.9 ----- * Bugfix: Open setup.py in binary mode. `#264 `_ `Fixes #263 `_ 1.1.8 ----- * Bugfix: Repair a regression in `--disable-cache`. `#261 `_ `Fixes #260 `_ 1.1.7 ----- * Add README and supported python versions to PyPI description. `#258 `_ * Use `open` with utf-8 support. `#231 `_ * Add `--pex-root` option. `#206 `_ 1.1.6 ----- This release is a quick fix for a regression that inadvertently went out in 1.1.5 (Issue #243). * Fix the ``bdist_pex`` ``setuptools`` command to work for python2. `#246 `_ `Fixes #243 `_ * Upgrade pex dependencies on ``setuptools`` and ``wheel``. `#244 `_ `Fixes #238 `_ 1.1.5 ----- * Fix ``PEXBuilder.clone`` and thus ``bdist_pex --pex-args`` for ``--python`` and ``--python-shebang``. `#234 `_ `Fixes #233 `_ * Fix old ``pkg_resources`` egg version normalization. `#227 `_ `Fixes #226 `_ * Fix the ``inherit_path`` handling. `#224 `_ * Fix handling of bad distribution script names when used as the pex entrypoint. `#221 `_ `Fixes #220 `_ 1.1.4 ----- This release is a quick fix for a regression that inadvertently went out in 1.1.3 (Issue #216). * Add a test for the regression in ``FixedEggMetadata._zipinfo_name`` and revert the breaking commit. `Fixes #216 `_ 1.1.3 ----- This release includes an initial body of work towards Windows support, ABI tag support for CPython 2.x and a fix for version number normalization. * Add python 2.x abi tag support. `#214 `_ `Fixes #213 `_ * Add .idea to .gitignore. `#205 `_ * Don't normalize version numbers as names. `#204 `_ * More fixes for windows. `#202 `_ * Fixes to get pex to work on windows. `#198 `_ 1.1.2 ----- * Bump setuptools & wheel version pinning. `#194 `_ * Unescape html in PageParser.href_match_to_url. `#191 `_ * Memoize calls to Crawler.crawl() for performance win in find-links based resolution. `#187 `_ 1.1.1 ----- * Fix infinite recursion when ``PEX_PYTHON`` points at a symlink. `#182 `_ * Add ``/etc/pexrc`` to the list of pexrc locations to check. `#183 `_ * Improve error messaging for platform constrained Untranslateable errors. `#179 `_ 1.1.0 ----- * Add support for ``.pexrc`` files for influencing the pex environment. See the notes `here `_. `#128 `_. * Bug fix: PEX_PROFILE_FILENAME and PEX_PROFILE_SORT were not respected. `#154 `_. * Adds the ``bdist_pex`` command to setuptools. `#99 `_. * Bug fix: We did not normalize package names in ``ResolvableSet``, so it was possible to depend on ``sphinx`` and ``Sphinx-1.4a0.tar.gz`` and get two versions build and included into the pex. `#147 `_. * Adds a pex-identifying User-Agent. `#101 `_. 1.0.3 ----- * Bug fix: Accommodate OSX ``Python`` python binaries. Previously the OSX python distributions shipped with OSX, XCode and available via https://www.python.org/downloads/ could fail to be detected using the ``PythonInterpreter`` class. Fixes `#144 `_. * Bug fix: PEX_SCRIPT failed when the script was from a not-zip-safe egg. Original PR `#139 `_. * Bug fix: ``sys.exit`` called without arguments would cause `None` to be printed on stderr since pex 1.0.1. `#143 `_. 1.0.2 ----- * Bug fix: PEX-INFO values were overridden by environment ``Variables`` with default values that were not explicitly set in the environment. Fixes `#135 `_. * Bug fix: Since `69649c1 `_ we have been unpatching the side-effects of ``sys.modules`` after ``PEX.execute``. This takes all modules imported during the PEX lifecycle and sets all their attributes to ``None``. Unfortunately, ``sys.excepthook``, ``atexit`` and ``__del__`` may still try to operate using these tainted modules, causing exceptions on interpreter teardown. This reverts just the ``sys`` unpatching so that the abovementioned teardown hooks behave more predictably. Fixes `#141 `_. 1.0.1 ----- * Allow PEXBuilder to optionally copy files into the PEX environment instead of hard-linking them. * Allow PEXBuilder to optionally skip precompilation of .py files into .pyc files. * Bug fix: PEXBuilder did not respect the target interpreter when compiling source to bytecode. Fixes `#127 `_. * Bug fix: Fix complex resolutions when using a cache. Fixes: `#120 `_. 1.0.0 ----- The 1.0.0 release of pex introduces a few breaking changes: ``pex -r`` now takes requirements.txt files instead of requirement specs, ``pex -s`` has now been removed since source specs are accepted as arguments, and ``pex -p`` has been removed in favor of its alias ``pex -o``. The pex *command line interface* now adheres to semver insofar as backwards incompatible CLI changes will invoke a major version change. Any backwards incompatible changes to the PEX environment variable semantics will also result in a major version change. The pex *API* adheres to semver insofar as backwards incompatible API changes will invoke minor version changes. For users of the PEX API, it is recommended to add minor version ranges, e.g. ``pex>=1.0,<1.1``. For users of the PEX CLI, major version ranges such as ``pex>=1,<2`` should be sufficient. * BREAKING CHANGE: Removes the ``-s`` option in favor of specifying directories directly as arguments to the pex command line. * BREAKING CHANGE: ``pex -r`` now takes requirements.txt filenames and *not* requirement specs. Requirement specs are now passed as arguments to the pex tool. Use ``--`` to escape command line arguments passed to interpreters spawned by pex. Implements `#5 `_. * Adds a number of flag aliases to be more compatible with pip command lines: ``--no-index``, ``-f``, ``--find-links``, ``--index-url``, ``--no-use-wheel``. Removes ``-p`` in favor of ``-o`` exclusively. * Adds ``--python-shebang`` option to the pex tool in order to set the ``#!`` shebang to an exact path. `#53 `_. * Adds support for ``PEX_PYTHON`` environment variable which will cause the pex file to reinvoke itself using the interpreter specified, e.g. ``PEX_PYTHON=python3.4`` or ``PEX_PYTHON=/exact/path/to/interpreter``. `#27 `_. * Adds support for ``PEX_PATH`` environment variable which allows merging of PEX environments at runtime. This can be used to inject plugins or entry_points or modules from one PEX into another without explicitly building them together. `#30 `_. * Consolidates documentation of ``PEX_`` environment variables and adds the ``--help-variables`` option to the pex client. Partially addresses `#13 `_. * Adds helper method to dump a package subdirectory onto disk from within a zipped PEX file. This can be useful for applications that know they're running within a PEX and would prefer some static assets dumped to disk instead of running as an unzipped PEX file. `#12 `_. * Now supports extras for static URLs and installable directories. `#65 `_. * Adds ``-m`` and ``--entry-point`` alias to the existing ``-e`` option for entry points in the pex tool to evoke the similarity to ``python -m``. * Adds console script support via ``-c/--script/--console-script`` and ``PEX_SCRIPT``. This allows you to reference the named entry point instead of the exact ``module:name`` pair. Also supports scripts defined in the ``scripts`` section of setup.py. `#59 `_. * Adds more debugging information when encountering unresolvable requirements. `#79 `_. * Bug fix: ``PEX_COVERAGE`` and ``PEX_PROFILE`` did not function correctly when SystemExit was raised. Fixes `#81 `_. * Bug fix: Fixes caching in the PEX tool since we don't cache the source distributions of installable directories. `#24 `_. 0.9.0 ----- This is the last release before the 1.0.0 development branch is started. * Change the setuptools range to >=2.2,<16 by handling EntryPoint changes as well as being flexible on whether ``pkg_resources`` is a package or a module. Fixes `#55 `_ and `#34 `_. * Adds option groups to the pex tool to make the help output slightly more readable. * Bug fix: Make ``pip install pex`` work better by removing ``extras_requires`` on the ``console_script`` entry point. Fixes `#48 `_ * New feature: Adds an interpreter cache to the ``pex`` tool. If the user does not explicitly disable the wheel feature and attempts to build a pex with wheels but does not have the wheel package installed, pex will download it in order to make the feature work. Implements `#47 `_ in order to fix `#48 `_ 0.8.6 ----- * Bug fix: Honor installed sys.excepthook in pex teardown. `RB #1733 `_ * Bug fix: ``UrllibContext`` used ``replace`` as a keyword argument for ``bytes.decode`` but this only works on Python 3. `Pull Request #46 `_ 0.8.5 ----- * Bug fix: Fixup string formatting in pex/bin/pex.py to support Python 2.6 `Pull Request #40 `_ 0.8.4 ----- * Performance improvement: Speed up the best-case scenario of dependency resolution. `RB #1685 `_ * Bug fix: Change from ``uuid4().get_hex()`` to ``uuid4().hex`` to maintain Python3 compatibility of pex.common. `Pull Request #39 `_ * Bug fix: Actually cache the results of translation. Previously bdist translations would be created in a temporary directory even if a cache location was specified. `RB #1666 `_ * Bug fix: Support all potential abi tag permutations when determining platform compatibility. `Pull Request #33 `_ 0.8.3 ----- * Performance improvement: Don't always write packages to disk if they've already been cached. This can significantly speed up launching PEX files with a large number of non-zip-safe dependencies. `RB #1642 `_ 0.8.2 ----- * Bug fix: Allow pex 0.8.x to parse pex files produced by earlier versions of pex and twitter.common.python. * Pin pex to setuptools prior to 9.x until we have a chance to make changes related to PEP440 and the change of pkg_resources.py to a package. 0.8.1 ----- * Bug fix: Fix issue where it'd be possible to ``os.path.getmtime`` on a remote ``Link`` object `Issue #29 `_ 0.8.0 ----- * *API change*: Decouple translation from package iteration. This removes the Obtainer construct entirely, which likely means if you're using PEX as a library, you will need to change your code if you were doing anything nontrivial. This adds a couple new options to ``resolve`` but simplifies the story around how to cache packages. `RB #785 `_ * Refactor http handling in pex to allow for alternate http implementations. Adds support for `requests `_, improving both performance and security. For more information, read the commit notes at `91c7f32 `_. `RB #778 `_ * Improvements to API documentation throughout. * Renamed ``Tracer`` to ``TraceLogger`` to prevent nondeterministic isort ordering. * Refactor tox.ini to increase the number of environment combinations and improve coverage. * Adds HTTP retry support for the RequestsContext. `RB #1303 `_ * Make pex --version correct. `Issue #19 `_ * Bug fix: Fix over-aggressive sys.modules scrubbing for namespace packages. Under certain circumstances, namespace packages in site-packages could conflict with packages within a PEX, causing them to fail importing. `RB #1378 `_ * Bug fix: Replace uses of ``os.unsetenv(...)`` with ``del os.environ[...]`` `Pull Request #11 `_ * Bug fix: Scrub sys.path and sys.modules based upon both supplied path and realpath of files and directories. Newer versions of virtualenv on Linux symlink site-packages which caused those packages to not be removed from sys.path correctly. `Issue #21 `_ * Bug fix: The pex -s option was not correctly pulling in transitive dependencies. `Issue #22 `_ * Bug fix: Adds ``content`` method to HTTP contexts that does HTML content decoding, fixing an encoding issue only experienced when using Python 3. `Issue #10 `_ 0.7.0 ----- * Rename ``twitter.common.python`` to ``pex`` and split out from the `twitter/commons `_ repo. 0.6.0 ----- * Change the interpretation of ``-i`` (and of PyPIFetcher's pypi_base) to match pip's ``-i``. This is useful for compatibility with devpi. 0.5.10 ------ * Ensures that .egg/.whl distributions on disk have their mtime updated even though we no longer overwrite them. This gives them a new time lease against their ttl. Without this change, once a distribution aged past the ttl it would never be used again, and builds would re-create the same distributions in tmpdirs over and over again. 0.5.9 ----- * Fixes an issue where SourceTranslator would overwrite .egg/.whl distributions already on disk. Instead it should always check to see if a copy already exists and reuse if there. This ordinarily should not be a problem but the zipimporter caches metadata by filename instead of stat/sha, so if the underlying contents changed a runtime error would be thrown due to seemingly corrupt zip file offsets. `RB #684 `_ 0.5.8 ----- * Adds ``-i/--index`` option to the pex tool. 0.5.7 ----- * Adds ``twitter.common.python.pex_bootstrap`` ``bootstrap_pex_env`` function in order to initialize a PEX environment from within a python interpreter. (Patch contributed by @kwlzn) * Adds stdin=,stdout=,stderr= keyword parameters to the ``PEX.run`` function. (Patch from @benjy) 0.5.6 ----- * The crawler now defaults to not follow links for security reasons. (Before the default behavior was to implicitly ``--follow-links`` for all requirements.) `RB #293 `_ 0.5.5 ----- * Improves scrubbing of site-packages from PEX environments. `RB #289 `_ 0.5.1 - 0.5.4 ------------- * Silences exceptions reported during interpreter teardown (the exceptions resulting from incorrect atexit handler behavior) introduced by 0.4.3 `RB #253 `_ `RB #249 `_ * Adds ``__hash__`` to ``Link`` so that Packages are hashed correctly in ``twitter.common.python.resolver`` ``resolve`` 0.5.0 ----- * Adds wheel support to ``twitter.common.python`` `RB #94 `_ `RB #154 `_ `RB #148 `_ 0.4.3 ----- * Adds ``twitter.common.python.finders`` which are additional finders for setuptools including: - find eggs within a .zip - find wheels within a directory - find wheels within a .zip `RB #86 `_ * Adds a new Package abstraction by refactoring Link into Link and Package. `RB #92 `_ * Adds support for PEP425 tagging necessary for wheel support. `RB #87 `_ * Improves python environment isolation by correctly scrubbing namespace packages injected into module ``__path__`` attributes by nspkg pth files. `RB #116 `_ * Adds ``twitter.common.python.resolver`` ``resolve`` method that handles transitive dependency resolution better. This means that if the requirement ``futures==2.1.2`` and an unqualified ``futures>=2`` is pulled in transitively, our resolver will correctly resolve futures 2.1.2 instead of reporting a VersionConflict if any version newer than 2.1.2 is available. `RB #129 `_ * Factors all ``twitter.common.python`` test helpers into ``twitter.common.python.testing`` `RB #91 `_ * Bug fix: Fix ``OrderedSet`` atexit exceptions `RB #147 `_ * Bug fix: Fix cross-device symlinking (patch from @benjy) * Bug fix: Raise a ``RuntimeError`` if we fail to write ``pkg_resources`` into a .pex `RB #115 `_ 0.4.2 ----- * Upgrade to ``setuptools>=1`` 0.4.1 ----- * ``twitter.common.python`` is no longer a namespace package 0.4.0 ----- * Kill the egg distiller. We now delegate .egg generation to bdist_egg. `RB #55 `_ 0.3.1 ----- * Short-circuit resolving a distribution if a local exact match is found. `RB #47 `_ * Correctly patch the global ``pkg_resources`` ``WorkingSet`` for the lifetime of the Python interpreter. `RB #52 `_ * Fixes a performance regression in setuptools ``build_zipmanifest`` `Setuptools Issue #154 `_ `RB #53 `_ 0.3.0 ----- * Plumb through the ``--zip-safe``, ``--always-write-cache``, ``--ignore-errors`` and ``--inherit-path`` flags to the pex tool. * Delete the unused ``PythonDirWrapper`` code. * Split ``PEXEnvironment`` resolution into ``twitter.common.python.environment`` and deconflate ``WorkingSet``/``Environment`` state. * Removes the monkeypatched zipimporter in favor of keeping all eggs unzipped within PEX files. Refactors the PEX dependency cache in ``util.py`` * Adds interpreter detection for Jython and PyPy. * Dependency translation errors should be made uniform. (Patch from @johnsirois) * Adds ``PEX_PROFILE_ENTRIES`` to limit the number of entries reported when ``PEX_PROFILE`` is enabled. (Patch from @rgs_) * Bug fix: Several fixes to error handling in ``twitter.common.python.http`` (From Marc Abramowitz) * Bug fix: PEX should not always assume that ``$PATH`` was available. (Patch from @jamesbroadhead) * Bug fix: Filename should be part of the .pex cache key or else multiple identical versions will incorrectly resolve (Patch from @tc) * Bug fix: Executed entry points shouldn't be forced to run in an environment with ``__future__`` imports enabled. (Patch from @lawson_patrick) * Bug fix: Detect versionless egg links and fail fast. (Patch from @johnsirois.) * Bug fix: Handle setuptools>=2.1 correctly in the zipimport monkeypatch (Patch from @johnsirois.) 0.2.3 ----- * Bug fix: Fix handling of Fetchers with ``file://`` urls. 0.2.2 ----- * Adds the pex tool as a standalone tool. 0.2.1 ----- * Bug fix: Bootstrapped ``twitter.common.python`` should declare ``twitter.common`` as a namespace package. 0.2.0 ----- * Make ``twitter.common.python`` fully standalone by consolidating external dependencies within ``twitter.common.python.common``. 0.1.0 ----- * Initial published version of ``twitter.common.python``. pex-1.1.14/docs/0000755000076500000240000000000012743552145014143 5ustar kwilsonstaff00000000000000pex-1.1.14/docs/api/0000755000076500000240000000000012743552145014714 5ustar kwilsonstaff00000000000000pex-1.1.14/docs/api/index.rst0000644000076500000240000000454012623452313016551 0ustar kwilsonstaff00000000000000PEX API Reference ================= Module contents --------------- .. automodule:: pex :members: :show-inheritance: pex.crawler module ------------------------ .. automodule:: pex.crawler :members: :show-inheritance: pex.environment module ---------------------- .. automodule:: pex.environment :members: :show-inheritance: pex.fetcher module ------------------ .. automodule:: pex.fetcher :members: :show-inheritance: pex.finders module ------------------ .. automodule:: pex.finders :members: :show-inheritance: pex.http module -------------------- .. automodule:: pex.http :members: :show-inheritance: pex.installer module -------------------- .. automodule:: pex.installer :members: :show-inheritance: pex.interpreter module ---------------------- .. automodule:: pex.interpreter :members: :show-inheritance: pex.iterator module ---------------------- .. automodule:: pex.iterator :members: :show-inheritance: pex.link module ---------------------- .. automodule:: pex.link :members: :show-inheritance: pex.package module ------------------ .. automodule:: pex.package :members: :show-inheritance: pex.pep425 module ----------------- .. automodule:: pex.pep425 :members: :show-inheritance: pex.pex module -------------- .. automodule:: pex.pex :members: :show-inheritance: pex.pex_builder module ---------------------- .. automodule:: pex.pex_builder :members: :show-inheritance: pex.pex_info module ------------------- .. automodule:: pex.pex_info :members: :show-inheritance: pex.platforms module -------------------- .. automodule:: pex.platforms :members: :show-inheritance: pex.resolver module ------------------- .. automodule:: pex.resolver :members: :show-inheritance: pex.testing module ------------------ .. automodule:: pex.testing :members: :show-inheritance: pex.tracer module ----------------- .. automodule:: pex.tracer :members: :show-inheritance: pex.translator module --------------------- .. automodule:: pex.translator :members: :show-inheritance: pex.util module --------------- .. automodule:: pex.util :members: :show-inheritance: pex.variables module -------------------- .. _PexVariables: .. automodule:: pex.variables :members: :show-inheritance: pex-1.1.14/docs/buildingpex.rst0000644000076500000240000003601712623452313017207 0ustar kwilsonstaff00000000000000.. _buildingpex: Building .pex files =================== The easiest way to build .pex files is with the ``pex`` utility, which is made available when you ``pip install pex``. Do this within a virtualenv, then you can use pex to bootstrap itself: .. code-block:: bash $ pex pex requests -c pex -o ~/bin/pex This command creates a pex file containing pex and requests, using the console script named "pex", saving it in ~/bin/pex. At this point, assuming ~/bin is on your $PATH, then you can use pex in or outside of any virtualenv. The second easiest way to build .pex files is using the ``bdist_pex`` setuptools command which is available if you ``pip install pex``. For example, to clone and build pip from source: .. code-block:: bash $ git clone https://github.com/pypa/pip && cd pip $ python setup.py bdist_pex running bdist_pex Writing pip to dist/pip-7.2.0.dev0.pex Both are described in more detail below. Invoking the ``pex`` utility ============================ The ``pex`` utility has no required arguments and by default will construct an empty environment and invoke it. When no entry point is specified, "invocation" means starting an interpreter: .. code-block:: bash $ pex Python 2.6.9 (unknown, Jan 2 2014, 14:52:48) [GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> This creates an ephemeral environment that only exists for the duration of the ``pex`` command invocation and is garbage collected immediately on exit. You can tailor which interpreter is used by specifying ``--python=PATH``. PATH can be either the absolute path of a Python binary or the name of a Python interpreter within the environment, e.g.: .. code-block:: bash $ pex --python=python3.3 Python 3.3.3 (default, Jan 2 2014, 14:57:01) [GCC 4.2.1 Compatible Apple Clang 4.0 ((tags/Apple/clang-421.0.60))] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> print "this won't work!" File "", line 1 print "this won't work!" ^ SyntaxError: invalid syntax Specifying requirements ----------------------- Requirements are specified using the same form as expected by ``pip`` and ``setuptools``, e.g. ``flask``, ``setuptools==2.1.2``, ``Django>=1.4,<1.6``. These are specified as arguments to pex and any number (including 0) may be specified. For example, to start an environment with ``flask`` and ``psutil>1``: .. code-block:: bash $ pex flask 'psutil>1' Python 2.6.9 (unknown, Jan 2 2014, 14:52:48) [GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> You can then import and manipulate modules like you would otherwise: .. code-block:: bash >>> import flask >>> import psutil >>> ... Requirements can also be specified using the requirements.txt format, using ``pex -r``. This can be a handy way to freeze a virtualenv into a PEX file: .. code-block:: bash $ pex -r <(pip freeze) -o my_application.pex Specifying entry points ----------------------- Entry points define how the environment is executed and may be specified in one of three ways. pex -- script.py ~~~~~~~~~~~~~~~~~~~~~~~~~~ As mentioned above, if no entry points are specified, the default behavior is to emulate an interpreter. First we create a simple flask application: .. code-block:: bash $ cat < flask_hello_world.py > from flask import Flask > app = Flask(__name__) > > @app.route('/') > def hello_world(): > return 'hello world!' > > app.run() > EOF Then, like an interpreter, if a source file is specified as a parameter to pex, it is invoked: .. code-block:: bash $ pex flask -- ./flask_hello_world.py * Running on http://127.0.0.1:5000/ pex -m ~~~~~~ Your code may be within the PEX file or it may be some predetermined entry point within the standard library. ``pex -m`` behaves very similarly to ``python -m``. Consider ``python -m pydoc``: .. code-block:: bash $ python -m pydoc pydoc - the Python documentation tool pydoc.py ... Show text documentation on something. may be the name of a Python keyword, topic, function, module, or package, or a dotted reference to a class or function within a module or module in a ... This can be emulated using the ``pex`` tool using ``-m pydoc``: .. code-block:: bash $ pex -m pydoc pydoc - the Python documentation tool tmpInGItD ... Show text documentation on something. may be the name of a Python keyword, topic, function, module, or package, or a dotted reference to a class or function within a module or module in a ... Arguments will be passed unescaped following ``--`` on the command line. So in order to get pydoc help on the ``flask.app`` package in Flask: .. code-block:: bash $ pex flask -m pydoc -- flask.app Help on module flask.app in flask: NAME flask.app FILE /private/var/folders/rd/_tjz8zts3g14md1kmf38z6w80000gn/T/tmp3PCy5a/.deps/Flask-0.10.1-py2-none-any.whl/flask/app.py DESCRIPTION flask.app ~~~~~~~~~ and so forth. Entry points can also take the form ``package:target``, such as ``sphinx:main`` or ``fabric.main:main`` for Sphinx and Fabric respectively. This is roughly equivalent to running a script that does ``from package import target; target()``. This can be a powerful way to invoke Python applications without ever having to ``pip install`` anything, for example a one-off invocation of Sphinx with the readthedocs theme available: .. code-block:: bash $ pex sphinx sphinx_rtd_theme -e sphinx:main -- --help Sphinx v1.2.2 Usage: /var/folders/4d/9tz0cd5n2n7947xs21gspsxc0000gp/T/tmpLr8ibZ [options] sourcedir outdir [filenames...] General options ^^^^^^^^^^^^^^^ -b builder to use; default is html -a write all files; default is to only write new and changed files -E don't use a saved environment, always read all files ... pex -c ~~~~~~ If you don't know the ``package:target`` for the console scripts of your favorite python packages, pex allows you to use ``-c`` to specify a console script as defined by the distribution. For example, Fabric provides the ``fab`` tool when pip installed: .. code-block:: bash $ pex Fabric -c fab -- --help Fatal error: Couldn't find any fabfiles! Remember that -f can be used to specify fabfile path, and use -h for help. Aborting. Even scripts defined by the "scripts" section of a distribution can be used, e.g. with boto: .. code-block:: bash $ pex boto -c mturk usage: mturk [-h] [-P] [--nicknames PATH] {bal,hit,hits,new,extend,expire,rm,as,approve,reject,unreject,bonus,notify,give-qual,revoke-qual} ... mturk: error: too few arguments Saving .pex files ----------------- Each of the commands above have been manipulating ephemeral PEX environments -- environments that only exist for the duration of the pex command lifetime and immediately garbage collected. If the ``-o PATH`` option is specified, a PEX file of the environment is saved to disk at ``PATH``. For example we can package a standalone Sphinx as above: .. code-block:: bash $ pex sphinx sphinx_rtd_theme -c sphinx -o sphinx.pex Instead of executing the environment, it is saved to disk: .. code-block:: bash $ ls -l sphinx.pex -rwxr-xr-x 1 wickman wheel 4988494 Mar 11 17:48 sphinx.pex This is an executable environment and can be executed as before: .. code-block:: bash $ ./sphinx.pex --help Sphinx v1.2.2 Usage: ./sphinx.pex [options] sourcedir outdir [filenames...] General options ^^^^^^^^^^^^^^^ -b builder to use; default is html -a write all files; default is to only write new and changed files -E don't use a saved environment, always read all files ... As before, entry points are not required, and if not specified the PEX will default to just dropping into an interpreter. If an alternate interpreter is specified with ``--python``, e.g. pypy, it will be the default hashbang in the PEX file: .. code-block:: bash $ pex --python=pypy flask -o flask-pypy.pex The hashbang of the PEX file specifies PyPy: .. code-block:: bash $ head -1 flask-pypy.pex #!/usr/bin/env pypy and when invoked uses the environment PyPy: .. code-block:: bash $ ./flask-pypy.pex Python 2.7.3 (87aa9de10f9c, Nov 24 2013, 20:57:21) [PyPy 2.2.1 with GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> import flask To specify an explicit Python shebang line (e.g. from a non-standard location or not on $PATH), you can use the ``--python-shebang`` option: .. code-block:: bash $ dist/pex --python-shebang='/Users/wickman/Python/CPython-3.4.2/bin/python3.4' -o my.pex $ head -1 my.pex #!/Users/wickman/Python/CPython-3.4.2/bin/python3.4 Furthermore, this can be manipulated at runtime using the ``PEX_PYTHON`` environment variable. Tailoring requirement resolution -------------------------------- In general, ``pex`` honors the same options as pip when it comes to resolving packages. Like pip, by default ``pex`` fetches artifacts from PyPI. This can be disabled with ``--no-index``. If PyPI fetching is disabled, you will need to specify a search repository via ``-f/--find-links``. This may be a directory on disk or a remote simple http server. For example, you can delegate artifact fetching and resolution to ``pip wheel`` for whatever reason -- perhaps you're running a firewalled mirror -- but continue to package with pex: .. code-block:: bash $ pip wheel -w /tmp/wheelhouse sphinx sphinx_rtd_theme $ pex -f /tmp/wheelhouse --no-index -e sphinx:main -o sphinx.pex sphinx sphinx_rtd_theme Tailoring PEX execution at build time ------------------------------------- There are a few options that can tailor how PEX environments are invoked. These can be found by running ``pex --help``. Every flag mentioned here has a corresponding environment variable that can be used to override the runtime behavior which can be set directly in your environment, or sourced from a ``.pexrc`` file (checking for ``~/.pexrc`` first, then for a relative ``.pexrc``). ``--zip-safe``/``--not-zip-safe`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Whether or not to treat the environment as zip-safe. By default PEX files are listed as zip safe. If ``--not-zip-safe`` is specified, the source of the PEX will be written to disk prior to invocation rather than imported via the zipimporter. NOTE: Distribution zip-safe bits will still be honored even if the PEX is marked as zip-safe. For example, included .eggs may be marked as zip-safe and invoked without the need to write to disk. Wheels are always marked as not-zip-safe and written to disk prior to PEX invocation. ``--not-zip-safe`` forces ``--always-write-cache``. ``--always-write-cache`` ~~~~~~~~~~~~~~~~~~~~~~~~ Always write all packaged dependencies within the PEX to disk prior to invocation. This forces the zip-safe bit of any dependency to be ignored. ``--inherit-path`` ~~~~~~~~~~~~~~~~~~ By default, PEX environments are completely scrubbed empty of any packages installed on the global site path. Setting ``--inherit-path`` allows packages within site-packages to be considered as candidate distributions to be included for the execution of this environment. This is strongly discouraged as it circumvents one of the biggest benefits of using .pex files, however there are some cases where it can be advantageous (for example if a package does not package correctly an an egg or wheel.) ``--ignore-errors`` ~~~~~~~~~~~~~~~~~~~ If not all of the PEX environment's dependencies resolve correctly (e.g. you are overriding the current Python interpreter with ``PEX_PYTHON``) this forces the PEX file to execute despite this. Can be useful in certain situations when particular extensions may not be necessary to run a particular command. ``--platform`` ~~~~~~~~~~~~~~ The platform to build the pex for. Right now it defaults to the current system, but you can specify something like ``linux-x86_64`` or ``macosx-10.6-x86_64``. This will look for bdists for the particular platform. Tailoring PEX execution at runtime ---------------------------------- Tailoring of PEX execution can be done at runtime by setting various environment variables. The source of truth for these environment variables can be found in the `pex.variables API `_. Using ``bdist_pex`` =================== pex provides a convenience command for use in setuptools. ``python setup.py bdist_pex`` is a simple way to build executables for Python projects that adhere to standard naming conventions. ``bdist_pex`` ------------- The default behavior of ``bdist_pex`` is to build an executable using the console script of the same name as the package. For example, pip has three entry points: ``pip``, ``pip2`` and ``pip2.7`` if you're using Python 2.7. Since there exists an entry point named ``pip`` in the ``console_scripts`` section of the entry points, that entry point is chosen and an executable pex is produced. The pex file will have the version number appended, e.g. ``pip-7.2.0.pex``. If no console scripts are provided, or the only console scripts available do not bear the same name as the package, then an environment pex will be produced. An environment pex is a pex file that drops you into an interpreter with all necessary dependencies but stops short of invoking a specific module or function. ``bdist_pex --bdist-all`` ------------------------- If you would like to build all the console scripts defined in the package instead of just the namesake script, ``--bdist-all`` will write all defined entry_points but omit version numbers and the ``.pex`` suffix. This can be useful if you would like to virtually install a Python package somewhere on your ``$PATH`` without doing something scary like ``sudo pip install``: .. code-block:: bash $ git clone https://github.com/sphinx-doc/sphinx && cd sphinx $ python setup.py bist_pex --bdist-all --bdist-dir=$HOME/bin running bdist_pex Writing sphinx-apidoc to /Users/wickman/bin/sphinx-apidoc Writing sphinx-build to /Users/wickman/bin/sphinx-build Writing sphinx-quickstart to /Users/wickman/bin/sphinx-quickstart Writing sphinx-autogen to /Users/wickman/bin/sphinx-autogen $ sphinx-apidoc --help | head -1 Usage: sphinx-apidoc [options] -o [exclude_path, ...] Other ways to build PEX files ============================= There are other supported ways to build pex files: * Using pants. See `Pants Python documentation `_. * Programmatically via the pex API. pex-1.1.14/docs/conf.py0000644000076500000240000002057712623452313015446 0ustar kwilsonstaff00000000000000# -*- coding: utf-8 -*- # # pex documentation build configuration file, created by # sphinx-quickstart on Fri Jul 25 15:16:37 2014. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import os import sys from datetime import datetime # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) from pex.version import __version__ as PEX_VERSION # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'pex' copyright = u'%s, Pants project contributors' % datetime.now().year # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '.'.join(PEX_VERSION.split('.')[0:2]) # The full version, including alpha/beta/rc tags. release = PEX_VERSION # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. try: import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] except ImportError: html_theme = 'default' sys.stderr.write('Failed to import sphinx_rtd_theme!') html_domain_indices = True html_show_sourcelink = True # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'pexdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'pex.tex', u'pex Documentation', u'Brian Wickman', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'pex', u'pex Documentation', [u'Brian Wickman'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'pex', u'pex Documentation', u'Brian Wickman', 'pex', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False pex-1.1.14/docs/index.rst0000644000076500000240000000261412623452313016000 0ustar kwilsonstaff00000000000000****** pex ****** This project is the home of the .pex file, and the ``pex`` tool which can create them. ``pex`` also provides a general purpose Python environment-virtualization solution similar to `virtualenv `_. pex is short for "Python Executable" in brief === To quickly get started building .pex files, go straight to :ref:`buildingpex`. New to python packaging? Check out `packaging.python.org `_. intro & history === pex contains the Python packaging and distribution libraries originally available through the `twitter commons `_ but since split out into a separate project. The most notable components of pex are the .pex (Python EXecutable) format and the associated ``pex`` tool which provide a general purpose Python environment virtualization solution similar in spirit to `virtualenv `_. PEX files have been used by Twitter to deploy Python applications to production since 2011. To learn more about what the .pex format is and why it could be useful for you, see :ref:`whatispex` For the impatient, there is also a (slightly outdated) lightning talk published by Twitter University: `WTF is PEX? `_. To go straight to building pex files, see :ref:`buildingpex`. Guide: .. toctree:: :maxdepth: 2 whatispex buildingpex api/index pex-1.1.14/docs/Makefile0000644000076500000240000001513612623452313015602 0ustar kwilsonstaff00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pex.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pex.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/pex" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pex" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." pex-1.1.14/docs/rtd/0000755000076500000240000000000012743552145014734 5ustar kwilsonstaff00000000000000pex-1.1.14/docs/rtd/requirements.txt0000644000076500000240000000003012623452313020202 0ustar kwilsonstaff00000000000000sphinx sphinx_rtd_theme pex-1.1.14/docs/whatispex.rst0000644000076500000240000000354012623452313016704 0ustar kwilsonstaff00000000000000.. _whatispex: ******************** What are .pex files? ******************** tl;dr ----- PEX files are self-contained executable Python virtual environments. More specifically, they are carefully constructed zip files with a ``#!/usr/bin/env python`` and special ``__main__.py`` that allows you to interact with the PEX runtime. For more information about zip applications, see `PEP 441 `_. To get started building your first pex files, go straight to :ref:`buildingpex`. Why .pex files? --------------- Files with the .pex extension -- "PEX files" or ".pex files" -- are self-contained executable Python virtual environments. PEX files make it easy to deploy Python applications: the deployment process becomes simply ``scp``. Single PEX files can support multiple platforms and python interpreters, making them an attractive option to distribute applications such as command line tools. For example, this feature allows the convenient use of the same PEX file on both OS X laptops and production Linux AMIs. How do .pex files work? ----------------------- PEX files rely on a feature in the Python importer that considers the presence of a ``__main__.py`` within the module as a signal to treat that module as an executable. For example, ``python -m my_module`` or ``python my_module`` will execute ``my_module/__main__.py`` if it exists. Because of the flexibility of the Python import subsystem, ``python -m my_module`` works regardless if ``my_module`` is on disk or within a zip file. Adding ``#!/usr/bin/env python`` to the top of a .zip file containing a ``__main__.py`` and marking it executable will turn it into an executable Python program. pex takes advantage of this feature in order to build executable .pex files. This is described more thoroughly in `PEP 441 `_. pex-1.1.14/LICENSE0000644000076500000240000002607312623452313014221 0ustar kwilsonstaff00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.pex-1.1.14/MANIFEST.in0000644000076500000240000000023112623452313014736 0ustar kwilsonstaff00000000000000include *.py *.rst *.ini MANIFEST.in LICENSE recursive-include docs * recursive-include tests * recursive-include scripts * recursive-exclude * *.pyc *~ pex-1.1.14/pex/0000755000076500000240000000000012743552145014007 5ustar kwilsonstaff00000000000000pex-1.1.14/pex/__init__.py0000644000076500000240000000020312623452313016104 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). pex-1.1.14/pex/archiver.py0000644000076500000240000000303012623452313016151 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import os import tarfile import zipfile from .common import safe_mkdtemp class Archiver(object): class Error(Exception): pass class UnpackError(Error): pass class InvalidArchive(Error): pass EXTENSIONS = { '.tar': (tarfile.TarFile.open, tarfile.ReadError), '.tar.gz': (tarfile.TarFile.open, tarfile.ReadError), '.tar.bz2': (tarfile.TarFile.open, tarfile.ReadError), '.tgz': (tarfile.TarFile.open, tarfile.ReadError), '.zip': (zipfile.ZipFile, zipfile.BadZipfile) } @classmethod def first_nontrivial_dir(cls, path): files = os.listdir(path) if len(files) == 1 and os.path.isdir(os.path.join(path, files[0])): return cls.first_nontrivial_dir(os.path.join(path, files[0])) else: return path @classmethod def get_extension(cls, filename): for ext in cls.EXTENSIONS: if filename.endswith(ext): return ext @classmethod def unpack(cls, filename, location=None): path = location or safe_mkdtemp() ext = cls.get_extension(filename) if ext is None: raise cls.InvalidArchive('Unknown archive format: %s' % filename) archive_class, error_class = cls.EXTENSIONS[ext] try: with contextlib.closing(archive_class(filename)) as package: package.extractall(path=path) except error_class: raise cls.UnpackError('Could not extract %s' % filename) return cls.first_nontrivial_dir(path) pex-1.1.14/pex/base.py0000644000076500000240000000215612623452313015270 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import from collections import Iterable from pkg_resources import Requirement from .compatibility import string as compatibility_string REQUIRED_ATTRIBUTES = ( 'extras', 'key', 'project_name', 'specs', ) def quacks_like_req(req): return all(hasattr(req, attr) for attr in REQUIRED_ATTRIBUTES) def maybe_requirement(req): if isinstance(req, Requirement) or quacks_like_req(req): return req elif isinstance(req, compatibility_string): return Requirement.parse(req) raise ValueError('Unknown requirement %r' % (req,)) def maybe_requirement_list(reqs): if isinstance(reqs, (compatibility_string, Requirement)) or quacks_like_req(reqs): return [maybe_requirement(reqs)] elif isinstance(reqs, Iterable): return [maybe_requirement(req) for req in reqs] raise ValueError('Unknown requirement list %r' % (reqs,)) def requirement_is_exact(req): return bool(req.specs and len(req.specs) == 1 and req.specs[0][0] == '==') pex-1.1.14/pex/bin/0000755000076500000240000000000012743552145014557 5ustar kwilsonstaff00000000000000pex-1.1.14/pex/bin/__init__.py0000644000076500000240000000020312623452313016654 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). pex-1.1.14/pex/bin/pex.py0000755000076500000240000004324112720677546015744 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). """ The pex.pex utility builds PEX environments and .pex files specified by sources, requirements and their dependencies. """ from __future__ import absolute_import, print_function import functools import os import shutil import sys from optparse import OptionGroup, OptionParser, OptionValueError from textwrap import TextWrapper from pex.archiver import Archiver from pex.base import maybe_requirement from pex.common import die, safe_delete, safe_mkdir, safe_mkdtemp from pex.crawler import Crawler from pex.fetcher import Fetcher, PyPIFetcher from pex.http import Context from pex.installer import EggInstaller from pex.interpreter import PythonInterpreter from pex.iterator import Iterator from pex.package import EggPackage, SourcePackage from pex.pex import PEX from pex.pex_builder import PEXBuilder from pex.platforms import Platform from pex.requirements import requirements_from_file from pex.resolvable import Resolvable from pex.resolver import CachingResolver, Resolver, Unsatisfiable from pex.resolver_options import ResolverOptionsBuilder from pex.tracer import TRACER from pex.variables import ENV, Variables from pex.version import SETUPTOOLS_REQUIREMENT, WHEEL_REQUIREMENT, __version__ CANNOT_DISTILL = 101 CANNOT_SETUP_INTERPRETER = 102 INVALID_OPTIONS = 103 INVALID_ENTRY_POINT = 104 class Logger(object): def _default_logger(self, msg, v): if v: print(msg, file=sys.stderr) _LOGGER = _default_logger def __call__(self, msg, v): self._LOGGER(msg, v) def set_logger(self, logger_callback): self._LOGGER = logger_callback log = Logger() def parse_bool(option, opt_str, _, parser): setattr(parser.values, option.dest, not opt_str.startswith('--no')) def increment_verbosity(option, opt_str, _, parser): verbosity = getattr(parser.values, option.dest, 0) setattr(parser.values, option.dest, verbosity + 1) def process_disable_cache(option, option_str, option_value, parser): setattr(parser.values, option.dest, None) def process_pypi_option(option, option_str, option_value, parser, builder): if option_str.startswith('--no'): setattr(parser.values, option.dest, []) builder.clear_indices() else: indices = getattr(parser.values, option.dest, []) pypi = PyPIFetcher() if pypi not in indices: indices.append(pypi) setattr(parser.values, option.dest, indices) builder.add_index(PyPIFetcher.PYPI_BASE) def process_find_links(option, option_str, option_value, parser, builder): repos = getattr(parser.values, option.dest, []) repo = Fetcher([option_value]) if repo not in repos: repos.append(repo) setattr(parser.values, option.dest, repos) builder.add_repository(option_value) def process_index_url(option, option_str, option_value, parser, builder): indices = getattr(parser.values, option.dest, []) index = PyPIFetcher(option_value) if index not in indices: indices.append(index) setattr(parser.values, option.dest, indices) builder.add_index(option_value) def process_precedence(option, option_str, option_value, parser, builder): if option_str == '--build': builder.allow_builds() elif option_str == '--no-build': builder.no_allow_builds() elif option_str == '--wheel': setattr(parser.values, option.dest, True) builder.use_wheel() elif option_str in ('--no-wheel', '--no-use-wheel'): setattr(parser.values, option.dest, False) builder.no_use_wheel() else: raise OptionValueError def print_variable_help(option, option_str, option_value, parser): for variable_name, variable_type, variable_help in Variables.iter_help(): print('\n%s: %s\n' % (variable_name, variable_type)) for line in TextWrapper(initial_indent=' ' * 4, subsequent_indent=' ' * 4).wrap(variable_help): print(line) sys.exit(0) def configure_clp_pex_resolution(parser, builder): group = OptionGroup( parser, 'Resolver options', 'Tailor how to find, resolve and translate the packages that get put into the PEX ' 'environment.') group.add_option( '--pypi', '--no-pypi', '--no-index', action='callback', dest='repos', callback=process_pypi_option, callback_args=(builder,), help='Whether to use pypi to resolve dependencies; Default: use pypi') group.add_option( '-f', '--find-links', '--repo', metavar='PATH/URL', action='callback', dest='repos', callback=process_find_links, callback_args=(builder,), type=str, help='Additional repository path (directory or URL) to look for requirements.') group.add_option( '-i', '--index', '--index-url', metavar='URL', action='callback', dest='repos', callback=process_index_url, callback_args=(builder,), type=str, help='Additional cheeseshop indices to use to satisfy requirements.') group.add_option( '--disable-cache', action='callback', dest='cache_dir', callback=process_disable_cache, help='Disable caching in the pex tool entirely.') group.add_option( '--cache-dir', dest='cache_dir', default='{pex_root}/build', help='The local cache directory to use for speeding up requirement ' 'lookups. [Default: ~/.pex/build]') group.add_option( '--cache-ttl', dest='cache_ttl', type=int, default=None, help='The cache TTL to use for inexact requirement specifications.') group.add_option( '--wheel', '--no-wheel', '--no-use-wheel', dest='use_wheel', default=True, action='callback', callback=process_precedence, callback_args=(builder,), help='Whether to allow wheel distributions; Default: allow wheels') group.add_option( '--build', '--no-build', action='callback', callback=process_precedence, callback_args=(builder,), help='Whether to allow building of distributions from source; Default: allow builds') # Set the pex tool to fetch from PyPI by default if nothing is specified. parser.set_default('repos', [PyPIFetcher()]) parser.add_option_group(group) def configure_clp_pex_options(parser): group = OptionGroup( parser, 'PEX output options', 'Tailor the behavior of the emitted .pex file if -o is specified.') group.add_option( '--zip-safe', '--not-zip-safe', dest='zip_safe', default=True, action='callback', callback=parse_bool, help='Whether or not the sources in the pex file are zip safe. If they are ' 'not zip safe, they will be written to disk prior to execution; ' 'Default: zip safe.') group.add_option( '--always-write-cache', dest='always_write_cache', default=False, action='store_true', help='Always write the internally cached distributions to disk prior to invoking ' 'the pex source code. This can use less memory in RAM constrained ' 'environments. [Default: %default]') group.add_option( '--ignore-errors', dest='ignore_errors', default=False, action='store_true', help='Ignore run-time requirement resolution errors when invoking the pex. ' '[Default: %default]') group.add_option( '--inherit-path', dest='inherit_path', default=False, action='store_true', help='Inherit the contents of sys.path (including site-packages) running the pex. ' '[Default: %default]') parser.add_option_group(group) def configure_clp_pex_environment(parser): group = OptionGroup( parser, 'PEX environment options', 'Tailor the interpreter and platform targets for the PEX environment.') group.add_option( '--python', dest='python', default=None, help='The Python interpreter to use to build the pex. Either specify an explicit ' 'path to an interpreter, or specify a binary accessible on $PATH. ' 'Default: Use current interpreter.') group.add_option( '--python-shebang', dest='python_shebang', default=None, help='The exact shebang (#!...) line to add at the top of the PEX file minus the ' '#!. This overrides the default behavior, which picks an environment python ' 'interpreter compatible with the one used to build the PEX file.') group.add_option( '--platform', dest='platform', default=Platform.current(), help='The platform for which to build the PEX. Default: %default') group.add_option( '--interpreter-cache-dir', dest='interpreter_cache_dir', default='{pex_root}/interpreters', help='The interpreter cache to use for keeping track of interpreter dependencies ' 'for the pex tool. [Default: ~/.pex/interpreters]') parser.add_option_group(group) def configure_clp_pex_entry_points(parser): group = OptionGroup( parser, 'PEX entry point options', 'Specify what target/module the PEX should invoke if any.') group.add_option( '-m', '-e', '--entry-point', dest='entry_point', metavar='MODULE[:SYMBOL]', default=None, help='Set the entry point to module or module:symbol. If just specifying module, pex ' 'behaves like python -m, e.g. python -m SimpleHTTPServer. If specifying ' 'module:symbol, pex imports that symbol and invokes it as if it were main.') group.add_option( '-c', '--script', '--console-script', dest='script', default=None, metavar='SCRIPT_NAME', help='Set the entry point as to the script or console_script as defined by a any of the ' 'distributions in the pex. For example: "pex -c fab fabric" or "pex -c mturk boto".') parser.add_option_group(group) def configure_clp(): usage = ( '%prog [-o OUTPUT.PEX] [options] [-- arg1 arg2 ...]\n\n' '%prog builds a PEX (Python Executable) file based on the given specifications: ' 'sources, requirements, their dependencies and other options.') parser = OptionParser(usage=usage, version='%prog {0}'.format(__version__)) resolver_options_builder = ResolverOptionsBuilder() configure_clp_pex_resolution(parser, resolver_options_builder) configure_clp_pex_options(parser) configure_clp_pex_environment(parser) configure_clp_pex_entry_points(parser) parser.add_option( '-o', '--output-file', dest='pex_name', default=None, help='The name of the generated .pex file: Omiting this will run PEX ' 'immediately and not save it to a file.') parser.add_option( '-r', '--requirement', dest='requirement_files', metavar='FILE', default=[], type=str, action='append', help='Add requirements from the given requirements file. This option can be used multiple ' 'times.') parser.add_option( '-v', dest='verbosity', default=0, action='callback', callback=increment_verbosity, help='Turn on logging verbosity, may be specified multiple times.') parser.add_option( '--pex-root', dest='pex_root', default=None, help='Specify the pex root used in this invocation of pex. [Default: ~/.pex]' ) parser.add_option( '--help-variables', action='callback', callback=print_variable_help, help='Print out help about the various environment variables used to change the behavior of ' 'a running PEX file.') return parser, resolver_options_builder def _safe_link(src, dst): try: os.unlink(dst) except OSError: pass os.symlink(src, dst) def _resolve_and_link_interpreter(requirement, fetchers, target_link, installer_provider): # Short-circuit if there is a local copy if os.path.exists(target_link) and os.path.exists(os.path.realpath(target_link)): egg = EggPackage(os.path.realpath(target_link)) if egg.satisfies(requirement): return egg context = Context.get() iterator = Iterator(fetchers=fetchers, crawler=Crawler(context)) links = [link for link in iterator.iter(requirement) if isinstance(link, SourcePackage)] with TRACER.timed('Interpreter cache resolving %s' % requirement, V=2): for link in links: with TRACER.timed('Fetching %s' % link, V=3): sdist = context.fetch(link) with TRACER.timed('Installing %s' % link, V=3): installer = installer_provider(sdist) dist_location = installer.bdist() target_location = os.path.join( os.path.dirname(target_link), os.path.basename(dist_location)) shutil.move(dist_location, target_location) _safe_link(target_location, target_link) return EggPackage(target_location) def resolve_interpreter(cache, fetchers, interpreter, requirement): """Resolve an interpreter with a specific requirement. Given a :class:`PythonInterpreter` and a requirement, return an interpreter with the capability of resolving that requirement or ``None`` if it's not possible to install a suitable requirement.""" requirement = maybe_requirement(requirement) # short circuit if interpreter.satisfies([requirement]): return interpreter def installer_provider(sdist): return EggInstaller( Archiver.unpack(sdist), strict=requirement.key != 'setuptools', interpreter=interpreter) interpreter_dir = os.path.join(cache, str(interpreter.identity)) safe_mkdir(interpreter_dir) egg = _resolve_and_link_interpreter( requirement, fetchers, os.path.join(interpreter_dir, requirement.key), installer_provider) if egg: return interpreter.with_extra(egg.name, egg.raw_version, egg.path) def interpreter_from_options(options): interpreter = None if options.python: if os.path.exists(options.python): interpreter = PythonInterpreter.from_binary(options.python) else: interpreter = PythonInterpreter.from_env(options.python) if interpreter is None: die('Failed to find interpreter: %s' % options.python) else: interpreter = PythonInterpreter.get() with TRACER.timed('Setting up interpreter %s' % interpreter.binary, V=2): resolve = functools.partial(resolve_interpreter, options.interpreter_cache_dir, options.repos) # resolve setuptools interpreter = resolve(interpreter, SETUPTOOLS_REQUIREMENT) # possibly resolve wheel if interpreter and options.use_wheel: interpreter = resolve(interpreter, WHEEL_REQUIREMENT) return interpreter def build_pex(args, options, resolver_option_builder): with TRACER.timed('Resolving interpreter', V=2): interpreter = interpreter_from_options(options) if interpreter is None: die('Could not find compatible interpreter', CANNOT_SETUP_INTERPRETER) pex_builder = PEXBuilder(path=safe_mkdtemp(), interpreter=interpreter) pex_info = pex_builder.info pex_info.zip_safe = options.zip_safe pex_info.always_write_cache = options.always_write_cache pex_info.ignore_errors = options.ignore_errors pex_info.inherit_path = options.inherit_path resolvables = [Resolvable.get(arg, resolver_option_builder) for arg in args] for requirements_txt in options.requirement_files: resolvables.extend(requirements_from_file(requirements_txt, resolver_option_builder)) resolver_kwargs = dict(interpreter=interpreter, platform=options.platform) if options.cache_dir: resolver = CachingResolver(options.cache_dir, options.cache_ttl, **resolver_kwargs) else: resolver = Resolver(**resolver_kwargs) with TRACER.timed('Resolving distributions'): try: resolveds = resolver.resolve(resolvables) except Unsatisfiable as e: die(e) for dist in resolveds: log(' %s' % dist, v=options.verbosity) pex_builder.add_distribution(dist) pex_builder.add_requirement(dist.as_requirement()) if options.entry_point and options.script: die('Must specify at most one entry point or script.', INVALID_OPTIONS) if options.entry_point: pex_builder.set_entry_point(options.entry_point) elif options.script: pex_builder.set_script(options.script) if options.python_shebang: pex_builder.set_shebang(options.python_shebang) return pex_builder def make_relative_to_root(path): """Update options so that defaults are user relative to specified pex_root.""" return os.path.normpath(path.format(pex_root=ENV.PEX_ROOT)) def main(args=None): args = args or sys.argv[1:] parser, resolver_options_builder = configure_clp() try: separator = args.index('--') args, cmdline = args[:separator], args[separator + 1:] except ValueError: args, cmdline = args, [] options, reqs = parser.parse_args(args=args) if options.pex_root: ENV.set('PEX_ROOT', options.pex_root) else: options.pex_root = ENV.PEX_ROOT # If option not specified fallback to env variable. # Don't alter cache if it is disabled. if options.cache_dir: options.cache_dir = make_relative_to_root(options.cache_dir) options.interpreter_cache_dir = make_relative_to_root(options.interpreter_cache_dir) with ENV.patch(PEX_VERBOSE=str(options.verbosity)): with TRACER.timed('Building pex'): pex_builder = build_pex(reqs, options, resolver_options_builder) if options.pex_name is not None: log('Saving PEX file to %s' % options.pex_name, v=options.verbosity) tmp_name = options.pex_name + '~' safe_delete(tmp_name) pex_builder.build(tmp_name) os.rename(tmp_name, options.pex_name) return 0 if options.platform != Platform.current(): log('WARNING: attempting to run PEX with differing platform!') pex_builder.freeze() log('Running PEX file at %s with args %s' % (pex_builder.path(), cmdline), v=options.verbosity) pex = PEX(pex_builder.path(), interpreter=pex_builder.interpreter) sys.exit(pex.run(args=list(cmdline))) if __name__ == '__main__': main() pex-1.1.14/pex/commands/0000755000076500000240000000000012743552145015610 5ustar kwilsonstaff00000000000000pex-1.1.14/pex/commands/__init__.py0000644000076500000240000000000012623452313017700 0ustar kwilsonstaff00000000000000pex-1.1.14/pex/commands/bdist_pex.py0000644000076500000240000000717512743540264020154 0ustar kwilsonstaff00000000000000import os import shlex from distutils import log from setuptools import Command from pex.bin.pex import build_pex, configure_clp, make_relative_to_root from pex.common import die from pex.compatibility import ConfigParser, StringIO, string from pex.variables import ENV # Suppress checkstyle violations due to setuptools command requirements. class bdist_pex(Command): # noqa description = "create a PEX file from a source distribution" # noqa user_options = [ # noqa ('bdist-all', None, 'pexify all defined entry points'), ('bdist-dir=', None, 'the directory into which pexes will be written, default: dist.'), ('pex-args=', None, 'additional arguments to the pex tool'), ] boolean_options = [ # noqa 'bdist-all', ] def initialize_options(self): self.bdist_all = False self.bdist_dir = None self.pex_args = '' def finalize_options(self): self.pex_args = shlex.split(self.pex_args) def _write(self, pex_builder, target, script=None): builder = pex_builder.clone() if script is not None: builder.set_script(script) builder.build(target) def parse_entry_points(self): def split_and_strip(entry_point): console_script, entry_point = entry_point.split('=', 2) return console_script.strip(), entry_point.strip() raw_entry_points = self.distribution.entry_points if isinstance(raw_entry_points, string): parser = ConfigParser() parser.readfp(StringIO(raw_entry_points)) if parser.has_section('console_scripts'): return dict(parser.items('console_scripts')) elif isinstance(raw_entry_points, dict): try: return dict(split_and_strip(script) for script in raw_entry_points.get('console_scripts', [])) except ValueError: pass elif raw_entry_points is not None: die('When entry_points is provided, it must be a string or dict.') return {} def run(self): name = self.distribution.get_name() version = self.distribution.get_version() parser, options_builder = configure_clp() package_dir = os.path.dirname(os.path.realpath(os.path.expanduser( self.distribution.script_name))) if self.bdist_dir is None: self.bdist_dir = os.path.join(package_dir, 'dist') options, reqs = parser.parse_args(self.pex_args) # Update cache_dir with pex_root in case this is being called directly. if options.cache_dir: options.cache_dir = make_relative_to_root(options.cache_dir) options.interpreter_cache_dir = make_relative_to_root(options.interpreter_cache_dir) if options.entry_point or options.script: die('Must not specify entry_point or script to --pex-args') reqs = [package_dir] + reqs with ENV.patch(PEX_VERBOSE=str(options.verbosity), PEX_ROOT=options.pex_root): pex_builder = build_pex(reqs, options, options_builder) console_scripts = self.parse_entry_points() target = os.path.join(self.bdist_dir, name + '-' + version + '.pex') if self.bdist_all: # Write all entry points into unversioned pex files. for script_name in console_scripts: target = os.path.join(self.bdist_dir, script_name) log.info('Writing %s to %s' % (script_name, target)) self._write(pex_builder, target, script=script_name) elif name in console_scripts: # The package has a namesake entry point, so use it. log.info('Writing %s to %s' % (name, target)) self._write(pex_builder, target, script=name) else: # The package has no namesake entry point, so build an environment pex. log.info('Writing environment pex into %s' % target) self._write(pex_builder, target, script=None) pex-1.1.14/pex/common.py0000644000076500000240000002267712722124676015670 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import print_function import atexit import contextlib import errno import os import shutil import stat import sys import tempfile import threading import zipfile from collections import defaultdict from uuid import uuid4 def die(msg, exit_code=1): print(msg, file=sys.stderr) sys.exit(exit_code) def safe_copy(source, dest, overwrite=False): def do_copy(): temp_dest = dest + uuid4().hex shutil.copyfile(source, temp_dest) os.rename(temp_dest, dest) # If the platform supports hard-linking, use that and fall back to copying. # Windows does not support hard-linking. if hasattr(os, 'link'): try: os.link(source, dest) except OSError as e: if e.errno == errno.EEXIST: # File already exists. If overwrite=True, write otherwise skip. if overwrite: do_copy() elif e.errno == errno.EXDEV: # Hard link across devices, fall back on copying do_copy() else: raise elif os.path.exists(dest): if overwrite: do_copy() else: do_copy() # See http://stackoverflow.com/questions/2572172/referencing-other-modules-in-atexit class MktempTeardownRegistry(object): def __init__(self): self._registry = defaultdict(set) self._getpid = os.getpid self._lock = threading.RLock() self._exists = os.path.exists self._getenv = os.getenv self._rmtree = shutil.rmtree atexit.register(self.teardown) def __del__(self): self.teardown() def register(self, path): with self._lock: self._registry[self._getpid()].add(path) return path def teardown(self): for td in self._registry.pop(self._getpid(), []): if self._exists(td): self._rmtree(td) _MKDTEMP_SINGLETON = MktempTeardownRegistry() @contextlib.contextmanager def open_zip(path, *args, **kwargs): """A contextmanager for zip files. Passes through positional and kwargs to zipfile.ZipFile.""" with contextlib.closing(zipfile.ZipFile(path, *args, **kwargs)) as zip: yield zip def safe_mkdtemp(**kw): """Create a temporary directory that is cleaned up on process exit. Takes the same parameters as tempfile.mkdtemp. """ # proper lock sanitation on fork [issue 6721] would be desirable here. return _MKDTEMP_SINGLETON.register(tempfile.mkdtemp(**kw)) def register_rmtree(directory): """Register an existing directory to be cleaned up at process exit.""" return _MKDTEMP_SINGLETON.register(directory) def safe_mkdir(directory, clean=False): """Safely create a directory. Ensures a directory is present. If it's not there, it is created. If it is, it's a no-op. no-op. If clean is True, ensures the directory is empty. """ if clean: safe_rmtree(directory) try: os.makedirs(directory) except OSError as e: if e.errno != errno.EEXIST: raise def safe_open(filename, *args, **kwargs): """Safely open a file. ``safe_open`` ensures that the directory components leading up the specified file have been created first. """ safe_mkdir(os.path.dirname(filename)) return open(filename, *args, **kwargs) # noqa: T802 def safe_delete(filename): """Delete a file safely. If it's not present, no-op.""" try: os.unlink(filename) except OSError as e: if e.errno != errno.ENOENT: raise def safe_rmtree(directory): """Delete a directory if it's present. If it's not present, no-op.""" if os.path.exists(directory): shutil.rmtree(directory, True) def rename_if_empty(src, dest, allowable_errors=(errno.EEXIST, errno.ENOTEMPTY)): """Rename `src` to `dest` using `os.rename()`. If an `OSError` with errno in `allowable_errors` is encountered during the rename, the `dest` dir is left unchanged and the `src` directory will simply be removed. """ try: os.rename(src, dest) except OSError as e: if e.errno in allowable_errors: safe_rmtree(src) else: raise def chmod_plus_x(path): """Equivalent of unix `chmod a+x path`""" path_mode = os.stat(path).st_mode path_mode &= int('777', 8) if path_mode & stat.S_IRUSR: path_mode |= stat.S_IXUSR if path_mode & stat.S_IRGRP: path_mode |= stat.S_IXGRP if path_mode & stat.S_IROTH: path_mode |= stat.S_IXOTH os.chmod(path, path_mode) def chmod_plus_w(path): """Equivalent of unix `chmod +w path`""" path_mode = os.stat(path).st_mode path_mode &= int('777', 8) path_mode |= stat.S_IWRITE os.chmod(path, path_mode) def touch(file, times=None): """Equivalent of unix `touch path`. :file The file to touch. :times Either a tuple of (atime, mtime) or else a single time to use for both. If not specified both atime and mtime are updated to the current time. """ if times: if len(times) > 2: raise ValueError('times must either be a tuple of (atime, mtime) or else a single time value ' 'to use for both.') if len(times) == 1: times = (times, times) with safe_open(file, 'a'): os.utime(file, times) class Chroot(object): """A chroot of files overlayed from one directory to another directory. Files may be tagged when added in order to keep track of multiple overlays in the chroot. """ class Error(Exception): pass class ChrootTaggingException(Error): def __init__(self, filename, orig_tag, new_tag): super(Chroot.ChrootTaggingException, self).__init__( # noqa: T800 "Trying to add %s to fileset(%s) but already in fileset(%s)!" % ( filename, new_tag, orig_tag)) def __init__(self, chroot_base): """Create the chroot. :chroot_base Directory for the creation of the target chroot. """ try: safe_mkdir(chroot_base) except OSError as e: raise self.ChrootException('Unable to create chroot in %s: %s' % (chroot_base, e)) self.chroot = chroot_base self.filesets = defaultdict(set) def clone(self, into=None): """Clone this chroot. :keyword into: (optional) An optional destination directory to clone the Chroot into. If not specified, a temporary directory will be created. .. versionchanged:: 0.8 The temporary directory created when ``into`` is not specified is now garbage collected on interpreter exit. """ into = into or safe_mkdtemp() new_chroot = Chroot(into) for label, fileset in self.filesets.items(): for fn in fileset: new_chroot.link(os.path.join(self.chroot, fn), fn, label=label) return new_chroot def path(self): """The path of the chroot.""" return self.chroot def _normalize(self, dst): dst = os.path.normpath(dst) if dst.startswith(os.sep) or dst.startswith('..'): raise self.Error('Destination path is not a relative path!') return dst def _check_tag(self, fn, label): for fs_label, fs in self.filesets.items(): if fn in fs and fs_label != label: raise self.ChrootTaggingException(fn, fs_label, label) def _tag(self, fn, label): self._check_tag(fn, label) self.filesets[label].add(fn) def _ensure_parent(self, path): safe_mkdir(os.path.dirname(os.path.join(self.chroot, path))) def copy(self, src, dst, label=None): """Copy file ``src`` to ``chroot/dst`` with optional label. May raise anything shutil.copyfile can raise, e.g. IOError(Errno 21 'EISDIR') May raise ChrootTaggingException if dst is already in a fileset but with a different label. """ dst = self._normalize(dst) self._tag(dst, label) self._ensure_parent(dst) shutil.copyfile(src, os.path.join(self.chroot, dst)) def link(self, src, dst, label=None): """Hard link file from ``src`` to ``chroot/dst`` with optional label. May raise anything os.link can raise, e.g. IOError(Errno 21 'EISDIR') May raise ChrootTaggingException if dst is already in a fileset but with a different label. """ dst = self._normalize(dst) self._tag(dst, label) self._ensure_parent(dst) abs_src = src abs_dst = os.path.join(self.chroot, dst) safe_copy(abs_src, abs_dst, overwrite=False) # TODO: Ensure the target and dest are the same if the file already exists. def write(self, data, dst, label=None, mode='wb'): """Write data to ``chroot/dst`` with optional label. Has similar exceptional cases as ``Chroot.copy`` """ dst = self._normalize(dst) self._tag(dst, label) self._ensure_parent(dst) with open(os.path.join(self.chroot, dst), mode) as wp: wp.write(data) def touch(self, dst, label=None): """Perform 'touch' on ``chroot/dst`` with optional label. Has similar exceptional cases as Chroot.copy """ dst = self._normalize(dst) self._tag(dst, label) touch(os.path.join(self.chroot, dst)) def get(self, label): """Get all files labeled with ``label``""" return self.filesets.get(label, set()) def files(self): """Get all files in the chroot.""" all_files = set() for label in self.filesets: all_files.update(self.filesets[label]) return all_files def labels(self): return self.filesets.keys() def __str__(self): return 'Chroot(%s {fs:%s})' % (self.chroot, ' '.join('%s' % foo for foo in self.filesets.keys())) def delete(self): shutil.rmtree(self.chroot) def zip(self, filename, mode='wb'): with contextlib.closing(zipfile.ZipFile(filename, mode)) as zf: for f in sorted(self.files()): zf.write(os.path.join(self.chroot, f), arcname=f, compress_type=zipfile.ZIP_DEFLATED) pex-1.1.14/pex/compatibility.py0000644000076500000240000000506112720650765017236 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). # This file contains several 2.x/3.x compatibility checkstyle violations for a reason # checkstyle: noqa import os from abc import ABCMeta from numbers import Integral, Real from sys import version_info as sys_version_info # TODO(wickman) Since the io package is available in 2.6.x, use that instead of # cStringIO/StringIO try: # CPython 2.x from cStringIO import StringIO except ImportError: try: # Python 2.x from StringIO import StringIO except: # Python 3.x from io import StringIO from io import BytesIO try: # Python 2.x from ConfigParser import ConfigParser except ImportError: # Python 3.x from configparser import ConfigParser AbstractClass = ABCMeta('AbstractClass', (object,), {}) PY2 = sys_version_info[0] == 2 PY3 = sys_version_info[0] == 3 StringIO = StringIO BytesIO = BytesIO if PY3 else StringIO integer = (Integral,) real = (Real,) numeric = integer + real string = (str,) if PY3 else (str, unicode) bytes = (bytes,) if PY2: def to_bytes(st, encoding='utf-8'): if isinstance(st, unicode): return st.encode(encoding) elif isinstance(st, bytes): return st else: raise ValueError('Cannot convert %s to bytes' % type(st)) else: def to_bytes(st, encoding='utf-8'): if isinstance(st, str): return st.encode(encoding) elif isinstance(st, bytes): return st else: raise ValueError('Cannot convert %s to bytes.' % type(st)) _PY3_EXEC_FUNCTION = """ def exec_function(ast, globals_map): locals_map = globals_map exec ast in globals_map, locals_map return locals_map """ if PY3: def exec_function(ast, globals_map): locals_map = globals_map exec(ast, globals_map, locals_map) return locals_map else: eval(compile(_PY3_EXEC_FUNCTION, "", "exec")) if PY3: from contextlib import contextmanager, ExitStack @contextmanager def nested(*context_managers): enters = [] with ExitStack() as stack: for manager in context_managers: enters.append(stack.enter_context(manager)) yield tuple(enters) else: from contextlib import nested if PY3: from urllib.request import pathname2url, url2pathname else: from urllib import pathname2url, url2pathname WINDOWS = os.name == 'nt' __all__ = ( 'AbstractClass', 'BytesIO', 'ConfigParser', 'PY2', 'PY3', 'StringIO', 'WINDOWS', 'bytes', 'exec_function', 'nested', 'pathname2url', 'string', 'to_bytes', 'url2pathname', ) pex-1.1.14/pex/compiler.py0000644000076500000240000000625712741504142016175 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import from .compatibility import to_bytes from .executor import Executor from .util import named_temporary_file _COMPILER_MAIN = """ from __future__ import print_function import os import py_compile import sys def compile(root, relpaths): compiled = [] errored = {} for relpath in relpaths: abspath = os.path.join(root, relpath) # NB: We give the compiled bytecode file a `.pyc` extension, but if PYTHONOPTIMIZE is in play # the generated bytecode will be optimized. Traditionally these optimized bytecode files would # have a `.pyo` extension, but the extension only matters for location of the file to execute # for a given module and not on the interpretation of its bytecode contents. As such we're # safe to pick the `.pyc` extension for all bytecode file cases without a need to interpret the # current optimization setting for the active python interpreter. pyc_relpath = relpath + 'c' pyc_abspath = os.path.join(root, pyc_relpath) try: py_compile.compile(abspath, cfile=pyc_abspath, dfile=relpath, doraise=True) compiled.append(pyc_relpath) except py_compile.PyCompileError as e: errored[e.file] = e.msg return compiled, errored def main(root, relpaths): compiled, errored = compile(root, relpaths) if not errored: for path in compiled: print(path) sys.exit(0) print('Encountered %%d errors compiling %%d files:' %% (len(errored), len(relpaths)), file=sys.stderr) for file, msg in errored.items(): print(' %%s: %%s' %% (file, msg), file=sys.stderr) sys.exit(1) root = %(root)r relpaths = %(relpaths)r main(root, relpaths) """ class Compiler(object): class Error(Exception): pass class CompilationFailure(Error): # N.B. This subclasses `Error` only for backwards compatibility. """Indicates an error compiling one or more python source files.""" def __init__(self, interpreter): """Creates a bytecode compiler for the given `interpreter`. :param interpreter: The interpreter to use to compile sources with. :type interpreter: :class:`pex.interpreter.PythonInterpreter` """ self._interpreter = interpreter def compile(self, root, relpaths): """Compiles the given python source files using this compiler's interpreter. :param string root: The root path all the source files are found under. :param list relpaths: The realtive paths from the `root` of the source files to compile. :returns: A list of relative paths of the compiled bytecode files. :raises: A :class:`Compiler.Error` if there was a problem bytecode compiling any of the files. """ with named_temporary_file() as fp: fp.write(to_bytes(_COMPILER_MAIN % {'root': root, 'relpaths': relpaths}, encoding='utf-8')) fp.flush() try: out, _ = Executor.execute([self._interpreter.binary, fp.name]) except Executor.NonZeroExit as e: raise self.CompilationFailure( 'encountered %r during bytecode compilation.\nstderr was:\n%s\n' % (e, e.stderr) ) return out.splitlines() pex-1.1.14/pex/crawler.py0000644000076500000240000001275112670614434016025 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). """Support for webpage parsing and crawling.""" import os import re import threading import traceback from .compatibility import PY3 from .http import Context from .link import Link from .tracer import TRACER from .util import Memoizer if PY3: from queue import Empty, Queue from urllib.parse import urlparse else: from Queue import Empty, Queue from urlparse import urlparse def unescape(s): """Unescapes html. Taken from https://wiki.python.org/moin/EscapingHtml""" s = s.replace("<", "<") s = s.replace(">", ">") # this has to be last: s = s.replace("&", "&") return s class PageParser(object): """A helper class to extract and differentiate ordinary and download links from webpages.""" HREF_RE = re.compile(r"""href=(?:"([^"]*)"|\'([^\']*)\'|([^>\s\n]*))""", re.I | re.S) REL_RE = re.compile(r"""<[^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*>""", re.I) REL_SKIP_EXTENSIONS = frozenset(['.zip', '.tar', '.tar.gz', '.tar.bz2', '.tgz', '.exe']) REL_TYPES = frozenset(['homepage', 'download']) @classmethod def href_match_to_url(cls, match): def pick(group): return '' if group is None else group return unescape(pick(match.group(1)) or pick(match.group(2)) or pick(match.group(3))) @classmethod def rel_links(cls, page): """return rel= links that should be scraped, skipping obviously data links.""" for match in cls.REL_RE.finditer(page): href, rel = match.group(0), match.group(1) if rel not in cls.REL_TYPES: continue href_match = cls.HREF_RE.search(href) if href_match: href = cls.href_match_to_url(href_match) parsed_href = urlparse(href) if any(parsed_href.path.endswith(ext) for ext in cls.REL_SKIP_EXTENSIONS): continue yield href @classmethod def links(cls, page): """return all links on a page, including potentially rel= links.""" for match in cls.HREF_RE.finditer(page): yield cls.href_match_to_url(match) def partition(L, pred): return filter(lambda v: not pred(v), L), filter(lambda v: pred(v), L) class Crawler(object): """A multi-threaded crawler that supports local (disk) and remote (web) crawling.""" # Memoizer for calls to Crawler.crawl(). _CRAWL_CACHE = Memoizer() @classmethod def reset_cache(cls): """Reset the internal crawl cache. This is intended primarily for tests.""" cls._CRAWL_CACHE = Memoizer() @classmethod def crawl_local(cls, link): try: dirents = os.listdir(link.local_path) except OSError as e: TRACER.log('Failed to read %s: %s' % (link.local_path, e), V=1) return set(), set() files, dirs = partition([os.path.join(link.local_path, fn) for fn in dirents], os.path.isdir) return set(map(Link.from_filename, files)), set(map(Link.from_filename, dirs)) @classmethod def crawl_remote(cls, context, link): try: content = context.content(link) except context.Error as e: TRACER.log('Failed to read %s: %s' % (link.url, e), V=1) return set(), set() links = set(link.join(href) for href in PageParser.links(content)) rel_links = set(link.join(href) for href in PageParser.rel_links(content)) return links, rel_links @classmethod def crawl_link(cls, context, link): if link.local: return cls.crawl_local(link) elif link.remote: return cls.crawl_remote(context, link) else: TRACER.log('Failed to crawl %s: unknown scheme %s' % (link.url, link.scheme)) return set(), set() def __init__(self, context=None, threads=1): self._threads = threads self.context = context or Context.get() def _make_cache_key(self, links, follow_links): return (follow_links,) + tuple(links) def crawl(self, link_or_links, follow_links=False): links = list(Link.wrap_iterable(link_or_links)) cache_key = self._make_cache_key(links, follow_links) # Memoize crawling to a global Memoizer (Crawler._CRAWL_CACHE). result = self._CRAWL_CACHE.get(cache_key) if result is None: result = self._crawl(links, follow_links) self._CRAWL_CACHE.store(cache_key, result) return result def _crawl(self, link_or_links, follow_links): links, seen = set(), set() queue = Queue() converged = threading.Event() def execute(): while not converged.is_set(): try: link = queue.get(timeout=0.01) except Empty: continue if link not in seen: seen.add(link) try: roots, rels = self.crawl_link(self.context, link) except Exception as e: TRACER.log('Unknown exception encountered: %s' % e) for line in traceback.format_exc().splitlines(): TRACER.log(line) queue.task_done() continue links.update(roots) if follow_links: for rel in rels: if rel not in seen: queue.put(rel) queue.task_done() for i, link in enumerate(link_or_links): TRACER.log('crawling link i=%s link=%s follow_links=%s' % (i, link, follow_links), V=3) queue.put(link) workers = [] for _ in range(self._threads): worker = threading.Thread(target=execute) workers.append(worker) worker.daemon = True worker.start() queue.join() converged.set() # We deliberately do not join the worker threads, since they are no longer of any use to us. return links pex-1.1.14/pex/environment.py0000644000076500000240000001710512623452313016722 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import, print_function import itertools import os import site import sys import uuid from pkg_resources import ( DistributionNotFound, Environment, Requirement, WorkingSet, find_distributions ) from .common import die, open_zip, safe_mkdir, safe_rmtree from .interpreter import PythonInterpreter from .package import distribution_compatible from .pex_builder import PEXBuilder from .pex_info import PexInfo from .tracer import TRACER from .util import CacheHelper, DistributionHelper class PEXEnvironment(Environment): @classmethod def force_local(cls, pex, pex_info): if pex_info.code_hash is None: # Do not support force_local if code_hash is not set. (It should always be set.) return pex explode_dir = os.path.join(pex_info.zip_unsafe_cache, pex_info.code_hash) TRACER.log('PEX is not zip safe, exploding to %s' % explode_dir) if not os.path.exists(explode_dir): explode_tmp = explode_dir + '.' + uuid.uuid4().hex with TRACER.timed('Unzipping %s' % pex): try: safe_mkdir(explode_tmp) with open_zip(pex) as pex_zip: pex_files = (x for x in pex_zip.namelist() if not x.startswith(PEXBuilder.BOOTSTRAP_DIR) and not x.startswith(PexInfo.INTERNAL_CACHE)) pex_zip.extractall(explode_tmp, pex_files) except: # noqa: T803 safe_rmtree(explode_tmp) raise TRACER.log('Renaming %s to %s' % (explode_tmp, explode_dir)) os.rename(explode_tmp, explode_dir) return explode_dir @classmethod def update_module_paths(cls, new_code_path): # Force subsequent imports to come from the .pex directory rather than the .pex file. TRACER.log('Adding to the head of sys.path: %s' % new_code_path) sys.path.insert(0, new_code_path) for name, module in sys.modules.items(): if hasattr(module, "__path__"): module_dir = os.path.join(new_code_path, *name.split(".")) TRACER.log('Adding to the head of %s.__path__: %s' % (module.__name__, module_dir)) module.__path__.insert(0, module_dir) @classmethod def write_zipped_internal_cache(cls, pex, pex_info): prefix_length = len(pex_info.internal_cache) + 1 existing_cached_distributions = [] newly_cached_distributions = [] zip_safe_distributions = [] with open_zip(pex) as zf: # Distribution names are the first element after ".deps/" and before the next "/" distribution_names = set(filter(None, (filename[prefix_length:].split('/')[0] for filename in zf.namelist() if filename.startswith(pex_info.internal_cache)))) # Create Distribution objects from these, and possibly write to disk if necessary. for distribution_name in distribution_names: internal_dist_path = '/'.join([pex_info.internal_cache, distribution_name]) # First check if this is already cached dist_digest = pex_info.distributions.get(distribution_name) or CacheHelper.zip_hash( zf, internal_dist_path) cached_location = os.path.join(pex_info.install_cache, '%s.%s' % ( distribution_name, dist_digest)) if os.path.exists(cached_location): dist = DistributionHelper.distribution_from_path(cached_location) existing_cached_distributions.append(dist) continue else: dist = DistributionHelper.distribution_from_path(os.path.join(pex, internal_dist_path)) if DistributionHelper.zipsafe(dist) and not pex_info.always_write_cache: zip_safe_distributions.append(dist) continue with TRACER.timed('Caching %s' % dist): newly_cached_distributions.append( CacheHelper.cache_distribution(zf, internal_dist_path, cached_location)) return existing_cached_distributions, newly_cached_distributions, zip_safe_distributions @classmethod def load_internal_cache(cls, pex, pex_info): """Possibly cache out the internal cache.""" internal_cache = os.path.join(pex, pex_info.internal_cache) with TRACER.timed('Searching dependency cache: %s' % internal_cache, V=2): if os.path.isdir(pex): for dist in find_distributions(internal_cache): yield dist else: for dist in itertools.chain(*cls.write_zipped_internal_cache(pex, pex_info)): yield dist def __init__(self, pex, pex_info, interpreter=None, **kw): self._internal_cache = os.path.join(pex, pex_info.internal_cache) self._pex = pex self._pex_info = pex_info self._activated = False self._working_set = None self._interpreter = interpreter or PythonInterpreter.get() super(PEXEnvironment, self).__init__( search_path=sys.path if pex_info.inherit_path else [], **kw) def update_candidate_distributions(self, distribution_iter): for dist in distribution_iter: if self.can_add(dist): with TRACER.timed('Adding %s' % dist, V=2): self.add(dist) def can_add(self, dist): return distribution_compatible(dist, self._interpreter, self.platform) def activate(self): if not self._activated: with TRACER.timed('Activating PEX virtual environment from %s' % self._pex): self._working_set = self._activate() self._activated = True return self._working_set def _resolve(self, working_set, reqs): reqs = reqs[:] unresolved_reqs = set() resolveds = set() # Resolve them one at a time so that we can figure out which ones we need to elide should # there be an interpreter incompatibility. for req in reqs: with TRACER.timed('Resolving %s' % req, V=2): try: resolveds.update(working_set.resolve([req], env=self)) except DistributionNotFound as e: TRACER.log('Failed to resolve a requirement: %s' % e) unresolved_reqs.add(e.args[0].project_name) # Older versions of pkg_resources just call `DistributionNotFound(req)` instead of the # modern `DistributionNotFound(req, requirers)` and so we may not have the 2nd requirers # slot at all. if len(e.args) >= 2 and e.args[1]: unresolved_reqs.update(e.args[1]) unresolved_reqs = set([req.lower() for req in unresolved_reqs]) if unresolved_reqs: TRACER.log('Unresolved requirements:') for req in unresolved_reqs: TRACER.log(' - %s' % req) TRACER.log('Distributions contained within this pex:') if not self._pex_info.distributions: TRACER.log(' None') else: for dist in self._pex_info.distributions: TRACER.log(' - %s' % dist) if not self._pex_info.ignore_errors: die('Failed to execute PEX file, missing compatible dependencies for:\n%s' % ( '\n'.join(map(str, unresolved_reqs)))) return resolveds def _activate(self): self.update_candidate_distributions(self.load_internal_cache(self._pex, self._pex_info)) if not self._pex_info.zip_safe and os.path.isfile(self._pex): self.update_module_paths(self.force_local(self._pex, self._pex_info)) all_reqs = [Requirement.parse(req) for req in self._pex_info.requirements] working_set = WorkingSet([]) resolved = self._resolve(working_set, all_reqs) for dist in resolved: with TRACER.timed('Activating %s' % dist, V=2): working_set.add(dist) if os.path.isdir(dist.location): with TRACER.timed('Adding sitedir', V=2): site.addsitedir(dist.location) dist.activate() return working_set pex-1.1.14/pex/executor.py0000644000076500000240000000721412743540264016222 0ustar kwilsonstaff00000000000000# Copyright 2016 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import errno import subprocess from .compatibility import string class Executor(object): """Handles execution of subprocesses in a structured way.""" class ExecutionError(Exception): """Indicates failure to execute.""" def __init__(self, msg, cmd, exc=None): super(Executor.ExecutionError, self).__init__( # noqa '%s while trying to execute `%s`' % (msg, cmd) ) self.executable = cmd.split()[0] if isinstance(cmd, string) else cmd[0] self.cmd = cmd self.exc = exc class NonZeroExit(ExecutionError): """Indicates a non-zero exit code.""" def __init__(self, cmd, exit_code, stdout, stderr): super(Executor.NonZeroExit, self).__init__( # noqa 'received exit code %s during execution of `%s`' % (exit_code, cmd), cmd ) self.exit_code = exit_code self.stdout = stdout self.stderr = stderr class ExecutableNotFound(ExecutionError): """Indicates the executable was not found while attempting to execute.""" def __init__(self, cmd, exc): super(Executor.ExecutableNotFound, self).__init__( # noqa 'caught %r while trying to execute `%s`' % (exc, cmd), cmd ) self.exc = exc @classmethod def open_process(cls, cmd, env=None, cwd=None, combined=False, **kwargs): """Opens a process object via subprocess.Popen(). :param string|list cmd: A list or string representing the command to run. :param dict env: An environment dict for the execution. :param string cwd: The target cwd for command execution. :param bool combined: Whether or not to combine stdin and stdout streams. :return: A `subprocess.Popen` object. :raises: `Executor.ExecutableNotFound` when the executable requested to run does not exist. """ assert len(cmd) > 0, 'cannot execute an empty command!' try: return subprocess.Popen( cmd, stdin=kwargs.pop('stdin', subprocess.PIPE), stdout=kwargs.pop('stdout', subprocess.PIPE), stderr=kwargs.pop('stderr', subprocess.STDOUT if combined else subprocess.PIPE), cwd=cwd, env=env, **kwargs ) except (IOError, OSError) as e: if e.errno == errno.ENOENT: raise cls.ExecutableNotFound(cmd, e) else: raise cls.ExecutionError(repr(e), cmd, e) @classmethod def execute(cls, cmd, env=None, cwd=None, stdin_payload=None, **kwargs): """Execute a command via subprocess.Popen and returns the stdio. :param string|list cmd: A list or string representing the command to run. :param dict env: An environment dict for the execution. :param string cwd: The target cwd for command execution. :param string stdin_payload: A string representing the stdin payload, if any, to send. :return: A tuple of strings representing (stdout, stderr), pre-decoded for utf-8. :raises: `Executor.ExecutableNotFound` when the executable requested to run does not exist. `Executor.NonZeroExit` when the execution fails with a non-zero exit code. """ process = cls.open_process(cmd=cmd, env=env, cwd=cwd, **kwargs) stdout_raw, stderr_raw = process.communicate(input=stdin_payload) # N.B. In cases where `stdout` or `stderr` is passed as parameters, these can be None. stdout = stdout_raw.decode('utf-8') if stdout_raw is not None else stdout_raw stderr = stderr_raw.decode('utf-8') if stderr_raw is not None else stderr_raw if process.returncode != 0: raise cls.NonZeroExit(cmd, process.returncode, stdout, stderr) return stdout, stderr pex-1.1.14/pex/fetcher.py0000644000076500000240000000315612623452313015777 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import import warnings from abc import abstractmethod from .base import maybe_requirement from .compatibility import PY3, AbstractClass if PY3: import urllib.parse as urlparse from urllib.parse import urljoin else: import urlparse from urlparse import urljoin class FetcherBase(AbstractClass): """ A fetcher takes a Requirement and tells us where to crawl to find it. """ @abstractmethod def urls(self, req): raise NotImplementedError class Fetcher(FetcherBase): def __init__(self, urls): self._urls = urls def urls(self, _): return self._urls def __eq__(self, other): if not isinstance(other, Fetcher): return False return self._urls == other._urls class PyPIFetcher(FetcherBase): PYPI_BASE = 'https://pypi.python.org/simple/' def __init__(self, pypi_base=PYPI_BASE, use_mirrors=False): if use_mirrors: warnings.warn('use_mirrors is now deprecated.') if not pypi_base.endswith('/'): pypi_base += '/' pypi_url = urlparse.urlparse(pypi_base) if not pypi_url.scheme: self._pypi_base = 'http://' + pypi_base else: self._pypi_base = pypi_base def urls(self, req): req = maybe_requirement(req) return [urljoin(self._pypi_base, '%s/' % req.project_name)] def __eq__(self, other): if not isinstance(other, PyPIFetcher): return False return self._pypi_base == other._pypi_base def __repr__(self): return 'PyPIFetcher(%r)' % self._pypi_base pex-1.1.14/pex/finders.py0000644000076500000240000002403612671105375016017 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). """The finders we wish we had in setuptools. As of setuptools 3.3, the only finder for zip-based distributions is for eggs. The path-based finder only searches paths ending in .egg and not in .whl (zipped or unzipped.) pex.finders augments pkg_resources with additional finders to achieve functional parity between wheels and eggs in terms of findability with find_distributions. To use: >>> from pex.finders import register_finders >>> register_finders() """ import os import pkgutil import sys import zipimport import pkg_resources if sys.version_info >= (3, 3) and sys.implementation.name == "cpython": import importlib._bootstrap as importlib_bootstrap else: importlib_bootstrap = None class ChainedFinder(object): """A utility to chain together multiple pkg_resources finders.""" @classmethod def of(cls, *chained_finder_or_finder): finders = [] for finder in chained_finder_or_finder: if isinstance(finder, cls): finders.extend(finder.finders) else: finders.append(finder) return cls(finders) def __init__(self, finders): self.finders = finders def __call__(self, importer, path_item, only=False): for finder in self.finders: for dist in finder(importer, path_item, only=only): yield dist def __eq__(self, other): if not isinstance(other, ChainedFinder): return False return self.finders == other.finders # The following methods are somewhat dangerous as pkg_resources._distribution_finders is not an # exposed API. As it stands, pkg_resources doesn't provide an API to chain multiple distribution # finders together. This is probably possible using importlib but that does us no good as the # importlib machinery supporting this is only available in Python >= 3.1. def _get_finder(importer): if not hasattr(pkg_resources, '_distribution_finders'): return None return pkg_resources._distribution_finders.get(importer) def _add_finder(importer, finder): """Register a new pkg_resources path finder that does not replace the existing finder.""" existing_finder = _get_finder(importer) if not existing_finder: pkg_resources.register_finder(importer, finder) else: pkg_resources.register_finder(importer, ChainedFinder.of(existing_finder, finder)) def _remove_finder(importer, finder): """Remove an existing finder from pkg_resources.""" existing_finder = _get_finder(importer) if not existing_finder: return if isinstance(existing_finder, ChainedFinder): try: existing_finder.finders.remove(finder) except ValueError: return if len(existing_finder.finders) == 1: pkg_resources.register_finder(importer, existing_finder.finders[0]) elif len(existing_finder.finders) == 0: pkg_resources.register_finder(importer, pkg_resources.find_nothing) else: pkg_resources.register_finder(importer, pkg_resources.find_nothing) class WheelMetadata(pkg_resources.EggMetadata): """Metadata provider for zipped wheels.""" @classmethod def _split_wheelname(cls, wheelname): split_wheelname = wheelname.split('-') return '-'.join(split_wheelname[:-3]) def _setup_prefix(self): path = self.module_path old = None while path != old: if path.lower().endswith('.whl'): self.egg_name = os.path.basename(path) # TODO(wickman) Test the regression where we have both upper and lower cased package # names. self.egg_info = os.path.join(path, '%s.dist-info' % self._split_wheelname(self.egg_name)) self.egg_root = path break old = path path, base = os.path.split(path) # See https://bitbucket.org/tarek/distribute/issue/274 class FixedEggMetadata(pkg_resources.EggMetadata): """An EggMetadata provider that has functional parity with the disk-based provider.""" @classmethod def normalized_elements(cls, path): path_split = path.split('/') while path_split[-1] in ('', '.'): path_split.pop(-1) return path_split def _fn(self, base, resource_name): # super() does not work here as EggMetadata is an old-style class. original_fn = pkg_resources.EggMetadata._fn(self, base, resource_name) return '/'.join(self.normalized_elements(original_fn)) def _zipinfo_name(self, fspath): fspath = self.normalized_elements(fspath) zip_pre = self.normalized_elements(self.zip_pre) if fspath[:len(zip_pre)] == zip_pre: return '/'.join(fspath[len(zip_pre):]) assert "%s is not a subpath of %s" % (fspath, self.zip_pre) def wheel_from_metadata(location, metadata): if not metadata.has_metadata(pkg_resources.DistInfoDistribution.PKG_INFO): return None from email.parser import Parser pkg_info = Parser().parsestr(metadata.get_metadata(pkg_resources.DistInfoDistribution.PKG_INFO)) return pkg_resources.DistInfoDistribution( location=location, metadata=metadata, # TODO(wickman) Is this necessary or will they get picked up correctly? project_name=pkg_info.get('Name'), version=pkg_info.get('Version'), platform=None) def find_wheels_on_path(importer, path_item, only=False): if not os.path.isdir(path_item) or not os.access(path_item, os.R_OK): return if not only: for entry in os.listdir(path_item): if entry.lower().endswith('.whl'): for dist in pkg_resources.find_distributions(os.path.join(path_item, entry)): yield dist def find_eggs_in_zip(importer, path_item, only=False): if importer.archive.endswith('.whl'): # Defer to wheel importer return metadata = FixedEggMetadata(importer) if metadata.has_metadata('PKG-INFO'): yield pkg_resources.Distribution.from_filename(path_item, metadata=metadata) if only: return # don't yield nested distros for subitem in metadata.resource_listdir('/'): if subitem.endswith('.egg'): subpath = os.path.join(path_item, subitem) for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath): yield dist def find_wheels_in_zip(importer, path_item, only=False): metadata = WheelMetadata(importer) dist = wheel_from_metadata(path_item, metadata) if dist: yield dist __PREVIOUS_FINDER = None def register_finders(): """Register finders necessary for PEX to function properly.""" # If the previous finder is set, then we've already monkeypatched, so skip. global __PREVIOUS_FINDER if __PREVIOUS_FINDER: return # save previous finder so that it can be restored previous_finder = _get_finder(zipimport.zipimporter) assert previous_finder, 'This appears to be using an incompatible setuptools.' # replace the zip finder with our own implementation of find_eggs_in_zip which uses the correct # metadata handler, in addition to find_wheels_in_zip pkg_resources.register_finder( zipimport.zipimporter, ChainedFinder.of(find_eggs_in_zip, find_wheels_in_zip)) # append the wheel finder _add_finder(pkgutil.ImpImporter, find_wheels_on_path) if importlib_bootstrap is not None: _add_finder(importlib_bootstrap.FileFinder, find_wheels_on_path) __PREVIOUS_FINDER = previous_finder def unregister_finders(): """Unregister finders necessary for PEX to function properly.""" global __PREVIOUS_FINDER if not __PREVIOUS_FINDER: return pkg_resources.register_finder(zipimport.zipimporter, __PREVIOUS_FINDER) _remove_finder(pkgutil.ImpImporter, find_wheels_on_path) if importlib_bootstrap is not None: _remove_finder(importlib_bootstrap.FileFinder, find_wheels_on_path) __PREVIOUS_FINDER = None def get_script_from_egg(name, dist): """Returns location, content of script in distribution or (None, None) if not there.""" if name in dist.metadata_listdir('scripts'): return ( os.path.join(dist.egg_info, 'scripts', name), dist.get_metadata('scripts/%s' % name).replace('\r\n', '\n').replace('\r', '\n')) return None, None def safer_name(name): return name.replace('-', '_') def get_script_from_whl(name, dist): # This is true as of at least wheel==0.24. Might need to take into account the # metadata version bundled with the wheel. wheel_scripts_dir = '%s-%s.data/scripts' % (safer_name(dist.key), dist.version) if dist.resource_isdir(wheel_scripts_dir) and name in dist.resource_listdir(wheel_scripts_dir): script_path = os.path.join(wheel_scripts_dir, name) return ( os.path.join(dist.egg_info, script_path), dist.get_resource_string('', script_path).replace(b'\r\n', b'\n').replace(b'\r', b'\n')) return None, None def get_script_from_distribution(name, dist): # PathMetadata: exploded distribution on disk. if isinstance(dist._provider, pkg_resources.PathMetadata): if dist.egg_info.endswith('EGG-INFO'): return get_script_from_egg(name, dist) elif dist.egg_info.endswith('.dist-info'): return get_script_from_whl(name, dist) else: return None, None # FixedEggMetadata: Zipped egg elif isinstance(dist._provider, FixedEggMetadata): return get_script_from_egg(name, dist) # WheelMetadata: Zipped whl (in theory should not experience this at runtime.) elif isinstance(dist._provider, WheelMetadata): return get_script_from_whl(name, dist) return None, None def get_script_from_distributions(name, dists): for dist in dists: script_path, script_content = get_script_from_distribution(name, dist) if script_path: return dist, script_path, script_content return None, None, None def get_entry_point_from_console_script(script, dists): # check all distributions for the console_script "script" entries = frozenset(filter(None, ( dist.get_entry_map().get('console_scripts', {}).get(script) for dist in dists))) # if multiple matches, freak out if len(entries) > 1: raise RuntimeError( 'Ambiguous script specification %s matches multiple entry points:%s' % ( script, ' '.join(map(str, entries)))) if entries: entry_point = next(iter(entries)) # entry points are of the form 'foo = bar', we just want the 'bar' part: return str(entry_point).split('=')[1].strip() pex-1.1.14/pex/http.py0000644000076500000240000002020312720650765015337 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import hashlib import os import shutil import uuid from abc import abstractmethod from email import message_from_string from .common import safe_mkdtemp, safe_open from .compatibility import PY3, AbstractClass from .tracer import TRACER from .variables import ENV from .version import __version__ as PEX_VERSION try: import requests except ImportError: requests = None try: from cachecontrol import CacheControl from cachecontrol.caches import FileCache except ImportError: CacheControl = FileCache = None if PY3: import urllib.request as urllib_request else: import urllib2 as urllib_request # This is available as hashlib.algorithms_guaranteed in >=3.2 and as # hashlib.algorithms in >=2.7, but not available in 2.6, so we enumerate # here. HASHLIB_ALGORITHMS = frozenset(['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']) class Context(AbstractClass): """Encapsulate the networking necessary to do requirement resolution. At a minimum, the Context must implement ``open(link)`` by returning a file-like object. Reference implementations of ``read(link)`` and ``fetch(link)`` are provided based upon ``open(link)`` but may be further specialized by individual implementations. """ DEFAULT_ENCODING = 'iso-8859-1' class Error(Exception): """Error base class for Contexts to wrap application-specific exceptions.""" pass _REGISTRY = [] @classmethod def register(cls, context_impl): """Register a concrete implementation of a :class:`Context` to be recognized.""" cls._REGISTRY.insert(0, context_impl) @classmethod def get(cls): for context_class in cls._REGISTRY: try: context = context_class() TRACER.log('Constructed %s context %r' % (context.__class__.__name__, context), V=4) return context except cls.Error: continue raise cls.Error('Could not initialize a request context.') @abstractmethod def open(self, link): """Return an open file-like object to the link. :param link: The :class:`Link` to open. """ def read(self, link): """Return the binary content associated with the link. :param link: The :class:`Link` to read. """ with contextlib.closing(self.open(link)) as fp: return fp.read() def content(self, link): """Return the encoded content associated with the link. :param link: The :class:`Link` to read. """ def fetch(self, link, into=None): """Fetch the binary content associated with the link and write to a file. :param link: The :class:`Link` to fetch. :keyword into: If specified, write into the directory ``into``. If ``None``, creates a new temporary directory that persists for the duration of the interpreter. """ target = os.path.join(into or safe_mkdtemp(), link.filename) if os.path.exists(target): # Assume that if the local file already exists, it is safe to use. return target with TRACER.timed('Fetching %s' % link.url, V=2): target_tmp = '%s.%s' % (target, uuid.uuid4()) with contextlib.closing(self.open(link)) as in_fp: with safe_open(target_tmp, 'wb') as out_fp: shutil.copyfileobj(in_fp, out_fp) os.rename(target_tmp, target) return target class UrllibContext(Context): """Default Python standard library Context.""" def open(self, link): return urllib_request.urlopen(link.url) def content(self, link): if link.local: raise self.Error('Context.content only works with remote URLs.') with contextlib.closing(self.open(link)) as fp: encoding = message_from_string(str(fp.headers)).get_content_charset(self.DEFAULT_ENCODING) return fp.read().decode(encoding, 'replace') def __init__(self, *args, **kw): TRACER.log('Warning, using a UrllibContext which is known to be flaky.') TRACER.log('Please build pex with the requests module for more reliable downloads.') super(UrllibContext, self).__init__(*args, **kw) Context.register(UrllibContext) class StreamFilelike(object): """A file-like object wrapper around requests streams that performs hash validation.""" @classmethod def detect_algorithm(cls, link): """Detect the hashing algorithm from the fragment in the link, if any.""" if any(link.fragment.startswith('%s=' % algorithm) for algorithm in HASHLIB_ALGORITHMS): algorithm, value = link.fragment.split('=', 2) try: return hashlib.new(algorithm), value except ValueError: # unsupported algorithm return None, None return None, None def __init__(self, request, link, chunk_size=16384): self._iterator = request.iter_content(chunk_size) self.encoding = request.encoding self._bytes = b'' self._link = link self._hasher, self._hash_value = self.detect_algorithm(link) def read(self, length=None): while length is None or len(self._bytes) < length: try: next_chunk = next(self._iterator) if self._hasher: self._hasher.update(next_chunk) self._bytes += next_chunk except StopIteration: self._validate() break if length is None: length = len(self._bytes) chunk, self._bytes = self._bytes[:length], self._bytes[length:] return chunk def _validate(self): if self._hasher: if self._hash_value != self._hasher.hexdigest(): raise Context.Error('%s failed checksum!' % (self._link.url)) else: TRACER.log('Validated %s (%s)' % (self._link.filename, self._link.fragment), V=3) def close(self): pass class RequestsContext(Context): """A requests-based Context.""" USER_AGENT = 'pex/%s' % PEX_VERSION @staticmethod def _create_session(max_retries): session = requests.session() retrying_adapter = requests.adapters.HTTPAdapter(max_retries=max_retries) session.mount('http://', retrying_adapter) session.mount('https://', retrying_adapter) return session def __init__(self, session=None, verify=True, env=ENV): if requests is None: raise RuntimeError('requests is not available. Cannot use a RequestsContext.') self._verify = verify max_retries = env.PEX_HTTP_RETRIES if max_retries < 0: raise ValueError('max_retries may not be negative.') self._max_retries = max_retries self._session = session or self._create_session(self._max_retries) def open(self, link): # requests does not support file:// -- so we must short-circuit manually if link.local: return open(link.local_path, 'rb') # noqa: T802 for attempt in range(self._max_retries + 1): try: return StreamFilelike(self._session.get( link.url, verify=self._verify, stream=True, headers={'User-Agent': self.USER_AGENT}), link) except requests.exceptions.ReadTimeout: # Connect timeouts are handled by the HTTPAdapter, unfortunately read timeouts are not # so we'll retry them ourselves. TRACER.log('Read timeout trying to fetch %s, retrying. %d retries remain.' % ( link.url, self._max_retries - attempt)) except requests.exceptions.RequestException as e: raise self.Error(e) raise self.Error( requests.packages.urllib3.exceptions.MaxRetryError( None, link, 'Exceeded max retries of %d' % self._max_retries)) def content(self, link): if link.local: raise self.Error('Context.content only works with remote URLs.') with contextlib.closing(self.open(link)) as request: return request.read().decode(request.encoding or self.DEFAULT_ENCODING, 'replace') if requests: Context.register(RequestsContext) class CachedRequestsContext(RequestsContext): """A requests-based Context with CacheControl support.""" DEFAULT_CACHE = os.path.join(ENV.PEX_ROOT, 'cache') def __init__(self, cache=None, **kw): self._cache = os.path.realpath(os.path.expanduser(cache or self.DEFAULT_CACHE)) super(CachedRequestsContext, self).__init__( CacheControl(requests.session(), cache=FileCache(self._cache)), **kw) if CacheControl: Context.register(CachedRequestsContext) pex-1.1.14/pex/installer.py0000644000076500000240000001716012741504142016353 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import, print_function import os import sys import tempfile from pkg_resources import Distribution, PathMetadata from .common import safe_mkdtemp, safe_rmtree from .compatibility import WINDOWS from .executor import Executor from .interpreter import PythonInterpreter from .tracer import TRACER from .version import SETUPTOOLS_REQUIREMENT, WHEEL_REQUIREMENT __all__ = ( 'Installer', 'Packager' ) def after_installation(function): def function_wrapper(self, *args, **kw): self._installed = self.run() if not self._installed: raise Installer.InstallFailure('Failed to install %s' % self._source_dir) return function(self, *args, **kw) return function_wrapper class InstallerBase(object): SETUP_BOOTSTRAP_HEADER = "import sys" SETUP_BOOTSTRAP_MODULE = "sys.path.insert(0, %(path)r); import %(module)s" SETUP_BOOTSTRAP_FOOTER = """ __file__ = 'setup.py' sys.argv[0] = 'setup.py' exec(compile(open(__file__, 'rb').read(), __file__, 'exec')) """ class Error(Exception): pass class InstallFailure(Error): pass class IncapableInterpreter(Error): pass def __init__(self, source_dir, strict=True, interpreter=None, install_dir=None): """ Create an installer from an unpacked source distribution in source_dir. If strict=True, fail if any installation dependencies (e.g. distribute) are missing. """ self._source_dir = source_dir self._install_tmp = install_dir or safe_mkdtemp() self._installed = None self._strict = strict self._interpreter = interpreter or PythonInterpreter.get() if not self._interpreter.satisfies(self.capability) and strict: raise self.IncapableInterpreter('Interpreter %s not capable of running %s' % ( self._interpreter.binary, self.__class__.__name__)) def mixins(self): """Return a map from import name to requirement to load into setup script prior to invocation. May be subclassed. """ return {} @property def install_tmp(self): return self._install_tmp def _setup_command(self): """the setup command-line to run, to be implemented by subclasses.""" raise NotImplementedError def _postprocess(self): """a post-processing function to run following setup.py invocation.""" @property def capability(self): """returns the list of requirements for the interpreter to run this installer.""" return list(self.mixins().values()) @property def bootstrap_script(self): bootstrap_modules = [] for module, requirement in self.mixins().items(): path = self._interpreter.get_location(requirement) if not path: assert not self._strict # This should be caught by validation continue bootstrap_modules.append(self.SETUP_BOOTSTRAP_MODULE % {'path': path, 'module': module}) return '\n'.join( [self.SETUP_BOOTSTRAP_HEADER] + bootstrap_modules + [self.SETUP_BOOTSTRAP_FOOTER]) def run(self): if self._installed is not None: return self._installed with TRACER.timed('Installing %s' % self._install_tmp, V=2): command = [self._interpreter.binary, '-'] + self._setup_command() try: Executor.execute(command, env=self._interpreter.sanitized_environment(), cwd=self._source_dir, stdin_payload=self.bootstrap_script.encode('ascii')) self._installed = True except Executor.NonZeroExit as e: self._installed = False name = os.path.basename(self._source_dir) print('**** Failed to install %s (caused by: %r\n):' % (name, e), file=sys.stderr) print('stdout:\n%s\nstderr:\n%s\n' % (e.stdout, e.stderr), file=sys.stderr) return self._installed self._postprocess() return self._installed def cleanup(self): safe_rmtree(self._install_tmp) class Installer(InstallerBase): """Install an unpacked distribution with a setup.py.""" def __init__(self, source_dir, strict=True, interpreter=None): """ Create an installer from an unpacked source distribution in source_dir. If strict=True, fail if any installation dependencies (e.g. setuptools) are missing. """ super(Installer, self).__init__(source_dir, strict=strict, interpreter=interpreter) self._egg_info = None fd, self._install_record = tempfile.mkstemp() os.close(fd) def _setup_command(self): return ['install', '--root=%s' % self._install_tmp, '--prefix=', '--single-version-externally-managed', '--record', self._install_record] def _postprocess(self): installed_files = [] egg_info = None with open(self._install_record) as fp: installed_files = fp.read().splitlines() for line in installed_files: if line.endswith('.egg-info'): assert line.startswith('/'), 'Expect .egg-info to be within install_tmp!' egg_info = line break if not egg_info: self._installed = False return self._installed installed_files = [os.path.relpath(fn, egg_info) for fn in installed_files if fn != egg_info] self._egg_info = os.path.join(self._install_tmp, egg_info[1:]) with open(os.path.join(self._egg_info, 'installed-files.txt'), 'w') as fp: fp.write('\n'.join(installed_files)) fp.write('\n') return self._installed @after_installation def egg_info(self): return self._egg_info @after_installation def root(self): egg_info = self.egg_info() assert egg_info return os.path.realpath(os.path.dirname(egg_info)) @after_installation def distribution(self): base_dir = self.root() egg_info = self.egg_info() metadata = PathMetadata(base_dir, egg_info) return Distribution.from_location(base_dir, os.path.basename(egg_info), metadata=metadata) class DistributionPackager(InstallerBase): def mixins(self): mixins = super(DistributionPackager, self).mixins().copy() mixins.update(setuptools=SETUPTOOLS_REQUIREMENT) return mixins def find_distribution(self): dists = os.listdir(self.install_tmp) if len(dists) == 0: raise self.InstallFailure('No distributions were produced!') elif len(dists) > 1: raise self.InstallFailure('Ambiguous source distributions found: %s' % (' '.join(dists))) else: return os.path.join(self.install_tmp, dists[0]) class Packager(DistributionPackager): """ Create a source distribution from an unpacked setup.py-based project. """ def _setup_command(self): if WINDOWS: return ['sdist', '--formats=zip', '--dist-dir=%s' % self._install_tmp] else: return ['sdist', '--formats=gztar', '--dist-dir=%s' % self._install_tmp] @after_installation def sdist(self): return self.find_distribution() class EggInstaller(DistributionPackager): """ Create a source distribution from an unpacked setup.py-based project. """ def _setup_command(self): return ['bdist_egg', '--dist-dir=%s' % self._install_tmp] @after_installation def bdist(self): return self.find_distribution() class WheelInstaller(DistributionPackager): """ Create a source distribution from an unpacked setup.py-based project. """ MIXINS = { 'setuptools': SETUPTOOLS_REQUIREMENT, 'wheel': WHEEL_REQUIREMENT, } def mixins(self): mixins = super(WheelInstaller, self).mixins().copy() mixins.update(self.MIXINS) return mixins def _setup_command(self): return ['bdist_wheel', '--dist-dir=%s' % self._install_tmp] @after_installation def bdist(self): return self.find_distribution() pex-1.1.14/pex/interpreter.py0000644000076500000240000003112712741504142016720 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). """pex support for interacting with interpreters.""" from __future__ import absolute_import import os import re import sys from collections import defaultdict from pkg_resources import Distribution, Requirement, find_distributions from .base import maybe_requirement from .compatibility import string from .executor import Executor from .tracer import TRACER try: from numbers import Integral except ImportError: Integral = (int, long) # Determine in the most platform-compatible way possible the identity of the interpreter # and its known packages. ID_PY = b""" import sys if hasattr(sys, 'pypy_version_info'): subversion = 'PyPy' elif sys.platform.startswith('java'): subversion = 'Jython' else: subversion = 'CPython' print("%s %s %s %s" % ( subversion, sys.version_info[0], sys.version_info[1], sys.version_info[2])) setuptools_path = None try: import pkg_resources except ImportError: sys.exit(0) requirements = {} for item in sys.path: for dist in pkg_resources.find_distributions(item): requirements[str(dist.as_requirement())] = dist.location for requirement_str, location in requirements.items(): rs = requirement_str.split('==', 2) if len(rs) == 2: print('%s %s %s' % (rs[0], rs[1], location)) """ class PythonIdentity(object): class Error(Exception): pass class InvalidError(Error): pass class UnknownRequirement(Error): pass # TODO(wickman) Support interpreter-specific versions, e.g. PyPy-2.2.1 HASHBANGS = { 'CPython': 'python%(major)d.%(minor)d', 'Jython': 'jython', 'PyPy': 'pypy', } @classmethod def get_subversion(cls): if hasattr(sys, 'pypy_version_info'): subversion = 'PyPy' elif sys.platform.startswith('java'): subversion = 'Jython' else: subversion = 'CPython' return subversion @classmethod def get(cls): return cls(cls.get_subversion(), sys.version_info[0], sys.version_info[1], sys.version_info[2]) @classmethod def from_id_string(cls, id_string): values = id_string.split() if len(values) != 4: raise cls.InvalidError("Invalid id string: %s" % id_string) return cls(str(values[0]), int(values[1]), int(values[2]), int(values[3])) @classmethod def from_path(cls, dirname): interp, version = dirname.split('-') major, minor, patch = version.split('.') return cls(str(interp), int(major), int(minor), int(patch)) def __init__(self, interpreter, major, minor, patch): for var in (major, minor, patch): assert isinstance(var, Integral) self._interpreter = interpreter self._version = (major, minor, patch) @property def interpreter(self): return self._interpreter @property def version(self): return self._version @property def requirement(self): return self.distribution.as_requirement() @property def distribution(self): return Distribution(project_name=self._interpreter, version='.'.join(map(str, self._version))) @classmethod def parse_requirement(cls, requirement, default_interpreter='CPython'): if isinstance(requirement, Requirement): return requirement elif isinstance(requirement, string): try: requirement = Requirement.parse(requirement) except ValueError: try: requirement = Requirement.parse('%s%s' % (default_interpreter, requirement)) except ValueError: raise ValueError('Unknown requirement string: %s' % requirement) return requirement else: raise ValueError('Unknown requirement type: %r' % (requirement,)) def matches(self, requirement): """Given a Requirement, check if this interpreter matches.""" try: requirement = self.parse_requirement(requirement, self._interpreter) except ValueError as e: raise self.UnknownRequirement(str(e)) return self.distribution in requirement def hashbang(self): hashbang_string = self.HASHBANGS.get(self.interpreter, 'CPython') % { 'major': self._version[0], 'minor': self._version[1], 'patch': self._version[2], } return '#!/usr/bin/env %s' % hashbang_string @property def python(self): # return the python version in the format of the 'python' key for distributions # specifically, '2.6', '2.7', '3.2', etc. return '%d.%d' % (self.version[0:2]) def __str__(self): return '%s-%s.%s.%s' % (self._interpreter, self._version[0], self._version[1], self._version[2]) def __repr__(self): return 'PythonIdentity(%r, %s, %s, %s)' % ( self._interpreter, self._version[0], self._version[1], self._version[2]) def __eq__(self, other): return all([isinstance(other, PythonIdentity), self.interpreter == other.interpreter, self.version == other.version]) def __hash__(self): return hash((self._interpreter, self._version)) class PythonInterpreter(object): REGEXEN = ( re.compile(r'jython$'), # NB: OSX ships python binaries named Python so we allow for capital-P. re.compile(r'[Pp]ython$'), re.compile(r'python[23].[0-9]$'), re.compile(r'pypy$'), re.compile(r'pypy-1.[0-9]$'), ) CACHE = {} # memoize executable => PythonInterpreter try: # Versions of distribute prior to the setuptools merge would automatically replace # 'setuptools' requirements with 'distribute'. It provided the 'replacement' kwarg # to toggle this, but it was removed post-merge. COMPATIBLE_SETUPTOOLS = Requirement.parse('setuptools>=1.0', replacement=False) except TypeError: COMPATIBLE_SETUPTOOLS = Requirement.parse('setuptools>=1.0') class Error(Exception): pass class IdentificationError(Error): pass class InterpreterNotFound(Error): pass @classmethod def get(cls): return cls.from_binary(sys.executable) @classmethod def all(cls, paths=None): if paths is None: paths = os.getenv('PATH', '').split(':') return cls.filter(cls.find(paths)) @classmethod def _parse_extras(cls, output_lines): def iter_lines(): for line in output_lines: try: dist_name, dist_version, location = line.split() except ValueError: raise cls.IdentificationError('Could not identify requirement: %s' % line) yield ((dist_name, dist_version), location) return dict(iter_lines()) @classmethod def _from_binary_internal(cls, path_extras): def iter_extras(): for item in sys.path + list(path_extras): for dist in find_distributions(item): if dist.version: yield ((dist.key, dist.version), dist.location) return cls(sys.executable, PythonIdentity.get(), dict(iter_extras())) @classmethod def _from_binary_external(cls, binary, path_extras): environ = cls.sanitized_environment() environ['PYTHONPATH'] = ':'.join(path_extras) stdout, _ = Executor.execute([binary], env=environ, stdin_payload=ID_PY) output = stdout.splitlines() if len(output) == 0: raise cls.IdentificationError('Could not establish identity of %s' % binary) identity, extras = output[0], output[1:] return cls(binary, PythonIdentity.from_id_string(identity), extras=cls._parse_extras(extras)) @classmethod def expand_path(cls, path): if os.path.isfile(path): return [path] elif os.path.isdir(path): return [os.path.join(path, fn) for fn in os.listdir(path)] return [] @classmethod def from_env(cls, hashbang): """Resolve a PythonInterpreter as /usr/bin/env would. :param hashbang: A string, e.g. "python3.3" representing some binary on the $PATH. """ paths = os.getenv('PATH', '').split(':') for path in paths: for fn in cls.expand_path(path): basefile = os.path.basename(fn) if hashbang == basefile: try: return cls.from_binary(fn) except Exception as e: TRACER.log('Could not identify %s: %s' % (fn, e)) @classmethod def from_binary(cls, binary, path_extras=None): path_extras = path_extras or () if binary not in cls.CACHE: if binary == sys.executable: cls.CACHE[binary] = cls._from_binary_internal(path_extras) else: cls.CACHE[binary] = cls._from_binary_external(binary, path_extras) return cls.CACHE[binary] @classmethod def find(cls, paths): """ Given a list of files or directories, try to detect python interpreters amongst them. Returns a list of PythonInterpreter objects. """ pythons = [] for path in paths: for fn in cls.expand_path(path): basefile = os.path.basename(fn) if any(matcher.match(basefile) is not None for matcher in cls.REGEXEN): try: pythons.append(cls.from_binary(fn)) except Exception as e: TRACER.log('Could not identify %s: %s' % (fn, e)) continue return pythons @classmethod def filter(cls, pythons): """ Given a map of python interpreters in the format provided by PythonInterpreter.find(), filter out duplicate versions and versions we would prefer not to use. Returns a map in the same format as find. """ good = [] MAJOR, MINOR, SUBMINOR = range(3) def version_filter(version): return (version[MAJOR] == 2 and version[MINOR] >= 6 or version[MAJOR] == 3 and version[MINOR] >= 2) all_versions = set(interpreter.identity.version for interpreter in pythons) good_versions = filter(version_filter, all_versions) for version in good_versions: # For each candidate, use the latest version we find on the filesystem. candidates = defaultdict(list) for interp in pythons: if interp.identity.version == version: candidates[interp.identity.interpreter].append(interp) for interp_class in candidates: candidates[interp_class].sort( key=lambda interp: os.path.getmtime(interp.binary), reverse=True) good.append(candidates[interp_class].pop(0)) return good @classmethod def sanitized_environment(cls): # N.B. This is merely a hack because sysconfig.py on the default OS X # installation of 2.6/2.7 breaks. env_copy = os.environ.copy() env_copy.pop('MACOSX_DEPLOYMENT_TARGET', None) return env_copy @classmethod def replace(cls, requirement): self = cls.get() if self.identity.matches(requirement): return False for pi in cls.all(): if pi.identity.matches(requirement): break else: raise cls.InterpreterNotFound('Could not find interpreter matching filter!') os.execve(pi.binary, [pi.binary] + sys.argv, cls.sanitized_environment()) def __init__(self, binary, identity, extras=None): """Construct a PythonInterpreter. You should probably PythonInterpreter.from_binary instead. :param binary: The full path of the python binary. :param identity: The :class:`PythonIdentity` of the PythonInterpreter. :param extras: A mapping from (dist.key, dist.version) to dist.location of the extras associated with this interpreter. """ self._binary = os.path.realpath(binary) self._extras = extras or {} self._identity = identity def with_extra(self, key, version, location): extras = self._extras.copy() extras[(key, version)] = location return self.__class__(self._binary, self._identity, extras) @property def extras(self): return self._extras.copy() @property def binary(self): return self._binary @property def identity(self): return self._identity @property def python(self): return self._identity.python @property def version(self): return self._identity.version @property def version_string(self): return str(self._identity) def satisfies(self, capability): if not isinstance(capability, list): raise TypeError('Capability must be a list, got %s' % type(capability)) return not any(self.get_location(req) is None for req in capability) def get_location(self, req): req = maybe_requirement(req) for dist, location in self.extras.items(): dist_name, dist_version = dist if req.key == dist_name and dist_version in req: return location def __hash__(self): return hash((self._binary, self._identity)) def __eq__(self, other): if not isinstance(other, PythonInterpreter): return False return (self._binary, self._identity) == (other._binary, other._identity) def __lt__(self, other): if not isinstance(other, PythonInterpreter): return False return self.version < other.version def __repr__(self): return '%s(%r, %r, %r)' % (self.__class__.__name__, self._binary, self._identity, self._extras) pex-1.1.14/pex/iterator.py0000644000076500000240000000244712623452313016212 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). """The glue between fetchers, crawlers and requirements.""" import itertools from abc import abstractmethod from .compatibility import AbstractClass from .crawler import Crawler from .fetcher import PyPIFetcher from .package import Package class IteratorInterface(AbstractClass): @abstractmethod def iter(self, req): """Return a list of packages that satisfy the requirement.""" pass class Iterator(IteratorInterface): """A requirement iterator, the glue between fetchers, crawlers and requirements.""" def __init__(self, fetchers=None, crawler=None, follow_links=False): self._crawler = crawler or Crawler() self._fetchers = fetchers if fetchers is not None else [PyPIFetcher()] self.__follow_links = follow_links def _iter_requirement_urls(self, req): return itertools.chain.from_iterable(fetcher.urls(req) for fetcher in self._fetchers) def iter(self, req): url_iterator = self._iter_requirement_urls(req) crawled_url_iterator = self._crawler.crawl(url_iterator, follow_links=self.__follow_links) for package in filter(None, map(Package.from_href, crawled_url_iterator)): if package.satisfies(req): yield package pex-1.1.14/pex/link.py0000644000076500000240000000773312670614434015327 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import import os import posixpath from collections import Iterable from .compatibility import string as compatible_string from .compatibility import PY3, WINDOWS, pathname2url, url2pathname from .util import Memoizer if PY3: import urllib.parse as urlparse else: import urlparse class Link(object): """Wrapper around a URL.""" @classmethod def wrap(cls, url): """Given a url that is either a string or :class:`Link`, return a :class:`Link`. :param url: A string-like or :class:`Link` object to wrap. :returns: A :class:`Link` object wrapping the url. """ if isinstance(url, cls): return url elif isinstance(url, compatible_string): return cls(url) else: raise ValueError('url must be either a string or Link.') @classmethod def wrap_iterable(cls, url_or_urls): """Given a string or :class:`Link` or iterable, return an iterable of :class:`Link` objects. :param url_or_urls: A string or :class:`Link` object, or iterable of string or :class:`Link` objects. :returns: A list of :class:`Link` objects. """ try: return [cls.wrap(url_or_urls)] except ValueError: pass if isinstance(url_or_urls, Iterable): return [cls.wrap(url) for url in url_or_urls] raise ValueError('url_or_urls must be string/Link or iterable of strings/Links') @classmethod def _normalize(cls, filename): return urlparse.urljoin('file:', pathname2url( os.path.realpath(os.path.expanduser(filename)))) # A cache for the result of from_filename _FROM_FILENAME_CACHE = Memoizer() @classmethod def from_filename(cls, filename): """Return a :class:`Link` wrapping the local filename.""" result = cls._FROM_FILENAME_CACHE.get(filename) if result is None: result = cls(cls._normalize(filename)) cls._FROM_FILENAME_CACHE.store(filename, result) return result def __init__(self, url): """Construct a :class:`Link` from a url. :param url: A string-like object representing a url. """ purl = urlparse.urlparse(url) if purl.scheme == '' or ( WINDOWS and len(purl.scheme) == 1): # This is likely a drive letter. purl = urlparse.urlparse(self._normalize(url)) self._url = purl def __ne__(self, other): return not self.__eq__(other) def __eq__(self, link): return self.__class__ == link.__class__ and self._url == link._url def __hash__(self): return hash(self._url) def join(self, href): """Given a href relative to this link, return the :class:`Link` of the absolute url. :param href: A string-like path relative to this link. """ return self.wrap(urlparse.urljoin(self.url, href)) @property def filename(self): """The basename of this url.""" return urlparse.unquote(posixpath.basename(self._url.path)) @property def path(self): """The full path of this url with any hostname and scheme components removed.""" return urlparse.unquote(self._url.path) @property def local_path(self): """Returns the local filesystem path (only works for file:// urls).""" assert self.local, 'local_path called on a non-file:// url %s' % (self.url,) return url2pathname(self.path) @property def url(self): """The url string to which this link points.""" return urlparse.urlunparse(self._url) @property def fragment(self): """The url fragment following '#' if any.""" return urlparse.unquote(self._url.fragment) @property def scheme(self): """The URI scheme used by this Link.""" return self._url.scheme @property def local(self): """Is the url a local file?""" return self._url.scheme in ('', 'file') @property def remote(self): """Is the url a remote file?""" return self._url.scheme in ('http', 'https') def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.url) pex-1.1.14/pex/orderedset.py0000644000076500000240000000411112623452313016507 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). # # OrderedSet recipe referenced in the Python standard library docs (bottom): # http://docs.python.org/library/collections.html # # Copied from recipe code found here: http://code.activestate.com/recipes/576694/ with small # modifications # import collections class OrderedSet(collections.MutableSet): KEY, PREV, NEXT = range(3) def __init__(self, iterable=None): self.end = end = [] end += [None, end, end] # sentinel node for doubly linked list self.map = {} # key --> [key, prev, next] if iterable is not None: self |= iterable def __len__(self): return len(self.map) def __contains__(self, key): return key in self.map def add(self, key): if key not in self.map: end = self.end curr = end[self.PREV] curr[self.NEXT] = end[self.PREV] = self.map[key] = [key, curr, end] def update(self, iterable): for key in iterable: self.add(key) def discard(self, key): if key in self.map: key, prev, next = self.map.pop(key) prev[self.NEXT] = next next[self.PREV] = prev def __iter__(self): end = self.end curr = end[self.NEXT] while curr is not end: yield curr[self.KEY] curr = curr[self.NEXT] def __reversed__(self): end = self.end curr = end[self.PREV] while curr is not end: yield curr[self.KEY] curr = curr[self.PREV] def pop(self, last=True): if not self: raise KeyError('set is empty') key = next(reversed(self)) if last else next(iter(self)) self.discard(key) return key def __repr__(self): if not self: return '%s()' % (self.__class__.__name__,) return '%s(%r)' % (self.__class__.__name__, list(self)) def __eq__(self, other): if isinstance(other, OrderedSet): return len(self) == len(other) and list(self) == list(other) return set(self) == set(other) def __del__(self): self.clear() # remove circular references pex-1.1.14/pex/package.py0000644000076500000240000002004612720650765015760 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from pkg_resources import EGG_NAME, parse_version, safe_name, safe_version from .archiver import Archiver from .base import maybe_requirement from .interpreter import PythonInterpreter from .link import Link from .pep425 import PEP425, PEP425Extras from .platforms import Platform from .util import Memoizer class Package(Link): """Base class for named Python binary packages (e.g. source, egg, wheel).""" class Error(Exception): pass class InvalidPackage(Error): pass # The registry of concrete implementations _REGISTRY = set() # The cache of packages that we have already constructed. _HREF_TO_PACKAGE_CACHE = Memoizer() @classmethod def register(cls, package_type): """Register a concrete implementation of a Package to be recognized by pex.""" if not issubclass(package_type, cls): raise TypeError('package_type must be a subclass of Package.') cls._REGISTRY.add(package_type) @classmethod def from_href(cls, href, **kw): """Convert from a url to Package. :param href: The url to parse :type href: string :returns: A Package object if a valid concrete implementation exists, otherwise None. """ package = cls._HREF_TO_PACKAGE_CACHE.get(href) if package is not None: return package link_href = Link.wrap(href) for package_type in cls._REGISTRY: try: package = package_type(link_href.url, **kw) break except package_type.InvalidPackage: continue if package is not None: cls._HREF_TO_PACKAGE_CACHE.store(href, package) return package @property def name(self): return NotImplementedError @property def raw_version(self): return NotImplementedError @property def version(self): return parse_version(self.raw_version) def satisfies(self, requirement): """Determine whether this package matches the requirement. :param requirement: The requirement to compare this Package against :type requirement: string or :class:`pkg_resources.Requirement` :returns: True if the package matches the requirement, otherwise False """ requirement = maybe_requirement(requirement) link_name = safe_name(self.name).lower() if link_name != requirement.key: return False return self.raw_version in requirement def compatible(self, identity, platform=Platform.current()): """Is this link compatible with the given :class:`PythonIdentity` identity and platform? :param identity: The Python identity (e.g. CPython 2.7.5) against which compatibility should be checked. :type identity: :class:`PythonIdentity` :param platform: The platform against which compatibility should be checked. If None, do not check platform compatibility. :type platform: string or None """ raise NotImplementedError class SourcePackage(Package): """A Package representing an uncompiled/unbuilt source distribution.""" @classmethod def split_fragment(cls, fragment): """A heuristic used to split a string into version name/fragment: >>> SourcePackage.split_fragment('pysolr-2.1.0-beta') ('pysolr', '2.1.0-beta') >>> SourcePackage.split_fragment('cElementTree-1.0.5-20051216') ('cElementTree', '1.0.5-20051216') >>> SourcePackage.split_fragment('pil-1.1.7b1-20090412') ('pil', '1.1.7b1-20090412') >>> SourcePackage.split_fragment('django-plugin-2-2.3') ('django-plugin-2', '2.3') """ def likely_version_component(enumerated_fragment): return sum(bool(v and v[0].isdigit()) for v in enumerated_fragment[1].split('.')) fragments = fragment.split('-') if len(fragments) == 1: return fragment, '' max_index, _ = max(enumerate(fragments), key=likely_version_component) return '-'.join(fragments[0:max_index]), '-'.join(fragments[max_index:]) def __init__(self, url, **kw): super(SourcePackage, self).__init__(url, **kw) ext = Archiver.get_extension(self.filename) if ext is None: raise self.InvalidPackage('%s is not a recognized archive format.' % self.filename) fragment = self.filename[:-len(ext)] self._name, self._raw_version = self.split_fragment(fragment) @property def name(self): return safe_name(self._name) @property def raw_version(self): return safe_version(self._raw_version) # SourcePackages are always compatible as they can be translated to a distribution. def compatible(self, identity, platform=Platform.current()): return True class EggPackage(Package): """A Package representing a built egg.""" def __init__(self, url, **kw): super(EggPackage, self).__init__(url, **kw) filename, ext = os.path.splitext(self.filename) if ext.lower() != '.egg': raise self.InvalidPackage('Not an egg: %s' % filename) matcher = EGG_NAME(filename) if not matcher: raise self.InvalidPackage('Could not match egg: %s' % filename) self._name, self._raw_version, self._py_version, self._platform = matcher.group( 'name', 'ver', 'pyver', 'plat') if self._raw_version is None or self._py_version is None: raise self.InvalidPackage('url with .egg extension but bad name: %s' % url) def __hash__(self): return hash((self.name, self.version, self.py_version, self.platform)) @property def name(self): return safe_name(self._name) @property def raw_version(self): return safe_version(self._raw_version) @property def py_version(self): return self._py_version @property def platform(self): return self._platform def compatible(self, identity, platform=Platform.current()): if not Platform.version_compatible(self.py_version, identity.python): return False if not Platform.compatible(self.platform, platform): return False return True class WheelPackage(Package): """A Package representing a built wheel.""" def __init__(self, url, **kw): super(WheelPackage, self).__init__(url, **kw) filename, ext = os.path.splitext(self.filename) if ext.lower() != '.whl': raise self.InvalidPackage('Not a wheel: %s' % filename) try: self._name, self._raw_version, self._py_tag, self._abi_tag, self._arch_tag = ( filename.split('-')) except ValueError: raise self.InvalidPackage('Wheel filename malformed.') # See https://github.com/pypa/pip/issues/1150 for why this is unavoidable. self._name.replace('_', '-') self._raw_version.replace('_', '-') self._supported_tags = frozenset(self._iter_tags()) @property def name(self): return self._name @property def raw_version(self): return self._raw_version def _iter_tags(self): for py in self._py_tag.split('.'): for abi in self._abi_tag.split('.'): for arch in self._arch_tag.split('.'): for real_arch in PEP425Extras.platform_iterator(arch): yield (py, abi, real_arch) def compatible(self, identity, platform=Platform.current()): for tag in PEP425.iter_supported_tags(identity, platform): if tag in self._supported_tags: return True return False Package.register(SourcePackage) Package.register(EggPackage) Package.register(WheelPackage) def distribution_compatible(dist, interpreter=None, platform=None): """Is this distribution compatible with the given interpreter/platform combination? :param interpreter: The Python interpreter against which compatibility should be checked. If None specified, the current interpreter is used. :type identity: :class:`PythonInterpreter` or None :param platform: The platform against which compatibility should be checked. If None, the current platform will be used :type platform: string or None :returns: True if the distribution is compatible, False if it is unrecognized or incompatible. """ interpreter = interpreter or PythonInterpreter.get() platform = platform or Platform.current() package = Package.from_href(dist.location) if not package: return False return package.compatible(interpreter.identity, platform=platform) pex-1.1.14/pex/pep425.py0000644000076500000240000001220512670614434015377 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). """PEP425 handling for pex PEP425 (http://legacy.python.org/dev/peps/pep-0425/) describes a tagging system used to determine whether or not a distribution's platform is compatible with the current platform. It is the tagging system used to describe platform compatibility for wheel files. """ from pkg_resources import get_supported_platform from .platforms import Platform class PEP425Extras(object): """Extensions to platform handling beyond PEP425.""" @classmethod def is_macosx_platform(cls, platform): return platform.startswith('macosx') @classmethod def parse_macosx_tag(cls, platform_tag): invalid_tag = ValueError('invalid macosx tag: %s' % platform_tag) if not cls.is_macosx_platform(platform_tag): raise invalid_tag segments = platform_tag.split('_', 3) if len(segments) != 4: raise invalid_tag if segments[0] != 'macosx': raise invalid_tag try: major, minor = int(segments[1]), int(segments[2]) platform = segments[3] except ValueError: raise invalid_tag return major, minor, platform @classmethod def iter_compatible_osx_platforms(cls, supported_platform): platform_major, platform_minor, platform = cls.parse_macosx_tag(supported_platform) platform_equivalents = set(Platform.MACOSX_PLATFORM_COMPATIBILITY.get(platform, ())) platform_equivalents.add(platform) for minor in range(platform_minor, -1, -1): for binary_compat in platform_equivalents: yield 'macosx_%s_%s_%s' % (platform_major, minor, binary_compat) @classmethod def platform_iterator(cls, platform): """Iterate over all compatible platform tags of a supplied platform tag. :param platform: the platform tag to iterate over """ if cls.is_macosx_platform(platform): for plat in cls.iter_compatible_osx_platforms(platform): yield plat else: yield platform class PEP425(object): # noqa INTERPRETER_TAGS = { 'CPython': 'cp', 'Jython': 'jy', 'PyPy': 'pp', 'IronPython': 'ip', } @classmethod def get_implementation_tag(cls, interpreter_subversion): return cls.INTERPRETER_TAGS.get(interpreter_subversion) @classmethod def get_version_tag(cls, interpreter_version): return ''.join(map(str, interpreter_version[:2])) @classmethod def translate_platform_to_tag(cls, platform): return platform.replace('.', '_').replace('-', '_') @classmethod def get_platform_tag(cls): return cls.translate_platform_to_tag(get_supported_platform()) # TODO(wickman) This implementation is technically incorrect but we need to be able to # predict the supported tags of an interpreter that may not be on this machine or # of a different platform. Alternatively we could store the manifest of supported tags # of a targeted platform in a file to be more correct. @classmethod def _iter_supported_tags(cls, impl, version, platform): """Given a set of tags, iterate over supported tags. :param impl: Python implementation tag e.g. cp, jy, pp. :param version: E.g. '26', '33' :param platform: Platform as from :function:`pkg_resources.get_supported_platform`, for example 'linux-x86_64' or 'macosx-10.4-x86_64'. :returns: Iterator over (pyver, abi, platform) tuples. """ # Predict soabi for reasonable interpreters. This is technically wrong but essentially right. abis = [] if impl == 'cp' and (version.startswith('2') or version.startswith('3')): abis.extend([ 'cp%s' % version, 'cp%sdmu' % version, 'cp%sdm' % version, 'cp%sdu' % version, 'cp%sd' % version, 'cp%smu' % version, 'cp%sm' % version, 'cp%su' % version ]) if version.startswith('3'): abis.extend([ 'abi3' ]) major_version = int(version[0]) minor_versions = [] for minor in range(int(version[1]), -1, -1): minor_versions.append('%d%d' % (major_version, minor)) platforms = list(PEP425Extras.platform_iterator(cls.translate_platform_to_tag(platform))) # interpreter specific for p in platforms: for abi in abis: yield ('%s%s' % (impl, version), abi, p) # everything else for p in platforms + ['any']: for i in ('py', impl): yield ('%s%d' % (i, major_version), 'none', p) for minor_version in minor_versions: yield ('%s%s' % (i, minor_version), 'none', p) @classmethod def iter_supported_tags(cls, identity, platform=get_supported_platform()): """Iterate over the supported tag tuples of this interpreter. :param identity: python interpreter identity over which tags should iterate. :type identity: :class:`PythonIdentity` :param platform: python platform over which tags should iterate, by default the current platform. :returns: Iterator over valid PEP425 tag tuples. """ impl_tag = cls.get_implementation_tag(identity.interpreter) vers_tag = cls.get_version_tag(identity.version) tag_iterator = cls._iter_supported_tags(impl_tag, vers_tag, platform) for tag in tag_iterator: yield tag pex-1.1.14/pex/pex.py0000644000076500000240000004202512743540264015157 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import, print_function import os import sys from contextlib import contextmanager from distutils import sysconfig from site import USER_SITE import pkg_resources from pkg_resources import EntryPoint, WorkingSet, find_distributions from .common import die from .compatibility import exec_function from .environment import PEXEnvironment from .executor import Executor from .finders import get_entry_point_from_console_script, get_script_from_distributions from .interpreter import PythonInterpreter from .orderedset import OrderedSet from .pex_info import PexInfo from .tracer import TRACER from .variables import ENV class DevNull(object): def __init__(self): pass def write(self, *args, **kw): pass class PEX(object): # noqa: T000 """PEX, n. A self-contained python environment.""" class Error(Exception): pass class NotFound(Error): pass @classmethod def clean_environment(cls): try: del os.environ['MACOSX_DEPLOYMENT_TARGET'] except KeyError: pass # Cannot change dictionary size during __iter__ filter_keys = [key for key in os.environ if key.startswith('PEX_')] for key in filter_keys: del os.environ[key] def __init__(self, pex=sys.argv[0], interpreter=None, env=ENV): self._pex = pex self._interpreter = interpreter or PythonInterpreter.get() self._pex_info = PexInfo.from_pex(self._pex) self._pex_info_overrides = PexInfo.from_env(env=env) self._vars = env self._envs = [] self._working_set = None def _activate(self): if not self._working_set: working_set = WorkingSet([]) # set up the local .pex environment pex_info = self._pex_info.copy() pex_info.update(self._pex_info_overrides) self._envs.append(PEXEnvironment(self._pex, pex_info)) # set up other environments as specified in PEX_PATH for pex_path in filter(None, self._vars.PEX_PATH.split(os.pathsep)): pex_info = PexInfo.from_pex(pex_path) pex_info.update(self._pex_info_overrides) self._envs.append(PEXEnvironment(pex_path, pex_info)) # activate all of them for env in self._envs: for dist in env.activate(): working_set.add(dist) self._working_set = working_set return self._working_set @classmethod def _extras_paths(cls): standard_lib = sysconfig.get_python_lib(standard_lib=True) try: makefile = sysconfig.parse_makefile(sysconfig.get_makefile_filename()) except (AttributeError, IOError): # This is not available by default in PyPy's distutils.sysconfig or it simply is # no longer available on the system (IOError ENOENT) makefile = {} extras_paths = filter(None, makefile.get('EXTRASPATH', '').split(':')) for path in extras_paths: yield os.path.join(standard_lib, path) @classmethod def _get_site_packages(cls): try: from site import getsitepackages return set(getsitepackages()) except ImportError: return set() @classmethod def site_libs(cls): site_libs = cls._get_site_packages() site_libs.update([sysconfig.get_python_lib(plat_specific=False), sysconfig.get_python_lib(plat_specific=True)]) # On windows getsitepackages() returns the python stdlib too. if sys.prefix in site_libs: site_libs.remove(sys.prefix) real_site_libs = set(os.path.realpath(path) for path in site_libs) return site_libs | real_site_libs @classmethod def _tainted_path(cls, path, site_libs): paths = frozenset([path, os.path.realpath(path)]) return any(path.startswith(site_lib) for site_lib in site_libs for path in paths) @classmethod def minimum_sys_modules(cls, site_libs, modules=None): """Given a set of site-packages paths, return a "clean" sys.modules. When importing site, modules within sys.modules have their __path__'s populated with additional paths as defined by *-nspkg.pth in site-packages, or alternately by distribution metadata such as *.dist-info/namespace_packages.txt. This can possibly cause namespace packages to leak into imports despite being scrubbed from sys.path. NOTE: This method mutates modules' __path__ attributes in sys.module, so this is currently an irreversible operation. """ modules = modules or sys.modules new_modules = {} for module_name, module in modules.items(): # builtins can stay if not hasattr(module, '__path__'): new_modules[module_name] = module continue # Pop off site-impacting __path__ elements in-place. for k in reversed(range(len(module.__path__))): if cls._tainted_path(module.__path__[k], site_libs): TRACER.log('Scrubbing %s.__path__: %s' % (module_name, module.__path__[k]), V=3) module.__path__.pop(k) # It still contains path elements not in site packages, so it can stay in sys.modules if module.__path__: new_modules[module_name] = module return new_modules @classmethod def minimum_sys_path(cls, site_libs, inherit_path): scrub_paths = OrderedSet() site_distributions = OrderedSet() user_site_distributions = OrderedSet() def all_distribution_paths(path): locations = set(dist.location for dist in find_distributions(path)) return set([path]) | locations | set(os.path.realpath(path) for path in locations) for path_element in sys.path: if cls._tainted_path(path_element, site_libs): TRACER.log('Tainted path element: %s' % path_element) site_distributions.update(all_distribution_paths(path_element)) else: TRACER.log('Not a tainted path element: %s' % path_element, V=2) user_site_distributions.update(all_distribution_paths(USER_SITE)) if not inherit_path: scrub_paths = site_distributions | user_site_distributions for path in user_site_distributions: TRACER.log('Scrubbing from user site: %s' % path) for path in site_distributions: TRACER.log('Scrubbing from site-packages: %s' % path) scrubbed_sys_path = list(OrderedSet(sys.path) - scrub_paths) scrub_from_importer_cache = filter( lambda key: any(key.startswith(path) for path in scrub_paths), sys.path_importer_cache.keys()) scrubbed_importer_cache = dict((key, value) for (key, value) in sys.path_importer_cache.items() if key not in scrub_from_importer_cache) for importer_cache_entry in scrub_from_importer_cache: TRACER.log('Scrubbing from path_importer_cache: %s' % importer_cache_entry, V=2) return scrubbed_sys_path, scrubbed_importer_cache @classmethod def minimum_sys(cls, inherit_path): """Return the minimum sys necessary to run this interpreter, a la python -S. :returns: (sys.path, sys.path_importer_cache, sys.modules) tuple of a bare python installation. """ site_libs = set(cls.site_libs()) for site_lib in site_libs: TRACER.log('Found site-library: %s' % site_lib) for extras_path in cls._extras_paths(): TRACER.log('Found site extra: %s' % extras_path) site_libs.add(extras_path) site_libs = set(os.path.normpath(path) for path in site_libs) sys_path, sys_path_importer_cache = cls.minimum_sys_path(site_libs, inherit_path) sys_modules = cls.minimum_sys_modules(site_libs) return sys_path, sys_path_importer_cache, sys_modules @classmethod @contextmanager def patch_pkg_resources(cls, working_set): """Patch pkg_resources given a new working set.""" def patch(working_set): pkg_resources.working_set = working_set pkg_resources.require = working_set.require pkg_resources.iter_entry_points = working_set.iter_entry_points pkg_resources.run_script = pkg_resources.run_main = working_set.run_script pkg_resources.add_activation_listener = working_set.subscribe old_working_set = pkg_resources.working_set patch(working_set) try: yield finally: patch(old_working_set) # Thar be dragons -- when this contextmanager exits, the interpreter is # potentially in a wonky state since the patches here (minimum_sys_modules # for example) actually mutate global state. This should not be # considered a reversible operation despite being a contextmanager. @classmethod @contextmanager def patch_sys(cls, inherit_path): """Patch sys with all site scrubbed.""" def patch_dict(old_value, new_value): old_value.clear() old_value.update(new_value) def patch_all(path, path_importer_cache, modules): sys.path[:] = path patch_dict(sys.path_importer_cache, path_importer_cache) patch_dict(sys.modules, modules) old_sys_path, old_sys_path_importer_cache, old_sys_modules = ( sys.path[:], sys.path_importer_cache.copy(), sys.modules.copy()) new_sys_path, new_sys_path_importer_cache, new_sys_modules = cls.minimum_sys(inherit_path) patch_all(new_sys_path, new_sys_path_importer_cache, new_sys_modules) yield def _wrap_coverage(self, runner, *args): if not self._vars.PEX_COVERAGE and self._vars.PEX_COVERAGE_FILENAME is None: runner(*args) return try: import coverage except ImportError: die('Could not bootstrap coverage module, aborting.') pex_coverage_filename = self._vars.PEX_COVERAGE_FILENAME if pex_coverage_filename is not None: cov = coverage.coverage(data_file=pex_coverage_filename) else: cov = coverage.coverage(data_suffix=True) TRACER.log('Starting coverage.') cov.start() try: runner(*args) finally: TRACER.log('Stopping coverage') cov.stop() # TODO(wickman) Post-process coverage to elide $PEX_ROOT and make # the report more useful/less noisy. #89 if pex_coverage_filename: cov.save() else: cov.report(show_missing=False, ignore_errors=True, file=sys.stdout) def _wrap_profiling(self, runner, *args): if not self._vars.PEX_PROFILE and self._vars.PEX_PROFILE_FILENAME is None: runner(*args) return pex_profile_filename = self._vars.PEX_PROFILE_FILENAME pex_profile_sort = self._vars.PEX_PROFILE_SORT try: import cProfile as profile except ImportError: import profile profiler = profile.Profile() try: return profiler.runcall(runner, *args) finally: if pex_profile_filename is not None: profiler.dump_stats(pex_profile_filename) else: profiler.print_stats(sort=pex_profile_sort) def execute(self): """Execute the PEX. This function makes assumptions that it is the last function called by the interpreter. """ teardown_verbosity = self._vars.PEX_TEARDOWN_VERBOSE try: pex_inherit_path = self._vars.PEX_INHERIT_PATH or self._pex_info.inherit_path with self.patch_sys(pex_inherit_path): working_set = self._activate() TRACER.log('PYTHONPATH contains:') for element in sys.path: TRACER.log(' %c %s' % (' ' if os.path.exists(element) else '*', element)) TRACER.log(' * - paths that do not exist or will be imported via zipimport') with self.patch_pkg_resources(working_set): self._wrap_coverage(self._wrap_profiling, self._execute) except Exception: # Allow the current sys.excepthook to handle this app exception before we tear things down in # finally, then reraise so that the exit status is reflected correctly. sys.excepthook(*sys.exc_info()) raise except SystemExit as se: # Print a SystemExit error message, avoiding a traceback in python3. # This must happen here, as sys.stderr is about to be torn down if not isinstance(se.code, int) and se.code is not None: print(se.code, file=sys.stderr) raise finally: # squash all exceptions on interpreter teardown -- the primary type here are # atexit handlers failing to run because of things such as: # http://stackoverflow.com/questions/2572172/referencing-other-modules-in-atexit if not teardown_verbosity: sys.stderr.flush() sys.stderr = DevNull() sys.excepthook = lambda *a, **kw: None def _execute(self): force_interpreter = self._vars.PEX_INTERPRETER self.clean_environment() if force_interpreter: TRACER.log('PEX_INTERPRETER specified, dropping into interpreter') return self.execute_interpreter() if self._pex_info_overrides.script and self._pex_info_overrides.entry_point: die('Cannot specify both script and entry_point for a PEX!') if self._pex_info.script and self._pex_info.entry_point: die('Cannot specify both script and entry_point for a PEX!') if self._pex_info_overrides.script: return self.execute_script(self._pex_info_overrides.script) elif self._pex_info_overrides.entry_point: return self.execute_entry(self._pex_info_overrides.entry_point) elif self._pex_info.script: return self.execute_script(self._pex_info.script) elif self._pex_info.entry_point: return self.execute_entry(self._pex_info.entry_point) else: TRACER.log('No entry point specified, dropping into interpreter') return self.execute_interpreter() def execute_interpreter(self): if sys.argv[1:]: try: with open(sys.argv[1]) as fp: name, content = sys.argv[1], fp.read() except IOError as e: die("Could not open %s in the environment [%s]: %s" % (sys.argv[1], sys.argv[0], e)) sys.argv = sys.argv[1:] self.execute_content(name, content) else: import code code.interact() def execute_script(self, script_name): dists = list(self._activate()) entry_point = get_entry_point_from_console_script(script_name, dists) if entry_point: sys.exit(self.execute_entry(entry_point)) dist, script_path, script_content = get_script_from_distributions(script_name, dists) if not dist: raise self.NotFound('Could not find script %s in pex!' % script_name) TRACER.log('Found script %s in %s' % (script_name, dist)) return self.execute_content(script_path, script_content, argv0=script_name) @classmethod def execute_content(cls, name, content, argv0=None): argv0 = argv0 or name try: ast = compile(content, name, 'exec', flags=0, dont_inherit=1) except SyntaxError: die('Unable to parse %s. PEX script support only supports Python scripts.' % name) old_name, old_file = globals().get('__name__'), globals().get('__file__') try: old_argv0, sys.argv[0] = sys.argv[0], argv0 globals()['__name__'] = '__main__' globals()['__file__'] = name exec_function(ast, globals()) finally: if old_name: globals()['__name__'] = old_name else: globals().pop('__name__') if old_file: globals()['__file__'] = old_file else: globals().pop('__file__') sys.argv[0] = old_argv0 @classmethod def execute_entry(cls, entry_point): runner = cls.execute_pkg_resources if ':' in entry_point else cls.execute_module return runner(entry_point) @staticmethod def execute_module(module_name): import runpy runpy.run_module(module_name, run_name='__main__') @staticmethod def execute_pkg_resources(spec): entry = EntryPoint.parse("run = {0}".format(spec)) # See https://pythonhosted.org/setuptools/history.html#id25 for rationale here. if hasattr(entry, 'resolve'): # setuptools >= 11.3 runner = entry.resolve() else: # setuptools < 11.3 runner = entry.load(require=False) return runner() def cmdline(self, args=()): """The commandline to run this environment. :keyword args: Additional arguments to be passed to the application being invoked by the environment. """ cmds = [self._interpreter.binary] cmds.append(self._pex) cmds.extend(args) return cmds def run(self, args=(), with_chroot=False, blocking=True, setsid=False, **kwargs): """Run the PythonEnvironment in an interpreter in a subprocess. :keyword args: Additional arguments to be passed to the application being invoked by the environment. :keyword with_chroot: Run with cwd set to the environment's working directory. :keyword blocking: If true, return the return code of the subprocess. If false, return the Popen object of the invoked subprocess. :keyword setsid: If true, run the PEX in a separate operating system session. Remaining keyword arguments are passed directly to subprocess.Popen. """ self.clean_environment() cmdline = self.cmdline(args) TRACER.log('PEX.run invoking %s' % ' '.join(cmdline)) process = Executor.open_process(cmdline, cwd=self._pex if with_chroot else os.getcwd(), preexec_fn=os.setsid if setsid else None, stdin=kwargs.pop('stdin', None), stdout=kwargs.pop('stdout', None), stderr=kwargs.pop('stderr', None), **kwargs) return process.wait() if blocking else process pex-1.1.14/pex/pex_bootstrapper.py0000644000076500000240000000617412623453545017772 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import os import sys import zipfile __all__ = ('bootstrap_pex',) def pex_info_name(entry_point): """Return the PEX-INFO for an entry_point""" return os.path.join(entry_point, 'PEX-INFO') def is_compressed(entry_point): return os.path.exists(entry_point) and not os.path.exists(pex_info_name(entry_point)) def read_pexinfo_from_directory(entry_point): with open(pex_info_name(entry_point), 'rb') as fp: return fp.read() def read_pexinfo_from_zip(entry_point): with contextlib.closing(zipfile.ZipFile(entry_point)) as zf: return zf.read('PEX-INFO') def read_pex_info_content(entry_point): """Return the raw content of a PEX-INFO.""" if is_compressed(entry_point): return read_pexinfo_from_zip(entry_point) else: return read_pexinfo_from_directory(entry_point) def get_pex_info(entry_point): """Return the PexInfo object for an entry point.""" from . import pex_info pex_info_content = read_pex_info_content(entry_point) if pex_info_content: return pex_info.PexInfo.from_json(pex_info_content) raise ValueError('Invalid entry_point: %s' % entry_point) # TODO(wickman) Remove once resolved (#91): # https://bitbucket.org/pypa/setuptools/issue/154/build_zipmanifest-results-should-be def monkeypatch_build_zipmanifest(): import pkg_resources if not hasattr(pkg_resources, 'build_zipmanifest'): return old_build_zipmanifest = pkg_resources.build_zipmanifest def memoized_build_zipmanifest(archive, memo={}): if archive not in memo: memo[archive] = old_build_zipmanifest(archive) return memo[archive] pkg_resources.build_zipmanifest = memoized_build_zipmanifest def find_in_path(target_interpreter): if os.path.exists(target_interpreter): return target_interpreter for directory in os.getenv('PATH', '').split(os.pathsep): try_path = os.path.join(directory, target_interpreter) if os.path.exists(try_path): return try_path def maybe_reexec_pex(): from .variables import ENV if not ENV.PEX_PYTHON: return from .common import die from .tracer import TRACER target_python = ENV.PEX_PYTHON target = find_in_path(target_python) if not target: die('Failed to find interpreter specified by PEX_PYTHON: %s' % target) if os.path.exists(target) and os.path.realpath(target) != os.path.realpath(sys.executable): TRACER.log('Detected PEX_PYTHON, re-exec to %s' % target) ENV.delete('PEX_PYTHON') os.execve(target, [target_python] + sys.argv, ENV.copy()) def bootstrap_pex(entry_point): from .finders import register_finders monkeypatch_build_zipmanifest() register_finders() maybe_reexec_pex() from . import pex pex.PEX(entry_point).execute() def bootstrap_pex_env(entry_point): """Bootstrap the current runtime environment using a given pex.""" from .environment import PEXEnvironment from .finders import register_finders from .pex_info import PexInfo monkeypatch_build_zipmanifest() register_finders() PEXEnvironment(entry_point, PexInfo.from_pex(entry_point)).activate() pex-1.1.14/pex/pex_builder.py0000644000076500000240000004146612720650765016700 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import import logging import os from pkg_resources import DefaultProvider, ZipProvider, get_provider from .common import Chroot, chmod_plus_x, open_zip, safe_mkdir, safe_mkdtemp from .compatibility import to_bytes from .compiler import Compiler from .finders import get_entry_point_from_console_script, get_script_from_distributions from .interpreter import PythonInterpreter from .pex_info import PexInfo from .util import CacheHelper, DistributionHelper BOOTSTRAP_ENVIRONMENT = b""" import os import sys __entry_point__ = None if '__file__' in locals() and __file__ is not None: __entry_point__ = os.path.dirname(__file__) elif '__loader__' in locals(): from zipimport import zipimporter from pkgutil import ImpLoader if hasattr(__loader__, 'archive'): __entry_point__ = __loader__.archive elif isinstance(__loader__, ImpLoader): __entry_point__ = os.path.dirname(__loader__.get_filename()) if __entry_point__ is None: sys.stderr.write('Could not launch python executable!\\n') sys.exit(2) sys.path[0] = os.path.abspath(sys.path[0]) sys.path.insert(0, os.path.abspath(os.path.join(__entry_point__, '.bootstrap'))) from _pex.pex_bootstrapper import bootstrap_pex bootstrap_pex(__entry_point__) """ class PEXBuilder(object): """Helper for building PEX environments.""" class Error(Exception): pass class ImmutablePEX(Error): pass class InvalidDistribution(Error): pass class InvalidDependency(Error): pass class InvalidExecutableSpecification(Error): pass BOOTSTRAP_DIR = ".bootstrap" def __init__(self, path=None, interpreter=None, chroot=None, pex_info=None, preamble=None, copy=False): """Initialize a pex builder. :keyword path: The path to write the PEX as it is built. If ``None`` is specified, a temporary directory will be created. :keyword interpreter: The interpreter to use to build this PEX environment. If ``None`` is specified, the current interpreter is used. :keyword chroot: If specified, preexisting :class:`Chroot` to use for building the PEX. :keyword pex_info: A preexisting PexInfo to use to build the PEX. :keyword preamble: If supplied, execute this code prior to bootstrapping this PEX environment. :type preamble: str :keyword copy: If False, attempt to create the pex environment via hard-linking, falling back to copying across devices. If True, always copy. .. versionchanged:: 0.8 The temporary directory created when ``path`` is not specified is now garbage collected on interpreter exit. """ self._chroot = chroot or Chroot(path or safe_mkdtemp()) self._pex_info = pex_info or PexInfo.default() self._frozen = False self._interpreter = interpreter or PythonInterpreter.get() self._shebang = self._interpreter.identity.hashbang() self._logger = logging.getLogger(__name__) self._preamble = to_bytes(preamble or '') self._copy = copy self._distributions = set() def _ensure_unfrozen(self, name='Operation'): if self._frozen: raise self.ImmutablePEX('%s is not allowed on a frozen PEX!' % name) @property def interpreter(self): return self._interpreter def chroot(self): return self._chroot def clone(self, into=None): """Clone this PEX environment into a new PEXBuilder. :keyword into: (optional) An optional destination directory to clone this PEXBuilder into. If not specified, a temporary directory will be created. Clones PEXBuilder into a new location. This is useful if the PEXBuilder has been frozen and rendered immutable. .. versionchanged:: 0.8 The temporary directory created when ``into`` is not specified is now garbage collected on interpreter exit. """ chroot_clone = self._chroot.clone(into=into) clone = self.__class__( chroot=chroot_clone, interpreter=self._interpreter, pex_info=self._pex_info.copy(), preamble=self._preamble, copy=self._copy) clone.set_shebang(self._shebang) for dist in self._distributions: clone.add_distribution(dist) return clone def path(self): return self.chroot().path() @property def info(self): return self._pex_info @info.setter def info(self, value): if not isinstance(value, PexInfo): raise TypeError('PEXBuilder.info must be a PexInfo!') self._ensure_unfrozen('Changing PexInfo') self._pex_info = value def add_source(self, filename, env_filename): """Add a source to the PEX environment. :param filename: The source filename to add to the PEX. :param env_filename: The destination filename in the PEX. This path must be a relative path. """ self._ensure_unfrozen('Adding source') self._copy_or_link(filename, env_filename, "source") def add_resource(self, filename, env_filename): """Add a resource to the PEX environment. :param filename: The source filename to add to the PEX. :param env_filename: The destination filename in the PEX. This path must be a relative path. """ self._ensure_unfrozen('Adding a resource') self._copy_or_link(filename, env_filename, "resource") def add_requirement(self, req): """Add a requirement to the PEX environment. :param req: A requirement that should be resolved in this environment. .. versionchanged:: 0.8 Removed ``dynamic`` and ``repo`` keyword arguments as they were unused. """ self._ensure_unfrozen('Adding a requirement') self._pex_info.add_requirement(req) def set_executable(self, filename, env_filename=None): """Set the executable for this environment. :param filename: The file that should be executed within the PEX environment when the PEX is invoked. :keyword env_filename: (optional) The name that the executable file should be stored as within the PEX. By default this will be the base name of the given filename. The entry point of the PEX may also be specified via ``PEXBuilder.set_entry_point``. """ self._ensure_unfrozen('Setting the executable') if self._pex_info.script: raise self.InvalidExecutableSpecification('Cannot set both entry point and script of PEX!') if env_filename is None: env_filename = os.path.basename(filename) if self._chroot.get("executable"): raise self.InvalidExecutableSpecification( "Setting executable on a PEXBuilder that already has one!") self._copy_or_link(filename, env_filename, "executable") entry_point = env_filename entry_point.replace(os.path.sep, '.') self._pex_info.entry_point = entry_point.rpartition('.')[0] def set_script(self, script): """Set the entry point of this PEX environment based upon a distribution script. :param script: The script name as defined either by a console script or ordinary script within the setup.py of one of the distributions added to the PEX. :raises: :class:`PEXBuilder.InvalidExecutableSpecification` if the script is not found in any distribution added to the PEX. """ # check if 'script' is a console_script entry_point = get_entry_point_from_console_script(script, self._distributions) if entry_point: self.set_entry_point(entry_point) return # check if 'script' is an ordinary script script_path, _, _ = get_script_from_distributions(script, self._distributions) if script_path: if self._pex_info.entry_point: raise self.InvalidExecutableSpecification('Cannot set both entry point and script of PEX!') self._pex_info.script = script return raise self.InvalidExecutableSpecification( 'Could not find script %r in any distribution %s within PEX!' % ( script, ', '.join(str(d) for d in self._distributions))) def set_entry_point(self, entry_point): """Set the entry point of this PEX environment. :param entry_point: The entry point of the PEX in the form of ``module`` or ``module:symbol``, or ``None``. :type entry_point: string or None By default the entry point is None. The behavior of a ``None`` entry point is dropping into an interpreter. If ``module``, it will be executed via ``runpy.run_module``. If ``module:symbol``, it is equivalent to ``from module import symbol; symbol()``. The entry point may also be specified via ``PEXBuilder.set_executable``. """ self._ensure_unfrozen('Setting an entry point') self._pex_info.entry_point = entry_point def set_shebang(self, shebang): """Set the exact shebang line for the PEX file. For example, pex_builder.set_shebang('/home/wickman/Local/bin/python3.4'). This is used to override the default behavior which is to have a #!/usr/bin/env line referencing an interpreter compatible with the one used to build the PEX. :param shebang: The shebang line. If it does not include the leading '#!' it will be added. :type shebang: str """ self._shebang = '#!%s' % shebang if not shebang.startswith('#!') else shebang def _add_dist_dir(self, path, dist_name): for root, _, files in os.walk(path): for f in files: filename = os.path.join(root, f) relpath = os.path.relpath(filename, path) target = os.path.join(self._pex_info.internal_cache, dist_name, relpath) self._copy_or_link(filename, target) return CacheHelper.dir_hash(path) def _add_dist_zip(self, path, dist_name): with open_zip(path) as zf: for name in zf.namelist(): if name.endswith('/'): continue target = os.path.join(self._pex_info.internal_cache, dist_name, name) self._chroot.write(zf.read(name), target) return CacheHelper.zip_hash(zf) def _prepare_code_hash(self): self._pex_info.code_hash = CacheHelper.pex_hash(self._chroot.path()) def add_distribution(self, dist, dist_name=None): """Add a :class:`pkg_resources.Distribution` from its handle. :param dist: The distribution to add to this environment. :keyword dist_name: (optional) The name of the distribution e.g. 'Flask-0.10.0'. By default this will be inferred from the distribution itself should it be formatted in a standard way. :type dist: :class:`pkg_resources.Distribution` """ self._ensure_unfrozen('Adding a distribution') dist_name = dist_name or os.path.basename(dist.location) self._distributions.add(dist) if os.path.isdir(dist.location): dist_hash = self._add_dist_dir(dist.location, dist_name) else: dist_hash = self._add_dist_zip(dist.location, dist_name) # add dependency key so that it can rapidly be retrieved from cache self._pex_info.add_distribution(dist_name, dist_hash) def add_dist_location(self, dist, name=None): """Add a distribution by its location on disk. :param dist: The path to the distribution to add. :keyword name: (optional) The name of the distribution, should the dist directory alone be ambiguous. Packages contained within site-packages directories may require specifying ``name``. :raises PEXBuilder.InvalidDistribution: When the path does not contain a matching distribution. PEX supports packed and unpacked .whl and .egg distributions, as well as any distribution supported by setuptools/pkg_resources. """ self._ensure_unfrozen('Adding a distribution') bdist = DistributionHelper.distribution_from_path(dist) if bdist is None: raise self.InvalidDistribution('Could not find distribution at %s' % dist) self.add_distribution(bdist) self.add_requirement(bdist.as_requirement()) def add_egg(self, egg): """Alias for add_dist_location.""" self._ensure_unfrozen('Adding an egg') return self.add_dist_location(egg) # TODO(wickman) Consider changing this behavior to put the onus on the consumer # of pex to write the pex sources correctly. def _prepare_inits(self): relative_digest = self._chroot.get("source") init_digest = set() for path in relative_digest: split_path = path.split(os.path.sep) for k in range(1, len(split_path)): sub_path = os.path.sep.join(split_path[0:k] + ['__init__.py']) if sub_path not in relative_digest and sub_path not in init_digest: import_string = "__import__('pkg_resources').declare_namespace(__name__)" try: self._chroot.write(import_string, sub_path) except TypeError: # Python 3 self._chroot.write(bytes(import_string, 'UTF-8'), sub_path) init_digest.add(sub_path) def _precompile_source(self): source_relpaths = [path for label in ('source', 'executable', 'main', 'bootstrap') for path in self._chroot.filesets.get(label, ()) if path.endswith('.py')] compiler = Compiler(self.interpreter) compiled_relpaths = compiler.compile(self._chroot.path(), source_relpaths) for compiled in compiled_relpaths: self._chroot.touch(compiled, label='bytecode') def _prepare_manifest(self): self._chroot.write(self._pex_info.dump().encode('utf-8'), PexInfo.PATH, label='manifest') def _prepare_main(self): self._chroot.write(self._preamble + b'\n' + BOOTSTRAP_ENVIRONMENT, '__main__.py', label='main') def _copy_or_link(self, src, dst, label=None): if self._copy: self._chroot.copy(src, dst, label) else: self._chroot.link(src, dst, label) # TODO(wickman) Ideally we unqualify our setuptools dependency and inherit whatever is # bundled into the environment so long as it is compatible (and error out if not.) # # As it stands, we're picking and choosing the pieces we think we need, which means # if there are bits of setuptools imported from elsewhere they may be incompatible with # this. def _prepare_bootstrap(self): # Writes enough of setuptools into the .pex .bootstrap directory so that we can be fully # self-contained. wrote_setuptools = False setuptools = DistributionHelper.distribution_from_path( self._interpreter.get_location('setuptools'), name='setuptools') if setuptools is None: raise RuntimeError('Failed to find setuptools while building pex!') for fn, content_stream in DistributionHelper.walk_data(setuptools): if fn.startswith('pkg_resources') or fn.startswith('_markerlib'): if not fn.endswith('.pyc'): # We'll compile our own .pyc's later. dst = os.path.join(self.BOOTSTRAP_DIR, fn) self._chroot.write(content_stream.read(), dst, 'bootstrap') wrote_setuptools = True if not wrote_setuptools: raise RuntimeError( 'Failed to extract pkg_resources from setuptools. Perhaps pants was linked with an ' 'incompatible setuptools.') libraries = { 'pex': '_pex', } for source_name, target_location in libraries.items(): provider = get_provider(source_name) if not isinstance(provider, DefaultProvider): mod = __import__(source_name, fromlist=['ignore']) provider = ZipProvider(mod) for fn in provider.resource_listdir(''): if fn.endswith('.py'): self._chroot.write(provider.get_resource_string(source_name, fn), os.path.join(self.BOOTSTRAP_DIR, target_location, fn), 'bootstrap') def freeze(self, bytecode_compile=True): """Freeze the PEX. :param bytecode_compile: If True, precompile .py files into .pyc files when freezing code. Freezing the PEX writes all the necessary metadata and environment bootstrapping code. It may only be called once and renders the PEXBuilder immutable. """ self._ensure_unfrozen('Freezing the environment') self._prepare_inits() self._prepare_code_hash() self._prepare_manifest() self._prepare_bootstrap() self._prepare_main() if bytecode_compile: self._precompile_source() self._frozen = True def build(self, filename, bytecode_compile=True): """Package the PEX into a zipfile. :param filename: The filename where the PEX should be stored. :param bytecode_compile: If True, precompile .py files into .pyc files. If the PEXBuilder is not yet frozen, it will be frozen by ``build``. This renders the PEXBuilder immutable. """ if not self._frozen: self.freeze(bytecode_compile=bytecode_compile) try: os.unlink(filename + '~') self._logger.warn('Previous binary unexpectedly exists, cleaning: %s' % (filename + '~')) except OSError: # The expectation is that the file does not exist, so continue pass if os.path.dirname(filename): safe_mkdir(os.path.dirname(filename)) with open(filename + '~', 'ab') as pexfile: assert os.path.getsize(pexfile.name) == 0 pexfile.write(to_bytes('%s\n' % self._shebang)) self._chroot.zip(filename + '~', mode='a') if os.path.exists(filename): os.unlink(filename) os.rename(filename + '~', filename) chmod_plus_x(filename) pex-1.1.14/pex/pex_info.py0000644000076500000240000002175212720650765016201 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import, print_function import json import os import warnings from collections import namedtuple from .common import open_zip from .compatibility import string as compatibility_string from .compatibility import PY2 from .orderedset import OrderedSet from .variables import ENV PexPlatform = namedtuple('PexPlatform', 'interpreter version strict') # TODO(wickman) Split this into a PexInfoBuilder/PexInfo to ensure immutability. # Issue #92. class PexInfo(object): """PEX metadata. # Build metadata: build_properties: BuildProperties # (key-value information about the build system) code_hash: str # sha1 hash of all names/code in the archive distributions: {dist_name: str} # map from distribution name (i.e. path in # the internal cache) to its cache key (sha1) requirements: list # list of requirements for this environment # Environment options pex_root: string # root of all pex-related files eg: ~/.pex entry_point: string # entry point into this pex script: string # script to execute in this pex environment # at most one of script/entry_point can be specified zip_safe: True, default False # is this pex zip safe? inherit_path: True, default False # should this pex inherit site-packages + PYTHONPATH? ignore_errors: True, default False # should we ignore inability to resolve dependencies? always_write_cache: False # should we always write the internal cache to disk first? # this is useful if you have very large dependencies that # do not fit in RAM constrained environments .. versionchanged:: 0.8 Removed the ``repositories`` and ``indices`` information, as they were never implemented. """ PATH = 'PEX-INFO' INTERNAL_CACHE = '.deps' @classmethod def make_build_properties(cls): from .interpreter import PythonInterpreter from pkg_resources import get_platform pi = PythonInterpreter.get() return { 'class': pi.identity.interpreter, 'version': pi.identity.version, 'platform': get_platform(), } @classmethod def default(cls): pex_info = { 'requirements': [], 'distributions': {}, 'build_properties': cls.make_build_properties(), } return cls(info=pex_info) @classmethod def from_pex(cls, pex): if os.path.isfile(pex): with open_zip(pex) as zf: pex_info = zf.read(cls.PATH) else: with open(os.path.join(pex, cls.PATH)) as fp: pex_info = fp.read() return cls.from_json(pex_info) @classmethod def from_json(cls, content): if isinstance(content, bytes): content = content.decode('utf-8') return cls(info=json.loads(content)) @classmethod def from_env(cls, env=ENV): supplied_env = env.strip_defaults() zip_safe = None if supplied_env.PEX_FORCE_LOCAL is None else not supplied_env.PEX_FORCE_LOCAL pex_info = { 'pex_root': supplied_env.PEX_ROOT, 'entry_point': supplied_env.PEX_MODULE, 'script': supplied_env.PEX_SCRIPT, 'zip_safe': zip_safe, 'inherit_path': supplied_env.PEX_INHERIT_PATH, 'ignore_errors': supplied_env.PEX_IGNORE_ERRORS, 'always_write_cache': supplied_env.PEX_ALWAYS_CACHE, } # Filter out empty entries not explicitly set in the environment. return cls(info=dict((k, v) for (k, v) in pex_info.items() if v is not None)) @classmethod def _parse_requirement_tuple(cls, requirement_tuple): if isinstance(requirement_tuple, (tuple, list)): if len(requirement_tuple) != 3: raise ValueError('Malformed PEX requirement: %r' % (requirement_tuple,)) # pre 0.8.x requirement type: warnings.warn('Attempting to use deprecated PEX feature. Please upgrade past PEX 0.8.x.') return requirement_tuple[0] elif isinstance(requirement_tuple, compatibility_string): return requirement_tuple raise ValueError('Malformed PEX requirement: %r' % (requirement_tuple,)) def __init__(self, info=None): """Construct a new PexInfo. This should not be used directly.""" if info is not None and not isinstance(info, dict): raise ValueError('PexInfo can only be seeded with a dict, got: ' '%s of type %s' % (info, type(info))) self._pex_info = info or {} self._distributions = self._pex_info.get('distributions', {}) requirements = self._pex_info.get('requirements', []) if not isinstance(requirements, (list, tuple)): raise ValueError('Expected requirements to be a list, got %s' % type(requirements)) self._requirements = OrderedSet(self._parse_requirement_tuple(req) for req in requirements) def _get_safe(self, key): if key not in self._pex_info: return None value = self._pex_info[key] return value.encode('utf-8') if PY2 else value @property def build_properties(self): """Information about the system on which this PEX was generated. :returns: A dictionary containing metadata about the environment used to build this PEX. """ return self._pex_info.get('build_properties', {}) @build_properties.setter def build_properties(self, value): if not isinstance(value, dict): raise TypeError('build_properties must be a dictionary!') self._pex_info['build_properties'] = self.make_build_properties() self._pex_info['build_properties'].update(value) @property def zip_safe(self): """Whether or not this PEX should be treated as zip-safe. If set to false and the PEX is zipped, the contents of the PEX will be unpacked into a directory within the PEX_ROOT prior to execution. This allows code and frameworks depending upon __file__ existing on disk to operate normally. By default zip_safe is True. May be overridden at runtime by the $PEX_FORCE_LOCAL environment variable. """ return self._pex_info.get('zip_safe', True) @zip_safe.setter def zip_safe(self, value): self._pex_info['zip_safe'] = bool(value) @property def inherit_path(self): """Whether or not this PEX should be allowed to inherit system dependencies. By default, PEX environments are scrubbed of all system distributions prior to execution. This means that PEX files cannot rely upon preexisting system libraries. By default inherit_path is False. This may be overridden at runtime by the $PEX_INHERIT_PATH environment variable. """ return self._pex_info.get('inherit_path', False) @inherit_path.setter def inherit_path(self, value): self._pex_info['inherit_path'] = bool(value) @property def ignore_errors(self): return self._pex_info.get('ignore_errors', False) @ignore_errors.setter def ignore_errors(self, value): self._pex_info['ignore_errors'] = bool(value) @property def code_hash(self): return self._pex_info.get('code_hash') @code_hash.setter def code_hash(self, value): self._pex_info['code_hash'] = value @property def entry_point(self): return self._get_safe('entry_point') @entry_point.setter def entry_point(self, value): self._pex_info['entry_point'] = value @property def script(self): return self._get_safe('script') @script.setter def script(self, value): self._pex_info['script'] = value def add_requirement(self, requirement): self._requirements.add(str(requirement)) @property def requirements(self): return self._requirements def add_distribution(self, location, sha): self._distributions[location] = sha @property def distributions(self): return self._distributions @property def always_write_cache(self): return self._pex_info.get('always_write_cache', False) @always_write_cache.setter def always_write_cache(self, value): self._pex_info['always_write_cache'] = bool(value) @property def pex_root(self): return os.path.expanduser(self._pex_info.get('pex_root', os.path.join('~', '.pex'))) @pex_root.setter def pex_root(self, value): self._pex_info['pex_root'] = value @property def internal_cache(self): return self.INTERNAL_CACHE @property def install_cache(self): return os.path.join(self.pex_root, 'install') @property def zip_unsafe_cache(self): return os.path.join(self.pex_root, 'code') def update(self, other): if not isinstance(other, PexInfo): raise TypeError('Cannot merge a %r with PexInfo' % type(other)) self._pex_info.update(other._pex_info) self._distributions.update(other.distributions) self._requirements.update(other.requirements) def dump(self, **kwargs): pex_info_copy = self._pex_info.copy() pex_info_copy['requirements'] = list(self._requirements) pex_info_copy['distributions'] = self._distributions.copy() return json.dumps(pex_info_copy, **kwargs) def copy(self): return self.from_json(self.dump()) pex-1.1.14/pex/platforms.py0000644000076500000240000000452312623452313016365 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import import re import sys from pkg_resources import compatible_platforms, get_supported_platform class Platform(object): class UnknownPlatformError(Exception): def __init__(self, platform): super(Platform.UnknownPlatformError, self).__init__('Unknown platform: %s' % platform) # noqa # It blows my mind this code is not in distutils or distribute. MACOSX_VERSION_STRING = re.compile(r"macosx-(\d+)\.(\d+)-(\S+)") MACOSX_PLATFORM_COMPATIBILITY = { 'i386': ('i386',), 'ppc': ('ppc',), 'x86_64': ('x86_64',), 'ppc64': ('ppc64',), 'fat': ('i386', 'ppc'), 'intel': ('i386', 'x86_64'), 'fat3': ('i386', 'ppc', 'x86_64'), 'fat64': ('ppc64', 'x86_64'), 'universal': ('i386', 'ppc', 'ppc64', 'x86_64') } @staticmethod def current(): return get_supported_platform() @staticmethod def python(): return sys.version[:3] @classmethod def compatible(cls, package, platform): if package is None or platform is None or package == platform: return True MAJOR, MINOR, PLATFORM = range(1, 4) package_match = cls.MACOSX_VERSION_STRING.match(package) platform_match = cls.MACOSX_VERSION_STRING.match(platform) if not (package_match and platform_match): return compatible_platforms(package, platform) if package_match.group(MAJOR) != platform_match.group(MAJOR): return False if int(package_match.group(MINOR)) > int(platform_match.group(MINOR)): return False package_platform = package_match.group(PLATFORM) if package_platform not in cls.MACOSX_PLATFORM_COMPATIBILITY: raise cls.UnknownPlatformError(package_platform) sys_platform = platform_match.group(PLATFORM) if sys_platform not in cls.MACOSX_PLATFORM_COMPATIBILITY: raise cls.UnknownPlatformError(sys_platform) package_compatibility = set(cls.MACOSX_PLATFORM_COMPATIBILITY[package_platform]) system_compatibility = set(cls.MACOSX_PLATFORM_COMPATIBILITY[sys_platform]) return bool(package_compatibility.intersection(system_compatibility)) @staticmethod def version_compatible(package_py_version, py_version): return package_py_version is None or py_version is None or package_py_version == py_version pex-1.1.14/pex/requirements.py0000644000076500000240000000627012623452313017102 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from .resolvable import Resolvable from .resolver_options import ResolverOptionsBuilder class UnsupportedLine(Exception): pass def _startswith_any(line, things): return any(line.startswith(thing) for thing in things) def _get_parameter(line): sline = line.split('=') if len(sline) != 2: sline = line.split() if len(sline) != 2: raise UnsupportedLine('Unrecognized line format: %s' % line) return sline[1] class RequirementsTxtSentinel(object): def __init__(self, filename): self.filename = filename # Process lines in the requirements.txt format as defined here: # https://pip.pypa.io/en/latest/reference/pip_install.html#requirements-file-format def requirements_from_lines(lines, builder=None, relpath=None): relpath = relpath or os.getcwd() builder = builder.clone() if builder else ResolverOptionsBuilder() to_resolve = [] for line in lines: line = line.strip() if not line or line.startswith('#'): continue elif line.startswith('-e '): raise UnsupportedLine('Editable distributions not supported: %s' % line) elif _startswith_any(line, ('-i ', '--index-url')): builder.set_index(_get_parameter(line)) elif line.startswith('--extra-index-url'): builder.add_index(_get_parameter(line)) elif _startswith_any(line, ('-f ', '--find-links')): builder.add_repository(_get_parameter(line)) elif line.startswith('--allow-external'): builder.allow_external(_get_parameter(line)) elif line.startswith('--allow-all-external'): builder.allow_all_external() elif line.startswith('--allow-unverified'): builder.allow_unverified(_get_parameter(line)) elif line.startswith('--no-index'): builder.clear_indices() elif line.startswith('--no-use-wheel'): builder.no_use_wheel() # defer the conversion of strings/files to resolvables until all options defined # within the current grouping of lines has been processed. elif _startswith_any(line, ('-r ', '--requirement')): path = os.path.join(relpath, _get_parameter(line)) to_resolve.append(RequirementsTxtSentinel(path)) else: to_resolve.append(line) resolvables = [] for resolvable in to_resolve: if isinstance(resolvable, RequirementsTxtSentinel): resolvables.extend(requirements_from_file(resolvable.filename, builder=builder)) else: try: resolvables.append(Resolvable.get(resolvable, builder)) except Resolvable.Error as e: raise UnsupportedLine('Could not resolve line: %s (%s)' % (resolvable, e)) return resolvables def requirements_from_file(filename, builder=None): """Return a list of :class:`Resolvable` objects from a requirements.txt file. :param filename: The filename of the requirements.txt :keyword builder: (optional) The ResolverOptionsBuilder from which we should inherit default resolver options. :type builder: :class:`ResolverOptionsBuilder` """ relpath = os.path.dirname(filename) with open(filename, 'r') as fp: return requirements_from_lines(fp.readlines(), builder=builder, relpath=relpath) pex-1.1.14/pex/resolvable.py0000644000076500000240000002304512623452313016514 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import re from abc import abstractmethod, abstractproperty from pkg_resources import Requirement, safe_extra from .base import maybe_requirement, requirement_is_exact from .compatibility import string as compatibility_string from .compatibility import AbstractClass from .installer import InstallerBase, Packager from .package import Package from .resolver_options import ResolverOptionsBuilder, ResolverOptionsInterface # Extract extras as specified per "declaring extras": # https://pythonhosted.org/setuptools/setuptools.html _EXTRAS_PATTERN = re.compile(r'(?P
.*)\[(?P.*)\]$') def strip_extras(resolvable_string): match = _EXTRAS_PATTERN.match(resolvable_string) if match: resolvable_string, extras = match.groupdict()['main'], match.groupdict()['extras'] extras = [safe_extra(extra.strip()) for extra in extras.split(',')] else: extras = [] return resolvable_string, extras class Resolvable(AbstractClass): """An entity that can be resolved into a package.""" class Error(Exception): pass class InvalidRequirement(Error): pass _REGISTRY = [] @classmethod def register(cls, implementation): """Register an implementation of a Resolvable. :param implementation: The resolvable implementation. :type implementation: :class:`Resolvable` """ cls._REGISTRY.append(implementation) @classmethod def get(cls, resolvable_string, options_builder=None): """Get a :class:`Resolvable` from a string. :returns: A :class:`Resolvable` or ``None`` if no implementation was appropriate. """ options_builder = options_builder or ResolverOptionsBuilder() for resolvable_impl in cls._REGISTRY: try: return resolvable_impl.from_string(resolvable_string, options_builder) except cls.InvalidRequirement: continue raise cls.InvalidRequirement('Unknown requirement type: %s' % resolvable_string) # @abstractmethod - Only available in Python 3.3+ @classmethod def from_string(cls, requirement_string, options_builder): """Produce a resolvable from this requirement string. :returns: Instance of the particular Resolvable implementation. :raises InvalidRequirement: If requirement_string is not a valid string representation of the resolvable. """ raise cls.InvalidRequirement('Resolvable is abstract.') def __init__(self, options): if not isinstance(options, ResolverOptionsInterface): raise TypeError('Resolvable must be initialized with a ResolverOptionsInterface, got %s' % ( type(options))) self._options = options @property def options(self): """The ResolverOptions for this Resolvable.""" return self._options @abstractmethod def compatible(self, iterator): """Given a finder of type :class:`Iterator` (possibly ignored), determine which packages are compatible with this resolvable. :returns: An iterable of compatible :class:`Package` objects. """ @abstractmethod def packages(self): """Return a list of :class:`Package` objects that this resolvable resolves. :returns: An iterable of compatible :class:`Package` objects. """ @abstractproperty def name(self): """The distribution key associated with this resolvable, i.e. the name of the packages this resolvable will produce.""" # TODO(wickman) Call this "cacheable" instead? @abstractproperty def exact(self): """Whether or not this resolvable specifies an exact (cacheable) requirement.""" # TODO(wickman) Currently 'interpreter' is unused but it is reserved for environment # marker evaluation per PEP426 and: # https://bitbucket.org/pypa/setuptools/issue/353/allow-distributionrequires-be-evaluated def extras(self, interpreter=None): """Return the "extras" tags associated with this resolvable if any.""" return [] class ResolvableRepository(Resolvable): """A VCS repository resolvable, e.g. 'git+', 'svn+', 'hg+', 'bzr+' packages.""" COMPATIBLE_VCS = frozenset(['git', 'svn', 'hg', 'bzr']) @classmethod def from_string(cls, requirement_string, options_builder): if any(requirement_string.startswith('%s+' % vcs) for vcs in cls.COMPATIBLE_VCS): # further delegate pass # TODO(wickman) Implement: Issue #93. raise cls.InvalidRequirement('Versioning system URLs not supported.') def __init__(self, options): super(ResolvableRepository, self).__init__(options) def compatible(self, iterator): return [] def packages(self): return [] @property def name(self): raise NotImplemented @property def exact(self): return True class ResolvablePackage(Resolvable): """A package (.tar.gz, .egg, .whl, etc) resolvable.""" # TODO(wickman) Implement extras parsing for ResolvablePackage @classmethod def from_string(cls, requirement_string, options_builder): requirement_string, extras = strip_extras(requirement_string) package = Package.from_href(requirement_string) if package is None: raise cls.InvalidRequirement('Requirement string does not appear to be a package.') return cls(package, options_builder.build(package.name), extras=extras) def __init__(self, package, options, extras=None): self.package = package self._extras = extras super(ResolvablePackage, self).__init__(options) def compatible(self, iterator): return [] def packages(self): return [self.package] @property def name(self): return self.package.name @property def exact(self): return True def extras(self, interpreter=None): return self._extras def __eq__(self, other): return isinstance(other, ResolvablePackage) and self.package == other.package def __hash__(self): return hash(self.package) def __str__(self): return str(self.package) class ResolvableRequirement(Resolvable): """A requirement (e.g. 'setuptools', 'Flask>=0.8,<0.9', 'pex[whl]').""" @classmethod def from_string(cls, requirement_string, options_builder): try: req = maybe_requirement(requirement_string) except ValueError: raise cls.InvalidRequirement('%s does not appear to be a requirement string.' % requirement_string) return cls(req, options_builder.build(req.key)) def __init__(self, requirement, options): self.requirement = requirement super(ResolvableRequirement, self).__init__(options) def compatible(self, iterator): sorter = self.options.get_sorter() return sorter.sort(package for package in iterator.iter(self.requirement)) def packages(self): iterator = self.options.get_iterator() sorter = self.options.get_sorter() return sorter.sort(iterator.iter(self.requirement)) @property def name(self): return self.requirement.key @property def exact(self): return requirement_is_exact(self.requirement) def extras(self, interpreter=None): return list(self.requirement.extras) def __eq__(self, other): return isinstance(other, ResolvableRequirement) and self.requirement == other.requirement def __hash__(self): return hash(self.requirement) def __str__(self): return str(self.requirement) class ResolvableDirectory(ResolvablePackage): """A source directory (with setup.py) resolvable.""" @classmethod def is_installable(cls, requirement_string): if not os.path.isdir(requirement_string): return False return os.path.isfile(os.path.join(requirement_string, 'setup.py')) @classmethod def from_string(cls, requirement_string, options_builder): requirement_string, extras = strip_extras(requirement_string) if cls.is_installable(requirement_string): try: # TODO(wickman) This is one case where interpreter is necessary to be fully correct. This # may indicate that packages() should take interpreter like extras does. Once we have # metadata in setup.cfg or whatever, then we can get the interpreter out of the equation. sdist = Packager(requirement_string).sdist() except InstallerBase.Error: raise cls.InvalidRequirement('Could not create source distribution for %s' % requirement_string) package = Package.from_href(sdist) return ResolvablePackage(package, options_builder.build(package.name), extras=extras) else: raise cls.InvalidRequirement('%s does not appear to be an installable directory.' % requirement_string) Resolvable.register(ResolvableDirectory) Resolvable.register(ResolvableRepository) Resolvable.register(ResolvablePackage) Resolvable.register(ResolvableRequirement) # TODO(wickman) Because we explicitly acknowledge all implementations of Resolvable here, # perhaps move away from a registry pattern and integrate into Resolvable classmethod. def resolvables_from_iterable(iterable, builder): """Given an iterable of resolvable-like objects, return list of Resolvable objects. :param iterable: An iterable of :class:`Resolvable`, :class:`Requirement`, :class:`Package`, or `str` to map into an iterable of :class:`Resolvable` objects. :returns: A list of :class:`Resolvable` objects. """ def translate(obj): if isinstance(obj, Resolvable): return obj elif isinstance(obj, Requirement): return ResolvableRequirement(obj, builder.build(obj.key)) elif isinstance(obj, Package): return ResolvablePackage(obj, builder.build(obj.name)) elif isinstance(obj, compatibility_string): return Resolvable.get(obj, builder) else: raise ValueError('Do not know how to resolve %s' % type(obj)) return list(map(translate, iterable)) pex-1.1.14/pex/resolver.py0000644000076500000240000003440312670614434016225 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import print_function import os import shutil import time from collections import namedtuple from pkg_resources import safe_name from .common import safe_mkdir from .fetcher import Fetcher from .interpreter import PythonInterpreter from .iterator import Iterator, IteratorInterface from .orderedset import OrderedSet from .package import Package, distribution_compatible from .platforms import Platform from .resolvable import ResolvableRequirement, resolvables_from_iterable from .resolver_options import ResolverOptionsBuilder from .tracer import TRACER from .util import DistributionHelper class Untranslateable(Exception): pass class Unsatisfiable(Exception): pass class StaticIterator(IteratorInterface): """An iterator that iterates over a static list of packages.""" def __init__(self, packages): self._packages = packages def iter(self, req): for package in self._packages: if package.satisfies(req): yield package class _ResolvedPackages(namedtuple('_ResolvedPackages', 'resolvable packages parent')): @classmethod def empty(cls): return cls(None, OrderedSet(), None) def merge(self, other): if other.resolvable is None: return _ResolvedPackages(self.resolvable, self.packages, self.parent) return _ResolvedPackages( self.resolvable, self.packages & other.packages, self.parent) class _ResolvableSet(object): @classmethod def normalize(cls, name): return safe_name(name).lower() def __init__(self, tuples=None): # A list of _ResolvedPackages self.__tuples = tuples or [] def _collapse(self): # Collapse all resolvables by name along with the intersection of all compatible packages. # If the set of compatible packages is the empty set, then we cannot satisfy all the # specifications for a particular name (e.g. "setuptools==2.2 setuptools>4".) # # We need to return the resolvable since it carries its own network context and configuration # regarding package precedence. This is arbitrary -- we could just as easily say "last # resolvable wins" but it seems highly unlikely this will materially affect anybody # adversely but could be the source of subtle resolution quirks. resolvables = {} for resolved_packages in self.__tuples: key = self.normalize(resolved_packages.resolvable.name) previous = resolvables.get(key, _ResolvedPackages.empty()) if previous.resolvable is None: resolvables[key] = resolved_packages else: resolvables[key] = previous.merge(resolved_packages) return resolvables def _synthesize_parents(self, name): def render_resolvable(resolved_packages): return '%s%s' % ( str(resolved_packages.resolvable), '(from: %s)' % resolved_packages.parent if resolved_packages.parent else '') return ', '.join( render_resolvable(resolved_packages) for resolved_packages in self.__tuples if self.normalize(resolved_packages.resolvable.name) == self.normalize(name)) def _check(self): # Check whether or not the resolvables in this set are satisfiable, raise an exception if not. for name, resolved_packages in self._collapse().items(): if not resolved_packages.packages: raise Unsatisfiable('Could not satisfy all requirements for %s:\n %s' % ( resolved_packages.resolvable, self._synthesize_parents(name))) def merge(self, resolvable, packages, parent=None): """Add a resolvable and its resolved packages.""" self.__tuples.append(_ResolvedPackages(resolvable, OrderedSet(packages), parent)) self._check() def get(self, name): """Get the set of compatible packages given a resolvable name.""" resolvable, packages, parent = self._collapse().get( self.normalize(name), _ResolvedPackages.empty()) return packages def packages(self): """Return a snapshot of resolvable => compatible packages set from the resolvable set.""" return list(self._collapse().values()) def extras(self, name): return set.union( *[set(tup.resolvable.extras()) for tup in self.__tuples if self.normalize(tup.resolvable.name) == self.normalize(name)]) def replace_built(self, built_packages): """Return a copy of this resolvable set but with built packages. :param dict built_packages: A mapping from a resolved package to its locally built package. :returns: A new resolvable set with built package replacements made. """ def map_packages(resolved_packages): packages = OrderedSet(built_packages.get(p, p) for p in resolved_packages.packages) return _ResolvedPackages(resolved_packages.resolvable, packages, resolved_packages.parent) return _ResolvableSet([map_packages(rp) for rp in self.__tuples]) class Resolver(object): """Interface for resolving resolvable entities into python packages.""" class Error(Exception): pass @classmethod def filter_packages_by_interpreter(cls, packages, interpreter, platform): return [package for package in packages if package.compatible(interpreter.identity, platform)] def __init__(self, interpreter=None, platform=None): self._interpreter = interpreter or PythonInterpreter.get() self._platform = platform or Platform.current() def package_iterator(self, resolvable, existing=None): if existing: existing = resolvable.compatible(StaticIterator(existing)) else: existing = resolvable.packages() return self.filter_packages_by_interpreter(existing, self._interpreter, self._platform) def build(self, package, options): context = options.get_context() translator = options.get_translator(self._interpreter, self._platform) with TRACER.timed('Fetching %s' % package.url, V=2): local_package = Package.from_href(context.fetch(package)) if local_package is None: raise Untranslateable('Could not fetch package %s' % package) with TRACER.timed('Translating %s into distribution' % local_package.local_path, V=2): dist = translator.translate(local_package) if dist is None: raise Untranslateable('Package %s is not translateable by %s' % (package, translator)) if not distribution_compatible(dist, self._interpreter, self._platform): raise Untranslateable( 'Could not get distribution for %s on platform %s.' % (package, self._platform)) return dist def resolve(self, resolvables, resolvable_set=None): resolvables = [(resolvable, None) for resolvable in resolvables] resolvable_set = resolvable_set or _ResolvableSet() processed_resolvables = set() processed_packages = {} distributions = {} while resolvables: while resolvables: resolvable, parent = resolvables.pop(0) if resolvable in processed_resolvables: continue packages = self.package_iterator(resolvable, existing=resolvable_set.get(resolvable.name)) resolvable_set.merge(resolvable, packages, parent) processed_resolvables.add(resolvable) built_packages = {} for resolvable, packages, parent in resolvable_set.packages(): assert len(packages) > 0, 'ResolvableSet.packages(%s) should not be empty' % resolvable package = next(iter(packages)) if resolvable.name in processed_packages: # TODO implement backtracking? if package != processed_packages[resolvable.name]: raise self.Error('Ambiguous resolvable: %s' % resolvable) continue if package not in distributions: dist = self.build(package, resolvable.options) built_package = Package.from_href(dist.location) built_packages[package] = built_package distributions[built_package] = dist package = built_package distribution = distributions[package] processed_packages[resolvable.name] = package new_parent = '%s->%s' % (parent, resolvable) if parent else str(resolvable) resolvables.extend( (ResolvableRequirement(req, resolvable.options), new_parent) for req in distribution.requires(extras=resolvable_set.extras(resolvable.name))) resolvable_set = resolvable_set.replace_built(built_packages) return list(distributions.values()) class CachingResolver(Resolver): """A package resolver implementing a package cache.""" @classmethod def filter_packages_by_ttl(cls, packages, ttl, now=None): now = now if now is not None else time.time() return [package for package in packages if package.remote or package.local and (now - os.path.getmtime(package.local_path)) < ttl] def __init__(self, cache, cache_ttl, *args, **kw): self.__cache = cache self.__cache_ttl = cache_ttl safe_mkdir(self.__cache) super(CachingResolver, self).__init__(*args, **kw) # Short-circuiting package iterator. def package_iterator(self, resolvable, existing=None): iterator = Iterator(fetchers=[Fetcher([self.__cache])]) packages = self.filter_packages_by_interpreter( resolvable.compatible(iterator), self._interpreter, self._platform) if packages: if resolvable.exact: return packages if self.__cache_ttl: packages = self.filter_packages_by_ttl(packages, self.__cache_ttl) if packages: return packages return super(CachingResolver, self).package_iterator(resolvable, existing=existing) # Caching sandwich. def build(self, package, options): # cache package locally if package.remote: package = Package.from_href(options.get_context().fetch(package, into=self.__cache)) os.utime(package.local_path, None) # build into distribution dist = super(CachingResolver, self).build(package, options) # if distribution is not in cache, copy target = os.path.join(self.__cache, os.path.basename(dist.location)) if not os.path.exists(target): shutil.copyfile(dist.location, target + '~') os.rename(target + '~', target) os.utime(target, None) return DistributionHelper.distribution_from_path(target) def resolve( requirements, fetchers=None, interpreter=None, platform=None, context=None, precedence=None, cache=None, cache_ttl=None): """Produce all distributions needed to (recursively) meet `requirements` :param requirements: An iterator of Requirement-like things, either :class:`pkg_resources.Requirement` objects or requirement strings. :keyword fetchers: (optional) A list of :class:`Fetcher` objects for locating packages. If unspecified, the default is to look for packages on PyPI. :keyword interpreter: (optional) A :class:`PythonInterpreter` object to use for building distributions and for testing distribution compatibility. :keyword platform: (optional) A PEP425-compatible platform string to use for filtering compatible distributions. If unspecified, the current platform is used, as determined by `Platform.current()`. :keyword context: (optional) A :class:`Context` object to use for network access. If unspecified, the resolver will attempt to use the best available network context. :type threads: int :keyword precedence: (optional) An ordered list of allowable :class:`Package` classes to be used for producing distributions. For example, if precedence is supplied as ``(WheelPackage, SourcePackage)``, wheels will be preferred over building from source, and eggs will not be used at all. If ``(WheelPackage, EggPackage)`` is suppplied, both wheels and eggs will be used, but the resolver will not resort to building anything from source. :keyword cache: (optional) A directory to use to cache distributions locally. :keyword cache_ttl: (optional integer in seconds) If specified, consider non-exact matches when resolving requirements. For example, if ``setuptools==2.2`` is specified and setuptools 2.2 is available in the cache, it will always be used. However, if a non-exact requirement such as ``setuptools>=2,<3`` is specified and there exists a setuptools distribution newer than cache_ttl seconds that satisfies the requirement, then it will be used. If the distribution is older than cache_ttl seconds, it will be ignored. If ``cache_ttl`` is not specified, resolving inexact requirements will always result in making network calls through the ``context``. :returns: List of :class:`pkg_resources.Distribution` instances meeting ``requirements``. :raises Unsatisfiable: If ``requirements`` is not transitively satisfiable. :raises Untranslateable: If no compatible distributions could be acquired for a particular requirement. This method improves upon the setuptools dependency resolution algorithm by maintaining sets of all compatible distributions encountered for each requirement rather than the single best distribution encountered for each requirement. This prevents situations where ``tornado`` and ``tornado==2.0`` could be treated as incompatible with each other because the "best distribution" when encountering ``tornado`` was tornado 3.0. Instead, ``resolve`` maintains the set of compatible distributions for each requirement as it is encountered, and iteratively filters the set. If the set of distributions ever becomes empty, then ``Unsatisfiable`` is raised. .. versionchanged:: 0.8 A number of keywords were added to make requirement resolution slightly easier to configure. The optional ``obtainer`` keyword was replaced by ``fetchers``, ``translator``, ``context``, ``threads``, ``precedence``, ``cache`` and ``cache_ttl``, also all optional keywords. .. versionchanged:: 1.0 The ``translator`` and ``threads`` keywords have been removed. The choice of threading policy is now implicit. The choice of translation policy is dictated by ``precedence`` directly. .. versionchanged:: 1.0 ``resolver`` is now just a wrapper around the :class:`Resolver` and :class:`CachingResolver` classes. """ builder = ResolverOptionsBuilder( fetchers=fetchers, precedence=precedence, context=context, ) if cache: resolver = CachingResolver(cache, cache_ttl, interpreter=interpreter, platform=platform) else: resolver = Resolver(interpreter=interpreter, platform=platform) return resolver.resolve(resolvables_from_iterable(requirements, builder)) pex-1.1.14/pex/resolver_options.py0000644000076500000240000001321712623452313017772 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import print_function from pkg_resources import safe_name from .crawler import Crawler from .fetcher import Fetcher, PyPIFetcher from .http import Context from .installer import EggInstaller, WheelInstaller from .iterator import Iterator from .package import EggPackage, SourcePackage, WheelPackage from .sorter import Sorter from .translator import ChainedTranslator, EggTranslator, SourceTranslator, WheelTranslator class ResolverOptionsInterface(object): def get_context(self): raise NotImplemented def get_crawler(self): raise NotImplemented def get_sorter(self): raise NotImplemented def get_translator(self, interpreter, platform): raise NotImplemented def get_iterator(self): raise NotImplemented class ResolverOptionsBuilder(object): """A helper that processes options into a ResolverOptions object. Used by command-line and requirements.txt processors to configure a resolver. """ def __init__(self, fetchers=None, allow_all_external=False, allow_external=None, allow_unverified=None, precedence=None, context=None): self._fetchers = fetchers if fetchers is not None else [PyPIFetcher()] self._allow_all_external = allow_all_external self._allow_external = allow_external if allow_external is not None else set() self._allow_unverified = allow_unverified if allow_unverified is not None else set() self._precedence = precedence if precedence is not None else Sorter.DEFAULT_PACKAGE_PRECEDENCE self._context = context or Context.get() def clone(self): return ResolverOptionsBuilder( fetchers=self._fetchers[:], allow_all_external=self._allow_all_external, allow_external=self._allow_external.copy(), allow_unverified=self._allow_unverified.copy(), precedence=self._precedence[:], context=self._context, ) def add_index(self, index): fetcher = PyPIFetcher(index) if fetcher not in self._fetchers: self._fetchers.append(fetcher) return self def set_index(self, index): self._fetchers = [PyPIFetcher(index)] return self def add_repository(self, repo): fetcher = Fetcher([repo]) if fetcher not in self._fetchers: self._fetchers.append(fetcher) return self def clear_indices(self): self._fetchers = [fetcher for fetcher in self._fetchers if not isinstance(fetcher, PyPIFetcher)] return self def allow_all_external(self): self._allow_all_external = True return self def allow_external(self, key): self._allow_external.add(safe_name(key).lower()) return self def allow_unverified(self, key): self._allow_unverified.add(safe_name(key).lower()) return self def use_wheel(self): if WheelPackage not in self._precedence: self._precedence = (WheelPackage,) + self._precedence return self def no_use_wheel(self): self._precedence = tuple( [precedent for precedent in self._precedence if precedent is not WheelPackage]) return self def allow_builds(self): if SourcePackage not in self._precedence: self._precedence = self._precedence + (SourcePackage,) return self def no_allow_builds(self): self._precedence = tuple( [precedent for precedent in self._precedence if precedent is not SourcePackage]) return self def build(self, key): return ResolverOptions( fetchers=self._fetchers, allow_external=self._allow_all_external or key in self._allow_external, allow_unverified=key in self._allow_unverified, precedence=self._precedence, context=self._context, ) class ResolverOptions(ResolverOptionsInterface): def __init__(self, fetchers=None, allow_external=False, allow_unverified=False, precedence=None, context=None): self._fetchers = fetchers if fetchers is not None else [PyPIFetcher()] self._allow_external = allow_external self._allow_unverified = allow_unverified self._precedence = precedence if precedence is not None else Sorter.DEFAULT_PACKAGE_PRECEDENCE self._context = context or Context.get() # TODO(wickman) Revisit with Github #58 def get_context(self): return self._context def get_crawler(self): return Crawler(self.get_context()) # get_sorter and get_translator are arguably options that should be global # except that --no-use-wheel fucks this shit up. hm. def get_sorter(self): return Sorter(self._precedence) def get_translator(self, interpreter, platform): translators = [] # TODO(wickman) This is not ideal -- consider an explicit link between a Package # and its Installer type rather than mapping this here, precluding the ability to # easily add new package types (or we just forego that forever.) for package in self._precedence: if package is WheelPackage: translators.append(WheelTranslator(interpreter=interpreter, platform=platform)) elif package is EggPackage: translators.append(EggTranslator(interpreter=interpreter, platform=platform)) elif package is SourcePackage: installer_impl = WheelInstaller if WheelPackage in self._precedence else EggInstaller translators.append(SourceTranslator(installer_impl=installer_impl, interpreter=interpreter)) return ChainedTranslator(*translators) def get_iterator(self): return Iterator( fetchers=self._fetchers, crawler=self.get_crawler(), follow_links=self._allow_external, ) pex-1.1.14/pex/sorter.py0000644000076500000240000000257312623452313015677 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from .package import EggPackage, SourcePackage, WheelPackage class Sorter(object): DEFAULT_PACKAGE_PRECEDENCE = ( WheelPackage, EggPackage, SourcePackage, ) @classmethod def package_type_precedence(cls, package, precedence=DEFAULT_PACKAGE_PRECEDENCE): for rank, package_type in enumerate(reversed(precedence)): if isinstance(package, package_type): return rank # If we do not recognize the package, it gets lowest precedence return -1 @classmethod def package_precedence(cls, package, precedence=DEFAULT_PACKAGE_PRECEDENCE): return ( package.version, # highest version cls.package_type_precedence(package, precedence=precedence), # type preference package.local) # prefer not fetching over the wire def __init__(self, precedence=None): self._precedence = precedence or self.DEFAULT_PACKAGE_PRECEDENCE # return sorted list of (possibly filtered) packages from the list def sort(self, packages, filter=True): key = lambda package: self.package_precedence(package, self._precedence) return [ package for package in sorted(packages, key=key, reverse=True) if not filter or any(isinstance(package, package_cls) for package_cls in self._precedence)] pex-1.1.14/pex/testing.py0000644000076500000240000001720312741504142016031 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import os import random import sys import tempfile import zipfile from collections import namedtuple from textwrap import dedent from .bin.pex import log, main from .common import safe_mkdir, safe_rmtree from .compatibility import nested from .executor import Executor from .installer import EggInstaller, Packager from .pex_builder import PEXBuilder from .util import DistributionHelper, named_temporary_file @contextlib.contextmanager def temporary_dir(): td = tempfile.mkdtemp() try: yield td finally: safe_rmtree(td) @contextlib.contextmanager def temporary_filename(): """Creates a temporary filename. This is useful when you need to pass a filename to an API. Windows requires all handles to a file be closed before deleting/renaming it, so this makes it a bit simpler.""" with named_temporary_file() as fp: fp.write(b'') fp.close() yield fp.name def random_bytes(length): return ''.join( map(chr, (random.randint(ord('a'), ord('z')) for _ in range(length)))).encode('utf-8') @contextlib.contextmanager def temporary_content(content_map, interp=None, seed=31337): """Write content to disk where content is map from string => (int, string). If target is int, write int random bytes. Otherwise write contents of string.""" random.seed(seed) interp = interp or {} with temporary_dir() as td: for filename, size_or_content in content_map.items(): safe_mkdir(os.path.dirname(os.path.join(td, filename))) with open(os.path.join(td, filename), 'wb') as fp: if isinstance(size_or_content, int): fp.write(random_bytes(size_or_content)) else: fp.write((size_or_content % interp).encode('utf-8')) yield td def yield_files(directory): for root, _, files in os.walk(directory): for f in files: filename = os.path.join(root, f) rel_filename = os.path.relpath(filename, directory) yield filename, rel_filename def write_zipfile(directory, dest, reverse=False): with contextlib.closing(zipfile.ZipFile(dest, 'w')) as zf: for filename, rel_filename in sorted(yield_files(directory), reverse=reverse): zf.write(filename, arcname=rel_filename) return dest PROJECT_CONTENT = { 'setup.py': dedent(''' from setuptools import setup setup( name=%(project_name)r, version='0.0.0', zip_safe=%(zip_safe)r, packages=['my_package'], scripts=[ 'scripts/hello_world', 'scripts/shell_script', ], package_data={'my_package': ['package_data/*.dat']}, install_requires=%(install_requires)r, ) '''), 'scripts/hello_world': '#!/usr/bin/env python\nprint("hello world!")\n', 'scripts/shell_script': '#!/usr/bin/env bash\necho hello world\n', 'my_package/__init__.py': 0, 'my_package/my_module.py': 'def do_something():\n print("hello world!")\n', 'my_package/package_data/resource1.dat': 1000, 'my_package/package_data/resource2.dat': 1000, } @contextlib.contextmanager def make_installer(name='my_project', installer_impl=EggInstaller, zip_safe=True, install_reqs=None): interp = {'project_name': name, 'zip_safe': zip_safe, 'install_requires': install_reqs or []} with temporary_content(PROJECT_CONTENT, interp=interp) as td: yield installer_impl(td) @contextlib.contextmanager def make_source_dir(name='my_project', install_reqs=None): interp = {'project_name': name, 'zip_safe': True, 'install_requires': install_reqs or []} with temporary_content(PROJECT_CONTENT, interp=interp) as td: yield td def make_sdist(name='my_project', zip_safe=True, install_reqs=None): with make_installer(name=name, installer_impl=Packager, zip_safe=zip_safe, install_reqs=install_reqs) as packager: return packager.sdist() @contextlib.contextmanager def make_bdist(name='my_project', installer_impl=EggInstaller, zipped=False, zip_safe=True): with make_installer(name=name, installer_impl=installer_impl, zip_safe=zip_safe) as installer: dist_location = installer.bdist() if zipped: yield DistributionHelper.distribution_from_path(dist_location) else: with temporary_dir() as td: extract_path = os.path.join(td, os.path.basename(dist_location)) with contextlib.closing(zipfile.ZipFile(dist_location)) as zf: zf.extractall(extract_path) yield DistributionHelper.distribution_from_path(extract_path) COVERAGE_PREAMBLE = """ try: from coverage import coverage cov = coverage(auto_data=True, data_suffix=True) cov.start() except ImportError: pass """ def write_simple_pex(td, exe_contents, dists=None, coverage=False): """Write a pex file that contains an executable entry point :param td: temporary directory path :param exe_contents: entry point python file :type exe_contents: string :param dists: distributions to include, typically sdists or bdists :param coverage: include coverage header """ dists = dists or [] with open(os.path.join(td, 'exe.py'), 'w') as fp: fp.write(exe_contents) pb = PEXBuilder(path=td, preamble=COVERAGE_PREAMBLE if coverage else None) for dist in dists: pb.add_egg(dist.location) pb.set_executable(os.path.join(td, 'exe.py')) pb.freeze() return pb class IntegResults(namedtuple('results', 'output return_code exception')): """Convenience object to return integration run results.""" def assert_success(self): assert self.exception is None and self.return_code is None def assert_failure(self): assert self.exception or self.return_code def run_pex_command(args, env=None): """Simulate running pex command for integration testing. This is different from run_simple_pex in that it calls the pex command rather than running a generated pex. This is useful for testing end to end runs with specific command line arguments or env options. """ def logger_callback(_output): def mock_logger(msg, v=None): _output.append(msg) return mock_logger exception = None error_code = None output = [] log.set_logger(logger_callback(output)) try: main(args=args) except SystemExit as e: error_code = e.code except Exception as e: exception = e return IntegResults(output, error_code, exception) # TODO(wickman) Why not PEX.run? def run_simple_pex(pex, args=(), env=None, stdin=None): process = Executor.open_process([sys.executable, pex] + list(args), env=env, combined=True) stdout, _ = process.communicate(input=stdin) return stdout.replace(b'\r', b''), process.returncode def run_simple_pex_test(body, args=(), env=None, dists=None, coverage=False): with nested(temporary_dir(), temporary_dir()) as (td1, td2): pb = write_simple_pex(td1, body, dists=dists, coverage=coverage) pex = os.path.join(td2, 'app.pex') pb.build(pex) return run_simple_pex(pex, args=args, env=env) def _iter_filter(data_dict): fragment = '/%s/_pex/' % PEXBuilder.BOOTSTRAP_DIR for filename, records in data_dict.items(): try: bi = filename.index(fragment) except ValueError: continue # rewrite to look like root source yield ('pex/' + filename[bi + len():], records) def combine_pex_coverage(coverage_file_iter): from coverage.data import CoverageData combined = CoverageData(basename='.coverage_combined') for filename in coverage_file_iter: cov = CoverageData(basename=filename) cov.read() combined.add_line_data(dict(_iter_filter(cov.line_data()))) combined.add_arc_data(dict(_iter_filter(cov.arc_data()))) combined.write() return combined.filename pex-1.1.14/pex/tracer.py0000644000076500000240000000705412623452313015640 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import sys import threading import time from contextlib import contextmanager from .variables import ENV __all__ = ('TraceLogger',) class Trace(object): __slots__ = ('msg', 'verbosity', 'parent', 'children', '_clock', '_start', '_stop') def __init__(self, msg, parent=None, verbosity=1, clock=time): self.msg = msg self.verbosity = verbosity self.parent = parent if parent is not None: parent.children.append(self) self.children = [] self._clock = clock self._start = self._clock.time() self._stop = None def stop(self): self._stop = self._clock.time() def duration(self): assert self._stop is not None return self._stop - self._start class TraceLogger(object): """ A multi-threaded tracer. """ def __init__(self, predicate=None, output=sys.stderr, clock=time, prefix=''): """ If predicate specified, it should take a "verbosity" integer and determine whether or not to log, e.g. def predicate(verbosity): try: return verbosity < int(os.environ.get('APP_VERBOSITY', 0)) except ValueError: return False output defaults to sys.stderr, but can take any file-like object. """ self._predicate = predicate or (lambda verbosity: True) self._length = None self._output = output self._isatty = getattr(output, 'isatty', False) and output.isatty() self._lock = threading.RLock() self._local = threading.local() self._clock = clock self._prefix = prefix def should_log(self, V): return self._predicate(V) def log(self, msg, V=1, end='\n'): if not self.should_log(V): return if not self._isatty and end == '\r': # force newlines if we're not a tty end = '\n' trailing_whitespace = '' with self._lock: if self._length and self._length > (len(self._prefix) + len(msg)): trailing_whitespace = ' ' * (self._length - len(msg) - len(self._prefix)) self._output.write(''.join([self._prefix, msg, trailing_whitespace, end])) self._output.flush() self._length = (len(self._prefix) + len(msg)) if end == '\r' else 0 def print_trace_snippet(self): parent = self._local.parent parent_verbosity = parent.verbosity if not self.should_log(parent_verbosity): return traces = [] while parent: if self.should_log(parent.verbosity): traces.append(parent.msg) parent = parent.parent self.log(' :: '.join(reversed(traces)), V=parent_verbosity, end='\r') def print_trace(self, indent=0, node=None): node = node or self._local.parent with self._lock: self.log(' ' * indent + ('%s: %.1fms' % (node.msg, 1000.0 * node.duration())), V=node.verbosity) for child in node.children: self.print_trace(indent=indent + 2, node=child) @contextmanager def timed(self, msg, V=1): if getattr(self._local, 'parent', None) is None: self._local.parent = Trace(msg, verbosity=V, clock=self._clock) else: parent = self._local.parent self._local.parent = Trace(msg, parent=parent, verbosity=V, clock=self._clock) self.print_trace_snippet() yield self._local.parent.stop() if self._local.parent.parent is not None: self._local.parent = self._local.parent.parent else: self.print_trace() self._local.parent = None TRACER = TraceLogger( predicate=lambda verbosity: verbosity <= ENV.PEX_VERBOSE, prefix='pex: ' ) pex-1.1.14/pex/translator.py0000644000076500000240000001446512670614434016563 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import import os import traceback from abc import abstractmethod from .archiver import Archiver from .common import chmod_plus_w, safe_copy, safe_mkdtemp, safe_rmtree from .compatibility import AbstractClass from .installer import WheelInstaller from .interpreter import PythonInterpreter from .package import EggPackage, Package, SourcePackage, WheelPackage from .platforms import Platform from .tracer import TRACER from .util import DistributionHelper class TranslatorBase(AbstractClass): """ Translate a link into a distribution. """ @abstractmethod def translate(self, link, into=None): pass class ChainedTranslator(TranslatorBase): """ Glue a sequence of Translators together in priority order. The first Translator to resolve a requirement wins. """ def __init__(self, *translators): self._translators = list(filter(None, translators)) for tx in self._translators: if not isinstance(tx, TranslatorBase): raise ValueError('Expected a sequence of translators, got %s instead.' % type(tx)) def translate(self, package, into=None): for tx in self._translators: dist = tx.translate(package, into=into) if dist: return dist def __str__(self): return 'ChainedTranslator(%s)' % ( ', '.join((tx.__class__.__name__ for tx in self._translators))) class SourceTranslator(TranslatorBase): @classmethod def run_2to3(cls, path): from lib2to3.refactor import get_fixers_from_package, RefactoringTool rt = RefactoringTool(get_fixers_from_package('lib2to3.fixes')) with TRACER.timed('Translating %s' % path): for root, dirs, files in os.walk(path): for fn in files: full_fn = os.path.join(root, fn) if full_fn.endswith('.py'): with TRACER.timed('%s' % fn, V=3): try: chmod_plus_w(full_fn) rt.refactor_file(full_fn, write=True) except IOError: TRACER.log('Failed to translate %s' % fn) TRACER.log(traceback.format_exc()) def __init__(self, interpreter=PythonInterpreter.get(), platform=Platform.current(), use_2to3=False, installer_impl=WheelInstaller): self._interpreter = interpreter self._installer_impl = installer_impl self._use_2to3 = use_2to3 self._platform = platform def translate(self, package, into=None): """From a SourcePackage, translate to a binary distribution.""" if not isinstance(package, SourcePackage): return None if not package.local: raise ValueError('SourceTranslator cannot translate remote packages.') installer = None version = self._interpreter.version unpack_path = Archiver.unpack(package.local_path) into = into or safe_mkdtemp() try: if self._use_2to3 and version >= (3,): with TRACER.timed('Translating 2->3 %s' % package.name): self.run_2to3(unpack_path) installer = self._installer_impl( unpack_path, interpreter=self._interpreter, strict=(package.name not in ('distribute', 'setuptools'))) with TRACER.timed('Packaging %s' % package.name): try: dist_path = installer.bdist() except self._installer_impl.InstallFailure as e: TRACER.log('Failed to install package at %s: %s' % (unpack_path, e)) return None target_path = os.path.join(into, os.path.basename(dist_path)) safe_copy(dist_path, target_path) target_package = Package.from_href(target_path) if not target_package: TRACER.log('Target path %s does not look like a Package.' % target_path) return None if not target_package.compatible(self._interpreter.identity, platform=self._platform): TRACER.log('Target package %s is not compatible with %s / %s' % ( target_package, self._interpreter.identity, self._platform)) return None return DistributionHelper.distribution_from_path(target_path) except Exception as e: TRACER.log('Failed to translate %s' % package) TRACER.log(traceback.format_exc()) finally: if installer: installer.cleanup() if unpack_path: safe_rmtree(unpack_path) class BinaryTranslator(TranslatorBase): def __init__(self, package_type, interpreter=PythonInterpreter.get(), platform=Platform.current()): self._package_type = package_type self._platform = platform self._identity = interpreter.identity def translate(self, package, into=None): """From a binary package, translate to a local binary distribution.""" if not package.local: raise ValueError('BinaryTranslator cannot translate remote packages.') if not isinstance(package, self._package_type): return None if not package.compatible(identity=self._identity, platform=self._platform): TRACER.log('Target package %s is not compatible with %s / %s' % ( package, self._identity, self._platform)) return None into = into or safe_mkdtemp() target_path = os.path.join(into, package.filename) safe_copy(package.local_path, target_path) return DistributionHelper.distribution_from_path(target_path) class EggTranslator(BinaryTranslator): def __init__(self, **kw): super(EggTranslator, self).__init__(EggPackage, **kw) class WheelTranslator(BinaryTranslator): def __init__(self, **kw): super(WheelTranslator, self).__init__(WheelPackage, **kw) class Translator(object): @staticmethod def default(platform=Platform.current(), interpreter=None): # TODO(wickman) Consider interpreter=None to indicate "universal" packages # since the .whl format can support this. # Also consider platform=None to require platform-inspecific packages. # Issue #95. interpreter = interpreter or PythonInterpreter.get() whl_translator = WheelTranslator(platform=platform, interpreter=interpreter) egg_translator = EggTranslator(platform=platform, interpreter=interpreter) source_translator = SourceTranslator(platform=platform, interpreter=interpreter) return ChainedTranslator(whl_translator, egg_translator, source_translator) pex-1.1.14/pex/util.py0000644000076500000240000001754712722124676015355 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from __future__ import absolute_import import contextlib import os import shutil import tempfile import uuid from hashlib import sha1 from threading import Lock from pkg_resources import find_distributions, resource_isdir, resource_listdir, resource_string from .common import rename_if_empty, safe_mkdir, safe_mkdtemp, safe_open from .finders import register_finders class DistributionHelper(object): @classmethod def walk_data(cls, dist, path='/'): """Yields filename, stream for files identified as data in the distribution""" for rel_fn in filter(None, dist.resource_listdir(path)): full_fn = os.path.join(path, rel_fn) if dist.resource_isdir(full_fn): for fn, stream in cls.walk_data(dist, full_fn): yield fn, stream else: yield full_fn[1:], dist.get_resource_stream(dist._provider, full_fn) @staticmethod def zipsafe(dist): """Returns whether or not we determine a distribution is zip-safe.""" # zip-safety is only an attribute of eggs. wheels are considered never # zip safe per implications of PEP 427. if hasattr(dist, 'egg_info') and dist.egg_info.endswith('EGG-INFO'): egg_metadata = dist.metadata_listdir('') return 'zip-safe' in egg_metadata and 'native_libs.txt' not in egg_metadata else: return False @classmethod def access_zipped_assets(cls, static_module_name, static_path, dir_location=None): """ Create a copy of static resource files as we can't serve them from within the pex file. :param static_module_name: Module name containing module to cache in a tempdir :type static_module_name: string, for example 'twitter.common.zookeeper' or similar :param static_path: Module name, for example 'serverset' :param dir_location: create a new temporary directory inside, or None to have one created :returns temp_dir: Temporary directory with the zipped assets inside :rtype: str """ # asset_path is initially a module name that's the same as the static_path, but will be # changed to walk the directory tree def walk_zipped_assets(static_module_name, static_path, asset_path, temp_dir): for asset in resource_listdir(static_module_name, asset_path): asset_target = os.path.normpath( os.path.join(os.path.relpath(asset_path, static_path), asset)) if resource_isdir(static_module_name, os.path.join(asset_path, asset)): safe_mkdir(os.path.join(temp_dir, asset_target)) walk_zipped_assets(static_module_name, static_path, os.path.join(asset_path, asset), temp_dir) else: with open(os.path.join(temp_dir, asset_target), 'wb') as fp: path = os.path.join(static_path, asset_target) file_data = resource_string(static_module_name, path) fp.write(file_data) if dir_location is None: temp_dir = safe_mkdtemp() else: temp_dir = dir_location walk_zipped_assets(static_module_name, static_path, static_path, temp_dir) return temp_dir @classmethod def distribution_from_path(cls, path, name=None): """Return a distribution from a path. If name is provided, find the distribution. If none is found matching the name, return None. If name is not provided and there is unambiguously a single distribution, return that distribution otherwise None. """ # Monkeypatch pkg_resources finders should it not already be so. register_finders() if name is None: distributions = list(find_distributions(path)) if len(distributions) == 1: return distributions[0] else: for dist in find_distributions(path): if dist.project_name == name: return dist class CacheHelper(object): @classmethod def update_hash(cls, filelike, digest): """Update the digest of a single file in a memory-efficient manner.""" block_size = digest.block_size * 1024 for chunk in iter(lambda: filelike.read(block_size), b''): digest.update(chunk) @classmethod def hash(cls, path, digest=None, hasher=sha1): """Return the digest of a single file in a memory-efficient manner.""" if digest is None: digest = hasher() with open(path, 'rb') as fh: cls.update_hash(fh, digest) return digest.hexdigest() @classmethod def _compute_hash(cls, names, stream_factory): digest = sha1() # Always use / as the path separator, since that's what zip uses. hashed_names = [n.replace(os.sep, '/') for n in names] digest.update(''.join(hashed_names).encode('utf-8')) for name in names: with contextlib.closing(stream_factory(name)) as fp: cls.update_hash(fp, digest) return digest.hexdigest() @classmethod def zip_hash(cls, zf, prefix=''): """Return the hash of the contents of a zipfile, comparable with a cls.dir_hash.""" prefix_length = len(prefix) names = sorted(name[prefix_length:] for name in zf.namelist() if name.startswith(prefix) and not name.endswith('.pyc') and not name.endswith('/')) def stream_factory(name): return zf.open(prefix + name) return cls._compute_hash(names, stream_factory) @classmethod def _iter_files(cls, directory): normpath = os.path.realpath(os.path.normpath(directory)) for root, _, files in os.walk(normpath): for f in files: yield os.path.relpath(os.path.join(root, f), normpath) @classmethod def pex_hash(cls, d): """Return a reproducible hash of the contents of a directory.""" names = sorted(f for f in cls._iter_files(d) if not (f.endswith('.pyc') or f.startswith('.'))) def stream_factory(name): return open(os.path.join(d, name), 'rb') # noqa: T802 return cls._compute_hash(names, stream_factory) @classmethod def dir_hash(cls, d): """Return a reproducible hash of the contents of a directory.""" names = sorted(f for f in cls._iter_files(d) if not f.endswith('.pyc')) def stream_factory(name): return open(os.path.join(d, name), 'rb') # noqa: T802 return cls._compute_hash(names, stream_factory) @classmethod def cache_distribution(cls, zf, source, target_dir): """Possibly cache an egg from within a zipfile into target_cache. Given a zipfile handle and a filename corresponding to an egg distribution within that zip, maybe write to the target cache and return a Distribution.""" dependency_basename = os.path.basename(source) if not os.path.exists(target_dir): target_dir_tmp = target_dir + '.' + uuid.uuid4().hex for name in zf.namelist(): if name.startswith(source) and not name.endswith('/'): # strip off prefix + '/' target_name = os.path.join(dependency_basename, name[len(source) + 1:]) with contextlib.closing(zf.open(name)) as zi: with safe_open(os.path.join(target_dir_tmp, target_name), 'wb') as fp: shutil.copyfileobj(zi, fp) rename_if_empty(target_dir_tmp, target_dir) dist = DistributionHelper.distribution_from_path(target_dir) assert dist is not None, 'Failed to cache distribution %s' % source return dist class Memoizer(object): """A thread safe class for memoizing the results of a computation.""" def __init__(self): self._data = {} self._lock = Lock() def get(self, key, default=None): with self._lock: return self._data.get(key, default) def store(self, key, value): with self._lock: self._data[key] = value @contextlib.contextmanager def named_temporary_file(*args, **kwargs): """ Due to a bug in python (https://bugs.python.org/issue14243), we need this to be able to use the temporary file without deleting it. """ assert 'delete' not in kwargs kwargs['delete'] = False fp = tempfile.NamedTemporaryFile(*args, **kwargs) try: with fp: yield fp finally: os.remove(fp.name) pex-1.1.14/pex/variables.py0000644000076500000240000002377412720650765016350 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). # Due to the PEX_ properties, disable checkstyle. # checkstyle: noqa import os import sys from contextlib import contextmanager from .common import die __all__ = ('ENV', 'Variables') class Variables(object): """Environment variables supported by the PEX runtime.""" @classmethod def process_pydoc(cls, pydoc): if pydoc is None: return 'Unknown', 'Unknown' pydoc = pydoc.splitlines() variable_type = pydoc[0] variable_text = ' '.join(filter(None, (line.strip() for line in pydoc[2:]))) return variable_type, variable_text @classmethod def iter_help(cls): for variable_name, value in sorted(cls.__dict__.items()): if not variable_name.startswith('PEX_'): continue variable_type, variable_text = cls.process_pydoc(getattr(value, '__doc__')) yield variable_name, variable_type, variable_text def __init__(self, environ=None, rc='~/.pexrc', use_defaults=True): self._use_defaults = use_defaults self._environ = environ.copy() if environ else os.environ if not self.PEX_IGNORE_RCFILES: rc_values = self._from_rc(rc).copy() rc_values.update(self._environ) self._environ = rc_values def copy(self): return self._environ.copy() def delete(self, variable): self._environ.pop(variable, None) def set(self, variable, value): self._environ[variable] = str(value) def _from_rc(self, rc): ret_vars = {} for filename in ['/etc/pexrc', rc, os.path.join(os.path.dirname(sys.argv[0]), '.pexrc')]: try: with open(os.path.expanduser(filename)) as fh: rc_items = map(self._get_kv, fh) ret_vars.update(dict(filter(None, rc_items))) except IOError: continue return ret_vars def _get_kv(self, variable): kv = variable.strip().split('=') if len(list(filter(None, kv))) == 2: return kv def _defaulted(self, default): return default if self._use_defaults else None def _get_bool(self, variable, default=False): value = self._environ.get(variable) if value is not None: if value.lower() in ('0', 'false'): return False elif value.lower() in ('1', 'true'): return True else: die('Invalid value for %s, must be 0/1/false/true, got %r' % (variable, value)) else: return self._defaulted(default) def _get_string(self, variable, default=None): return self._environ.get(variable, self._defaulted(default)) def _get_path(self, variable, default=None): value = self._get_string(variable, default=default) if value is not None: return os.path.realpath(os.path.expanduser(value)) def _get_int(self, variable, default=None): try: return int(self._environ[variable]) except ValueError: die('Invalid value for %s, must be an integer, got %r' % (variable, self._environ[variable])) except KeyError: return self._defaulted(default) def strip_defaults(self): """Returns a copy of these variables but with defaults stripped. Any variables not explicitly set in the environment will have a value of `None`. """ return Variables(environ=self.copy(), use_defaults=False) @contextmanager def patch(self, **kw): """Update the environment for the duration of a context.""" old_environ = self._environ self._environ = self._environ.copy() self._environ.update(kw) yield self._environ = old_environ @property def PEX_ALWAYS_CACHE(self): """Boolean Always write PEX dependencies to disk prior to invoking regardless whether or not the dependencies are zip-safe. For certain dependencies that are very large such as numpy, this can reduce the RAM necessary to launch the PEX. The data will be written into $PEX_ROOT, which by default is $HOME/.pex. Default: false. """ return self._get_bool('PEX_ALWAYS_CACHE', default=False) @property def PEX_COVERAGE(self): """Boolean Enable coverage reporting for this PEX file. This requires that the "coverage" module is available in the PEX environment. Default: false. """ return self._get_bool('PEX_COVERAGE', default=False) @property def PEX_COVERAGE_FILENAME(self): """Filename Write the coverage data to the specified filename. If PEX_COVERAGE_FILENAME is not specified but PEX_COVERAGE is, coverage information will be printed to stdout and not saved. """ return self._get_path('PEX_COVERAGE_FILENAME', default=None) @property def PEX_FORCE_LOCAL(self): """Boolean Force this PEX to be not-zip-safe. This forces all code and dependencies to be written into $PEX_ROOT prior to invocation. This is an option for applications with static assets that refer to paths relative to __file__ instead of using pkgutil/pkg_resources. Default: false. """ return self._get_bool('PEX_FORCE_LOCAL', default=False) @property def PEX_IGNORE_ERRORS(self): """Boolean Ignore any errors resolving dependencies when invoking the PEX file. This can be useful if you know that a particular failing dependency is not necessary to run the application. Default: false. """ return self._get_bool('PEX_IGNORE_ERRORS', default=False) @property def PEX_INHERIT_PATH(self): """Boolean Allow inheriting packages from site-packages. By default, PEX scrubs any packages and namespace packages from sys.path prior to invoking the application. This is generally not advised, but can be used in situations when certain dependencies do not conform to standard packaging practices and thus cannot be bundled into PEX files. Default: false. """ return self._get_bool('PEX_INHERIT_PATH', default=False) @property def PEX_INTERPRETER(self): """Boolean Drop into a REPL instead of invoking the predefined entry point of this PEX. This can be useful for inspecting the PEX environment interactively. It can also be used to treat the PEX file as an interpreter in order to execute other scripts in the context of the PEX file, e.g. "PEX_INTERPRETER=1 ./app.pex my_script.py". Equivalent to setting PEX_MODULE to empty. Default: false. """ return self._get_bool('PEX_INTERPRETER', default=False) @property def PEX_MODULE(self): """String Override the entry point into the PEX file. Can either be a module, e.g. 'SimpleHTTPServer', or a specific entry point in module:symbol form, e.g. "myapp.bin:main". """ return self._get_string('PEX_MODULE', default=None) @property def PEX_PROFILE(self): """Boolean Enable application profiling. If specified and PEX_PROFILE_FILENAME is not specified, PEX will print profiling information to stdout. """ return self._get_path('PEX_PROFILE', default=None) @property def PEX_PROFILE_FILENAME(self): """Filename Profile the application and dump a profile into the specified filename in the standard "profile" module format. """ return self._get_path('PEX_PROFILE_FILENAME', default=None) @property def PEX_PROFILE_SORT(self): """String Toggle the profile sorting algorithm used to print out profile columns. Default: 'cumulative'. """ return self._get_string('PEX_PROFILE_SORT', default='cumulative') @property def PEX_PYTHON(self): """String Override the Python interpreter used to invoke this PEX. Can be either an absolute path to an interpreter or a base name e.g. "python3.3". If a base name is provided, the $PATH will be searched for an appropriate match. """ return self._get_string('PEX_PYTHON', default=None) @property def PEX_ROOT(self): """Directory The directory location for PEX to cache any dependencies and code. PEX must write not-zip-safe eggs and all wheels to disk in order to activate them. Default: ~/.pex """ return self._get_path('PEX_ROOT', default=os.path.expanduser('~/.pex')) @property def PEX_PATH(self): """A set of one or more PEX files Merge the packages from other PEX files into the current environment. This allows you to do things such as create a PEX file containing the "coverage" module or create PEX files containing plugin entry points to be consumed by a main application. Paths should be specified in the same manner as $PATH, e.g. PEX_PATH=/path/to/pex1.pex:/path/to/pex2.pex and so forth. """ return self._get_string('PEX_PATH', default='') @property def PEX_SCRIPT(self): """String The script name within the PEX environment to execute. This must either be an entry point as defined in a distribution's console_scripts, or a script as defined in a distribution's scripts section. While Python supports any script including shell scripts, PEX only supports invocation of Python scripts in this fashion. """ return self._get_string('PEX_SCRIPT', default=None) @property def PEX_TEARDOWN_VERBOSE(self): """Boolean Enable verbosity for when the interpreter shuts down. This is mostly only useful for debugging PEX itself. Default: false. """ return self._get_bool('PEX_TEARDOWN_VERBOSE', default=False) @property def PEX_VERBOSE(self): """Integer Set the verbosity level of PEX debug logging. The higher the number, the more logging, with 0 being disabled. This environment variable can be extremely useful in debugging PEX environment issues. Default: 0 """ return self._get_int('PEX_VERBOSE', default=0) # TODO(wickman) Remove and push into --flags. #94 @property def PEX_HTTP_RETRIES(self): """Integer The number of HTTP retries when performing dependency resolution when building a PEX file. Default: 5. """ return self._get_int('PEX_HTTP_RETRIES', default=5) @property def PEX_IGNORE_RCFILES(self): """Boolean Explicitly disable the reading/parsing of pexrc files (~/.pexrc). Default: false. """ return self._get_bool('PEX_IGNORE_RCFILES', default=False) # Global singleton environment ENV = Variables() pex-1.1.14/pex/version.py0000644000076500000240000000037212743540304016042 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). __version__ = '1.1.14' SETUPTOOLS_REQUIREMENT = 'setuptools>=2.2,<20.11' WHEEL_REQUIREMENT = 'wheel>=0.24.0,<0.30.0' pex-1.1.14/pex.egg-info/0000755000076500000240000000000012743552145015501 5ustar kwilsonstaff00000000000000pex-1.1.14/pex.egg-info/dependency_links.txt0000644000076500000240000000000112743552145021547 0ustar kwilsonstaff00000000000000 pex-1.1.14/pex.egg-info/entry_points.txt0000644000076500000240000000015512743552145021000 0ustar kwilsonstaff00000000000000[console_scripts] pex = pex.bin.pex:main [distutils.commands] bdist_pex = pex.commands.bdist_pex:bdist_pex pex-1.1.14/pex.egg-info/PKG-INFO0000644000076500000240000010243212743552145016600 0ustar kwilsonstaff00000000000000Metadata-Version: 1.1 Name: pex Version: 1.1.14 Summary: The PEX packaging toolchain. Home-page: https://github.com/pantsbuild/pex Author: UNKNOWN Author-email: UNKNOWN License: Apache License, Version 2.0 Description: PEX === .. image:: https://travis-ci.org/pantsbuild/pex.svg?branch=master :target: https://travis-ci.org/pantsbuild/pex pex is a library for generating .pex (Python EXecutable) files which are executable Python environments in the spirit of `virtualenvs `_. pex is an expansion upon the ideas outlined in `PEP 441 `_ and makes the deployment of Python applications as simple as ``cp``. pex files may even include multiple platform-specific Python distributions, meaning that a single pex file can be portable across Linux and OS X. pex files can be built using the ``pex`` tool. Build systems such as `Pants `_ and `Buck `_ also support building .pex files directly. Still unsure about what pex does or how it works? Watch this quick lightning talk: `WTF is PEX? `_. pex is licensed under the Apache2 license. Installation ============ To install pex, simply .. code-block:: bash $ pip install pex You can also build pex in a git clone using tox: .. code-block:: bash $ tox -e py27-package $ cp dist/pex ~/bin This builds a pex binary in ``dist/pex`` that can be copied onto your ``$PATH``. The advantage to this approach is that it keeps your Python environment as empty as possible and is more in-line with what pex does philosophically. Simple Examples =============== Launch an interpreter with ``requests``, ``flask`` and ``psutil`` in the environment: .. code-block:: bash $ pex requests flask 'psutil>2,<3' Or instead freeze your current virtualenv via requirements.txt and execute it anywhere: .. code-block:: bash $ pex -r <(pip freeze) -o my_virtualenv.pex $ deactivate $ ./my_virtualenv.pex Run webserver.py in an environment containing ``flask`` as a quick way to experiment: .. code-block:: bash $ pex flask -- webserver.py Launch Sphinx in an ephemeral pex environment using the Sphinx entry point ``sphinx:main``: .. code-block:: bash $ pex sphinx -e sphinx:main -- --help Build a standalone pex binary into ``pex.pex`` using the ``pex`` console_scripts entry point: .. code-block:: bash $ pex pex -c pex -o pex.pex You can also build pex files that use a specific interpreter type: .. code-block:: bash $ pex pex -c pex --python=pypy -o pypy-pex.pex Most pex options compose well with one another, so the above commands can be mixed and matched. For a full list of options, just type ``pex --help``. Integrating pex into your workflow ================================== If you use tox (and you should!), a simple way to integrate pex into your workflow is to add a packaging test environment to your ``tox.ini``: .. code-block:: ini [testenv:package] deps = pex commands = pex . -o dist/app.pex Then ``tox -e package`` will produce a relocateable copy of your application that you can copy to staging or production environments. Documentation ============= More documentation about pex, building .pex files, and how .pex files work is available at https://pex.readthedocs.io. Development =========== pex uses `tox `_ for test and development automation. To run the test suite, just invoke tox: .. code-block:: bash $ tox If you don't have tox, you can generate a pex of tox: .. code-block:: $ pex tox -c tox -o ~/bin/tox Contributing ============ To contribute, follow these instructions: http://pantsbuild.github.io/howto_contribute.html Release Notes ============= 1.1.14 ------ * Repair Executor error handling for other classes of IOError/OSError. (#292) `#292 `_ * Fix bdist_pex --pex-args. (#285) `#285 `_ * Inherit user site with --inherit-path. (#284) `#284 `_ 1.1.13 ------ * Repair passing of stdio kwargs to PEX.run(). (#288) `#288 `_ 1.1.12 ------ * Fix bdist_pex interpreter cache directory. (#286) `#286 `_ * Normalize and edify subprocess execution. (#255) `#255 `_ * Don't ignore exit codes when using setuptools entry points. (#280) `#280 `_ `Fixes #137 `_ 1.1.11 ------ * Update cache dir when bdist_pex.run is called directly. `#278 `_ `Fixes #274 `_ 1.1.10 ------ * Improve failure modes for os.rename() as used in distribution caching. `#271 `_ `Fixes #265 `_ 1.1.9 ----- * Bugfix: Open setup.py in binary mode. `#264 `_ `Fixes #263 `_ 1.1.8 ----- * Bugfix: Repair a regression in `--disable-cache`. `#261 `_ `Fixes #260 `_ 1.1.7 ----- * Add README and supported python versions to PyPI description. `#258 `_ * Use `open` with utf-8 support. `#231 `_ * Add `--pex-root` option. `#206 `_ 1.1.6 ----- This release is a quick fix for a regression that inadvertently went out in 1.1.5 (Issue #243). * Fix the ``bdist_pex`` ``setuptools`` command to work for python2. `#246 `_ `Fixes #243 `_ * Upgrade pex dependencies on ``setuptools`` and ``wheel``. `#244 `_ `Fixes #238 `_ 1.1.5 ----- * Fix ``PEXBuilder.clone`` and thus ``bdist_pex --pex-args`` for ``--python`` and ``--python-shebang``. `#234 `_ `Fixes #233 `_ * Fix old ``pkg_resources`` egg version normalization. `#227 `_ `Fixes #226 `_ * Fix the ``inherit_path`` handling. `#224 `_ * Fix handling of bad distribution script names when used as the pex entrypoint. `#221 `_ `Fixes #220 `_ 1.1.4 ----- This release is a quick fix for a regression that inadvertently went out in 1.1.3 (Issue #216). * Add a test for the regression in ``FixedEggMetadata._zipinfo_name`` and revert the breaking commit. `Fixes #216 `_ 1.1.3 ----- This release includes an initial body of work towards Windows support, ABI tag support for CPython 2.x and a fix for version number normalization. * Add python 2.x abi tag support. `#214 `_ `Fixes #213 `_ * Add .idea to .gitignore. `#205 `_ * Don't normalize version numbers as names. `#204 `_ * More fixes for windows. `#202 `_ * Fixes to get pex to work on windows. `#198 `_ 1.1.2 ----- * Bump setuptools & wheel version pinning. `#194 `_ * Unescape html in PageParser.href_match_to_url. `#191 `_ * Memoize calls to Crawler.crawl() for performance win in find-links based resolution. `#187 `_ 1.1.1 ----- * Fix infinite recursion when ``PEX_PYTHON`` points at a symlink. `#182 `_ * Add ``/etc/pexrc`` to the list of pexrc locations to check. `#183 `_ * Improve error messaging for platform constrained Untranslateable errors. `#179 `_ 1.1.0 ----- * Add support for ``.pexrc`` files for influencing the pex environment. See the notes `here `_. `#128 `_. * Bug fix: PEX_PROFILE_FILENAME and PEX_PROFILE_SORT were not respected. `#154 `_. * Adds the ``bdist_pex`` command to setuptools. `#99 `_. * Bug fix: We did not normalize package names in ``ResolvableSet``, so it was possible to depend on ``sphinx`` and ``Sphinx-1.4a0.tar.gz`` and get two versions build and included into the pex. `#147 `_. * Adds a pex-identifying User-Agent. `#101 `_. 1.0.3 ----- * Bug fix: Accommodate OSX ``Python`` python binaries. Previously the OSX python distributions shipped with OSX, XCode and available via https://www.python.org/downloads/ could fail to be detected using the ``PythonInterpreter`` class. Fixes `#144 `_. * Bug fix: PEX_SCRIPT failed when the script was from a not-zip-safe egg. Original PR `#139 `_. * Bug fix: ``sys.exit`` called without arguments would cause `None` to be printed on stderr since pex 1.0.1. `#143 `_. 1.0.2 ----- * Bug fix: PEX-INFO values were overridden by environment ``Variables`` with default values that were not explicitly set in the environment. Fixes `#135 `_. * Bug fix: Since `69649c1 `_ we have been unpatching the side-effects of ``sys.modules`` after ``PEX.execute``. This takes all modules imported during the PEX lifecycle and sets all their attributes to ``None``. Unfortunately, ``sys.excepthook``, ``atexit`` and ``__del__`` may still try to operate using these tainted modules, causing exceptions on interpreter teardown. This reverts just the ``sys`` unpatching so that the abovementioned teardown hooks behave more predictably. Fixes `#141 `_. 1.0.1 ----- * Allow PEXBuilder to optionally copy files into the PEX environment instead of hard-linking them. * Allow PEXBuilder to optionally skip precompilation of .py files into .pyc files. * Bug fix: PEXBuilder did not respect the target interpreter when compiling source to bytecode. Fixes `#127 `_. * Bug fix: Fix complex resolutions when using a cache. Fixes: `#120 `_. 1.0.0 ----- The 1.0.0 release of pex introduces a few breaking changes: ``pex -r`` now takes requirements.txt files instead of requirement specs, ``pex -s`` has now been removed since source specs are accepted as arguments, and ``pex -p`` has been removed in favor of its alias ``pex -o``. The pex *command line interface* now adheres to semver insofar as backwards incompatible CLI changes will invoke a major version change. Any backwards incompatible changes to the PEX environment variable semantics will also result in a major version change. The pex *API* adheres to semver insofar as backwards incompatible API changes will invoke minor version changes. For users of the PEX API, it is recommended to add minor version ranges, e.g. ``pex>=1.0,<1.1``. For users of the PEX CLI, major version ranges such as ``pex>=1,<2`` should be sufficient. * BREAKING CHANGE: Removes the ``-s`` option in favor of specifying directories directly as arguments to the pex command line. * BREAKING CHANGE: ``pex -r`` now takes requirements.txt filenames and *not* requirement specs. Requirement specs are now passed as arguments to the pex tool. Use ``--`` to escape command line arguments passed to interpreters spawned by pex. Implements `#5 `_. * Adds a number of flag aliases to be more compatible with pip command lines: ``--no-index``, ``-f``, ``--find-links``, ``--index-url``, ``--no-use-wheel``. Removes ``-p`` in favor of ``-o`` exclusively. * Adds ``--python-shebang`` option to the pex tool in order to set the ``#!`` shebang to an exact path. `#53 `_. * Adds support for ``PEX_PYTHON`` environment variable which will cause the pex file to reinvoke itself using the interpreter specified, e.g. ``PEX_PYTHON=python3.4`` or ``PEX_PYTHON=/exact/path/to/interpreter``. `#27 `_. * Adds support for ``PEX_PATH`` environment variable which allows merging of PEX environments at runtime. This can be used to inject plugins or entry_points or modules from one PEX into another without explicitly building them together. `#30 `_. * Consolidates documentation of ``PEX_`` environment variables and adds the ``--help-variables`` option to the pex client. Partially addresses `#13 `_. * Adds helper method to dump a package subdirectory onto disk from within a zipped PEX file. This can be useful for applications that know they're running within a PEX and would prefer some static assets dumped to disk instead of running as an unzipped PEX file. `#12 `_. * Now supports extras for static URLs and installable directories. `#65 `_. * Adds ``-m`` and ``--entry-point`` alias to the existing ``-e`` option for entry points in the pex tool to evoke the similarity to ``python -m``. * Adds console script support via ``-c/--script/--console-script`` and ``PEX_SCRIPT``. This allows you to reference the named entry point instead of the exact ``module:name`` pair. Also supports scripts defined in the ``scripts`` section of setup.py. `#59 `_. * Adds more debugging information when encountering unresolvable requirements. `#79 `_. * Bug fix: ``PEX_COVERAGE`` and ``PEX_PROFILE`` did not function correctly when SystemExit was raised. Fixes `#81 `_. * Bug fix: Fixes caching in the PEX tool since we don't cache the source distributions of installable directories. `#24 `_. 0.9.0 ----- This is the last release before the 1.0.0 development branch is started. * Change the setuptools range to >=2.2,<16 by handling EntryPoint changes as well as being flexible on whether ``pkg_resources`` is a package or a module. Fixes `#55 `_ and `#34 `_. * Adds option groups to the pex tool to make the help output slightly more readable. * Bug fix: Make ``pip install pex`` work better by removing ``extras_requires`` on the ``console_script`` entry point. Fixes `#48 `_ * New feature: Adds an interpreter cache to the ``pex`` tool. If the user does not explicitly disable the wheel feature and attempts to build a pex with wheels but does not have the wheel package installed, pex will download it in order to make the feature work. Implements `#47 `_ in order to fix `#48 `_ 0.8.6 ----- * Bug fix: Honor installed sys.excepthook in pex teardown. `RB #1733 `_ * Bug fix: ``UrllibContext`` used ``replace`` as a keyword argument for ``bytes.decode`` but this only works on Python 3. `Pull Request #46 `_ 0.8.5 ----- * Bug fix: Fixup string formatting in pex/bin/pex.py to support Python 2.6 `Pull Request #40 `_ 0.8.4 ----- * Performance improvement: Speed up the best-case scenario of dependency resolution. `RB #1685 `_ * Bug fix: Change from ``uuid4().get_hex()`` to ``uuid4().hex`` to maintain Python3 compatibility of pex.common. `Pull Request #39 `_ * Bug fix: Actually cache the results of translation. Previously bdist translations would be created in a temporary directory even if a cache location was specified. `RB #1666 `_ * Bug fix: Support all potential abi tag permutations when determining platform compatibility. `Pull Request #33 `_ 0.8.3 ----- * Performance improvement: Don't always write packages to disk if they've already been cached. This can significantly speed up launching PEX files with a large number of non-zip-safe dependencies. `RB #1642 `_ 0.8.2 ----- * Bug fix: Allow pex 0.8.x to parse pex files produced by earlier versions of pex and twitter.common.python. * Pin pex to setuptools prior to 9.x until we have a chance to make changes related to PEP440 and the change of pkg_resources.py to a package. 0.8.1 ----- * Bug fix: Fix issue where it'd be possible to ``os.path.getmtime`` on a remote ``Link`` object `Issue #29 `_ 0.8.0 ----- * *API change*: Decouple translation from package iteration. This removes the Obtainer construct entirely, which likely means if you're using PEX as a library, you will need to change your code if you were doing anything nontrivial. This adds a couple new options to ``resolve`` but simplifies the story around how to cache packages. `RB #785 `_ * Refactor http handling in pex to allow for alternate http implementations. Adds support for `requests `_, improving both performance and security. For more information, read the commit notes at `91c7f32 `_. `RB #778 `_ * Improvements to API documentation throughout. * Renamed ``Tracer`` to ``TraceLogger`` to prevent nondeterministic isort ordering. * Refactor tox.ini to increase the number of environment combinations and improve coverage. * Adds HTTP retry support for the RequestsContext. `RB #1303 `_ * Make pex --version correct. `Issue #19 `_ * Bug fix: Fix over-aggressive sys.modules scrubbing for namespace packages. Under certain circumstances, namespace packages in site-packages could conflict with packages within a PEX, causing them to fail importing. `RB #1378 `_ * Bug fix: Replace uses of ``os.unsetenv(...)`` with ``del os.environ[...]`` `Pull Request #11 `_ * Bug fix: Scrub sys.path and sys.modules based upon both supplied path and realpath of files and directories. Newer versions of virtualenv on Linux symlink site-packages which caused those packages to not be removed from sys.path correctly. `Issue #21 `_ * Bug fix: The pex -s option was not correctly pulling in transitive dependencies. `Issue #22 `_ * Bug fix: Adds ``content`` method to HTTP contexts that does HTML content decoding, fixing an encoding issue only experienced when using Python 3. `Issue #10 `_ 0.7.0 ----- * Rename ``twitter.common.python`` to ``pex`` and split out from the `twitter/commons `_ repo. 0.6.0 ----- * Change the interpretation of ``-i`` (and of PyPIFetcher's pypi_base) to match pip's ``-i``. This is useful for compatibility with devpi. 0.5.10 ------ * Ensures that .egg/.whl distributions on disk have their mtime updated even though we no longer overwrite them. This gives them a new time lease against their ttl. Without this change, once a distribution aged past the ttl it would never be used again, and builds would re-create the same distributions in tmpdirs over and over again. 0.5.9 ----- * Fixes an issue where SourceTranslator would overwrite .egg/.whl distributions already on disk. Instead it should always check to see if a copy already exists and reuse if there. This ordinarily should not be a problem but the zipimporter caches metadata by filename instead of stat/sha, so if the underlying contents changed a runtime error would be thrown due to seemingly corrupt zip file offsets. `RB #684 `_ 0.5.8 ----- * Adds ``-i/--index`` option to the pex tool. 0.5.7 ----- * Adds ``twitter.common.python.pex_bootstrap`` ``bootstrap_pex_env`` function in order to initialize a PEX environment from within a python interpreter. (Patch contributed by @kwlzn) * Adds stdin=,stdout=,stderr= keyword parameters to the ``PEX.run`` function. (Patch from @benjy) 0.5.6 ----- * The crawler now defaults to not follow links for security reasons. (Before the default behavior was to implicitly ``--follow-links`` for all requirements.) `RB #293 `_ 0.5.5 ----- * Improves scrubbing of site-packages from PEX environments. `RB #289 `_ 0.5.1 - 0.5.4 ------------- * Silences exceptions reported during interpreter teardown (the exceptions resulting from incorrect atexit handler behavior) introduced by 0.4.3 `RB #253 `_ `RB #249 `_ * Adds ``__hash__`` to ``Link`` so that Packages are hashed correctly in ``twitter.common.python.resolver`` ``resolve`` 0.5.0 ----- * Adds wheel support to ``twitter.common.python`` `RB #94 `_ `RB #154 `_ `RB #148 `_ 0.4.3 ----- * Adds ``twitter.common.python.finders`` which are additional finders for setuptools including: - find eggs within a .zip - find wheels within a directory - find wheels within a .zip `RB #86 `_ * Adds a new Package abstraction by refactoring Link into Link and Package. `RB #92 `_ * Adds support for PEP425 tagging necessary for wheel support. `RB #87 `_ * Improves python environment isolation by correctly scrubbing namespace packages injected into module ``__path__`` attributes by nspkg pth files. `RB #116 `_ * Adds ``twitter.common.python.resolver`` ``resolve`` method that handles transitive dependency resolution better. This means that if the requirement ``futures==2.1.2`` and an unqualified ``futures>=2`` is pulled in transitively, our resolver will correctly resolve futures 2.1.2 instead of reporting a VersionConflict if any version newer than 2.1.2 is available. `RB #129 `_ * Factors all ``twitter.common.python`` test helpers into ``twitter.common.python.testing`` `RB #91 `_ * Bug fix: Fix ``OrderedSet`` atexit exceptions `RB #147 `_ * Bug fix: Fix cross-device symlinking (patch from @benjy) * Bug fix: Raise a ``RuntimeError`` if we fail to write ``pkg_resources`` into a .pex `RB #115 `_ 0.4.2 ----- * Upgrade to ``setuptools>=1`` 0.4.1 ----- * ``twitter.common.python`` is no longer a namespace package 0.4.0 ----- * Kill the egg distiller. We now delegate .egg generation to bdist_egg. `RB #55 `_ 0.3.1 ----- * Short-circuit resolving a distribution if a local exact match is found. `RB #47 `_ * Correctly patch the global ``pkg_resources`` ``WorkingSet`` for the lifetime of the Python interpreter. `RB #52 `_ * Fixes a performance regression in setuptools ``build_zipmanifest`` `Setuptools Issue #154 `_ `RB #53 `_ 0.3.0 ----- * Plumb through the ``--zip-safe``, ``--always-write-cache``, ``--ignore-errors`` and ``--inherit-path`` flags to the pex tool. * Delete the unused ``PythonDirWrapper`` code. * Split ``PEXEnvironment`` resolution into ``twitter.common.python.environment`` and deconflate ``WorkingSet``/``Environment`` state. * Removes the monkeypatched zipimporter in favor of keeping all eggs unzipped within PEX files. Refactors the PEX dependency cache in ``util.py`` * Adds interpreter detection for Jython and PyPy. * Dependency translation errors should be made uniform. (Patch from @johnsirois) * Adds ``PEX_PROFILE_ENTRIES`` to limit the number of entries reported when ``PEX_PROFILE`` is enabled. (Patch from @rgs_) * Bug fix: Several fixes to error handling in ``twitter.common.python.http`` (From Marc Abramowitz) * Bug fix: PEX should not always assume that ``$PATH`` was available. (Patch from @jamesbroadhead) * Bug fix: Filename should be part of the .pex cache key or else multiple identical versions will incorrectly resolve (Patch from @tc) * Bug fix: Executed entry points shouldn't be forced to run in an environment with ``__future__`` imports enabled. (Patch from @lawson_patrick) * Bug fix: Detect versionless egg links and fail fast. (Patch from @johnsirois.) * Bug fix: Handle setuptools>=2.1 correctly in the zipimport monkeypatch (Patch from @johnsirois.) 0.2.3 ----- * Bug fix: Fix handling of Fetchers with ``file://`` urls. 0.2.2 ----- * Adds the pex tool as a standalone tool. 0.2.1 ----- * Bug fix: Bootstrapped ``twitter.common.python`` should declare ``twitter.common`` as a namespace package. 0.2.0 ----- * Make ``twitter.common.python`` fully standalone by consolidating external dependencies within ``twitter.common.python.common``. 0.1.0 ----- * Initial published version of ``twitter.common.python``. Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: Unix Classifier: Operating System :: POSIX :: Linux Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 pex-1.1.14/pex.egg-info/requires.txt0000644000076500000240000000002712743552145020100 0ustar kwilsonstaff00000000000000setuptools>=2.2,<20.11 pex-1.1.14/pex.egg-info/SOURCES.txt0000644000076500000240000000356012743552145017371 0ustar kwilsonstaff00000000000000CHANGES.rst LICENSE MANIFEST.in README.rst RELEASE.rst setup.cfg setup.py tox.ini docs/Makefile docs/buildingpex.rst docs/conf.py docs/index.rst docs/whatispex.rst docs/api/index.rst docs/rtd/requirements.txt pex/__init__.py pex/archiver.py pex/base.py pex/common.py pex/compatibility.py pex/compiler.py pex/crawler.py pex/environment.py pex/executor.py pex/fetcher.py pex/finders.py pex/http.py pex/installer.py pex/interpreter.py pex/iterator.py pex/link.py pex/orderedset.py pex/package.py pex/pep425.py pex/pex.py pex/pex_bootstrapper.py pex/pex_builder.py pex/pex_info.py pex/platforms.py pex/requirements.py pex/resolvable.py pex/resolver.py pex/resolver_options.py pex/sorter.py pex/testing.py pex/tracer.py pex/translator.py pex/util.py pex/variables.py pex/version.py pex.egg-info/PKG-INFO pex.egg-info/SOURCES.txt pex.egg-info/dependency_links.txt pex.egg-info/entry_points.txt pex.egg-info/requires.txt pex.egg-info/top_level.txt pex.egg-info/zip-safe pex/bin/__init__.py pex/bin/pex.py pex/commands/__init__.py pex/commands/bdist_pex.py scripts/combine_coverage.py scripts/coverage.sh scripts/do_nothing.py tests/test_archiver.py tests/test_bdist_pex.py tests/test_common.py tests/test_compatibility.py tests/test_compiler.py tests/test_crawler.py tests/test_environment.py tests/test_executor.py tests/test_fetcher.py tests/test_finders.py tests/test_http.py tests/test_inherits_path_option.py tests/test_integration.py tests/test_interpreter.py tests/test_iterator.py tests/test_link.py tests/test_package.py tests/test_pep425.py tests/test_pex.py tests/test_pex_binary.py tests/test_pex_bootstrapper.py tests/test_pex_builder.py tests/test_pex_info.py tests/test_platform.py tests/test_requirements.py tests/test_resolvable.py tests/test_resolver.py tests/test_sorter.py tests/test_translator.py tests/test_util.py tests/test_variables.py tests/example_packages/setuptools-18.0.1-py2.7.eggpex-1.1.14/pex.egg-info/top_level.txt0000644000076500000240000000000412743552145020225 0ustar kwilsonstaff00000000000000pex pex-1.1.14/pex.egg-info/zip-safe0000644000076500000240000000000112743552145017131 0ustar kwilsonstaff00000000000000 pex-1.1.14/PKG-INFO0000644000076500000240000010243212743552145014312 0ustar kwilsonstaff00000000000000Metadata-Version: 1.1 Name: pex Version: 1.1.14 Summary: The PEX packaging toolchain. Home-page: https://github.com/pantsbuild/pex Author: UNKNOWN Author-email: UNKNOWN License: Apache License, Version 2.0 Description: PEX === .. image:: https://travis-ci.org/pantsbuild/pex.svg?branch=master :target: https://travis-ci.org/pantsbuild/pex pex is a library for generating .pex (Python EXecutable) files which are executable Python environments in the spirit of `virtualenvs `_. pex is an expansion upon the ideas outlined in `PEP 441 `_ and makes the deployment of Python applications as simple as ``cp``. pex files may even include multiple platform-specific Python distributions, meaning that a single pex file can be portable across Linux and OS X. pex files can be built using the ``pex`` tool. Build systems such as `Pants `_ and `Buck `_ also support building .pex files directly. Still unsure about what pex does or how it works? Watch this quick lightning talk: `WTF is PEX? `_. pex is licensed under the Apache2 license. Installation ============ To install pex, simply .. code-block:: bash $ pip install pex You can also build pex in a git clone using tox: .. code-block:: bash $ tox -e py27-package $ cp dist/pex ~/bin This builds a pex binary in ``dist/pex`` that can be copied onto your ``$PATH``. The advantage to this approach is that it keeps your Python environment as empty as possible and is more in-line with what pex does philosophically. Simple Examples =============== Launch an interpreter with ``requests``, ``flask`` and ``psutil`` in the environment: .. code-block:: bash $ pex requests flask 'psutil>2,<3' Or instead freeze your current virtualenv via requirements.txt and execute it anywhere: .. code-block:: bash $ pex -r <(pip freeze) -o my_virtualenv.pex $ deactivate $ ./my_virtualenv.pex Run webserver.py in an environment containing ``flask`` as a quick way to experiment: .. code-block:: bash $ pex flask -- webserver.py Launch Sphinx in an ephemeral pex environment using the Sphinx entry point ``sphinx:main``: .. code-block:: bash $ pex sphinx -e sphinx:main -- --help Build a standalone pex binary into ``pex.pex`` using the ``pex`` console_scripts entry point: .. code-block:: bash $ pex pex -c pex -o pex.pex You can also build pex files that use a specific interpreter type: .. code-block:: bash $ pex pex -c pex --python=pypy -o pypy-pex.pex Most pex options compose well with one another, so the above commands can be mixed and matched. For a full list of options, just type ``pex --help``. Integrating pex into your workflow ================================== If you use tox (and you should!), a simple way to integrate pex into your workflow is to add a packaging test environment to your ``tox.ini``: .. code-block:: ini [testenv:package] deps = pex commands = pex . -o dist/app.pex Then ``tox -e package`` will produce a relocateable copy of your application that you can copy to staging or production environments. Documentation ============= More documentation about pex, building .pex files, and how .pex files work is available at https://pex.readthedocs.io. Development =========== pex uses `tox `_ for test and development automation. To run the test suite, just invoke tox: .. code-block:: bash $ tox If you don't have tox, you can generate a pex of tox: .. code-block:: $ pex tox -c tox -o ~/bin/tox Contributing ============ To contribute, follow these instructions: http://pantsbuild.github.io/howto_contribute.html Release Notes ============= 1.1.14 ------ * Repair Executor error handling for other classes of IOError/OSError. (#292) `#292 `_ * Fix bdist_pex --pex-args. (#285) `#285 `_ * Inherit user site with --inherit-path. (#284) `#284 `_ 1.1.13 ------ * Repair passing of stdio kwargs to PEX.run(). (#288) `#288 `_ 1.1.12 ------ * Fix bdist_pex interpreter cache directory. (#286) `#286 `_ * Normalize and edify subprocess execution. (#255) `#255 `_ * Don't ignore exit codes when using setuptools entry points. (#280) `#280 `_ `Fixes #137 `_ 1.1.11 ------ * Update cache dir when bdist_pex.run is called directly. `#278 `_ `Fixes #274 `_ 1.1.10 ------ * Improve failure modes for os.rename() as used in distribution caching. `#271 `_ `Fixes #265 `_ 1.1.9 ----- * Bugfix: Open setup.py in binary mode. `#264 `_ `Fixes #263 `_ 1.1.8 ----- * Bugfix: Repair a regression in `--disable-cache`. `#261 `_ `Fixes #260 `_ 1.1.7 ----- * Add README and supported python versions to PyPI description. `#258 `_ * Use `open` with utf-8 support. `#231 `_ * Add `--pex-root` option. `#206 `_ 1.1.6 ----- This release is a quick fix for a regression that inadvertently went out in 1.1.5 (Issue #243). * Fix the ``bdist_pex`` ``setuptools`` command to work for python2. `#246 `_ `Fixes #243 `_ * Upgrade pex dependencies on ``setuptools`` and ``wheel``. `#244 `_ `Fixes #238 `_ 1.1.5 ----- * Fix ``PEXBuilder.clone`` and thus ``bdist_pex --pex-args`` for ``--python`` and ``--python-shebang``. `#234 `_ `Fixes #233 `_ * Fix old ``pkg_resources`` egg version normalization. `#227 `_ `Fixes #226 `_ * Fix the ``inherit_path`` handling. `#224 `_ * Fix handling of bad distribution script names when used as the pex entrypoint. `#221 `_ `Fixes #220 `_ 1.1.4 ----- This release is a quick fix for a regression that inadvertently went out in 1.1.3 (Issue #216). * Add a test for the regression in ``FixedEggMetadata._zipinfo_name`` and revert the breaking commit. `Fixes #216 `_ 1.1.3 ----- This release includes an initial body of work towards Windows support, ABI tag support for CPython 2.x and a fix for version number normalization. * Add python 2.x abi tag support. `#214 `_ `Fixes #213 `_ * Add .idea to .gitignore. `#205 `_ * Don't normalize version numbers as names. `#204 `_ * More fixes for windows. `#202 `_ * Fixes to get pex to work on windows. `#198 `_ 1.1.2 ----- * Bump setuptools & wheel version pinning. `#194 `_ * Unescape html in PageParser.href_match_to_url. `#191 `_ * Memoize calls to Crawler.crawl() for performance win in find-links based resolution. `#187 `_ 1.1.1 ----- * Fix infinite recursion when ``PEX_PYTHON`` points at a symlink. `#182 `_ * Add ``/etc/pexrc`` to the list of pexrc locations to check. `#183 `_ * Improve error messaging for platform constrained Untranslateable errors. `#179 `_ 1.1.0 ----- * Add support for ``.pexrc`` files for influencing the pex environment. See the notes `here `_. `#128 `_. * Bug fix: PEX_PROFILE_FILENAME and PEX_PROFILE_SORT were not respected. `#154 `_. * Adds the ``bdist_pex`` command to setuptools. `#99 `_. * Bug fix: We did not normalize package names in ``ResolvableSet``, so it was possible to depend on ``sphinx`` and ``Sphinx-1.4a0.tar.gz`` and get two versions build and included into the pex. `#147 `_. * Adds a pex-identifying User-Agent. `#101 `_. 1.0.3 ----- * Bug fix: Accommodate OSX ``Python`` python binaries. Previously the OSX python distributions shipped with OSX, XCode and available via https://www.python.org/downloads/ could fail to be detected using the ``PythonInterpreter`` class. Fixes `#144 `_. * Bug fix: PEX_SCRIPT failed when the script was from a not-zip-safe egg. Original PR `#139 `_. * Bug fix: ``sys.exit`` called without arguments would cause `None` to be printed on stderr since pex 1.0.1. `#143 `_. 1.0.2 ----- * Bug fix: PEX-INFO values were overridden by environment ``Variables`` with default values that were not explicitly set in the environment. Fixes `#135 `_. * Bug fix: Since `69649c1 `_ we have been unpatching the side-effects of ``sys.modules`` after ``PEX.execute``. This takes all modules imported during the PEX lifecycle and sets all their attributes to ``None``. Unfortunately, ``sys.excepthook``, ``atexit`` and ``__del__`` may still try to operate using these tainted modules, causing exceptions on interpreter teardown. This reverts just the ``sys`` unpatching so that the abovementioned teardown hooks behave more predictably. Fixes `#141 `_. 1.0.1 ----- * Allow PEXBuilder to optionally copy files into the PEX environment instead of hard-linking them. * Allow PEXBuilder to optionally skip precompilation of .py files into .pyc files. * Bug fix: PEXBuilder did not respect the target interpreter when compiling source to bytecode. Fixes `#127 `_. * Bug fix: Fix complex resolutions when using a cache. Fixes: `#120 `_. 1.0.0 ----- The 1.0.0 release of pex introduces a few breaking changes: ``pex -r`` now takes requirements.txt files instead of requirement specs, ``pex -s`` has now been removed since source specs are accepted as arguments, and ``pex -p`` has been removed in favor of its alias ``pex -o``. The pex *command line interface* now adheres to semver insofar as backwards incompatible CLI changes will invoke a major version change. Any backwards incompatible changes to the PEX environment variable semantics will also result in a major version change. The pex *API* adheres to semver insofar as backwards incompatible API changes will invoke minor version changes. For users of the PEX API, it is recommended to add minor version ranges, e.g. ``pex>=1.0,<1.1``. For users of the PEX CLI, major version ranges such as ``pex>=1,<2`` should be sufficient. * BREAKING CHANGE: Removes the ``-s`` option in favor of specifying directories directly as arguments to the pex command line. * BREAKING CHANGE: ``pex -r`` now takes requirements.txt filenames and *not* requirement specs. Requirement specs are now passed as arguments to the pex tool. Use ``--`` to escape command line arguments passed to interpreters spawned by pex. Implements `#5 `_. * Adds a number of flag aliases to be more compatible with pip command lines: ``--no-index``, ``-f``, ``--find-links``, ``--index-url``, ``--no-use-wheel``. Removes ``-p`` in favor of ``-o`` exclusively. * Adds ``--python-shebang`` option to the pex tool in order to set the ``#!`` shebang to an exact path. `#53 `_. * Adds support for ``PEX_PYTHON`` environment variable which will cause the pex file to reinvoke itself using the interpreter specified, e.g. ``PEX_PYTHON=python3.4`` or ``PEX_PYTHON=/exact/path/to/interpreter``. `#27 `_. * Adds support for ``PEX_PATH`` environment variable which allows merging of PEX environments at runtime. This can be used to inject plugins or entry_points or modules from one PEX into another without explicitly building them together. `#30 `_. * Consolidates documentation of ``PEX_`` environment variables and adds the ``--help-variables`` option to the pex client. Partially addresses `#13 `_. * Adds helper method to dump a package subdirectory onto disk from within a zipped PEX file. This can be useful for applications that know they're running within a PEX and would prefer some static assets dumped to disk instead of running as an unzipped PEX file. `#12 `_. * Now supports extras for static URLs and installable directories. `#65 `_. * Adds ``-m`` and ``--entry-point`` alias to the existing ``-e`` option for entry points in the pex tool to evoke the similarity to ``python -m``. * Adds console script support via ``-c/--script/--console-script`` and ``PEX_SCRIPT``. This allows you to reference the named entry point instead of the exact ``module:name`` pair. Also supports scripts defined in the ``scripts`` section of setup.py. `#59 `_. * Adds more debugging information when encountering unresolvable requirements. `#79 `_. * Bug fix: ``PEX_COVERAGE`` and ``PEX_PROFILE`` did not function correctly when SystemExit was raised. Fixes `#81 `_. * Bug fix: Fixes caching in the PEX tool since we don't cache the source distributions of installable directories. `#24 `_. 0.9.0 ----- This is the last release before the 1.0.0 development branch is started. * Change the setuptools range to >=2.2,<16 by handling EntryPoint changes as well as being flexible on whether ``pkg_resources`` is a package or a module. Fixes `#55 `_ and `#34 `_. * Adds option groups to the pex tool to make the help output slightly more readable. * Bug fix: Make ``pip install pex`` work better by removing ``extras_requires`` on the ``console_script`` entry point. Fixes `#48 `_ * New feature: Adds an interpreter cache to the ``pex`` tool. If the user does not explicitly disable the wheel feature and attempts to build a pex with wheels but does not have the wheel package installed, pex will download it in order to make the feature work. Implements `#47 `_ in order to fix `#48 `_ 0.8.6 ----- * Bug fix: Honor installed sys.excepthook in pex teardown. `RB #1733 `_ * Bug fix: ``UrllibContext`` used ``replace`` as a keyword argument for ``bytes.decode`` but this only works on Python 3. `Pull Request #46 `_ 0.8.5 ----- * Bug fix: Fixup string formatting in pex/bin/pex.py to support Python 2.6 `Pull Request #40 `_ 0.8.4 ----- * Performance improvement: Speed up the best-case scenario of dependency resolution. `RB #1685 `_ * Bug fix: Change from ``uuid4().get_hex()`` to ``uuid4().hex`` to maintain Python3 compatibility of pex.common. `Pull Request #39 `_ * Bug fix: Actually cache the results of translation. Previously bdist translations would be created in a temporary directory even if a cache location was specified. `RB #1666 `_ * Bug fix: Support all potential abi tag permutations when determining platform compatibility. `Pull Request #33 `_ 0.8.3 ----- * Performance improvement: Don't always write packages to disk if they've already been cached. This can significantly speed up launching PEX files with a large number of non-zip-safe dependencies. `RB #1642 `_ 0.8.2 ----- * Bug fix: Allow pex 0.8.x to parse pex files produced by earlier versions of pex and twitter.common.python. * Pin pex to setuptools prior to 9.x until we have a chance to make changes related to PEP440 and the change of pkg_resources.py to a package. 0.8.1 ----- * Bug fix: Fix issue where it'd be possible to ``os.path.getmtime`` on a remote ``Link`` object `Issue #29 `_ 0.8.0 ----- * *API change*: Decouple translation from package iteration. This removes the Obtainer construct entirely, which likely means if you're using PEX as a library, you will need to change your code if you were doing anything nontrivial. This adds a couple new options to ``resolve`` but simplifies the story around how to cache packages. `RB #785 `_ * Refactor http handling in pex to allow for alternate http implementations. Adds support for `requests `_, improving both performance and security. For more information, read the commit notes at `91c7f32 `_. `RB #778 `_ * Improvements to API documentation throughout. * Renamed ``Tracer`` to ``TraceLogger`` to prevent nondeterministic isort ordering. * Refactor tox.ini to increase the number of environment combinations and improve coverage. * Adds HTTP retry support for the RequestsContext. `RB #1303 `_ * Make pex --version correct. `Issue #19 `_ * Bug fix: Fix over-aggressive sys.modules scrubbing for namespace packages. Under certain circumstances, namespace packages in site-packages could conflict with packages within a PEX, causing them to fail importing. `RB #1378 `_ * Bug fix: Replace uses of ``os.unsetenv(...)`` with ``del os.environ[...]`` `Pull Request #11 `_ * Bug fix: Scrub sys.path and sys.modules based upon both supplied path and realpath of files and directories. Newer versions of virtualenv on Linux symlink site-packages which caused those packages to not be removed from sys.path correctly. `Issue #21 `_ * Bug fix: The pex -s option was not correctly pulling in transitive dependencies. `Issue #22 `_ * Bug fix: Adds ``content`` method to HTTP contexts that does HTML content decoding, fixing an encoding issue only experienced when using Python 3. `Issue #10 `_ 0.7.0 ----- * Rename ``twitter.common.python`` to ``pex`` and split out from the `twitter/commons `_ repo. 0.6.0 ----- * Change the interpretation of ``-i`` (and of PyPIFetcher's pypi_base) to match pip's ``-i``. This is useful for compatibility with devpi. 0.5.10 ------ * Ensures that .egg/.whl distributions on disk have their mtime updated even though we no longer overwrite them. This gives them a new time lease against their ttl. Without this change, once a distribution aged past the ttl it would never be used again, and builds would re-create the same distributions in tmpdirs over and over again. 0.5.9 ----- * Fixes an issue where SourceTranslator would overwrite .egg/.whl distributions already on disk. Instead it should always check to see if a copy already exists and reuse if there. This ordinarily should not be a problem but the zipimporter caches metadata by filename instead of stat/sha, so if the underlying contents changed a runtime error would be thrown due to seemingly corrupt zip file offsets. `RB #684 `_ 0.5.8 ----- * Adds ``-i/--index`` option to the pex tool. 0.5.7 ----- * Adds ``twitter.common.python.pex_bootstrap`` ``bootstrap_pex_env`` function in order to initialize a PEX environment from within a python interpreter. (Patch contributed by @kwlzn) * Adds stdin=,stdout=,stderr= keyword parameters to the ``PEX.run`` function. (Patch from @benjy) 0.5.6 ----- * The crawler now defaults to not follow links for security reasons. (Before the default behavior was to implicitly ``--follow-links`` for all requirements.) `RB #293 `_ 0.5.5 ----- * Improves scrubbing of site-packages from PEX environments. `RB #289 `_ 0.5.1 - 0.5.4 ------------- * Silences exceptions reported during interpreter teardown (the exceptions resulting from incorrect atexit handler behavior) introduced by 0.4.3 `RB #253 `_ `RB #249 `_ * Adds ``__hash__`` to ``Link`` so that Packages are hashed correctly in ``twitter.common.python.resolver`` ``resolve`` 0.5.0 ----- * Adds wheel support to ``twitter.common.python`` `RB #94 `_ `RB #154 `_ `RB #148 `_ 0.4.3 ----- * Adds ``twitter.common.python.finders`` which are additional finders for setuptools including: - find eggs within a .zip - find wheels within a directory - find wheels within a .zip `RB #86 `_ * Adds a new Package abstraction by refactoring Link into Link and Package. `RB #92 `_ * Adds support for PEP425 tagging necessary for wheel support. `RB #87 `_ * Improves python environment isolation by correctly scrubbing namespace packages injected into module ``__path__`` attributes by nspkg pth files. `RB #116 `_ * Adds ``twitter.common.python.resolver`` ``resolve`` method that handles transitive dependency resolution better. This means that if the requirement ``futures==2.1.2`` and an unqualified ``futures>=2`` is pulled in transitively, our resolver will correctly resolve futures 2.1.2 instead of reporting a VersionConflict if any version newer than 2.1.2 is available. `RB #129 `_ * Factors all ``twitter.common.python`` test helpers into ``twitter.common.python.testing`` `RB #91 `_ * Bug fix: Fix ``OrderedSet`` atexit exceptions `RB #147 `_ * Bug fix: Fix cross-device symlinking (patch from @benjy) * Bug fix: Raise a ``RuntimeError`` if we fail to write ``pkg_resources`` into a .pex `RB #115 `_ 0.4.2 ----- * Upgrade to ``setuptools>=1`` 0.4.1 ----- * ``twitter.common.python`` is no longer a namespace package 0.4.0 ----- * Kill the egg distiller. We now delegate .egg generation to bdist_egg. `RB #55 `_ 0.3.1 ----- * Short-circuit resolving a distribution if a local exact match is found. `RB #47 `_ * Correctly patch the global ``pkg_resources`` ``WorkingSet`` for the lifetime of the Python interpreter. `RB #52 `_ * Fixes a performance regression in setuptools ``build_zipmanifest`` `Setuptools Issue #154 `_ `RB #53 `_ 0.3.0 ----- * Plumb through the ``--zip-safe``, ``--always-write-cache``, ``--ignore-errors`` and ``--inherit-path`` flags to the pex tool. * Delete the unused ``PythonDirWrapper`` code. * Split ``PEXEnvironment`` resolution into ``twitter.common.python.environment`` and deconflate ``WorkingSet``/``Environment`` state. * Removes the monkeypatched zipimporter in favor of keeping all eggs unzipped within PEX files. Refactors the PEX dependency cache in ``util.py`` * Adds interpreter detection for Jython and PyPy. * Dependency translation errors should be made uniform. (Patch from @johnsirois) * Adds ``PEX_PROFILE_ENTRIES`` to limit the number of entries reported when ``PEX_PROFILE`` is enabled. (Patch from @rgs_) * Bug fix: Several fixes to error handling in ``twitter.common.python.http`` (From Marc Abramowitz) * Bug fix: PEX should not always assume that ``$PATH`` was available. (Patch from @jamesbroadhead) * Bug fix: Filename should be part of the .pex cache key or else multiple identical versions will incorrectly resolve (Patch from @tc) * Bug fix: Executed entry points shouldn't be forced to run in an environment with ``__future__`` imports enabled. (Patch from @lawson_patrick) * Bug fix: Detect versionless egg links and fail fast. (Patch from @johnsirois.) * Bug fix: Handle setuptools>=2.1 correctly in the zipimport monkeypatch (Patch from @johnsirois.) 0.2.3 ----- * Bug fix: Fix handling of Fetchers with ``file://`` urls. 0.2.2 ----- * Adds the pex tool as a standalone tool. 0.2.1 ----- * Bug fix: Bootstrapped ``twitter.common.python`` should declare ``twitter.common`` as a namespace package. 0.2.0 ----- * Make ``twitter.common.python`` fully standalone by consolidating external dependencies within ``twitter.common.python.common``. 0.1.0 ----- * Initial published version of ``twitter.common.python``. Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: Unix Classifier: Operating System :: POSIX :: Linux Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 pex-1.1.14/README.rst0000644000076500000240000000700612726137204014701 0ustar kwilsonstaff00000000000000PEX === .. image:: https://travis-ci.org/pantsbuild/pex.svg?branch=master :target: https://travis-ci.org/pantsbuild/pex pex is a library for generating .pex (Python EXecutable) files which are executable Python environments in the spirit of `virtualenvs `_. pex is an expansion upon the ideas outlined in `PEP 441 `_ and makes the deployment of Python applications as simple as ``cp``. pex files may even include multiple platform-specific Python distributions, meaning that a single pex file can be portable across Linux and OS X. pex files can be built using the ``pex`` tool. Build systems such as `Pants `_ and `Buck `_ also support building .pex files directly. Still unsure about what pex does or how it works? Watch this quick lightning talk: `WTF is PEX? `_. pex is licensed under the Apache2 license. Installation ============ To install pex, simply .. code-block:: bash $ pip install pex You can also build pex in a git clone using tox: .. code-block:: bash $ tox -e py27-package $ cp dist/pex ~/bin This builds a pex binary in ``dist/pex`` that can be copied onto your ``$PATH``. The advantage to this approach is that it keeps your Python environment as empty as possible and is more in-line with what pex does philosophically. Simple Examples =============== Launch an interpreter with ``requests``, ``flask`` and ``psutil`` in the environment: .. code-block:: bash $ pex requests flask 'psutil>2,<3' Or instead freeze your current virtualenv via requirements.txt and execute it anywhere: .. code-block:: bash $ pex -r <(pip freeze) -o my_virtualenv.pex $ deactivate $ ./my_virtualenv.pex Run webserver.py in an environment containing ``flask`` as a quick way to experiment: .. code-block:: bash $ pex flask -- webserver.py Launch Sphinx in an ephemeral pex environment using the Sphinx entry point ``sphinx:main``: .. code-block:: bash $ pex sphinx -e sphinx:main -- --help Build a standalone pex binary into ``pex.pex`` using the ``pex`` console_scripts entry point: .. code-block:: bash $ pex pex -c pex -o pex.pex You can also build pex files that use a specific interpreter type: .. code-block:: bash $ pex pex -c pex --python=pypy -o pypy-pex.pex Most pex options compose well with one another, so the above commands can be mixed and matched. For a full list of options, just type ``pex --help``. Integrating pex into your workflow ================================== If you use tox (and you should!), a simple way to integrate pex into your workflow is to add a packaging test environment to your ``tox.ini``: .. code-block:: ini [testenv:package] deps = pex commands = pex . -o dist/app.pex Then ``tox -e package`` will produce a relocateable copy of your application that you can copy to staging or production environments. Documentation ============= More documentation about pex, building .pex files, and how .pex files work is available at https://pex.readthedocs.io. Development =========== pex uses `tox `_ for test and development automation. To run the test suite, just invoke tox: .. code-block:: bash $ tox If you don't have tox, you can generate a pex of tox: .. code-block:: $ pex tox -c tox -o ~/bin/tox Contributing ============ To contribute, follow these instructions: http://pantsbuild.github.io/howto_contribute.html pex-1.1.14/RELEASE.rst0000644000076500000240000000511312742231260015014 0ustar kwilsonstaff00000000000000=================== Pex Release Process =================== .. contents:: Table of Contents Preparation =========== Version Bump and Changelog -------------------------- Bump the version in ``pex/version.py`` and update ``CHANGES.rst`` in a local commit: :: $ git log --stat -1 commit 1e70fddafd480311e717e58dbf9466cf40003137 Author: John Sirois Date: Mon Nov 30 23:30:22 2015 -0700 Release 1.1.1 CHANGES.rst | 13 +++++++++++++ pex/version.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) Push to Master -------------- Tag, push and watch Travis CI go green: :: $ git tag -am 'Release 1.1.1' v1.1.1 $ git push --tags origin HEAD PyPI Release ============ Upload to PyPI -------------- :: $ python setup.py bdist_wheel sdist upload --sign Dogfood ------- :: $ pip install --upgrade pex ... $ pex --version pex 1.1.1 Github Release ============== Prepare binary assets --------------------- :: $ tox -e py27-package ... $ ./dist/py27 --version pex27 1.1.1 $ tox -e py35-package ... $ ./dist/py35 --version pex35 1.1.1 Craft the Release ----------------- Open a tab on prior release as a template: - https://github.com/pantsbuild/pex/releases/edit/v1.1.0 Open a tab to construct the current: - https://github.com/pantsbuild/pex/releases/new?tag=v1.1.1 1. Use "Release " as the release name (e.g. "Release 1.1.1") 2. Copy and paste the most recent CHANGES.rst section. 3. Adapt the syntax from RestructuredText to Markdown (e.g. ``#ID `` -> ``#ID``). 4. Upload both the ``pex27`` and ``pex35`` artifacts. Check your work --------------- :: $ curl -L https://github.com/pantsbuild/pex/releases/download/v1.1.1/pex27 -O % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 578 0 578 0 0 525 0 --:--:-- 0:00:01 --:--:-- 525 100 1450k 100 1450k 0 0 128k 0 0:00:11 0:00:11 --:--:-- 139k $ ./pex27 --version pex27 1.1.1 $ curl -L https://github.com/pantsbuild/pex/releases/download/v1.1.1/pex35 -O % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 578 0 578 0 0 296 0 --:--:-- 0:00:01 --:--:-- 296 100 1406k 100 1406k 0 0 131k 0 0:00:10 0:00:10 --:--:-- 256k $ ./pex35 --version pex35 1.1.1 pex-1.1.14/scripts/0000755000076500000240000000000012743552145014702 5ustar kwilsonstaff00000000000000pex-1.1.14/scripts/combine_coverage.py0000644000076500000240000000372312623452313020541 0ustar kwilsonstaff00000000000000import os import pprint import sys from coverage.data import CoverageData from pex.pex_builder import PEXBuilder def _iter_filter(root_dir, data_dict): root_fragment = os.path.join(root_dir, 'pex/') pex_fragment = '/%s/_pex/' % PEXBuilder.BOOTSTRAP_DIR for filename, records in data_dict.items(): # already acceptable coverage if filename.startswith(root_fragment): yield (filename, dict((record, None) for record in records)) continue # possible it's coverage from within a pex environment try: bi = filename.index(pex_fragment) except ValueError: continue # rewrite to make up for fact that each pex environment is ephemeral. yield ( os.path.join(root_dir, 'pex', filename[bi + len(pex_fragment):]), dict((record, None) for record in records) ) def combine_pex_coverage(root_dir, coverage_file_iter, unlink=True): combined = CoverageData(basename='.coverage') for filename in coverage_file_iter: cov = CoverageData(basename=filename) cov.read() combined.add_line_data(dict(_iter_filter(root_dir, cov.line_data()))) combined.add_arc_data(dict(_iter_filter(root_dir, cov.arc_data()))) os.unlink(filename) # filter out non-pex files prefix = os.path.join(root_dir, 'pex/') non_pex = [filename for filename in combined.lines if not filename.startswith(prefix)] for filename in non_pex: combined.lines.pop(filename) non_pex = [filename for filename in combined.arcs if not filename.startswith(prefix)] for filename in non_pex: combined.arcs.pop(filename) combined.write() return combined.filename def main(args): script = os.path.realpath(args[0]) root = os.path.realpath(os.path.join(os.path.dirname(script), '..')) coverage_iterator = [ os.path.join(root, filename) for filename in os.listdir(root) if filename.startswith('.coverage')] combine_pex_coverage(root, coverage_iterator, unlink=False) if __name__ == '__main__': main(sys.argv) pex-1.1.14/scripts/coverage.sh0000755000076500000240000000046512643564600017037 0ustar kwilsonstaff00000000000000#!/bin/bash coverage run -p -m py.test tests coverage run -p -m pex.bin.pex -v --help >&/dev/null coverage run -p -m pex.bin.pex -v -- scripts/do_nothing.py coverage run -p -m pex.bin.pex -v requests -- scripts/do_nothing.py coverage run -p -m pex.bin.pex -v . 'setuptools>=2.2,<20' -- scripts/do_nothing.py pex-1.1.14/scripts/do_nothing.py0000644000076500000240000000000012623452313017363 0ustar kwilsonstaff00000000000000pex-1.1.14/setup.cfg0000644000076500000240000000012212743552145015027 0ustar kwilsonstaff00000000000000[wheel] universal = 1 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 pex-1.1.14/setup.py0000644000076500000240000000410412720650765014726 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from setuptools import setup with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as fp: LONG_DESCRIPTION = fp.read() + '\n' with open(os.path.join(os.path.dirname(__file__), 'CHANGES.rst')) as fp: LONG_DESCRIPTION += fp.read() # This seems to be a fairly standard version file pattern. # # Populates the following variables: # __version__ # __setuptools_requirement # __wheel_requirement __version__ = '' version_py_file = os.path.join(os.path.dirname(__file__), 'pex', 'version.py') with open(version_py_file) as version_py: exec(compile(version_py.read(), version_py_file, 'exec')) setup( name = 'pex', version = __version__, description = "The PEX packaging toolchain.", long_description = LONG_DESCRIPTION, url = 'https://github.com/pantsbuild/pex', license = 'Apache License, Version 2.0', zip_safe = True, classifiers = [ 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: Unix', 'Operating System :: POSIX :: Linux', 'Operating System :: MacOS :: MacOS X', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', ], packages = [ 'pex', 'pex.bin', 'pex.commands', ], install_requires = [ SETUPTOOLS_REQUIREMENT, ], tests_require = [ 'mock', 'twitter.common.contextutil>=0.3.1,<0.4.0', 'twitter.common.lang>=0.3.1,<0.4.0', 'twitter.common.testing>=0.3.1,<0.4.0', 'twitter.common.dirutil>=0.3.1,<0.4.0', 'pytest', ], entry_points = { 'distutils.commands': [ 'bdist_pex = pex.commands.bdist_pex:bdist_pex', ], 'console_scripts': [ 'pex = pex.bin.pex:main', ], }, ) pex-1.1.14/tests/0000755000076500000240000000000012743552145014355 5ustar kwilsonstaff00000000000000pex-1.1.14/tests/example_packages/0000755000076500000240000000000012743552145017646 5ustar kwilsonstaff00000000000000pex-1.1.14/tests/example_packages/setuptools-18.0.1-py2.7.egg0000644000076500000240000126763112671105375024172 0ustar kwilsonstaff00000000000000#!/bin/sh if [ `basename $0` = "setuptools-18.0.1-py2.7.egg" ] then exec python2.7 -c "import sys, os; sys.path.insert(0, os.path.abspath('$0')); from setuptools.command.easy_install import bootstrap; sys.exit(bootstrap())" "$@" else echo $0 is not the correct name for this egg file. echo Please rename it back to setuptools-18.0.1-py2.7.egg and try again. exec false fi PKƒ,ÒF\OºEi~easy_install.py-Ì1ƒ@ DÑ~Oa¹4 eŠ´\`d‘EYim#Ö¹=1Õ4ï3ó´Å7ÓKÚïm-¤Vš]UìÃÌ)•…Í#u€J1 {&:·l®Ôrìk¸×6ÜtÈgåî]} ºà]§¤PKò lH‰¤ræê>easy_install.pycU»N1EÇvHP=[nA¼VÑP¤I”&嬭ÄÂ{¥¤…Ïâ³ø'[ÀHs4Ï{Ù÷å¸ùúX¶ÐÅ|ÆŒ5B¬4EàÂû-( Š¥à¬Íà€x¼Àky–?¯‹Îi«‹3“´¶hƒsÒ«tŽ{!œ4^óƒQœ¤"çe®Òèx¥B+Dÿá¥ÓØÜdº] ÁFÞ«rNœ¬Y°„ˆwˆug¬ªÖÊÄÄlCÜO¦5ŸÖ“ýC#šûJo6Õ_!¾;Í]PÕOY7CzA®È/PKƒ,ÒF®šø|ú(_markerlib/__init__.pyP;nÃ0 Ýs ä†P c‡.º ŠM·B%Q è|Pôî•mEp‚å$RïCáëórY‰L’¥™³œo½) É`n;p?‚ä=ÜÕAh©}Æê¢õ¾–^ÞTëÀý7çJëBªÎ!rбÊ} º±¬‡½¼£CõÏšZù® !›\“ÒAzÐ7íÎþ·ˆ8™Èwâ~³<ØvïbDÜœðNOF’ÞTÔGð#Øq$Óh¯ÓB<ŽþNKB2¤~èï’L½Ó¸³Œ/Ï+í›ü¦jm_iíx®Êf‘•&÷>Ü~†žUÜ”ê9‘0wHOvȰ;b‹yýPKƒ,ÒF.ܤÆ‹_markerlib/markers.py­WmoÛ6þ®_qsHj]aM×­æÙêÙ²¤hж@– ŒD9\dR#i;ÆÒÿ¾;’’%GE¿L@`J¼7Þ=÷ðrÏž<ƒB•B.Žae«g¯èK4™LN¥åºÑÜÂÛù[xñÝKàr-´’K.-,™¾ãÚdQ4ÿôö\ ù0›=|3{Ê‚×à?+ýÀdy Y†’›[®¹ß¸áµ’ V“[PØ[eøq>Íßd¾FBI˜A|h²CÃ!$fk²°‘ Y©«o¯§ðèãóë´o©ZÕuÏ\O<3M-l’¢§ L&Ù’£PX¹¯¤ÐÔÌVJ/ƒ~ûêÝ„—lçcÿS’%—¬¸’÷%ç}Ép±ljN¹gvÏè@°Â Òœƒ±+<…ZÜqˆ²ïã)( ñFÈG1•;Šòœa–r´|—¼b«Úæ½’£F\¨e#jNKÑÂ#¾Ž"t­´fl»T¦]u‰ v¹áìNó ]߬Dm…̃Œ!¬¢Èêí±;J¥Õ²³­õ±³Gü¾à…S'3×ZioBT»Ï`ò7[³‰ß¡ç~sÖà({ ·ÌÐy`©ÊUͧp³²@ØþZÖ¡ZÉ‚–Yg“9g’îœÓƒÙ\i ÆÄíñšÚ¢“`Â`N¢”¥š–—`°G±ƒÖL vSsåNÞ]bÿûHÀî\ÇÆCÁ]Ã=j­ã£ëžê¼9ýôdž"r1ìa\Ê4¯]`>‰Ö±€ÛE/}c¶%NXà‰x¶È°?dGO§H%):*BUÌ(6J aoû>>R¿óC†¢ù9õ?!%¨Vƒlíµ6J=îöQ…Ðá}…®éGFaCêãpêÛà÷V3=WÈ2˜Ù[ÎkÀ\2õ9ŠÐiùÁØÄÁ'»ã[“¤i×8q“ îàè$¯ðS¦9Æ\ð¥ò8½FüuÛHÔ#¬Ò¶2Ð;þB5îBÂþöyõµºa5Ö^¸öbz›mõú†v|ði53N.ß¼–»sa;gçªäï5“†ÒËuðNÁåoaó<1¼®ðJÁœºÔöz”v²nƒ.‚n}”ENTKn [`:Å“³³‹ó×(íøyiìzùY©ú¢ñë‹ýŒ ¶Î tnu¦XéW—V{V?ÒÕpí*ožžW'2è]tjÞ»0Hr_QžÿãuµíïÜ/Neø5íï¹ 2gÝoÅÖ.Oeué^ ƒÝçs-±(½4cYçÒ¬4ïåWÉz‹Ð@¤ ‰Ä\×jƒýOЦƒAª›@ŒPY""IfêKθϺĩp¹EÛ÷î®Hb ¶ó˜|þ”‡†þ#ÖFždˆ›éWå‘“à‰;\V¨:WU…ŸÂSˆÿŠÓtwxØÀ:{”ݽÄçÚ¾X‚7ÈAH@ôQó5’6%kÕ€Â|{É79ÙA¨·N&î"™ÐäæÎ³fõŠg¢ô3²—†uaïGÏF„תð×:éÎånW¼}xîK“øŸpKÓÇ …Ý)Ýë|sŒ'ö^Ép°F0—-¸äxáæ>µ$™öɧU÷…é¥ É¹.óAdAoôÊ"—þø}?ǺÐG±Tb› ™áÕ*ìì½^Q–òï:[˜¹²øûŠñºãÓ$?LdŸ Ýv‚”º©Çᢱ4 °aã;wp醺~&\ˆWÞªŸÆÃ÷;ßö†8z$÷öb¢~÷JDMª¢ãø½¼’I/œ]‹8ã}­"^÷xaâž±r:2œµ‰ µÛ ±ìÁ4ý¿bm·aÕ”È4¦ŸüýsÐÜŠã8E!©“ÀAòó¾z¿²_´ÐšßþÑä3Ф "«µ@²—õiߊ×ê’šåy© ÷/Žÿ涇¸ëöP~ЧCtºFéþJF|÷ˤÓ–>DúPKò lHfpK‰ˆî_markerlib/markers.pyc­XërÛÖ^€‰4©›uµêŒ+ºcS¶“(nFr£X²G©*{@7r™Q1q(ƒ‚çPg虎•éåú«}€üèô•ú¯Ðîî Zö¿—åÁb±gÏ~{v÷0÷ßjyíßï~ß‚äUÄï7ø•ÿ2<€&R<¼å ‰ã YHÇEhAŒAsú³Ì,’ðI š%0öÃUÈ‹2—!þ†!rйÞ›ÿ¼qøHòÍ?á@hÀ+D:¨¨k^™/*à]kÞ«À]V¡3^¼ ¸@c'aÉ›Â;Zõ4Žò$sKœÑ“|q/J<šE͸‚9XkNÃù3 ¦¡sn^°u° M\Ì<ˆY8.B¼làm/éŸÎÝóhöõ7Ë~ö½E^ ²—@˜ÐY€6úô1Qéš‹àÝd‰%ðnñàˆ"tnÒíæ-ð>aæ9Õû~4 ù µÏ¶ÿ l;¡q7Êz±ýÂúü‹/-žúqžˆPY'n|,bY/—·_½°­üp°±1XÞ„‘²üðÀÒì(¸¡w`Õë(yöZÄBß8AIKE–ö­¨m©×‘_—˾º}¼ SœÀBkÃZ¹-ë·åŠu۪ɾ¬'7?lG?Ü?¸k}À|ppgXS»Cê†Äë²øªvÕ𑬇î‰@¡dÄ\z ¸ªÅ'Éó饞&¹¨_Îq•U»ó¾ä‰Ûzí‡bX2a]•LÖàŸtA¾wÕ•>*hq­v,„%Uì‡Gw­À?ÖÊÃúÚÊ]+Š­•3?üüáJY]GÔ=Ñv{r†`VcÈoE']?ª„c? ÿøÚ«aœ€šCòQTïtÜS7K $ÿ„"Œî`JhÔLì)J߱Љ]!ò×H{~à­z¾Tä©Hžß{p¿þàþ½óGkÎÚ«âèhÕÑaø‡«i€vûvŸ^&5&› +4‚PÁæ“„š¸\Ož"»-Ÿ¨O:Ø_‰-IþJGN‘Ì•(xŸ™.?f~Ü“d¢8W±Ë¦Ô™:™[ÍÔ­e2?%–Ã#"±…êšՊº¼Ù¨õÎ~ô¥uD‡n -ÏoÑlnܯ30 1y~çûM»1ZhHÅ£ S4›—û¯}%T—­ð~¿%ÁŸÈÀ%8‡™@©8Ï´À´ÈtŒé8Ó´±r`v/ƒÎÛD+Ð6á«Kn•éÓI¦SL§™Î0½Ît–éÓyh—Y F3™³@eŽ‹€Î¢Ðk™ BJU$èR.¨d7Ñ6“ˆ:ƒ‰‚AÛž¡ïÕ8AŠéÒW޳q¹=2s ©¹»:¨´ÅƒêN­LZ2qr´d¼‹ Ìb_@·Îcø½3 Ä ¢1` øl£Æë¹‡d;”½˜²S²\+ ƒ>F)F½JË ‚èLxVyBÖår–—”í‡/I·%~lÚŠ¼MþX£•*Ú¾DµÊ [‚3Ûæîîóýí-EÁÕèã¤çÛqÅìf–oEµÛR(EHºR©I6Â/c7”´aEÌ›ãuk¸ì©3²{d[e Ÿ~šîq0gŒ"¾oj¸È¸| ×# Eø ,&A¤ñ!hhT Þš,W„™ACÚä/i*ÌGJ„ˆˆ°q*ÊÈŠýÞ–Ûj ‰˜d©³FµÒ¥ïaÔ~qƒžP¤Ö÷øé`o¶Ô¹ª²“»}'ˆZºlåRÚ7HAŠ3g”®d /g3]Ð$E ÌšQ[J§vJåŽÃÑà8'‘× ðÒžÎKË~‚ÒÅ¢HUìÛ( žwygÊ훩[v#×ãÅ7TlÏ—.6C=ô<æŸí7üóLÝ3µÍ—Øñd·îHÜ ÌØÕb»(VПOF;!‡ý uM¥¹Nj(cRîWæ¼ùÔ,·Œ«ñXÏâq. ã­AdÀ°O`D( éù=vz\ð@` qâÐn§¢Ï¥`K8ŽŽD(b¿åèH*m4ëPØ eE#‹¨JjNr»A*‹œOçðÍN¡o1uÊ|’S‡FT´s†ÎŽ{’‚cýÃôöØþŠž¤ù[×mËcBó(V!sÒ¬ÉÛ,b°Ìb° /7–¯3¹,U|—rn e–ÍR~i¡T(å+fiñÿPKò lH—Ô`ÝEGG-INFO/dependency_links.txtÍM @á}¯áÚa@~M< P¦%Æ–¦iOo4qáÎÕË[}sï¥]+{ÉPö>¯ ¬ubÅÇ»ŸRcm}Ö˜Xd1Õž){æ€À¡û ÓqzŒê&©œ Ö“K|$$'zKšãp˜ÿ´6¶ååÍ´¾Öô3gG.Ð'#, B4Ü*-íˆÑx« Í“^PKò lHOÒ¨\|é EGG-INFO/entry_points.txt•VÁŽÛ ½óû›ÃöP ©×VU¥¶÷h…°=qQl €“¸_߀—XƱ/0xÞ›ÌÌÀ±VÒª˜­ÐξàvdBZÇ»îåË‹7h§Tgµê{.›CŽ =òóúvø¼•Gްnpâ…ðNp»l"¨hIå¹ Úv:©é$EŠÑýÕt’"å*¤|!ôaEªAt ƒ[‰šÔt’"Ek =Ò$.Ð)½ Jç½§›/þA”OªÀ‹Zš²ê&yHÆãÌÖÌQtþa²Ó‰jÝh&OÄXë䢳51ÐâéƒYf'-M1ÊqtÐÑûD,¿€*Æ•´4 Äú4,€½Š†‘ á\ÐÑûD”ìy õt§xÃUâÌ4“A ±3ŒWe|;ÀuãØ›SŸ<Ú{š™âÖz˜uFÈãi@ƒl@Ö#®åy# x †°j05l%IgF¦•‹ÁÕ >³DàVwCLóúŒYÃ/2s2á#ü;eo†‰½ÉOÜS…_¦ZˆÊŠ€ü†$ïÁ¢—ÉU™'­&û÷ýÔl{í ßçó)9/ߌ z­ŒãUw¸¤Ü·ƒ˜W{†þ€ôó~°JäÉÑ&Kéw70“|"ï!ýšY~ZÚF9¦~¸üKÿ÷o¯ß~ýõäÆ x¦Ïñ ˜WýÁ•®ßÉ‚Âs·ÂM lá]¹‘,™ªüK OoÖ@vûÏÛÄ– Ñ“,Uánÿ©n6û~¬#¥Y矛éÈbÇLÈ(±q'”|÷O õJjÃóËa*rMÈPKò lHt²Âu1EGG-INFO/PKG-INFO½Zmsã¶vþî_:wfmDe“ìÞDs“©ãÍ&ÎÍ®ÕÈé¶™;³‚HHBM¼iY™þ¡þŽþ±>ç$@‹öÚÛî—¥Eàà¼>ç|§j™ÉZŽÿUUV›b*^&/ÞË­š «ê¦¬ÉíQxûuò9Ì›íVVû©øAZïEfvEnd6ËFçøO¶–y>M¹®d¦FB™h ÿ»˜íë)D)Ó¹Vöè'³UãS±©ëÒN'“¥®—Mz£êÄTëI¹/å$âè¼jÚš1!]¬…{¡ë½_2V[©ó©È´­›ZçvlõúŸKÞF”~Ñ©*,žÍß S‰ßg¿½Q6­tY³Ìß>þïHø—N6b‚„ýÍÒÓ<°Ü®{*½î!IDjŠZµNÅÙÙµ\æJ˜•¸ð¿žnêY¬•ø 0Õ^ü¥U°ÓÁÆØZe¬ã ÞÉÆ-N6õ6ÿnñ19$;~èß}}HÒ"ÿQ5)=ÛgÐè®7JT*5Û­*2•‰Ü‹Úˆ¥15Ë2òVãd±vɶB[ZØzhP‹úã#ïIÊýâ#[¬j ¡kѰájXËj­êÖÇTq«+S€:oôj¥*G„8Ý›F@éYôP‡ÁÁËß]a£—í‹ä5ù>Œ¥ªD\›6€cè-®¯hW÷×+Ä»U¬ºEd%±Âʈƒ—É]Gñ/OŠùI%w“Žì¸ÜñÕ$2â°›’ß $oDY™[ͪ7"ÚEî!Énh7÷\*0‘:’¤$[‹›.EÚ¦`¬T®¤U x?FçEøÖž“œ‰6±0‡t>è>lÅÉÌì€Æã|ÙÙìô.oAcIÁš¼¶£¦ËJÝjÓXqë€o/_‹«`âßÚupúÅÇÓᶬ-Nvnà\iÞdä}$ËÜÉrJÂ(YåZUá< œßÞÝézÓÛÙ:«¢ÄS¿°¢4Öj2K™w™£)d:j‘:)<‰˜S!uÅ/ J‰Àæm×N§‡BÓ¿ïÄÉeqknÔøƒZþª(Ðë§Yþ4ñ¨.þS8„pøïômšíq¯,ëy¶Õ…¦sj *+}«s…dKz& ØBÓ16(#Ò—¤P®Æ¹IeÞþÈPþÿ#2rxÔ劙glõÀóeaÄoSY$Zà­ÁbkÓQ (íi¶˜p|xœõwÇçëÀVp­ÿ<ôÿZ{büå¿<>QžÐ½×çf΄ñ¨¹Ó ÛîeCÈ 7„™"½C.½l¸FXÁ?™\Ë–và Å`ËU‘ªžc –°S­œ0+Hªð ôþ£ß7¨MQ MlêÒÙb1gI,–Úf™!]¦\9Èt0‚Í·ˆ>ž8ïiGVf™CŽ)–[,fç×?ረº·ZZ’¿Á­ ì,L-d^)™…Üt¶\Œø˜Èt6¶#Ãòˆ¨àX,þ>¦ç³Ù›óëó¿9Mü­Û7`…ÃüÄŠÑ+­²Ç“Òp&jÉ„¡îéã<Þ“?ôŒÞ.”m„s*–‚‡µ.xÏm]•Ç6€ü……ZŠe…ó‘‚pÞªP«{ÂÒÇðùc(VÖì·©yò©Ú F7¼CM.~ÑEs× voåШ œùæiŸPÞzÄ‹ƒ8J¹s»óÐ}ñH†§aœ_!%´ÙáÞ{ÃyYÖ!ì)»JyÀ'de¾Û4ÀJ´ jvŠ—8;FY!‚zÚë §¯¤X¶É̃²çHk'ñ|?ŠKhq©BnáV"ŽÿRÖ›¼úIÎÁXÆŠÉ3¨·íˆNcà/ߨ¥(¿f§¹Š]ÍÅ«^dÛÓÄ âuÁ#V9³›"{är€DíÃn.]u”ªª(¥ä¯ä`¡àoq–¤‰µy²Bm—ï“çDØ¡ònen˜µË~çÊ@â‚À^ÿucÞÚÜHrà%µ”©i¼9è\’#?TÅaz_º`_Èó}_!ï’}ò‡.Ÿ«ÔÙ‹Ýn—„ÁÈb@üŽŸH ^ÇÛ@PSr“êz$m-Ê™5I²nÝtÙ¬!óä|$.ù¸Ýi®Ý¸$2âÕ7¶‹ÄÍ„œ¼úæ3WðÔãW_ýò›—¯¾£.%Te P;ØYÜlGá…œ´€µ=¸ýD\Ç…§•ÞŒc•?¯ùsô|Ôõâq ÞTÚTêSiǵZäïd*dÿ&N°/jÃøPÞÆ4Ôˆ´‚qæTä«6å‚_· ?ä–JÁKÓh%CóbADñáÃb1¾ /Æ•H\–?l fì‰gÍ0޳[‰Ê3ë·Wæp¥³5ÙRëÕ4†'ˆÛ î àÐg“¿¦hüÌ6Ì#|ÊÕ2úŽ¢­CÒ ºƒà©ƒ ë¥QÏ'«%yùª2[±˜÷:Ù~v {‘îb-@¢«W!Q½Ñ©—mÇS¹¦, ¨ÂD–WÇ;ñ“žº>aëÞý© š0æñ±<; };Á)“éV4» ŸQ{–p>?a“bÕ€ŒgQä†Þèw¢‹ÆµÔÄÎÁð:ï7Õ¢‘9j3ª“2UK{?hÃd$”-Uªïl:•öÜ :gèûOçƒ#1šH2SÍ…£}=zsŸdêÙ'}æÈcrãŽÜ#±ÚVó÷¡:«×·ácy˜€2k…`ª%§ÿò¾°H…È‚tuѦ³YBÜÕ„^dêý” U%òÊ8S“Âú˜8­Çkn]k?Á´˜òIÜô¹ˆ-ðhH (pZ$:u¹²'S¨VMéºYßP^*•EÈï4ƒ½…ÿó(•qˆ£åû6½SŽ0‹#ßaŒ¨[¯»P1}ž¼F/tÝPÿCXÛDÝ¡£|@¡ýcŸx!58L2µ’ûš¬ÿøL­×ßF¸®{çÝ8ÂÞ=k8³Ú‰…àKs7qË•ƒÌdà¨Ï_V]"LYCS–¶%çaD„Ò»—€[®«ä1K¢îÓÐp#ÙZÚ¯¯Fn~²ï¦taæ¼R²FaCö<>ϲɯjkhÖç¦5öØ;vG“¦_ˆ'xx¡†LzEMüN[7½ çÄ §oÚ>[Qº–U–+Û:Õýö>‡«hØ$ˆ\ìÚg]ÝÒµïŠ~£Ag»hþå¦0¿³ãG¥¢DuM£îš$º±M(Ž%Ï·ö~Z-{›Pç­ùS7ºP¯‡)DÜm-Y²~â 4ŽöJ?©½Ž,‡ QZ53FÍ8¥™)TWˆï$˜Ê?»Ë©Éc›‡CÙvr-skº­~=™êE<å{ÁfèýDåÁ ߈|cZkRÍ <8møfÇöÛëQ=‰`‘ç\’Þ¿ç¼YÌ %Û'Sì~R• 7†Þ¡ºìO°Ý£ð#R®Z¤¶'ôû¹’·•rI£·ÈL­r~X¯=HˆÒíL,hÜ—#4Y€ë¯¹i0OçM{Û’éþö(m¿q©IüH$W—7ëA®s$¯î„ÃÅ—¾ãs.Ë<0ERF[º‡¡é½«à|ê•AM/%• ~c7¦É3Žö à`‹Þ· UúŽ”N5'×ñUÈ®ÒuvöÑH]7¸éFUVÎÃËŸZ%¸QHà“¼ìi53Œµ•µå¯6Îx,HžF><ŸðH`=í€á3ž…O;5·‡öb±ƒ]ÕF?öÊ6 ÕÒ“ÞæÉ#Ê}ô¾¨Šìƒ/e†”´‚_kòŸLá ¢ýd‹±õš*ö V’¿Ud-TtQOšqZ)N‡Ë½˜m4ÊÆRü€g¢ò½YŠKtò¹® b—þäŒÌ·b2Ê´Ò•­#ª½fà#i@k¿V÷¿¬i‰ô˜ÝôÖ©©6XÓ'`›í@ Ÿ‰KÏ÷:%|é±»%¸¤öâ˜%§0aè®>î@œGçÆ¾3Іm~Êáz{ßÑï·ZŠ9Ë‹7kÕ«Ñ6ËV?”%PûqéFØ(‹¶K&Ôb“v>¨åx~ù£OÃæ?^FÄ$©Ñ_MfªÌÍžû%g¥Â–ºò:N "¦¬¹àÆ t£¥Ñ8…+mE‰<¦ ÑÅÿZßÒüTæ7–ÚâÙþÂߩܪa¿»{!ßs¿g AãêM·EUNfc1èDçn†Ìø³ÞŠ·è¶hÜ@-—ŸHo¨Ž Nú&QH$­›?#•piO÷¬¦‰^ÒÀ޼_<àH¨ŽVoñdDµë‰v «ø–}P¶6Ú~N8àè"ž|ËA.ùÃFâÑF•Wß•8î(3Â<·@II›àþp{è†ë¿%HÂäý‹x‡qÉ×}Í»U[9 Ê0ñØNWʪ.æü°3}9ÜfÕðG ˽ÀRÅ¡îÂGœ>¬xK³éo]Lû­—-‡ä…•´]r½ÿIwý¡1³Ëw±Œ‰èßé0H\ÍÏßÒ—7ôÍÝxû)í;}“<¾0àá{ ʱ¸–ûÜT§}OÝ(]wÔqJNhLUêµà”:fèl LFBQD. [”[Àêw}òòÙ;¾xöŽçsõUoǵ)a$¼èÌ{á”̼¬$ÏÒwðF„Ä:“žWéFß/´µÈOíšûïâo-Q—îú­¦âÌýPKò lH8BGEGG-INFO/requires.txtãŠNN-*)ŽåQ™i™¶¶†zz†\\ÑÅÅ9VÅ•Åñ9‰%iùE¹¶¶êå™yÆFê±\@¬«$¿(ÕÖÖ@ψ PKò lH“îÈ_ÐÁEGG-INFO/SOURCES.txt•WK“Û(¾ûWä¸{\™ÙJjSgvjk&©Ì&W £–Ld[ùõÛèac 4“‹-úûh éŸþ¹{~ؼäîäV÷›ßï7Ýàéîùñóæå¿œËÕ·ÍÝýS/Þ*å¬3Tçº]1%KÖùo ¶%\ZG…èÆ¿ˆ×tDm€ÀÇpû> X*‹­š.`™áÚ½ûóÃ,5çbî ÃØnªÌŠÄÉ™*zß™^\LK =¢‰ÔÑÆ×È¡ª2.KµþúïCöøüùK|ùòýÛ§¡þÆðÞ¹@²–.÷6IĤjZ¢—.M2ð³áÒ§4¾ö%¿¸Î,-§aQãu¦"u„©àtjÙÛúx!¸Ê"nt½ˆãøúœâø¶ƒa×mz‚:íb”ª"Þ† xyò€’·)AgÙ¾Âè£)ucsöG¼ô­Ù©1¢ -]\\QX÷!Zz•ÞƒäÐ3èª)pìI#P£¶HÄ7(ƼîÍ@lºO|&È7Jv-c /ùé\Êg`2±öpWÙ‘»]¶UÓ8`³kÊk*ÂBJ"@J<B‚_%â e!TBVÜÑF‰ù— å*nÖŽ†*ƒÝç,ÏZ™yÔ„_4ý%á[bÁÎÆbå3`ÅË_Hˆ8G\<@_óòŽ4–¯#¾æôÐÆE˜'wž{3°;ãÐÄõå‰hÕá®íš#©è_¿5Õr¬ð€+…¯’áõÔié§b7TŒøPKò lHìîc¥11EGG-INFO/top_level.txtÁA À0À»ŸS–"±5¸æßgF?«‰ ãQÿÙ!k¾Z`îz@!z¯Î ÊPKç“nF¬…¢EGG-INFO/zip-safeãåPKƒ,ÒF¹a~p® pkg_resources/__init__.pyå½{Ç‘(ú??Å\_ $pôr6Y%°W‘h‡ëq$ÙNÅ !9!8ϤàÄç³ßzuwuOH9ÎÞýý.vc˜žêîêêêz÷`0Ø{“Ï/óó"iжÞ4ó"yöæhï òÙÛ{æ•m’'Ëú¼œçËä¬\ɼ®ÖyY‹ä¦\_”<_1èqR7®õ^»9]”M1_×Í6Y_MQŸeIòþ¢0/xcIŠ+hܺ«üªh÷Öur‘_¡làÍõü§vmÿækH2›=˜ÍÆÉ½ª^ßKn.àÁuÑà[0 ½)ïÀ8ËÆò¢N y²i‹¤n3jQ¯ hPÖU›@ÏWyU®6Kf‡µGÃJN‹²:‡‘´-  ¬ -vóÈööz§Ø\myŽØƒ7nêæ’_ÕÍ• ¸Ý¶ëâʼߎ÷²âüœŸŒ“¼Z$› Ÿ÷¦r´Næ9,Ʋ¸´2Ëòª$ å[êh/û©\ñ;‹:ŸoÚu}•¼9|“bò¨û&ÐÆ,žù>¯—K b¤פl×ËòÔ|/®òr ÄÖ´…+îMg]|\ß4ùŠñ*Ã3HÅUà?ÀÞºÙ>ÝKà#OñÑ^ñq^¬ÖÉýtØ4uÃmö“7[Xµ*y’=†±^É—§å²\o5ø'É[†´÷æ¯O’ .Xû©…‰MËê¬N¾LÒ'ã<} OqA;XÞ3ü—û¢¡oš%LgkÀÃoô}Œ!5ÃßòêcÿÕ»¾&=¶ë–|Jt‚c^7ã½bÙ½O“â:_¦ÃMUÎëE18À)üï [¤Ëüêt‘'åÓ¤ÌèÇt4J¸Ãá&AƒFíííÃf\áVÀ a³Ÿn‘Y$-l»Óú#Œ„×¶níüˆêírO¯.™Ža7 ûT˲º¤†?¼=z8}÷Ý›7¯ß¾‡a¿o6Ũ€?à@ÍÖ'«¦>ÍO—[ ?ùæÙaî×À[нpÔ°!*$–ºâŸæ13SCO-½…°FÜ<»®K`€Íö s±!­êuQ­K`„8¤%®1¨E±Ì·ÈfÅüør{Õf¸ü]Òœ m&OFÄâð1¼Ð6qö Q˜L&É`¾¢Ý0xP?üƒT{•Ïá€+àøÊ[÷óÔþ¬ˆ+òPöª®Šî•­ß·DH&‘—.ϧæ,i³éuQ-ê&ãSˆÉ`àS^iá¼-ÏJxQú•0ð[^ÝA^gùry íp=«¶|ß”ð_àŒ‹DÆù{8©–õM›øÇ;µ@Jj8»î^4bæ£r×üc3Eú[óe{³­Η@ýK9înÊåŽvhqF"žü i6îºl϶,QÀÀ²½¦øq2ŽYjM†óá¸óûuYÜDŸà¯p å˃ðQ3¾±(®ñ÷ÿT¿ÿœÎöìWÂI2S#|‘Zž¶Á"ƒvD ;*¤=‰ƒæø¡æƒƒ¿ŽéÇQ§)Ð{ô†éøÏ0vÁòÁÁ[€„/?}t‚#>|ôøÉ¿ù÷ßþî?z íCûÍ®Ú\è?g}ª)[‘BÂ϶,– ê$û t½eú»îtºÔî¿=¼7¼ö¼6ûIQµ¬l€ “/WùƒÓb?˜ƒ\.ÐzâÎi£-"„½lz2ô׸^.üeî¬[c&ÉñIïºÇ %¶ð(B²ðhŠ¢L S4äé7ÅU}] ¡›Iæ B€ì´,rÔ¾òóè‹Ò H fîñðssÆ/ž+ªô×ñP ’Û=Ù]ýï[Le«z•vWޛȺÉA)!î§¢U‹tªô àjM Úk}f‰Ž`F¡íñCùìò®áò³|*ß"ínMRÛ‘#«ýå^"²¼Ý‚ŒKV™RmcÂÉðÔƒ?øk½a³ òa2ÖÆÜzËf¹F°ÿ_©ñH2KÞãØÚYœçó-À/aŒ€GÀ<< À•0“¶lQge¹{¯Š+³˜ ºBS/6s² šó*„÷»ìa–UÉUÝ¢-¯E{ô`€>•3Bq,›ª*`mÞl³äkeÌñ"D„À€­1æÉi™˜sºMØX»xGÔm ºóŠÎRZ8cÂÒ*B¥ñ¯æ}Göâ<„uº9wèRèõ´Î›ò”A?«Šb‘ üÊןüg0Ÿù岸.–“G?Í™"ìmÝð©pǾ­Õ‘=úőޢšÉó‘Vú;p¿%Z¼ úN¦“DúöÀú#@žï#äZX‹~dƒw1pÍŒ@ Ý®ªë|Y.¤ù€þÔìÞÞ¸00 F?óh§¢ÎóÓž¢‰oœÜ»wy#C?e›‡)<¡ ¢y´(çë 9.H|-4'q4’þPxä÷@™5¶EÖN·Áh’ä›59á’›Îq< Ñž5¿(æh ó]xžü˪¾Á!,kàê eÙ{ œ€ézk6&¡„·úÌÚ éáG mÌË5aƒmv9žÕp”Eºc7W›vÍþ4odóMÓà‰¯^C¼¾~'kr$â Ý‹rM-æðNK;/¯¶¬ßÚe-z°-Kèlö\ÀéíÉII{a–‰e+‘Ïçu³€ÆpŒ{6E„…¼(ätS.5Òó+xx•ÏkÃÇßQ—ÙU¾ž_¤Ø–›Ä|…Ë…:¸µ°Û±¢Y}‘77¥±ªwŽ5œ!uùñàóþ˜|ž¤ ¸e«K8ëøBéèøéã“Ñ8¹ÊΛz³JŸŒœ¸)'Í÷ùrS(K´ùìÓXÍŠKÛj^ƒ‚ý=bšNQ¡ÙcÌ[´­#p ‚Í)D• .Ç Šf›¬`ðk|0G”7ÆPHtý!Ðíå›Õ¿ÑŽmêërQ4ðÐPE¢SvJ=L©ó2ÿt•¯üÐb^%K…zµ5ÌŒ¦L_4:õS‘_y?¡4‡ž“ÎëèßáÑk\|„[ï'òÁË‚ÕÃêºlꊼ2KÒË›šÕÒ¡9ÐÉÓ{™§lëø5_,¦9ìƒkréЊ ‘È @[xˆ¤± ³†½Òä´¦è£ÂŸñ©6+§(´ÅYúÄtúWá†ÿ¦)¯@øN|׋ü“ÕPM»ùgðŽ'ðV:{™Wèø0]¾ð›é‡¸Žo˜,&iË™@ ä% ý€¯É®~^WgÀ ’îèU½þºÞT 3ˆï*dyÕ!¢Šzµ8ˆ¦ëŒ—^ó| U = Ó7Œ‹÷z=á ( ÊXôlܤiÝ<”2?cò°_ìC·rö$Å%¶G¨ý™ “TÔSL h“› É00ê 0ÈX×j+Àöbö`sI›xˆNå æ'ƒÞL›í7S/ƒ`øø.*„N ½p ÔÂÅ¢ n€›•¹µ!¿o¾™¾8z÷ýñèÕ³·µ_ß½þîíóCûõùŸŸÿùõwïí/¿?üöõùnz¼V5HÈv[N% H”JSœã8é§˺¾Ü¬0F†vô²XçIòÆ1¿á‘Ùúǯg¦±Y7€÷LôüÜûzµZo5ŒP|–¡¼Ú,—º@Ñ__ð¾×?ýïrõ&ÂÓ‹ §(?Yö5½Œ,ƒ§fCáŽi}.ä^3bŒáí&èCÑBëöèt½É›E [ÕÕÒBpò\å%íŸg×y¹Ìa7¼ðYäÞ‰ÑA&’Z&ã¤Ög§-±…ä””}oÚƒ€·t\òûIZ#‰°¾"iÄ|nÔ ø„oÈtŠF|@Étz_¢W2±GV_¸[Œ=p¯>Ã()8Ý·4n!‚Ñ:2£¢]»F"è½³âˆÔµ[uá^s°½ ‹{ÃJ°—W~ZücŠ¡AKÖ.§Éã±ö3Ja® žðC€KÏŒä.`þ¨U4çƒk€PváQ|üð¤ïu€ë۔DŽu nfš!wÎ×é½{¹‡Q7âwŠÒðcñݘ©NOµÇ,7~ŽÎt#`«b c3†\Kô˜õ 4 Z8ϹßM¾ H.‹v+Î ÕuÜ“Ùßqd˜ÜOR`< q×;¦ôž¿KúßÃýî/q3Ì‘! Á´’†,c°K×äëcÞ¨F"b»ßwªeïfÙ±Bü»g÷“!(¤n7Ìý<ÜAʦѭ$ýøÄâ3&@õ³žgŠh¹´cV§Îðýè\Ó”Ýþî€X[™&‘é(žÐÁOÓ¢Àÿó`ôÏìö¼‚{¹3ÇØcj ´OÃæO)º×†Hmù $š ñàéȨmôë³²)Ne÷!(]¹M¬%ó~bóNœE]´Õpmì÷É€$Ùä¬Àè,Å€q^^Å\#Zii BH¤eaL®oþ:}ùì¿^¿õƒBŸ>9Ù3'g˜ G>UQc:í5±äÍü"•Øgßó÷áŒóxó#ŠV«9ž°ôËV3gÚ ó„bŒ ”qbÀ9ÞÚ®o󠈑‰<¾òëÌÎ=!ªelüå/Iž³¹ehÂï[ŒAk6ÛétÁ$TÆJv; ïºå8ã  y>b¾-«ÍG: ŒYÚçβ³ß"ÿúrò${lŸRd0T[Ës bS°Y_¸¶áÏ) g Ûº‚âÇü4UŠÒ‚‡^H˜ÿõ6ê¸ =û.¯‘P 4‚½ÁóØÎ'™ !$ƒq2˜¢Q*ã…XdŸ/>oèˆÂ4;h}4Nôà‡ÎŒî„OðS PЫ‚²:û·ÐKª* cSæÅDñêÈQX닦ޜ_$’–&6ìÀRç³Ö¨3¤ë ¢ î0¸qô!£ÒìÞPÍÞù67ñÞ€ìÓž Œ[{š£n-ñ¼ÆÌ¾©„ g9p|äyŽ6 Eae#­-fÎk“œ ÷ø«=1é°„¶n6®mQú~¿y žÙÈ2¤3;Fòqä|™9ÆôŠ˜‰oÞ#jÈV$D§*?n½˜” %Z™9á Èç#ï7Ón21O5c*òvKA@¡FHb¡´Þ[b»èéÉ`âÓŽG»>fàüŠðf^1u’ºñm±³~ê“=ܨæX0D® ljÉr-Q‰ûô0û÷,y{9x/?£ü:Õȱˆ>ƒ¡X&òŒw£$™æÎ†¢ñõ‚ùÈ$‰ìÏÎôËB8ü~WY8N¼Ò5§í£QWÜ¡ñº÷Ÿ·™ð_^iûê8ñ~xÃ[(Ùñ·´¼¾„=Ìž ¶?ôJPÊïz¡|1ˆË`zø …éº%©â²L0 6䥈N’uç äœT¸uRÉUþ·Ú…1Èxé8DeΣj¡h‹VŒ·0Çÿâ“î‹Oâ±ýá‹8e¹ ð?‡ö v‰œÈ›!-’/é÷Dî2¢ËB^2Sç4ô™ Â8¯ÌÕÚëvÄ6 ëõOQÔš"Œq¿wÃ@ßÖèÏñ-|3ûÒŒkŠIf ÂLÀ6_µ¢WbôÓÚfaq³³©„ƒqJ„„¦ÇCãdžÈÛ^è•ß_?µa×M Õ½LÍW q p(96î«Ú3*”,'ük”P]«ƒÎñÐdžÀÑæJŸ#¾7; ±—7¬HjÁª¨öÜ›šGÖ -n½`žyŃƒÇQ–6óiSH^‘ðÆË®»Á!UV(ŒÏÝÉÊ®g!eü×!ŒC‘‘Ж'>%ˢ̘:uxL}–Ìè¶SyÏH¡¡+=Å,Œ $NYgTz<Ž€l°Œõ„ì&]E²ðF /ñPyØVb;ÛÀ¡Í ¡ÉÝFë…v‰Äb A™¶CÃȽôŠcÍÆö¥iÕö(%ÅÕ«HtE¬Å{{æd©™ÀŸqììi¸'$Ô9P|¨wøiE£*ƲÐ`ˆ4#ü׎³ù?i´b’þfgÄJKž¤_yÄȈ ÄtÇCŽaÁæmŸûž»ºð˜†c–¿„i„ѧ»º5Üï,õiÜC6±‹áteÌ–UÅÈ!ˆÑ©¾ ߢو̤¸—R’GÛòª\æ þ§S ,²)Êx—E«åéù9ìàPâû¢Ð :%ÌD½ÉëI*ÆÀ‰ÇH‡¬×Ù4õr:í“í3c\²‹}xJO"æâòˆZ3]‰ÑÉרÜ8ÌXý$.–»`¥¡ÿ6G,D0Lé¿&À“ X9t³ñ*G‡q:_¶>’íßo,"Æ7Ö˜GÝà$æKm¶îº¥„*@®€ÖÔĶÓihJŽšóñ³OEÖH“‚ƒãt?  %‚hÓtDNLO¾iµÚnŒ ïE ý³ºiM EªçÒµ‹û=QÕ˜É*!²¼0áz¨ß›ÙìZù.Lè O¬ØÆÉáø.ìãÎîË5¦ÈjâEµ—ZKÐqrÙOˆ°9­´Þ¬¿5‘‹š¨·N· ¹WLý<(Ê-ñZj<>Ñád?âÏÝìÔ"ÀSW±1-n[/¯ñ`ùp¥"ÞSe¢£ØP$¼’uɶC#°OEáÕ¦®Å‚Hõªl)€Üðãõò§ïqóÔïHΖÕi¤Š,Ê:Ü "ÌCˆò™êÕ61ÕŽ:2??=a\I_}´‰¤èºtL?ˆj|†XažŽ©{Øõlf`£3Ýþ¬Ml»§O©jÌfÝ4 žê˜ bpøQ®qË `Ø8pšHóºBXÕܱxì±³›°×-1 ˜$èÐ?=Ä>, |y“Ãá®hîÖŸ\QJhXáÐLÙ+èÝÆÎâ'5ùܧÅ4¥ˆa5¤€M„¢EQÞAn#ý(§¼ÊYè*ÀSЏÚÉ|±…¬™a´5ï¡FÇyfVC²¼=¡_e‰‹èl—òŒ­¤§È©iÌ®–¾gŽ $[ÉÇ\ùyíRÃ%ýÉZqIàQ®IÿÜ6«D$©uƒÂôó´vTÌi¶,é„‚'ylxŠÐ°€:R*œ¹¿ASJœ4 Dtö)ÄJ¢†ZÝ óxtDµÓ]±R*JF§Œ—n¯?\d¢Xù£ZÚ~zTõ*?>Ææ'q›—ΙhcN(ÁYÌ%~×ù¢vù¡ðs_µëõG1Ï'Å?õù¥ð£#¸M,A{»Ê ­¯È—Ýe>‘S)¨º:Xl8ºÜrÔý» ‡ª¯Ñ­9åK%åg(I 5 }mþ¦Pa$WéëV´-ŠÊWÖùÄ‘R6G\8&á  W ¤”.aîÓPò†²ò„¹še§©­Îå+ÆX²¢ØF:;ÆœDÃ6ñ;Â"®`P@•Ý&vlGuxeàP$r‚ŽFæš Íz‚òÎØ”2›°ÈÔçE’’à–E‚¦ZÏKUâœåeŸY[:ÙTV£ì`•F¡41 ©•eWîÖQÇk`/KQ_)èmM^ÕGezÈÏ4Á)úZ[_^NYp¿É) "ÞG™ÒL¬tH‡Ca3-¥¶‚•`lÕZ'I0½q„ÏÖŒ€HßTK´°ÏÌ’áÎ<†z¤!IÇræ-“ª óAÐßœRE£­‰‰²=àÇTœSúSoS“OÅtFñƒi-ù*‚k£8vlmÛ~KÛÖ{†Hl ±÷ݪhu[<Þý’×™÷²Mœã"ˆFË4à Ù ¢<¯P»(ayD,¨cæ­=E¦nw›NN¡x˜)®Òev4?Ѽ¬*rˆÇ]ûpvÑÞ´*n´ÉÄÅÑãñdÄA‚¸vœ‰’íþ`‡P>5y°°ÑbL‹,ê(úG †;óF…㋞€p¿uŒ‡™öjx¿;×LP¾‰UÍTÌr/jÙˆp=k4ÜXUH!G‰²N¡v"Áxy‚Ë¿¤<2 à¢Ýç&‘ÚÞ†Q9MŒw•Hœ!³Ñç3ÌÂ.ÊlìÍ¡Ã(Ê꺾4 †üÀZ#$oá<¯p§dšE£ ²ftSŸõà~3¬Ù¼ØÙLLJ ò]yV£‘)ÞýÏ@=R"f:fŽïafia²Ìnȵš¤Nv”(\‰hêæª¶HD)aäÎB¸oPöµÿ’×F!Ü#­¸å ç»ññ–¶D¸#8Y úÔZ”L÷A• ½TÈÕ¤‚‰‚kÊâˆçÝfÅ–¸Ó–[‡› YøSýÛèøéÓƒG'¨š¢Ñ›L¾¸ˆ3À=ö¤Ä}’­¾ô9äiAжj·®M–"ðû`Tðj…Ä_ŸùÔ[›¡ù»ÌO.׿W 6mq¶Y’ÀÙ’—îÈOÑtn3ú³a” >ÑWvd²Ù©$ŒDŸ\MSã)âco¾ÃT9š{û oéáô ÜúG±™àŠÆ%20c0‰«¾û ÙÕ\‰6<H´¿ ý$RhØw5ÞôŒ ñ©MÒáL=úø‘{¢OI¦ºîGÁq¥?qâ9R´`Ï£÷zK›Ï>Þ,à\B…ë‚ïâ 7 uxGÇ-à1Ÿm ÎP车ODŽcZAåµïk¯ˆþX ¥@è0Ãߦ6!a • Õ›Âw··ùåŽ [2t®³:£¯“…1Z‰€ÞVéë᫊=ky3¾Ëû, øÙO^׫–«> Wƒ¤­“³¼C¹ªÓÝëò£k~ô‘ëqÒyá6ãjæU ñÀöBÖ½i]õ^ï8­ÍÍ^þ‘‹h; Ž^Ø¡‰øåÚwN`µòÌù¹€_‚ì Ôæ³G+â÷)‰KJ×3쯻¸z‚Ö'äÂIŠÞ=•àPý¾=µhÍíDêø)Ó„ªˆÆF(”LQiG¸¾gºZnÎacŠúÃߦ°ƒÇ¦;½›dò“'Ì:Š@ü“þIîïXºg®c¥å~Ì1ùŽkT>}êcɃ1–‚Iè3²Ùí ;ë¤Y¢ô¿(›nŽñ( (<„èýeyÚFÙøA ¸¼8öÇ‚†‡pÌne6U`öð9é•Rç‹¡™øÈ7Žj|ÞM£-Hœ‘™’"‚eN¾í¶É€{uÑa­ö˜_Ѣσ4¨o;lÁ™¡qÍMþñS.½Qglø³=ŠÓÊ lç’K:§ø0 Ýͺ†s ogLˆ•-Tî|,zŽI¶VÖëj,&iR„ÖÛ•€»*r.].úf«ÂêÔ™îyÊFÛ¢¾Z,¬oÆMT |… Ã(AfÁûÀÚáÐuJ1 §[[ˆ;7ög‡3«'¯Î’³eŽêÂ,ø-–­%ñ榕tZ鋼¬$`±˜¸«'+EA„ŒØKgÛµW|—Öß*ìj‘é=–u°e?’ÇTkýi’Î<œÍÐV‹ÛˆÂög#\-í#ZKÉ{á¾é;5P͹š&y›‚60RêH¸vÑG¦ÚmÏ®ãKiŒ•kºíSë.dêqã»HkdP+-in*3¦Äneo5‰ÂÎà`˜‡WÞ!Žúæ¡SAßCX¾k7Dü.›,W¾ÅĈd¡å$â07&©¸ @–Àº•D×w+ãXð>í*k·¯t9Èi±&-q¡îÙ `g­Ôò¦Ï÷ëyZ¾T.džÑ&Õgv¾»®ƒmïOÔ©î†ÖÑ|®íû¾~˱ɋ|QßÈ]m~ÉAOK@ñõ¦q«•`ÛÒzàQéžñIÉ7 w(±‰ |xKð´ë3žk7c ä$x?,M³e›Á­ü–ŽNºÍ;ñ›mLŽÆu“Sádbö4£ ‰õ êV!¿¾Ž÷Š×î7à½×‰¯°`-mÒUáB+_mj™˜Ð—Ë¢X%çõ.]mM—¤÷vÙK­v±#iÖøñOéèÅ DßÒn(™eŒ@x)/ÛÄO4gé“Tc# /˜}È—h®=òª?ó©àœPF'šÓî©-EúÇ=O“ósŠÔuMþ@]\Žï¡°IÑzwñp– ¹EÓUݶå)”ÅS¬gEÅñzî±D”mMZJàì¨nMŒfÈWz‡Øâ`J–Ô”§ Ó^ñÂë¯ ëvº{ºYž‘¼ Ó=¢ ^ôtW!2óF›éçË ¹lM)…£’ðb\îÇR¶ß­A2ò‰‰5an¢vĆ­3°¡—]ª Ê’ ó53™8ÈÃ!ŸE2›;±)¥ãÝJk{…²ˆ¤€ˆFwÚJÞÆ9k]â±8~w{MÊ9Š£nЖi:C•›4ŒŠPï:ðÞ>ôÕ"ñ:Žiw9MÖÓ“qÇ?Î÷£Œ=£·üÖdG  ìS¿Â¤?< þéåôtª“lÈö?N¸Ïq¢“v䥽Ø,ÈHjæÓma³…ÔìüV6mÈ›m‘ ¿FOÚäei2LÌzW`I&ÒÚ*_q1Õ”›G-ɸ+‹›QYv1(™ò“¾«^üÅãk§'¦”¦¿9ß™1öyšÃ¡:¦ð¬ñoݤ35虋Âwq<ŽÑùï(KFàšW:=Ũ±"n’ð[³¢®õ|ƒ²™D,פåKs¢ÉÎr°x%Ïðé³»ë¾Ù3S]²ƒÊ«p[h•);a‹âLh‘eÎÌ&`Û¢%ÿ¦’5¥ö[Zdç nø${2œÍFÎÿ¹c,~µrüà¥yWh‘s—á ö£pžÂÿcw <E7õP ë7àN&²'ý‡¨C§j(Ö O¦~ø_'ÕÕóxJDWÍælåZ*;©½÷•oúôS“$zÔÎw;z¨RGò¸d¹[ÜïšÊH‹¥ÊEpýKh·EÚ›ãNcU9bI]mÍ=æ‘Ç»Í&nÔ%‰G ¼1ù:ö Á‹–ÂË6{Wð-ßÅ) g­¥ e½„èÉ2é$„°b‡Ip ÇçÃ3)ú Êî¢Þ~4ü; 0µc¥G?",§–iÅn‚þ@—hRÆþær¾ ÇåŸE©m÷nªq«•nЗšì¨mÛ Ûww.¾‰Iˆiñ ­=Ÿ\¼£ÖõÚ8Úµï„óâÚgœòj}‡a\X ãÉð^8Jçñ[«{‘)¤yC ™³2çìÖóÒ¶1»tèóÕ¨¢êÔºU˜î&åò'%E«c0Ì2‰ªo®(¹œ·Ûmî™ÄÉyvv*Èï2æt¡ L“’…•èL5úê)Fð1÷Ó2 Ï ŒzvÁ´XÂÜñ>·¿vša讥~5ˆ H‘ZøsØkBÆèh‚×äëºÉ°3 sô‡0…‹ùÕjHåq.®­ð®b7lPìXûUCgpÄãëÂËäYi8 Fx0žô úLŸçâDkÅéF)‰`Q6ŸTCà 8Ê™Ì-»Þgˉu™I„E©&G¹(öd]=ˆ^4Þ×o¬±nT'jxSÉFtäñá+Qƒâõ ¢Ô¹ Ü_Ê• ­Uš­“n¸¾Í¦ ã‰ÑÃ%y“t`Ù!F9b€ŽOÎ î‰s’øZßImÁ!%Á_“2&8Ž”mêΜîÈ$ A½S d§2¾—ÉŒ–`ðb>C»Œ œê$ ™VÑ¢h1Â×É¢¾!GÞAD”Ç渀<ï„ÅïÞü¯9œ·/3XÛ^g¢¢]—¹±2Öùj!FT´z<1(H‘>YÓu[aì™AÆ^Öë^²gÔÆ·sÖFIª\nr_|z613â÷÷*þ¾2媅 ¡À2ßoM†à‹º¾ß/^׊åTß—ˆ<ËűΞc*P›%äŠØCÆÒºä×Á§§:LË$>©ùäÍù†dÛn‚„ܶâèû„´AÒ¦*Anü³Âf{Â>Â4V cÏhò½Œ:ûvgwgâ‡sÜà™7¬CaDIZˆÐ€| ©9 sÉíY¸0TŽ#ª+ùu1 |o1KüX©—Gâøû2 ImŒQW趇XÅ‹'í†EMŒ“5‚=ox¾ Óõ»u s>Ïé¤ùïó‰Uã ‹ ó„FQñS/×-«EC*ï8 “R$"¾^hq‘+³§XA٬釬rY–kCªãÖ±ƒûlΞìíÅ‹À›ª±ñ» ý¸g'öo2MßnªuyU„—uÉ¥…6Ò#1·Æÿ1uÄx ÐPsV#G£§kCÁi*n/“ÁªsiÚñÝK‰7Ï dë–ÉCɇ Ò B9¶S/†áÐÁáâ²8eB@»kqDÝ”çe•/§„L$fFÒŽ(êÊA"ÇÌß uO_.© ÖY¼ó÷Ø ØÊ%ÅÑ mWùÂ’ó¥ënc(³½Ú¢ŽTQÇ­xµåävѨ¹÷iÝL=â.%õ‚Šw÷«ˆõÌ+ïp”í(è×[”ïO¡§d_å‚®xß/P0ÖàÐUC³ObµU.ñ\o/}éæ—Î9^ ³sì?R;óŸŸþÿ"ÈèÿY `=Î݆µ‚ÙâHÿ©Ùš•¿xº”ÅVìvýÏnp3äOÛâŠÏÓi‘¬¿)ùrC>¶A˜Æ0{#ï)_µúGºN[Wm?õrü~.]ø‹ë^ŽUÞ†;Wmf{pA‡Kãƒ0J”L)„/ž®ÍÍI&o¸{(e:œ°€Æ+{1çˆÙWßÍE¾jÑ9Ø ‡«Þ`(Ž©8I)¹TöPU/&©E—}Eßä<¯öæyu.)¼ÁN©ãµ±š¼ùëû?½~5ÅK'Ÿ?{þ§CÏïq7%±0¬”LeXÂ唬\ àlðOâ6“ÀX­óHÑ£ZÃÌHbAv >òˆ$"‰a_ºÂk«¸k·»HU€§~åaNv=z€ôu ëI:ŠóõSŠºÄXm.¹€"9ã˜Lü”*¶Ôz6L̵– lxÿ™2q‘§nëZHîWþ@¢pj…2e“4^sÎÓ´6ò«9+õí„Öj¾¬¹L$oʶ ´{Jd}-àÚÿT®èg*HÃÅ=aºA  %iIƸ f¬oSò’=”°éd„Ä /AK¼4~Àã9?¶Zâ5ËÔ“ }QR‹­¹_¶ÝŦ6ÈNûÏ$[D¹N§lØ$à”;Fö Š˜+ñ¨ðÉëc)Y‡_.Yjo0¿©žÖ±},õ<«1ÃyU4TwWie/c² 0+;|€ßÈr ¸`jqµÒ¹rœô£Cq€ŽçS“!„Äjtu‡7—ílã%e«¬ýé /¤ËÔ˜¡~×x£vÿ¦‘­³wÓ£^¿ÿSB8÷þæíIWí9]Éþ9U—Õó ú€h6*½Y"ÊD a²‹\Ï> pœÈïdM!ú‹*‹YòÖ†.VΙV„Ô" ,õaU †‰îÜpóš[m"vI[‰‘¶FÊQ>ÏÃ,\›á) pŒ‘Íü³’ôápXKʰ8HB,ܘyûÌdO‰‚ÚFBý<)723C×lÙr¦ÝxQЕË-×möE]¿/Ã_‡nÈMëÛõ…XÌ—|z  E­öÿÛî-Íæ%áýׯ¾ý«\ (Ù˜ä¤*i3%šISß…»à`ý-Ç’½zýž{@žYÙ6ÊcòôŒ”&î]gÑ‘›±¦„¡ DLñI÷4< ÁˆÕ¬­WÙÕJl®ê ’uSLØŠ–@^uS¢¸¿‚ííIª x(PLùq2Æ—xQüúÂ3Mâµ0ž‡?Â~ÒÔ0 ƒË„FÉ?’‡õo~ó›ð™‡õoáãA€çÐ0u”O¯©à±îƵ6€ðì}'{ItfÁœˆÜ.¶Å¬;÷Ö5‰µœZ VøˆÂ?v‰…;Ú4îFñÄáNtÃeDÜÑñ:ö#~p4aðª—>B!eán†núô”ð5½àmI¨Ù,äX³Y”g™â×z£Šux‰Éà6<²ÙÏsǰ¥z¾±WëÚóÛÂ3çø¨»ïå¶W…ôŒêcÓæ?!Êxš›•Ž˜ ø8î3È*³9Ôå0æŽ!Bž‰& !ãåö½Ù¯NËã[­)ži€øQÀl&r¼= ZŠZRÂÕ¢Xr’/\µ‰Š,•“­ }¾É› Ʋã1=ÙÌ[9k9è’+û=*rN_Õëâ)OGÔDe|…S®0Éȵþ»ëÅ€¥âÕÖ¢s€‚´ì(¬»å{¹æ:ª¡g†=â]„—òc.Gwét·r„XždêÁ´Ç²NNM—yøB¨tt3N¥ àéΙ’ãERíß/˜–ü•µLYK1[v÷Œ…©ð¡¸ÔQ&ê òÞÚZ…—êH˜*X«@ºBf*솉³MÅô-`T)„Å9V=ò›‹ S»º{˜¸ÿÆDE¨Üm^·ÿì¬@ÿ\n°(#í÷e¢eaj´tC6tÜ®_;‚Gòû€”kZ@ÞE)WÃuís]´þ%F®X|qzM++gŒ™€ vMŽÄeò6»Ã§ïz•¿üå/ê^Qÿt±ÞÈ@iu\xZ+[ÌlÔ=»î:8íNÚÃj­êÖJ+m `ÀFÚƒÃóóv Š­¶ˆ ž­¸ 5"öE¾ÎÊÞI•~)¡ÄXå¨,|òH¼ýA]ø—‡{9¬µjN[ÊwKâ÷Ÿ‹mp]];OßœöÙ5ÙX7¤Ô‰Á^E}1úc âpµ |<ååZö,ÿŒšå«Õ”.±/D×ж¸¨¯ø*,E>Ê™<ÚègzÉÏÜѦÃgoÞ¼xöþÙp<’r^cýô»w‡oß¼}ýõÑ·‡ÔÂŒÊoõ§×/_¼=úÚÐßož½ÿÓpgkj±`lDûÉüæÁüîÁËCÝú‡£W/ŽÞÆÀI  HB ž(’jMì=Õ»Uj¼‡öGÌÔ-ª+¥¼KMf±xb׳ðÉÏcM¢T–ˆ&Ès>yªòƒSýôÑð{þ "÷_ª=?ä÷üñ1¯ƒYüƒ~ð¸h[ˆ¼×ë;ñX“ã—r;-™ûÈMíßEûœ#ñɶ֜–k’%½ÏS«Ç 9"oÁÀÜ”fÃyþXAŸŠ”T M7åüAæ®+eAYlu STNN±áÁÐgU‚ѦÈßéðøÿ<;øßùÁOþ#;¹?ã î>[;?/ÿºYÒ¿wŸª æ‡ýÕÒ«L*Ÿkͧþ”JüŽà%›~+åI÷=÷Šé§çÕttüôɉ íb½Fº3­¯r /tkù©;¸ ZSBdZ~ðóŽû ËvZòÖ‡qàÚñņX³GÍúcáflÃÁ/oß$_<þwOŠeh¿7d£ëiiU:·I¥î|Þñ²áÅÓ[a¦@£W†Oâyï¶€”¶ªP<€¡Y¦;µ#N‹›ãXFlÔó±ïªÈoÈz{£”«"yRIa7Õ88ü0L pQÓ;H$_Uj×™º9Ö]nî O€Gžj‡+½ÊÑË‹§‘:®–)ûcrÃêQ»°6‰Çð3ÜT ФǾþZÂX°€ ðh ý¡!ž–6ô ) 9á¢hÙ‚_aX‚Žýb±óåŸ5ådI?)Ÿ!Ϊ:ö„]A8+Ê”ŸÆæY‡š0¾£“N§kÐ+xoVõ¢Xú™‚ûÉËïÞ½'«=¨Íú`^6ó êÜŠh¨L–ž3Ýuˆ†‹Kº>þ3·/QçóôüàÞ@³‚A§fÇe 2SŠ+%ô Õ(}4N¶9h ]û“¤ð×õ/]l0nßæöÆ<²]7õþÿMus,AÓ«^,aF˜ö£“㇮{,„®u}YTÙ·ož½í(>öÍÇø¦kü¶Ó˜æCʉbzéàP.¥•Í[´ƒ¨6ÔƒæÇ ͼ ß‚7òWäëx™m!¾8-<·ZÌØ"mà~亜æ^ž¼ÕN¾L¾ˆù’Ï/rJVw0%4 %ÇÛǾcü–\²^pX6ÕX¯è„«•þµäIzëûêÙËÃ1èIâÒ`ó'Ñ;¹¨#ŒS¨×Ãn7”!';MúKÙÉ‹l´t/v% žë’Xö´^¥ðCGŠèš©ðëRqC/%÷“Ab¶ä¯½`†þq€JöIÕ–îôäd´‹rͼ‘janŽõª{:·Û«Óz™!Ã}JÝá_ãXs|q3ó-Þ“4ƒ¿¢MÜVà†ª„€þ ¥9>ù8N¶O“&ý|454›L ™e·ÅÁãϼÇañáà©{¼ 0üÒ{|>þƒ|ÿÒ{|^ÄDØjy‹™H)ãR83pA†AÌ,ú±à\ZœÈþÀ¿CzÄÖõêdu…RºU4DޤÙÚ¿E£,v*h.qʳ/î;QÓ¦/œÂ¡YPÌKÂ/,ï¿[,E w'E ñû(h²èfújú#Ø0¤r€Íýør8Slªä™Ú·T¥>ýO¥w,ÿ@ÞD8×°ÖÁ–¸N†9,­ÀÇ©Yý;¾iíµŒž¸Â¸ø]lF`YžN-‹ºMë¼l(”Ç‚ÿÿ”b³(ÑEµVP¢©ýÍ-{›¼,Ö9ù!e“gþä‹ßŒbgH¦@½™²]æâX7F[òä[€³‡ P©.ÄåòÈn€æÚ£©ê2õ38ÅסÄRŒñj®ž‚¥V¬å(cSX§ó±´77¬àÅGÞ>s[͵£Sa0º¶å¯r±‡ÇÌ3¸Èò漑'bðÄþ­§Êni9gä"ÛÔÓC¾FU—„5A§ÿc俞F!7NЀ_(ˆÂ2lR©ZRŸïzˆ²p—‰Èâ²OœeÅÜ“h'“ÇOmS_¡è_ÉP³/i¬ïÄ"úÄs':ÃR/ësôS£3ãß­ÆÆ0謬Â.~æ3±_?—XaF=RŠ˜¹ 9òzÅàÅɤO.Öñ¶¨g­\­[ìÄ{î¿«8Ô™†ûyƒ ìUñÞ³ÈõMâÝû·G¯¾ ‚ã{æ/¯SÌÌgJ.“ý©›ÕvT‹Pñ1`^¥qÜ´·IõÑi¶Ç¼û~þ”Ôx ¾ÆË$ÛÊÓb›ã§Np,ƒá‡ÁÀðáÕBÇ–áøŽîÔt0ݦÃ,/ë‡0=ßt x ýYǾ½×e‡—‚&ƹñj³\šP9ëšyϵh,«V1^(˜]™ó–‚Ĭ#‹Nò‡én \HuZœŸOCk#þ&—+Øßø½ÝYíc9$Âìvû.pYRŒì9œNùÙ]T~©z“† 3âŠN#àÐxJÀ†Ã‘ŠR'8˘9^®?9Õ+³v&w«‘…oötëeDßµÓ²Îþ¸íçè5wËÛíµc./ùÓ&–å;£Aõï ˆd÷õïýâþÌ>þvtcɳ|â›Fid¥/ô Н¡üa’¤Oƪ/³»G$àˆ ë{KT Qnß³PñÓF÷LXÿ#Ç êÀÎÜt°YŸünµê#íÎ¥¦ÒBª]æM5¤ hÅŠ;Ѭ{áS©ÖNF÷ùitëû>Øä{ò@d.¨:Ö%’#Œë«èŸÜ1¥úqžhxÚܱxü:=ï@Žúã­16³¡Ú©ìæÎ˜ŽÆv“КzggO· ¯pž/ÅgÂeŠ–xAñ›?s ÇŠ0F¾£JJã²QH¿ÏÁœÚƒuýÀ€1!ñ”õmÝáMAž`òó/5Èxþ ›$¯ŽÀcIØf…¯åÊ$ÌX•K¹L¾)s»²…Z6šÈ]ít)‘ºFHÕë¨W6·/ßÝ9×CÄg3Ïa<“ 7=|Ýg€Nô°#›ï¢’G°¾ÁCÙ4ss!c€I‰¤Àp JÓÒV4ɹÿòÄ Ù o`â–XÖî±ôJÔós]*»ggì'/ŠëbY¯Èq‰î)õPÅŸ©ÂÁZ˜}œé8©ƒÄ¦¦jûÚ(¶-½™ ã¤ûÖ céH^™*í×Ù÷G:ûvÁ9»úRaꓺ” ÔÇÄö6¶ƒ˜?F‹ßUÄV,B´Ø”=ÅæÁ5(n«-þ·XÏé^²[1e`v=û³Šíš~†òΚïÀFf-T·“ר• ¸Ž¢äiwaÌ£ùS‡ÐÚ™ëå–€0ùxØ5lsVùÊësbØqÑÍåýÔ1ç]>øSM›Ð™ê5·©¦µf™Çà]Üzv?ÁíÊ¢ˆáùóèDO,aS¿H‡»jÖTW ò«¬ßüýg©KlE ~f§1åà†ÈëÚ/êg‘f3ö7W~áb <¥²¤$§bl/èÌëØ^ƒƒ_P´eò¤2ö&3xpdˆ"I=ˆO„™‘Ü‘ •üÇâû|õèøc ÖCñÁmi‹ÜšQÚÛ»Ç|Þ´Él¦·ûl¦®+?«7t È&¢Ëu(³Ùêò\)Ã8©\UþùòµâcŽžÃÌi¢‹{ì!UšH+©§KÝxËC!@SÙ˜üÞ}Ðï_q²ÁŠªkA¯Ë<™Y33P‹5J©žš¯®3Þ<64pÓÀ€¬°UtšŠÐ»Æ‰íS1óJ5Ÿ‘š8žÅÀ¡Hšï}!Dýûu)‘&WW®˜÷ýÞ\ϸuáõmýè6Índ‡ëX÷›‹¥¶†ìã½À6" ÒÀ»3xiÝ;tiݮŷhXI˰Z‘Œ©ÿÁë7àx¹Š¾ªSRþR”.cÒ7Û8aTM¶Ï®£R-HÏY‰æfX*.ž5Ö5 *ª£Ó"gsJ;½tRl÷êeÌÏñícüÖ-i &î!’e 38Ý ˜$J”U—b£j`*=Ʀψ™lk÷°Ò0eãô(—aïzI˜ö·©œ1êtm’{4Pݹ­ëÎ[õ^EÙ?öàè\Óm#?r¥Šù¶ ͹, v2¸_ÛfܵÇ`ÛìíôõŸ}вÏŸl”dì=ºukEŒ„ݽæ‰Ã=æ@=¥}ïʤé DîJIûI‹•f­Ä‰ˆµn’nD:~HW«Ö¹CgðE÷T` Þ³UèÃVXÀKDãUšòÝ‚ÇHŽòZ^Yt™u&M‹ø™\(ñV•eq•êÊJ„$AÊÏ ´E-¿¤nRîÈY×y¥ ccZ°×c§ZTvaÓ2©T;%âNÝU‰&RÓhqre`ñ㦼ΗPÄ2Pa=“‚¢A…1‡êÚ&–Å´jí Ï|Å6²gº&‰NÞ"òmJ,Êšm• ï6Â!_pHxæ3&ǹ¬æË ¥?ëxs'ΧözÞ‘5'ÞÑ@¡”ön4„,W·Õó‰éðêéùYØòÆ­…&¤½ð¾E#ÔÔ5Æ€+¸L¸\mö’¾Gßc§)³ôèÅ‚ ¡rÊîõ`YMI/9?MN’ÇpZb`oŽÄº“èÊ'út0N:ðS³cTê’ihRrZ{KâýëQªÎùa󀉽òÏ+üð}Þcþ`”yûP‚‹ðŸ^ŠÂ‰™š¿D+.p É& Æñú \˜†·_l'Ñ7G§Å¿7p»¿_ÈA&æRÞÚCÕtÈ'Kç SÙáW+PºùAo˜õ Ÿ™C“·0qê‘C<ȳç­Ó؅Ę3rì½Àä†lÈ+`ûó[ÐÐ}Î(b²á(cC*uWšúe¾u®„Ga‡Óih4ׄµx¬…z:tŽŸ;„?êï°ÿy„Êø¾Á*Ò7ŠŽÄŒjæÞÒÂt1pUܸ£™›å 8)ôŸtVË7›Bº0 B3`€R"\ð7>>¹ Ù´·Bq çXÇæßa³ï'rpòô… l؆Ónг%_,%•BHlÀX"ÙbÎéÒ7ºÜ~”ï›?^ŠìFIÛå$tQ˶#àÇÍ*‚šÔãÅ8}OB *€î~WÕ/·²gYÙÈn´Vº¹ Sáu0ÒHt9ù´&j®ÏZÜE¢‡@ý’;lºÛ¦sò†=ÃFŸ¼$ž(x÷óÑ® Öß ûö^{`f0À÷Æ»5äFá:—ðíFövj¹©µò.¢6_ïÖJrïi ‹ÒCk7™¸ÎüsaŒ¾El?¡úÚ*AÈètó´–ÿñ‚@wò„‡ð=´G#÷y´ @¯û ñéz}Ÿ~¸KÅ;%š­ðÖË_N³Zß… ãͺ³£°TA>  $Ðô+{!o€òCQ9¶° —ì_mšUÝrä… ®2w°Z»¦ø}ÊfîRª+É¿ 1ãi—ÝIÜæØÖvd¶¦Û¡äšŠ>ä„=š{%Lõ´=ã©øsLüsŒ ðþç 'läø :&©Aê¿–„:›wƽj—¡/ŒmÝ´¡_ ¯í¥šBð/ Š/cƒ'pä*`ª òãÍÕÚ÷Üšð>–Ö¤ ë"äM¸¢Ëøãipf¡´gÌŸ¡Óæ²\%§Ë¼ºäá=Á¶Œl!äÞö*äïǬÆlvl#œ’ÆlÝÍ¥Gzc·ø{è{®ÀP†¿÷íÑ«Ãéá«Dº™©'Ú >´÷ÒýìÞ諌2ÎÙg“²X~É÷°÷üõ«÷G¯¾;Œ¼þáC†vd$&ƒ{}o_Ç‘~¸ùÇñAv2º?RP®AoL(êëû÷ïŽ^¿Š½ú‡ÉWÿøþ7™À>›üãÿNF â½ég÷¨ˆ”Dâõ ^²Ä=Ï_¿|ù,}lß{ýÇ·Ïžÿùð} ǶÕó­Nl«—¯_|÷m›7÷ÓüwtÏ¡¯nÇk?üÆÌ>Í&I¿zóÜ©_ÿŸƒ“û#UÆé»Oèéj‹Ï)Ì0ÞÂÂÀ<Ö/³ûô«½àOù6ŸÁÊýñõ»Ãäøåè›W¯ß>öîp¼gfhúÐúù8ÔÚ¿h€½f&ÞÉW´EEn>¼K|µ,J ‚⣑ì¶üò®è¾J•Љ,°¤#¹¾ŒÿDBx‘™˜€xS#Zmú{,¸#  ÜÊn¬Y”fì"(¿",ÞË£ÖÁwò\}ó›Ñ”Ð2Fŧè[ÐOš¼-HK »±èR¢4|<þ¼=ÁÂx3<’RóÑh$/úÀ$”c5â t+aŸXmcbjkØ ;Sô³æìÄBž~N¸§Ãä¾;ç\Û.ž@ F‚Óêi«ºôT‘<{«3 y Š?oFTi\jàÆ«5¼2Ì“¼k&YM§"ÚJ7†1JÞ$–ÔK¼LzÝsÇS»Œ"¡kOÎ[ü—GDêçM…wédøG¤RÈ›¼¥ÛꩺV/¨ ÜÖs4NdIòµýÌŒ‹²ð»€23 )³W,·Ù ›güBÃô­ÛïùåÃÞ'ý§ÕH‡‘PXyr{})nLóÒÉHæ§€lüelP©ò­p 9è¸Ä Of)ˆ-"øøbZ3º2“…»mL@1ìd‚åâñ',#Š-~±\%3V›·[p*jUã̘y´fM€9+î ¼ŒÝC*/ o¢¢º&6>æ@×%(7¶®Y¢î g‹A.Ä:ÄWR©'m:ٲѹÖ5`4hêøÑ¦ábCCOmœï˜Ú7us‰B0Hï–¨MVÍS™á1›í*_¥úÕ|±07L ö@ ZEÄ í™¡újEìþW£àÙ$Ò–×ýËã7Haƒ§(¸A+$ÓfôU £åËLjUÔâ߸ɮ«Ý˜íR)»¶™Çw¬ðŠÍP)$-#N”•À˜9ƒæ¡j&WŸÕ—Ä^k¬ò4(û!x[cMÂËSúgŸÓ‰<òøDßAjE(û̉b%‚µª£þg³§´óf3ïN®ÙŒûiOà«äL^QEÕeœ$|¹œP Kq)`£“DÔ–ÛÑÜ!”\m°.,Y‡”b#h`ÑÅ mHØË׃ÈT€§…Õ{ ·ÊUvÞÔ›UÕ GdºWŽHƒ«ç´X êxÈ•óÂÈSô¿ O”V.ÅõÍÒó’nÊ;ôÆðqºÈWé O¿ {äÞ™DwÞ¾ê œH›ÿžb9ڮتF™·7࣒áð#JYº—àœÌðÇÐ.VÄ@ò£+oÙÁSZNž,ýÉaFímºò¶2½uD°§Çw驵‘èùUwN¢àå%Ãë°-­ÛÓƒ>‹•Ýmˆ|lb¨B7ƒÁ«Ì1  •ޤÓþ Ð ðâ\É ,VbàCØÇòäd¢r–¬µ·¼}ñ¢õã(Å[1´F3QgõÚ`ù”¡ÈÀ‡—I`&…ÌÓ¹§YB'¬SZÓ.‡ó’Kú¦.š?0ºÈúj¤à4x§ãËf²‰Öª&Z¯'®­7<¯»Öê|j-ßE™€Ýf‚P­y|þ7j1s“¨ŸFu»¶Aí1ý~¢w0€îÞï0 6JÐήêk ½Åo¦gM~Nw›àZ!ƒpùµ£ÃIõuú]6ÍR¶¥cÀpt×xÖAè|2ìê†ã’¼ˆns,x7ŽG^|‚éÉZM¼¼ÕÐnòC[ %sª´Š¾¾³ÉKøbäx_Ý<0QÃfW½ùó7SJÁ­8’ÙØTÌÀDж!ùüÕË£¥Ÿ¼…–KþLãíÔüðæ¯Ó—ÏþëõÛ±-¤y[9£µ ŒôvÕ?nh¼.•3vôÀÏP„ú¡wªÉpâ±1¶3jÓ|MåßÀøâf‰v|û%h$³Æ&ò§ßÀ XÒfnƒ0ì¿‘®õoÃ×Ñjë]°ƒ­û¡êÄÚÍ7¾+$H›¦EDUYß= –blP®©ÁÆm!ˆ“{_Ø×]/|±Z'Ü4ðVïè’” òk] kŸ†! .)£ï“Î/ÊåÙY®“ €DdLDcnd,2j Rù$Ü–zãi,}އð2ü—ì¿ø/@è5ô‡K‹„MÇ '!{C™×âHCg*(îÄLÕßüŽYİ11°eƾÚ[­÷"o/æW«+^ÚÝõ̱§ÑÁ;0òð²Øú¿FÏ)o«b}8f‚Llkbè#hàÇÙ÷š0ñaj*\!’¼W—î,¨Ñ«ßSaF^MþÀ­ÌwRñi&ý Î?mP_î€ôiƒúrÇ Š{A‰¢$Yjaê{N‰÷N§8ò#Wá -ÆQO’Œ êœRëÕèýbr±)MvL©º;ÆšfÁðëûhÎh©Œ îäeÊÿ]×$Ÿæ?my ùK>«ak@®¶Èrá 8Ë›j‰7JQÄ Ë?Ë­SgI’–Y‘Éöâ§]`ù–†ŒÂbÐD4Àæ1Íøph22R/k½þi¥×àe¯¸5ìоšÿÛ‘}¢éÒ'öÖ3rŸÇEjïé¨h&ƒÁÔizáMÁZÕ†ÚÂë(³âS”:Š(Ñ ¼ä<ŸoûFþí÷6ÊVÐô”}K/}de+Ð0N^Å$DF1Èk˜}wŒî~òÃ.eñK Ÿëb~Q•s"å<‘јçÚ®·ï Ù³…Sd¾øâ¡x_,asa]ÓËb‰‰'ê}»eæ¸EØð a•-´8šû’JœWr…7%(ùZcMZ¥@È;€–.œîºõu}{D0 rĶåÚDyÒÉ»ZÜ[Ä!†ËerŽª%Y]Ä¥à 93EaXßÞ•¯)ÖËAÖÊ!¦ËåËk»—p :^A(º ,[àñ¿Nµ¹?ÿë­ùs’þ] ÿ<¢ˆñÓ%Ú&:%dÅýý‚IÈêF•ª,ùk½!~FNêÅ -)«f«Ú¬aÊ¢ï½~T‘A¸œoðF-,ì+UÉZ.æ" ˜¯’‡Ùà !_šm1€²àzþWåyC‹S[z4×^-‹ØØ[H€À‘1C¨Ë’éŠåd¨„ïˆÄåÈØ„œÞ»w ød>0ã0`âìeÜ=Üc7óõ¹;0pmtõk½òi™ÑÊãõG)ßÒ$ãk˃¡Û¾¤Ö ,狲©ûépühtLvI;1A؈¦PËÆ¼,[ô¾$ÃïͰ“‹‚Ž€b–>o‰St]Ãsü<ñpg|p=Ë=]+2Q~Òz›·>eÁW¶ ¦yM‰d_HŽOºõS…wh¼„¦D-¼)Ìô5Um"°ÆìoDúòmšrã€Ë8¹°æÜäñ§Òã103ywCFí*o.¹”~W—<Š“™ê¬dSü”a¤üÏ-ÙÍøÙOþò—¿øµ)¢nÔîÌÄäˆx×VžþÔÝÖ áÆìPúÂ9TÃÁËãÑŸÅ•NË`|cn‡f±«qΞ–¼É£¨ ¸¸ê8ÚM™C<å[ò¿ÅØ úL{“Z‘Å]p ½Áµœ1˜i-8ýôÉ©öL¸ãà{PÞ1s`*Û©P«i%ÛÃk`ÆŽ¦ ùýÕ9O½¡Å³Ý€‚è2bЦñVxÜüBˆá¬Èט6òycƒ©h)v01kY¬ÂJÛ·–ë4ZáÎ"׳¬¯´u_8+6q#ÃâôטÀîÊ F£:Ctp`ÅE¿fI*›ab á£Àd²!»Ö^•2Ö­Y’1œ&Óº J(ˆæÅc½©/žõ§ƒåÕåyÀ0Œdóô×.7p\°wœYEø.Ï•)È\J‰h’¢ÿ7\¢ÞìyY©a+¥|›…«ÒHžd›Ÿz…ìS %<€ÿ_m%šÐß½µ?–§ƒØynôÍ[ÍlÆ9šÒŸžÕ-\j;F ?ÝknRÓüö`CÓm×…¥À!I?oGŠYôXWJs÷<‡A‹=¡žæédÌs“y@C0"ê³Q;¡aN¦ëƒç~îgµbƒã ³XóãÉ Ä5"G¥FMÑ#ß2HÓ°0üâ“ý‹·5g2n*ÔŠÎ+ÊÝZmN—åœ^!‘#³NyÑ€3asOºïÞÉ—Ýy¢'…w½Î$³¸Íãc7y|\Nàý =Î-°«ÄQŽÏÈÕî²µ}Õ3ëSðÀŬÿt°´ZìéçYy2›)ñe6c“¹ZpÙBn†å*æëå¶?F!æ=ˆ£D Íg«bΜo2é'×H;K»* Ÿ 5\ÝnàÇ YÄS=®ZDQ ²{Ä«ˆn(˜ ŸÎ¼€.gôêŒn?cDõ*PHIxtA£îZ¯YÑ£ÑDÕQ ‘"@U •^ãîm}ÅŠo~ ê‰ó>*Š? A3¨S¢˜ è'r 9]¶Ê ¡‰w™NȲ­fÊLâÓõÜ(ô‡1ñ4ˎГláˆLÃté½ì­¢ ¶‰{ðíàHQàÕ¢HÑ6±E²÷|ÞŽU$¤”èQ uŸ©œÖk6ÃÏfz•´ñÁ'ޤ¡90-Û‘:ÙÔ‰Ñä©—ÓÓéµâ $U„±34ú–¤È8Ø®Mª¡WžÒÂãNð¿rówÖ‰Wpá7»Í«Ãêð»[¬ÓxáùÊkT‘"‘§+²…FŠg’Z ÿ%IÛÌ^EãÒïc›_]T›«œi)eHÐX¦sB“èÊ×Ý‹aÈ `^¢9‘Ñ6 íàØ }éÝ·™×y%×°ž—”ô¡B’‹êârÆ+SÊðw«0æCãë¨Ì×:-ý\óáDléŠÈ±Û¦ UÑV>úºÜ&p÷Áë²7ñtý:+S¬]™ß`æ;:5¥äv#»“¯òø}‚ŽGŽH&bÎ¥\ñ½G˜t[E…¼Ö`/²AìÁî¿ÿ(j¦è“´»Žc?xõx\­N˜Ñà_Ú¼È?ëR7”)ëYeˆ|¡ h9çS`"… r^Õ 'Ø”Uq]²±@y«Ðé¨M’§éÎÅ®ÚåÂÍ×$â¢&Ö^]WOšwÓÌ{Ô5äE º#q¬Ãu½šR*OÌKÍûRvGY:L1º÷ýV{FÄúcå‚`P:ôJ»¡Í[­'~&³lDaŸyú§Jo—d‡SRo¦ÓŽB*ƒ;#—k’†%*Ïó‚|! n]ôҹݮëÕ¶›b*>¯HÚECŸÉ«hŠ’,Ø1ûy˹"|:{©œP$ûuTÃ>I°¤X…¦„0¥Îna´ÞÕ¯¦Í2w5 øH|WnÊ%]jCÛdܧtbñÆDÁhD r\ŇðÖ)–¥—êŬ¶]½ª·ër½!×7•>ÜCË«sX `7u³ ,K-ìÑ.Â@\/^ÕX6”YÊFyYÍñCQP–QÉw7I¹„°RÂåvpŸo´áßh{8ú¯ óÚ[ŠíÝ_rý §”PÚ礓”—x¤Úñ¢`¥ÿµœÐxØJ¬ìg‘¡>ÉÝ ¥Ö_þɀ걎m×Ûe ±~yøþÙ‹gïŸñ*þ¯ÃÿÖH?¤ã*nða‘Ý£|»ôxüat2ô;3EQGîiÕ“x~Ì"!¡7 Á£{ÒÁàŸ¢ª2Ùÿ@àêî2Û#: ¯òrÉúc“Ñ\ÐùMßÑLéß¿°{ø}8üosw|ÁüÜKOMÙË {¹ìÔ„Žw­È ):N>?Ǽ¥¨Þ‡UXb!~]×§y“¤F¿ONóŸ†x¤æ×ÉäžÀø»Ô;ä(˜Z6uE_Ø:Æså1¾æ…¢ò¬¤’¶NÔ­ ¼Œ §Bït™3ÉĬl^mÙ“ílŠèx³3>åß“O΀ãáп ìš/âK<žt²^pöù£îs6/ðz¦eÜÏ€éÁ‡G“ɇÇž ƶeô]ó§ sIÅC÷2âBÞ—šWÙŸ®MÕQ2ŠY<¥aÔG£_Î<‡ Êâî^–§"`$¿0^Hþ”6nÚ·EA¨)þ8x÷“#Fi]-J±¿b±ÖÆtÒÑ6Xü莄€9Ê—Ët(æËöϾáø$Þððl§Ýhðw¨:JQ…© ÷»¥ŽØ{cpJb¬Õ”]¿ƒXS—ÓÂûÊ\+Nüv ¸ñ ºî\Á¶Ž:1…Ó,E{BÇüäïœK;|Jÿü‘jñÃN_ᆆ±cäÁÊú©å˜ð¨G‹+Î 1~yTd—ùí ʵ䎓@_,F<8 †GO1™²ñ{çÅ+0J’ÎT Æ^' · µä‹žúÁàî ßêìnýx•Œ¸ÝÏ’Vç‹Ù\C‰Â¤j¨Ñ7Lÿ>_‘±lcµ(÷9B‘o9mÚ5׿€ÕGY—«”·É=PLïZ¨ªW©Ê Ö%)~¬ë©c£0(”-)(¼¡ªL¥4ìQv6•ÑbÇçþÒóÌíÐFðš6úâG%ªÂ#+yäUxq7*_ É7ìlp} ²wxaMcâÕÆ¡2%¼Ž«äúÀØlÍf ÍîŒÅ3#uøo›}j꾑‰;ORs%Ùß‚5B³g#÷ÝMQŸùÕÛ÷“¹¹š¯VÔ’^Y× ×É-tQûº¦/‰¹t_K;eìÔÙ‰·ùÐÕZéÑû×ãäýáÛ—G¯ž½ÇÔDNÊ^‰Í¿ec°© å¬QR¹ãX™öÐÔâàIŽw˜|üÕTaëiÑÙO¹b(Žœ6œgm†ïÃÎ!îwëzuDøíD˜”xøð™"Ðáà±– íœ~®\½®?ì[‹>t¢"u+ùu¸6;!ú¨"E<½ÎT¦ø¸â:Âh°‹€’ûbM{ÇhccN=þ}¼zzŒœ¨ÂÎ:oïSxüÛì>l߃ªe׋†HíC¾rúêª{{Rص~f£o%㶇ã!%›V‹ƒúì`Éwüüúè6艌Q# @èWeżc.*ç‰c±Aö6yáê&Q$¤ù›ÑrÉDi·¾Jw»dê½8䨂0×A/­ Sù úflk«h^g&dê(v‘ÿihÅÅ©íÑñéý0&lj)Ѩwúh<ÊA•+xï+2²/Q™¯K)R9NL¹M¿‹äq`hÅWÕ^0Ó޼Ηì~”/½ -œijZõ4ˆØÀæKQ¹BKþÎ;ùAN¯“W¯ß'ÏŸ}ûmòþOGï’ï^½xýü»—‡¯Þ¾H^¾ÿÓë¿'I¬2úL+’$œl*›¤?É1S4™?̶ïF°pŠœÿ`g®½em^昳\dï̟ãK_ÇóÇÇq²=áÕÅ?ÝÒº^#ýÕá¿þ#» ¸â#¬¬bb-€‡ÉœÏ1»3–ÛÜÉNöQà?sÚŒÍhÜ7N6N&AZñó ­8*ÎÚ™î.Òh²ÚˆÖFo›ZA=K#-Þâÿ { L&'ÞàwdúFÊ»y¿j¯Œ¼œ¸îêô\øAá]è'êòër]Së.J÷ï¤ô#ܸ@yÄ’®›ãõ¡¸?›Xš‹ÄÇk—LG€bþʺˆÔqþŒ®†\5…Ü €þ¯›|K)0”ôFyit4‘)w.¸¹úLA#{Bf˜ ÇqTk¾²ƒ L rÒ^åtõZ,¹œIySà(m2ŸÏ7RÂ2\ Ÿ²2ƒ|Á«š•½{"¿Ú½!Å6¶Ë­ã…Kÿ/˜+çÑš{­7²áÑÓ:GÞþí›0Ë­¨8=iôQ/µ`“ã‡~ÌA¤0’Cé5ÌoUãÁrJ’ë¼üªÖ­åút~IÊ‘[£©1BÖ)Óßkô"Áïro„w©]9çU ô (…Ûâ; ¯|¤c­ zjJ9óƒÂ Õ¼ÃaM§Çž2†ºdÞ]T|ÚâëS}ÕÇÈbIfj—œåBÄmõ錭Ã3óºd#«  Dc}J>xqy¾ðëhäó›5Û$nÔc¯OdU Ê™ÚH§TÅj·°¸‹g\`E›rIño4³‘ ³HØ™Ë1÷zWßJ353x~•_ð µO MnqQ§·ÌâðžÓúã·F¹ßFÂG00 ¨í‡· LOß}÷æÍë·*¦Lb^_3ý8ÌK€2®z¯¹œõG›{ d*c¾Á>C‘Ä>UJ¸l„8ÊzñbñgZÒS;–‡õoóƒÝ01R!”ƒ•ä!³uî ¾²Š­Ï/äò[s38KS˜FöNàÁIØDš™aÑ5'4œ]Î,:MÝ,É|ñèéAÄÁh>ù›O< ¯¿x¥&1 ‹Ž-  Oº¶¡ÔœZì'Xð Ù¬ØÐ×T¿ho˜£]]âI«®¡†eÄ»–™¥â_ôsà7Àwë&oJ Zf ÷Ó–~@ ¦!Gb² ]¼“XxÝÔ¾¹/·¡[TOA'Œõ(óØÃK:Þ!G›ó¦ñ*Àà‰›Ûº7€bT››VÊßÀ™\`O .®ZC¨¯`æc»úÅËÇ—½n–€2/ßH£"o–¨ênZ¾©Ïø1ÆΨN1ÕÅbE¶gþ»é€C.Ú0°õØôÄCÅX†gD[€G"Äßò&Ÿ×™­2ž<Êž0 aY”iÞ–‹"=ë+•/Ónòì ›ÿTp.šCJ ðKÏ'Ö}eŽÐò‘Üù÷Ä TŠ*?G†½(–åiÁ>Ÿ‘xóA›_㥮ôP¡w|ý%ÿ"»þüx8•6ò†Ñß–é™I<ÓäY·:Y4v挛ی&ÀLJÌnäÀé~)U^3uŸtg«ïÎ/¢;èÈÚ„{æ~3õ€;~ÇÑfþ!3ÿ°™zXÞÝïßÝšOÖì­¸iÁ1×O¾~”}xÔ„ã&:†·`*¯óÂÔqn5Ñ ^Ýæ¯>fÂí&zÌD›ùÇÍüq¸Ãß>i©ÛOòö.ûm&Ü͵zÊÔå÷i^ÇÓS&ÜÃÓ&¼žgLxÞnÂyP6áxpÖ„7ñàÞŒƒÂÔ³fê9–xõœ o1á^ÞjÂÛL(#P°Ï„2…ûMxÀ„w˜ð  ™pÒ„‡Mx§ ßd»Lx· e¹ÞlÂ#&¼×„o1á}&¼ß„2ßšð!ʾՄ`¶Â£&”i;fB™¦&”iyÜ„O˜P&àIÊ8Ÿ2¡ O&C’ÁÈ0dÒuéô³&”ÞJ?Ÿ7á &œ2á;Lø¢ _2á;MX1á´ «&œ1aÍ„¡ #3÷˜™z݈^àzÌúBÏ¢)^óW¥½ó&z¯ÖýÕ1û켿úFe¯.ø«ïäU àøq@vijÿLIÇfJú¶h¦jª)éaÓLE&lqþgM¸Äƒ93'wÙ¼Wž9oÂ6/ÖMó`ÞDƒf~Á„àõTîðtÑDófªi |¸e‹éºðÝ:Wrï{xïS¼'kð)ã{yã{xc³™ÿ^}O×ÿôîÉŸ»&¨ú>×){þý¾““ü~þþ¦ ?@<ø4¿úƒ&ü!^ü´‰¾ß}þÓúùïwcøtWwÆ=íΧýzÿ0Ûù!¶#ãû!ûáÕF§Âå'Ä„?Æ‹?jÂÏðàÇ^ÿ8Àkþ3fêÇÝ•ŸpW~Â]ùIwå'Ý•ŸrW~Ê]ùiwå§Ý•Ϻ+ŸuW~Æ]ùwåsîÊçÜ•¿ÅýýYó¨ ·ÿ6ȽÅÀŸõPòyþmŽæ à ööçýíŸ3áLôs¼úsþêM=«áÍüó%ùç‹&üysdêK&ü2Ûûyþ‚‰¾Ì7Ñ¿ù &ü%ÞþEðàùWü½_2á/óÞWLø+<øeþ*~Å„¿Æƒ_5á¯óà×Lø<øum2ó¿a¿cÂß4‘ð¬ß2"ý\ rAøÛ|âï˜HþÿM|$ü»XKPáßÂÅð«ü¸œþ6ˆ³OäêX¤g3r¦Z[¨ÎE¥v·VÚµ¨tôÌÉ‘Cëü72r4y¨—ª¥Fk®^«6J³õFTªµšj½…¥‹õÎùzSî/iÓK­vòôH¼2ÖÛQ­Ój¯•:ç£vÔš,•ž9¹2})E«Kòpœ\lV£x¤Ó*¯^ˆÐB½-ovÎËO[ž‹#ù·Ú±)MOžž>X:Ðlu”.ž—¢6Þ’¡;|Ó¾#ý¬ÇÒ—ã­’<^Z‰£R+žä­¥H¨·šqI¾¼XmÖ—VÒ˜ïÖ»Uš‰êÍ9éIKêMyŸ’qLŽŒ\uˆ2›a×ç0{òÆÅV{A;ßlµíÇkq'ZtïÇG&£¹9½s°Tm†¥•&îI É ÊÉN©V•ÅhĶ]®L£¾Xç U×ø¡‘É—ëKúÛâÇk+q§µX:sâLéî;ï’骆Q[†/sXŠW––Zí7==u*aµSØ?==²uηÂÉ‘:ô·‰@~:ãòS‰[•NT©/âÍSzgT~ð¶^ŒÚ‚nòR·†äg¥Ý…‰£Îˆž`Œ8Äi³^k…Q í¸¿Ç *âÙKÆÌÛÎò;ökò#ã^Œõ?õ v?ñCò3³Ro„‡BãÎäbµÖŠW½éÎÉ7Ýyhõ-G*Gî9,s{xia®âÖ/>\©Ô›õN¥2¹´Æ>?ب.΄ՇF“h÷µôpX{ØNzY.ºþõ©“eLžï\21+úb4‘w§‹ ‚¥|¼´y¸ÒlÔ› úNA~+šºZœÚ¯à(^jÔ;\¥šÌÊy! cr,tÏ=wž«¶›‚#^ÅGcbV6ËA$d, ¢Ÿ3e™¸*?#%ùïYàÔÅóQSɉPS~ã•H!¶ZÜŽIAqb!õÙº ;p¹ÖZ\j¬7 ïh€-ý™ä‰ëW©`¸• a®RYl…+ œò4lÕ*•d9úµ&[¥…óh “Y,tvãcg£ÎÊR§ÕjÄÏé°ž®¯Ö›½÷BzâÞ˹™y˜JpPÙÇÁ 8(BÀÁ ”x A?ÇÁ°Qµ|jk0œá¼áí˜.â2o. ËŠ„NDíòÎdnÏWãó2‚â¨1Û×™ÄÌ-»™4A ÿäÒ=¿O{~)@ç¥çí›Ý(\\Qtr¦“w+àªÜ;&ãÃÐõ¸ÞŒ;Õf-âpe½QyЖc.rÌ é±¤|›— ¸¯ã¾A‡eâ"Ç=lɽö±¯rìå=ø¹?=ƒÒƒ-ߨoLyƒ´ðò×;ÎÜ×?ÎhycÇy“´ð_ï8¾þqÎmðzÞ,-¼ÿëg¡ãìlì8KÒÂG¾Þqæ¿þq67x=o‘¾í*ã̹qn¶ãtÛ“‚Øï½Äì,Dk}Ô6YØî@ЪT>i†áØæñVtöû´³ó¸*r˜û¦>ö*Œõþ)È?à¥<”†`Õ>2Ÿ7Ê™æ9ZRGî2æ†*ã&œ^À ç`ª–u Ç`r¾’ ‚Õ› ƒvªäÿã/m2—sæRÎ<,³9Ç•‡€}*ÆRO¼ÞQºTzGõÐË/áàÅÉK¥Cû)êÖ8“KmŸåß õè"—i¶Þ¬6ñ¡CLC»Æ“GøF]à¤àXöݘ”9X­›RŠÕÎéy äƒ\ÑK„ßË<·àŸ„·ý°YÞbšr™¨’LßBÑ´+8Ÿ§;Cš’¡m|"×vóøœÌësNJΟb÷&ë#À‡ï|Ó]wßóæ#÷¾å¾:ä Þ>À±ààœ0Md¿/‹ª£×ødLQê£^ƒV±ÕŒšŠ°v´Ô¨Ö¢~Aà@ µ™ŠZ+Ô_Ío!(îìÙƒ¶æÆò0ñw;Öà3r0GàYýN¬„W)¸ï±`¢p+—Úũ̹ˆ8íЬîÃô¶§¹y³GfËÃs•æ‚å‡Ì9Y)ûä‡ý“|òÃé'çø$.äñù\°¼Çœëx 5Å8U>äHƒ®Ký¯ä¿xП¢˜x§ýOå,ü4Z£6WZ¤-™%ñ έ%¶ê’¨"¡’\/v¯rVËw«ë”ïî#ØÞj„ÙuüY´½ƒ+X öã¹QùÝš“¿ò'þNéÄ ­5^@Õ£©¢åŒò•F§Ôš-e¾:™ùÂdé™ó¢ü¨&š«ÖÖJ3‘4Xµçâùzí)-ÄÎl`uš’ ã’š…ÒÀÉÙÒš›£j“Â2­1è…LÑòJ½ UͰKòƒ{4EUK3+sÉSCZj·æå°¶ÔÚõm£Ú‘Y‰ÂI^µ…Ft!j¸Lš$*À°ä<~îDùÑÓgO…•t/ªv«'ðºòJÚµU}ùBÜi+ ’ ߟ;=/Î;@-¿ ?wõZUÌU*ŸB“7Hwù`ÐþËoÛ<>^ òƒÅ`0¿'˜£,oÃ4>jWT5(‡SH¥Gñ†¼¿|+~Ž›´XÑ/ÙbL M¡CÅÜp~¸˜ú“':ö(ͽú2æAõeQoÙ¿\f”ýïø iá÷ŒSïª÷IGŸ" ÿ5ê.¢.þÀw7çµSÊo͵͉wö\ó&Sè€ïzÒAò¯<ß-¡bJhîR‹&Ð8e ±ædó‚pˆÐN {•î.ôUcGR$öŸ;óF°c³°áŒô6LXY‡üv>°\.èß ‚«h®b:nt0Ö¹Fk¦ÚˆÕ²¶ #P¹ThPG:"Ý! ë5¥-³íÖ¢± )œ-ámkK ԞΠFÂ#Ú‘öè_¢á§dK@0-Ø¿„‰§ä .Òˆ›ˆ%GLljÇ_š0/æ “\Î[iðRÞìÞƒYÊ™=W8YrôàòæÜ%ÌuJµ–6b¥ŠøLù~0ø¼ZšÐEBÆÊOö-(RiЪücm¹`ôÃÂäK %…4ª[z^Eû‹­•F(ê‘UÔÃz@”‰¥hUt#ª%P TšYëêM©ôèJ‡ŽãÒŨt± e .¨Úù¨¶¨ިwÖ  Iû ÍÖEt‘myŸTO×DUiG¥mQž¤¥ð‚‹RÕeW´x‰¡Z‡/_a{ÑêR£^«w8“h<¢×‰Ž´Î§â3‹+¢ÂÑœéYm¥Ý†v˜z ózú¬]““³ºŽ¢õ…õŸ¨É;qiýæZI53·NÝN8Q'ë˜-ùGDíztPž]iÖØn|Þ-%”•¨Öj­v(‹BÈ6ÈõÂjû¢hŒÀX‹C·Çòù¹PFЃ|j¤¯€DÌóàÄË|ÙJ–gÙ'õzV;µóåšcBpºƒ¥ùWÚó-Q™I2´ùö\»%"=>ý\µ±h·[måÛE“ž¯]vÖ%%œ)il8nIöP0– ¬=‹°Ãî V /u¼G^0âB=ŒÚ-öº':ó Ö‹Pði¯U–0%¢ñ¤^[¬.QˆL®Ô›³-êhTASoÆŒpë(Œô\‹ª‹|Û_ƒ²O×ô–ôÕ†ô~èÌëѪ\ÙMÝÕhщ¹ á„S9áÒˆ8TتaX© ¸^`¿5e‚N³õf˜™¡¸Õ ,Eº]%”WIÂBdh®,%+Ê«œåh¶ºÒèTjU!0ìÆ‰æ…z»Õ\”ùâZÓn‰úÈ!–mOW›B&Ú\¿ã饢¯kíÛ8¹?ÃEsm4ø4A–×,nk5gP@vtµ{ªÕy¬µÒ ùÁg› +Í*ß>á­-bŽT¿j']‰Ëo3V Œ«³:ýlŽgNôép=I؈¿s¤kõHP½QoFºÚŒD%¬é¢Œ¸Ö¹*|£ÓJ oÔUëøm/D:‘\Yk¯Þ„s¬ÈøP&¾«lªþr¤K ÒqâñÇ+ÇOž}†ßzôä©£å’ó³§Ÿ-;¡çÀžcOœ8ö¶ÓÏ>£W¸”'ž;ñÔé3z@ròé¨SE°Í‡ ¼êÀÀ_ÅËɸÜã¼pFzå/¸ææü9:pbq©³æÛ`D®$Ô­œZi4ü3¶Žù:®@œyfª¾”y¦ÍÚ Ž\»>}Í#bå|µ6äöŽôm EªPõ½ŽØ·*È”¼äxf™âØ%p‹UwPË£ªõFU`' Ïq¯áHŸHñAeÕÃâI46ÔK3´? c #˜¢£fmQ^ŠX¥x÷Rà#*£Ï«h`A©k·“0 I*Zl+Ú~ÈSDj—Cã„ùëLŸ%c5â+•ÊS—ŠUÃLÌ‚XòÏ™°E}‹´ðd`åî¢(Ú~rnŽ÷®“,RT°Á/{àiÞ]Ì ‹‚¢BÀˆÜØp££›®®¢ºÑ©ÄÛÎ-]Œ;3(›Pä!+Eõ² FU'}“×’¶ÓàÈ0¼L«l+EÈU(¢)îE3‰ ¾¬–×¢´UÒ›Ò ï9)Ø¢WÅ6y@ 饥! âÛH(S+WÜ™ò–{µý ^þå‰iËï¼V÷¶wᱨRßÒEîAEà(¥Yð- qÈhÔxƒ a|g$®¹Ð?†Û µñx„:ŽFÎg…]Î1!‡—×qˆbUZ•ªAÍVó™ÇA¹C°šV4•ªÁåÛy£#¼y¥Úè@&ý#jþÆrwæpÕ7÷ Pª{ +ýœ`°E`t¥¦½‰g (…`KÀ0ºnŠùóƲ'a¯KÂäÖÊ_Äå/áçñóËBR?*-œAÑëb±˜+æÆ ã…á|ù—Œµ-dèë.úѼ-X¸{ª`¢™-‚ŠRqzŸ§¢¥®eÑEí.ZêÀ)Š`;Dì6°¨}Ðùì¬6ÊFÒB£¾ŸhóW%¡–@‚ã‹ZŸÐA—_-ɽ4¦üia5!04¨tÃËGД?_Ùè ,ÖK_,sc¹^8k^;ËÅiÁ¦¯ ?ìÐŒôFù9šb§i½ªt±3 wÊû°ú} —ÛwçÉUS\°.Ú14ÍW æõ€ ƒ+M9#¨šŸº\«“oðŒ™/}6¤«Ìš§ BÃMÌYÑê¬\šrFZºÿ«øYظ¥G`øf‡ &7,¤ükáüг_ÆÏ/lœ€c|<ÅÞ_ƒ;à7n>5l^æ±RùDJY‡¼%”íK~¥Íu¯üëf#¨ÝÇ s’(êE®˜//ç_}†²)2Â{ØŠâæ¾Ž `)í¥¹¡4UEŠö:Cë\ýBÔd>“‚Iv>ú?Øo•>顨½#`Vo8*Æ{)°nþ´ª÷ް©2^šv¶Êl•–iÍZˆJ§Sjû´ªF™K´#¢GNÀ¡áI2UUŸƒ4=­é“g¨LOdS ìët…1RÞÌ Ñá ËΪ–hkJêö9he «L-™žî±«LOs,”Al_ø–uañ*]½¨GÖc:6]ÀŒÔÝã¾®÷礅O{¤Ì„¶r¿Ý¸8\o|Ø|ÞúŽ–Þ+Cg ‰>%ƒYÛŠ Õy¥îä9ל0‘cáZdØÇ°}#È<‡ŠøÒ± µbÔѽĠZ+ÈÌ·ïM’µèY »šÚÅܤ„E2h›ÈãæÔ#²!ýÍøù&c)°D•Û¸t ?x™äK›VOÀÛ¢5µhj£š·f³ƒæ¢Ž(smu€Ð¶U©†Õ%A”òoëÊ$ h£§Û¢ÑS=Ós« ¢§}…èj?ØÈ)“n òÁÖ`,‘ßmIØ‚GýO)¯鸀¬½õ&æè>|‹ˆ$È â…>\¹. Ó¡å ½Œ x÷rž½õÛÁœ¢ÝåŽY¾h–_6êRœ¢râ¡Â^ 7TÆa°./§±s‡Ï2GòðSõ™vµ½vøX«Úê˜ ½gu‘É%Xï­ôR Ïð `q†~ÀŽ 9‚WIYÕ¼†j ¦iuð»ÀáÎy.œõ2à±óÕ°`½Gr¹QŸ)ÿ#´ôc#‘Õ°ÇPZûËO²ÊþŒ¹#U*›¾BDCZø" bY¢ŒGåw[0.Fƒ]¹=A¯±ñ~õœ-ÁsD«‘Ñp uRÔ=¥¡¹K5NÅÄîž9F«/+OWkHÏ«ÌDWòi'ø|½õßÁo½uÕvíüo¦Ä$cº"vþ¬ípu†¤C|êÁ¹æ-Bår¤r÷[˜%‡ÂCö·K.ÒÇúÙóD”¯”‹6¸}TÎמ±îv ÏÀ&ˆ0?€G¡Æ…C —8刑²'Ãz2 ôƒ>ov=·üUéßû÷›tÏUÝó ¨ô{üzBP»Ýóêr#IuWÙÊZFŸŠ•q?ÿüó¥cê=n¬ik–{ÇBK¢sMO_Ó£œlX'ëêÓF®ô¢%ÖT`xªÞ\Y%cwÎlåµ)µë;8$ ΂£NÄÂý+T*œ»8œ¼=•ÿÀað ˜ãv‰ íåÿ 4ÞkÏÌJ´/ÿsÓgYoVZø»sdø˜b>·C¨ýQanÊ?ܼAp},?Ä×%“ƒì‘ý/NòŸC“öÇîUŸ{æfúʃ& x:PJ=l†`UËðÇÆfà ƒëh¾á|Þ2~MXh¿-H !ˆŽË›ø‰Rþ¢0›‚iÿc 'âV`ÙÄe¤øà.Úã¼e)šK̃E/¾`.1vaÀÄ¿ÃëE^ÿǼ>ˆëøŒô´IuöR¾§e/H'wöîPêî½ÛÞÇûÙ¹Ÿïðx ÓÅ+Lhk?®OcŠ#*õXÞ‡0òò“zÃé$Ì¢½Ò,QÞ•ÛÎØ‘Ü~ëˆu&¨¤Ûi¯D¥úl)ªgÃ9êÀb„5YíǼ·•¡+Òrµ1™„SDãlD eºÚ†ô7ë«k‚ØQl›ÚðçöxRP”ú MB-þ»™ÝãÎî±±¸¦Bn<#£)Ïáª)‘+g¢=ÊÿO,:|}¬Úˆ# ÎËUß¡?kE_bd3¨ZpÃí ƒÇ‘ö\fB|’†ÌÛËúÐndÍØxUÖ”)¸2$WÚ6Oµj(“‘±É‘5TÀ_¦ €ÖzG McPèÉ.é a‚š1Éþ):éT6§?EØÊ,MÇ8›­Ø˜êò;ñeùØ‘\>á¿LŸúº¦ tÔÈû¹RèÃÎm±{$±éW"4] Ù-…LÄŒ¦€³Ý~«ñ+‘¹;€»ñ4åpˆþžÀ¸x½œ[§aù`°ÌJ©b¬ñ^iç# ,h(ÂàO°F‹hazí`úQ’Ž´uDMÛп4؃¯P#Ž©¹¬­8¢ÚRþ°[»gä©"L|±ß,9{sÖî%I…aüë#WýJíò+u%° ÿÖ&t<™Ûi…g<•ð«Æ4£ÅÔœ@„˜¦òZ­ÇQ)%z¨Õ]+_0.ö‹Žx•ÿ{¿'9˜K ¹=¹»Û{N=pß÷"f”òbuIǪãöev¥Ñ°Ê#©á^4.ÕÅ·¯#Eûw¦Fúš—øÁì`“ ª4ÚØáÞ¡@ÀQ;¦šëêë±´øÈ=©ûŸ·oÂŽùõ±!½–g:ø½ùðù9ÞŠT_°±:ûâ,á±å¤Ò§ôÖS:)ÁFÌ)’èî÷µræjU|²ƒÚgÔ•ílRç© C¤Òº T-׃‡_íŸö¢ç®5˜#@¼àÜŸiT› <Law#ÎQÿTTEø®F²]k°úÎùzG£´ ^b>––äcHm*E¢ù³ -h¥­ÙÆl-¯[§§Ñ Òz[ú’t¤v¾Š8,+!™¶ëaH“:×ÛºæZã¾ÚºŒ×qWøÖRi¢Q_@™-[‹l’«P¡÷oèèÀýÈøÍÇ_íÈ`ÑyÊ‚Š”H³8”€KΆînü椇f¿ú¤œcwW>b5ª­t¢ÔÚ©(醇`ìF=R\RpG¾ŽP¶j{íT*‹ó¿+Üøû.x>í¦ŠRâdúøùKü ᥌ñ–ƒÀ‰ÌÆô™ýü´p_Î… {ù»ùõmëDô} å¬\<BäŽzY–®«àÅŒC‰™³Ñ]™/~%8€¬î¥gêЙ:}B¯Èÿ}¼9OKÓ‹±=­Ù3Q—ÇÉt‹°€‹5j¤·zªS÷EvZÚÖmÿ̫œzz~`fGÈ-çèQ>-$õs’ÊyÀp!è3ÍØÞ=!š’ð«ŽÅôtX{«•r\-kç§Óóÿ«S"cyç«eM¯ ¸ŽäçšÏH~}Œ“üÜÝÚ×ÌÆék`ãýWùÝÒÂì׸³W¿&ÆÝ÷Á\6šæ¥ül½˜J$=•‹øÄÏ~0|µÿL åzÞîlˆàŸ4[Ã?йþ}ÓÅÖ¸ûŠ.÷ÄQF©Ø¹AÇ冗v\n„ ²‘M®nã¨ÛNa w£Í&GÝ©÷æ¹Å6^Gé)\Ùê®lFõ)\Ù†Tx};ÊPá`êåã`§Ý]{RlåÁn°Yæ:iôm44Û†¡È—ÊZÿb¦…Kj]Ý Z–âúb½QmS½Øïã’½"cÞñ Í€8ÜAÎÝrYô C¦ý ¬HóExâPÀèÜ:þÒvš5M⌖™sYè?&D];›üÅ@T*'Nóa¯a®¨ NLØt­‡Üxö«5š|Ú>Dû°&»¡x­È3<¦ÜW«63pyÑ‚­^¥?4V(DÊ_M•Ь‰Loô“j¶‡ž/¨™<˜ø'7ŒæÆ²Ò¸<ð¿yÇg·ç4Ïé6ï9}<“pI>¿¶5[.ê\óyªÀ§¦ù” Uïž}þ’ ŒQÇsÃ3m”nVA|±Ê€¤ÔÒ%Aã©jÄZ¸ÀZõãJ…6 ;väU*å- ÿ»q&dÄÝ2ÑÈf’ 2‰lÖŸZ#¦%ùbÌFúšh{ C½Œ5b¥©á ìÆryëØœón9FÓuš3Öצ•­‹M£1ó6€Þçñ¦ x3`—oî1çVï´^îã/ÝnàS+Z7Ö i?ËãA\äóÏùÿœÞ×·&.yCÚÛÓ+ú((4¡«éÈ–÷,•£‹¨•{‚’J ¶óm™Šu!*À­”àV‚mĪòVŒÖéíK‹–é.(ï|ÊÕ²fûbcµ×mî7ŸÛ& ~ܯî `^°SVuk~K0ìÈ%É Ÿ1©0TY×9®"±(åb V-ʦ‚ã/íqD‘˧ÕYräî4iü§Ò¡£!Ö…e¡4MOOZ2!ÂÔâ³ÖKòë” ;Ý›0;Azv°ÿÈ,*kº>îŠBp-ÕZm™Á¥–~Ø–[÷4zí Ë£Z£UHÖ< 'åû¼‰oø†ª‹Õµ¸¤uäô³ÙÁEˆÕ¬ÏÊ8T¨™a¢HF±OÆ"عÒl3Q­ŠšeÓÓ6ePµjÖ´Éh d— õj‘ŒU›¾©V³ùdzãH3m'‰Á.^ÇäÛ£·6óÎä~ÓºQG0'hg™›âÖ®àçOñ³×þ½qVëëôß+¤üQ ÓiF¶[‚]A¯[bOøÏçRÅ~•Ì ºê3Ö×m=.6he1…z)œ’¶fœŽsS`ã•XŽ$UGµßö\ÊŠp©/tùd2Ò±uo}¸K¼Õb7ˆ³ú s¶H§õ æªÿÙÃH–ÈNk#ËÒdÑ)å”#’ÚìW›×lº¤a­ á›rq¸‚o0<·@Wx¶E¶ˆK'ëæ (ûîKyÞ —ZÊã VÿÕöÑÕ dÚHÇ7‡ðn»£:ãÃ,¦Ó=9(˜Ö•ú¤T.¾prÝ9k¶^ëœ9gR"éÄvêÒß°Eײà«çG³Hü¥€æòoK ?Ÿ ñÎຜuª-×ÇÛX(³˜,#æ½”Rpà,þãfõFþØâb›(¢  rì›Í¹e ørA¦ƒ8@--¹7häÿ[ŸW§GÆ;KËT¬b‡óÓzðŸî2ÈÈúY¯L=ã`‰UÀ$év©C{·/EšF#ª ôü!%Ô ™‹ð·š5ù‰bß+ßÌL ŽûÅkßÀþØ-ž i=ëæo‡Q{\Pi!›Š5þ‚ â½”*Q1Á¬FK}…5iáïz·üàãS·‰jNò”¢dw( Áˆ¡,” e)ØË‚rº:µ.š%ÇÐÊL4 m#ëD³X¦ªI@Ëk f)ÿü ,YwèÊ€›ït0RLÇAùÏÝ ôÝiðÇW‰Vq‘²D×% ÛÕ,ÿ!Þ’ïh¡;°›;lÅg_ýÈxü¥;ìÊX¦tãT¨ƒ<¨B«gï3òÿ9Î9§x›E¬\‚áŠfy¾F%( Ç-‘C1Á‰ö¤i‹ê2Õ³ìËZ. ñNäÈÐJ]K©¢ñ‰a­ s‘4kd(ך‘|ø¨ ý\fØkþ¹×ò‹E¬ÆsÅÜÁ+Yl,rF{ü1ò¦}£+Øæ–Òn0–Ðæ{¬b/p`cù V“Wäò@ê"Ÿ´×‹ Ô£íwÙpiµÔ€„¿‹&J-¨ ¥’·´O |~6i èÓô UI=O_[Ý(á Ö‚ºcÅD»)“§ÄÕ8nÕê©M¦TŸÈò¯c”Vš^*9 Æ Ö±Ä‘þVÙ^?›€Ìéf)Z­[=˜ÑÖBß;ô”§>“½Q–³i(ô­ÉöÅY}bB›‹U¦­u)7û'Sš›—›Éƒ®íª(í³•Â¼åk˜9)*ý5M–ËÒV§&aÒWš ¸ê¦m!ö‡ ÊOgÄ(~‘]:HÔÛÖJ®tLºð†(B+3¬Áp]Ò«|{ë½g"6’¥X[Œ;55ã¨Ý©´šŠÇ5G¤Ýb*fß8yk“S¤4{ˆ=­4£‹jsðz)²\ý€Æ‘ƒЀ8`îê+5€B÷ŸA />Z våÔêp]°'WÈma-zü%eØbRáÞÿ-0‰-) ¬ýï}y¦õ€? ð·Èbõƒ¶:a‡±Î—‡Ìê`lÿgÚ,ØèË‚“ÃDí"jÕ/?DJR$Ŷè{yÄ\q4§hÎÐÕˆ?c¹Jp̿ҟM)Â%Boð_Íb›±ªÔ²A^[b<ÛäŽ7Yõi~”}Þd´fkŸ/ÚÞ<˜4,ŸuÝ u“M€“WG­:¶|–¤iÐÌoF¯©òýÿšã=—ǰ¹šÞÀ~ [Ì¥1àšº ÀÙõðhÍxSŸû|W±ÍôRAu°S­¥DÇSLÔV_Ænǘ,ˆhöÄõ¦µð,œ²~8¥æ¨S¾×ôZÈ–>àÅÑ:5ÅŠVÄ„ë@M€¬AòËø¹Ùq)&·ÇîÛp€™Ð‚e?• '¶xw4Qg¸ˆì£ ®c­:Û 2Xp´v|»…ð(äD ¿®¤Ÿ›FIIŒ4ã³²½)®TB–&Ü8ãÙaÖbמòÝ]Ò¡-2òøQ4¸cHàÅ XÏ çDÏÍ!#s4·3¸)(RãÝ60*\¸„#áÍ[äÞHpCþæ`,?\—Ûœ'w·²;¹óÑ4wV#‰æóÊ”ëdÊ |Òî/5_° úEæ{å¨9b­†»q™î9ˇ¹ r»ÁTÙûÕÆ÷Ž¿ô½`Æ«Ÿ ~7åïƒä¼›À²¥+s¸àÚ¾OFˆj†ø˜9×<` ‘ð þ;ë „W·nÆ*œü_›å›å=ÁùçùLGÆ\GÀL7ææÇ,ÄU¼pnù͹Ù-F2H¾«t‰þ«YoEµŒ Â[#¥ï±ÝL/5VæêÍ 8QBO¬V±_ ‹ûÞrƒâpºƒ¶^`é¡Rª é$½&Út<‘y›Í'ÌlÂ~?¬·éSÏ<›=»sÉ6zG£>C¾æ|™GŸŸî޼x0Ûïî¦å¦`îšMææR».ýÜwŒœÌ iïûÜÀ÷g•óô|¾:nùžµŸ§|*nߔ֣‚ýµ™6úŠ*±W¿šÄ¼ìM3:wµŽvÙI¤2°‹_½Ð‘òdiW \5—[{('2½žTÓQÇ OK>.Ì7kŒkÐ]é´„¦c+f™ «PBJÜG2‹K¼*FlDåƒVó 5‰õuÖ–ls‹QU‹lÀ[Ö^K µš)!å´r2L à]²QœÖ=³,QtÂ1«íÐk{•¾ºgÖ|1ý¸u§T>·zöÕéÒl£:W‚/¤õ¾™®x1²+™È!”óëal³¥V#L qÛò%ŒÔñÀRÝq'SµœëïE4ÛT8™Æ°]_ ¤t×!î~tib:3gÓ0 Xryz?V+m£êzÚn$e\4È+kTƒ`ÕMÕ\c¶”y;"REù¦»FËû2áWÁ:Õ’æ’©Ô­½}9UâYf`Úñ$°j)méXiº>•<*g:ÑF¦DLG<2D%Çok×Y ½ oò³ñ ŸvÏÝ2²+—Ü-+¯ã!rJHÊâÀŠ%.[h©ä–mŸ76¬A¦@Å/¼ÃpF/·PÖ`AUîVQ>Ÿ3eƽPÆdV¿ÊºíŒ¥1å»\P„à GöiggÕp'¿F*f¥'½ü&ïb>_ [ÁIʇ똢š-ÌA(ˆâÙº$ÍJßùë4~›ÈS¿r²Æäx<·+7–Û*ÿæƒ=ò;ÂQù]Á®<"¢Fr™Ú)Ü!2¶ZÃ;.=Nmˆ§Éi<ŠX9[À!à¦7ÞQýKJt£¾´ÂZhGTVMf€ƒ{ÃW£Lk 2 tK­8®Ï¿iÒ¿¸ß«Úi-©µfZëš ZîÒ~›aBü\æô$™x—g׆=(!Oéõ½mú-ÚT§JiZ~¸ŒYiÌ’eµªørÔvÔˆ.T›Ý“Ym§õ¶Zc…ÆCëÁÀÒ6g¤L¾X·U4Öµñ«uŸø†$bdbÝ/ßéT'Uÿý­p}6ïü­Ã;scÁÖuâ s\rEø`jÛ®†öT(¥øëÔ%»…®¿Îò´+õ¨áŽ]-Ä×V ð걑LèTcÚX3‡p(·_·Õ):Ciª†+FâÚí¸k€8sðWòÞù5Îê­©x+?wПÐÖíµÅ¹½tÊ–GìÖ¬êì ܨRžv’»Çû9v›4ø›y“Ú©Ë…{{{íOŸnR'Ž:ѵòxr\07Ͳ›¶%îªwg8à¨7ª¾Ž»}Õ%w³®B1=–'‚_,Ø´.l¬âM- o`GTaH@rÊhF>WHï蓌”ƒôÞ9©wkŒoe¡2S©éãoÌ>ÙÏ™À6H¿ë¡2€K‰é§&I]!ð P£O­B(£§¢cy':·Í…:–oÄB3èc§ß—^A ñú÷Žp);8·ô8œqt‹&cú`¤ý€‹´×ûM¼«!÷£<âñ˜‹ºßÌ`{9Ð{ƒ¨ûòÙ HBñ› v~D *J¥q³º$:IðE2}‹@ÑY÷Õ«Y®»?žHG{B;½ÙuZ_àÖÓI¸eâôZoÂ'³ï¤ôä.SJc¤^ÕßõÞìÓª¦µHWÂfÚ€µ(ûWN ê’oh.¶r‰{5«ü¼BÅ,/r¥ö¾‚j”õ2¼’Ø•çpƒ*$|ë|«iÇ‘˜8ºÆ#ð²Z³ìqÊ}†m”&¢É¹I™º}wOÞ½ozzÿ)ûóUû’ÝçÿagãEØ{’=ªà NÍù„Hˆ‡1c;¿_#mÕg™k­µ’òpÄ絚èRé€ðþÝV2hÌó˜^i+î™áŒîfwÙJÊI'ìàý8«àD)C©b@Pí¸jb¢´§‚6XR&h­öT¿y(ûŸxÙn›fgôoMbB­ôNÚuj…¿œi=JË/½°Öþë-ŸÿÊ0Ç­·ŠÏ´­ä®¹TŽS¸þÖ¬!/QŠ•£:“Á.*K™¥Ié)¯OëÉ-Ùº?ÍÚßÖîŬòôª%Ÿòþ|*Äkn7"Ö\âºndì/7š®6 ðgXhVŸ¼ uhzâžoðˬUî™Ïõ}úz¢ÅÖ…È­š7ü¥æËÆ$½ÍÅ+Ø‚WxmG[~»|ï/óÙèfÇì|L_’Úu °©]wij×ê×·‚©¤´ì‚ײï2ç–oN+-rdÎ"(?ˈz¬0ÙÂë½Pöʼñ¯+D8Qž5A=M¢ÈxFVÎb$˜B[ìàáöµ©êÖ5>Ó¢­²)nšNÐ¥Ÿôݲ!™OK«¹‚¢‡4mû:ªÝÍ&µìeÊ8ŸKBج¡&@?S\íº‡:­C°ÇoQí QœNûES¢gáÇ&÷pÆcoJ†‚gŸV&׮ǰ‹h¿ÂE«ªá÷”81ºáØÙU“'(á ¬­i:.¹’­è“-¼"¯.Dk)ž¯TãÍžt°œk¢æÂ´G×jº#HìëÚÞ*-l-8UQÖ¶7Aj%M)Q§xÙ’LYd§¥„dØDgï@ØÍ2£|yõÅ…^c¯Ôœî ˜k.X^}J‡±Gs*¤P$‹p»X:OwDÝe”ÎÛ]+œÙi&þFœòÓ®$ÚÖ>_[\²inÀÏHƒÔÊgœˆÄvÇÂÞ– J£Wÿ~gÚÅ>4ÕŽ­o ÆsQÅ«ÿÔôÚ.®ï·dRp£GÐü ÁuÁ(l/.èØ#(v´Æô§S .ÓåfŸ]½Ý–g°ñ.û ‚‹¦}ˆÏ,â®ÚºæïmùÂsÖÓ›‘W`5¿j¸·e‰RîÑé.÷ ŒW±u¶ÁúM„²ÌP&÷“OU×ï~J(cH([´›Äv¹½R.´u‚¨R‘V‰¨Õú}ÚPwä<[6AˆœÔwqÝÜ Ìùº¦æ]%.ˆÛ5­-:åIæ1åêk4œJ–ê'ƒr5b°q0qk¦À¤;Øh=–Üô·=Ãõ²œmÛgh\Ì7áç® á¸¥ÕÛ .uc ‰…æCI¹=/É^oL*_mWbL=›Èkÿ«4xZcª®––öwL[½öB]žn]¤70Ym©eá Eq&0kV,YˆãÝá´¾ÌÄl«ÂjÁ9…“~µ'RŸf¡lùœ5M5òÙ `Ñ X¯¿ƒ‚’ ídÖ•LçËùVkÁºc±õ4`x†ÝNª¯Q&°¾nuæ2YVHƒ‚%nZ9‹„ÖY ê°Ú§[#¦ÆSmÏ­P¶¶òZ†ß¤7p£'ó®~³žç¥Á¼ü0<ªfs'C0Û[ ¬îOò,™wv7X'£ÙÓÞ‚ž –·f«d*†i¶ †½Ò¬‹<ï ªVW±Tö*ÑÖ-ò6geN©c’òxÁi¹]HéQÉìvóÈ×:µ7;¦Ýªáyw›\µšÕÇTQ› ¢v³«ö¬ë }LÔ´7›sÍíðwkVÐl`vi`sR¾añ'›‡á¨î«Žtg·¥©,5æcU²ÇnoS÷•aÑ4oÝceVI¤øiwü² £HžH,_r?ïqºkþ€]ÂÍÐwJ¥Â©{¡àŒe¹DßÛœšÀžÉëºM–„ϼPyúè“§Ë4·Q¦¡‚J$µ ŒƒtƒÎqò½l„C øÇyË'Yi(Ý5¼i¸0:.¿Ã£»FG‡‹Ã£Þúõè#æê»V=°,žÆ´¸p–’Û®œÝõDY&ìw³-ðÞí(D}P.š–\‹¥l0™¸(÷h˘e¬ƒ¾ä”½©lI¦»ZÑF¸qJ%¨ˆvÈŠ“à³Yî d›Nöc×&Zíú\½YmT8™fÖ ²Ñô -KZbøŒŸo¿>{y}«Z°V³â˜_öœ[öïèZöp3ë&®nbÎÕMÌ;ç×5jL :Ï—/05NoÝ^‘sx¡VUÊç…rR¦"­( ¢”@¨ëåj©ºõ–FMÀvoïÁö¢"\iÞõÕåfgtá"dÍ ÚS—taÍ-€ zåYW(;på£s©BÙØIÇ—¾ë*Lj·*ádô¡Là÷0·sSiµ3^}/¸ö.ð?Êu¤ökŽ.Ê«”Æk&‘I‘¼Ô˜Q³-ep˜aÝÚxß襾Üè5ê¼ûñ™lp°ÈW®š(Å®#©¡¯ÃP¥ßæý_ßPïKõÚ=¯9Þâë1^H¨ùúÆ{{2ÞÞñ¤ z§Æ6øzŒíeiáÛÖÛ«CKTPc¾^wÑÑuÕ#gj—_ÜÄG>™¤ bòZÈKÆônOGMbéfjº¿w%V}ÛÿØ‚gŒ ª¸R•¢µVñûJÍV †iûñºîä©Ò’hlHáÐý²Ú-AƒÅ8-9'&âýºŸ ¶U}Ã>ánSñ˜›S!fd$+^u‰e¢ã ®uÚk¶ÌÕ:Mañ¬C[Za«”µnµñä¦~2%!Á<é·ó‚ǾÓò¯ž‰Úç«K1ómx{[+ˆ¢ï‚…šéu,–ª¥LQ-]ûqµjs¤v¾Úœ³éx]]˜á‡;Î.væ…gž8}ªrâñÇ+ÇŽ{âDÆåv¡Ú®“ø n3K¶¨ ¢=¨«þlž±¥­¸g ŽD¬ÓØäqc“×(s¨ÏC®X3—fðDÈdPuV`L¹ÿ¡r´aEÚ/X5¡­Ý×éIIõ™}ø>¯æ·ÛrùÍÛmÍF_Å£ 6 SÝpiœº»2$;8º"š»->Â"€k›í&[Z¤q«+ÍXdŠ”Ýôn~Ð)ïaÎíÞX`r–-ØñÓ¹„wÌÄ­Ч»4yذèƒT°Íz»| ›x:I€² çõ)&³)s+#=À}}¿ÍÑBßL‚¯³S(AlM¶‰;¶ãÔ W;½O½žkVLD›Pãlð6»£;¦(yþåú½e*wÙÇÉ¢ÙÞIiro‰I–6OÕN ŽÜ®U™„£TՇċ̙a'dÑðJ3ŒÚ{µ?ssûâ´(î–é*é(ö[L¬òå€Íž…$ÛûHî´“ÙæÈR"ìù¨ÙÙ8k»ÐXưì:ØV¦!ûúA[' ' *|ÎEM¸µ\=~¥Û-K)j¨Ú\Y*5ävbF'ß9ÔY\ÒYkxœŽ;ý©{‘Ûâ kØY¸1r¿â³<ZkGåbµÝ¬¬4ãêlTé&<• SìZLYö½ç-û¶R%æ¼VÛÜaQÎûJo@ñÐpB¿jÃ}dǶ7ù`3þæÆÒµa½ŒuѳèPwý;`9t‡~7Teº‚-1ßvŒ >‚Ð2`t·Ù÷÷{$~Î šGÚ1ÔUyp—ß@S–Pk[Œ†Ì›nWĤk„hãÙÒð¦U-Eº µ†‘ª Ê ›pÈ ‹Lð<ÐxE0\`î° c÷ZK\íK]ˆ­œVšØ ÁðMXN2aÝh¥Ü8ÖŒé±ÉpuÈF×\uE®]åߪkðBL–ÎUíîC+qÊ–g^i¡Ùº˜ô;Em{B"ÏFQ²CWTºõî{ß̾²$e z6â1t§´=J‘%×>Õ`Ï>4 Q€¬Y(«¦ÃÀf†¬4€ˆ–së[9yîô3OøãÇËgÊ ‰£Æº1ž•…ªAoÈ;*ÂÙs¸â¹¾ŠÒ `¿çÝp#o,‚mÁõA¾0¨‚Ë^òÖã Æ>ÈSgÚW¤}Tì®tš­––‰xÀ^S"<Ú¾µuâd…wl?S@fKÓp2uEÅ¸ŠªLbä^°ç#ì-Hãªÿz~¶šÑÖG•ìU)W÷%ñQZh¨¹Ö9ïÃ}« e*¶¡°•ÂŽr/³Õ4ê&á…§O=õB©:‹*ÔB0,$Ï­us(5®"ާÍêžUj¢ÔšFž:ýŒ~¥™ìK’ >®¦’“¬>1@¤Ãžýĺêf.ŠwwZØ1{F0A3ÖÇíÐ0SeÒ 2I 餪HÓZ³b>óruRÒnÐ.všÀp@‘‰V당õ¿÷i J¶ÁŠãÀÖB¯äI‰â,Ân¬)‹vå‹ýv4lÒÎ:8þSï:Ï]¿NÀæí^×PF­Sh+ö6x?©t÷{ˆ×·5F)wªTKTðòóŸðŽN‹2¡&˜Mf*“‰"'Ny4`眶~[àkBCe±« ¬1*#g†ÞtLJgü´¢nŸRIñNˆP9ñ8 U£¯â2=ÝM°§§×%Ù•ôã´µ’`H/Åq©«›ÛSƒŽÁr­ÝÐU_ÙÌ&‰±¼p/u°â¦æ~ôTïá”é0W–Ò¡/ŒÀÔ/ÏÕ‘hQ(µ¹ËK‚8y.ØžB ZOM°Èau¢"é–Û L ʦ§­œÀ8ÒRJ5"»áUV@‰•ƒð*ùò•lçVªíªHéQ¶îÛÕ>æS§­x ‘ÇZD5ûÅtðá©V'º_‡cu¬”¡[ÀÓjt:¹Þ·åšr>'”ÝN¡¹ãï|/|D>«ûÐÕÒ!“WaªÚ6mJj²ÝíêêA;·‰^j¿mƒ´¡-p7qê$©x€?4}¶Ã½WZøKïAÝŽFó¯´ÙÑ£¹”Ô}\A'»^;´ãd¬G–ƒ–†(§D m¢.&Ü)óÖšWY÷ÃUAm‰+¶P• —¢t1»ÒÔ¹ÏÚµXDPàœ²†‚ˆm5+õ·’ÊX¾1U4¬Î›Ñ‡/ºh°utŽj‚«=ÅE°òµÆ ʦ½K””E0¦Þxžt x¶Ö‡öä.Ô¯wÒÉ:t”j©D[x»š.Ü!òjaM~¾4aÇ'ê¨îëUjÆb\kpû•)^“Žd# {à&«—§û¼IÞû¤…ë¤in*d¿Éˆ€õh`L\cºµ|+t8Ð2OË5•þr3ð›cl&Äñ2¬ÂÄ-ͳ|_mû5²I +ën,ŒÈ#QÒÿ¹atÏøuÃ;†¯§r‹/…¬ÏµñDØsÖ?·‘Ë^ØaýóŠ<¶¸Ôjó¶ãYQd>Â-Ø/èw¢ ·¹ƒíî`§ wÙã9nÚ³ú]-tż˜³™½á&nIÒÔ o¶¥¬´wéý{îÓ¬÷­×å=º•Éò'Íù{lÿcæIÕ\äÝ;Û_Yñìò»Í9‘ CWW1Ü,4µ×b$ù†¬‰(cWPc¦SM]ð„Ç‹_«lƒbB®º@ª0 ß9Ñ¿[cZ’º0{ÕÒèÄÜ\¼7-†¬¥•{.i‘dàññj§º7e4gÍYÐU¥TàwPé]‡'5äP„OhÏhšîS¹X½3ûÍÕÝ Ö|ôÌ™ãGŸ9ªºòÙ¢?Ÿ~ìäS'˜¡ÿÄé§O/Ÿ|îezœ9*ÊvÁžÐ$qîä©ã'Ëelg£Ô\p'È3B›âÈ MWµdV@ âTïH“z®Úçºz®1Óý8Ý}}©÷ŠUê[î’ýP2\5OR;Zaùª×“h]`M–Õ%a—0)!£Ý´©¼ÒìÔíÎê~/¤êÒRÛ£ê>Trr^æ$fô!§Y¡Š+&ÿRµê{(",­·ØÐK3˜gÔ[ñoùb>¯»RùÜx~»6Ô…¿97+×»sùuêXŸè¼«ƒ ;cÞéY¨pxLs`h£kÏÔ;”žm­2_Wp*þ†Á+’#¬½¢eŸP†¼ÚXéN4Šv½vx2Ù¢X•kó³v/ÏÚ÷Ú§E´yÇ;šªzùÎC÷M¾tGyŸgˆØ}\Ë:®ÌlÌ6¹åo—Þ>à‚?üŒú”¤þ¯]ÏÚËž1¶Þp‹û„[èuÝÖëÙd[/]^ÂÓ0º™8k”p:^ýê¸Ô½É—Ëÿ3t‡±ÄhYµ^B¤Í–ÇJK¾m²Dù$®Þåæ¾ü-+|ñD¿'þÒ .¦Ï]lGögHïY¤µ†‡ìϽ&ÀÞGAlß«„éW Ñ•}êÒr{Ù”æ’0’Ü'™…Wýi\ÔŸ~fiÔwÄCßûºðR„Å€¢_o-óYÖ¡á¼_JÏ»önùÚpj;ë´èÙsæ©CQ\«.©L¼˜Ì¿„î©NÜõÙI—¹Ö)$Pë¤p7ˆN|·´ÐLè§«í…¨}6 2x ˆÉySwkàëƒâ{/çðˆ& 58‘ Q8¢‰aQ¯È£$ò¨ˆpÄ#Sƒ&J#›hÄÆ#^á™ÑJ¼ÂâÑÝêòŠ2Ù /qº™§ãI\#N·¸Ó-<ÝÍ]0IñÊ6÷Àvˆ·Ñ "rÿ‹‰¶ã2ñØ÷ØNžît§»Øá]î”›kBóÉDõð=æ»àGr…?è]à~­2¾¸êÔ$ vˆéš|Õcæïü†unÍwŽ*×Z\qö?Vé³Ârv3Q³ìùfßs )*©AãT`«£`!ˆÍIƒ¶­Ó7¸1•?Ø%ÝJ™’ˆØœbŽ›;]¬4E/Šh‘ó-ν;œƒ€Ý$yd›aZP‡ÔÍ×§„ä’Ooê&ñΜYÞÃ01ƈéÎÊ.]:Oê(´Ý>•ÂXfm\ÞÖtéeIPžg4!¶ZØ– WjQù9‡²²Ål¿k³F°—Y‚m ÏÔV•^ùj'Š;ß?àœx…|ðæÜÿœY,ÿMH¸?€ŸÄϧñóCøyζکI*ÿ~6fr”DÆ»ÊÄx²æ¨„{¸ã†5ÒåLûÞÌëM +ÀåcNXH9B]\ž¥qÀN†¾'дb2oÆM^ ¢{bq©³VòÈ+ô\î)ÉîFÕ ÕnoVÛ–ôìeR1±œ Ýi-عž:s´Ìƒ²”?éÖ¨k1ÈP:Jú½ÕNkñsés›…ì–¿[ƒ¢"ý@\ÿÌdwèY(˜ö>€+¢§\p¸wAs} ²xºq^Ámœ'k°G#E±f²-Úá\¯^¢xŽãËÎa{}?„s|_XÛî–·`k7œkac€ÂÆWa#èíMåww÷§…d'0ôïJjg0éΉV›>ˆûØù*KÖ$Tlì'ÔÏ«-?a*byGÏåU¢š¨7y¨þ¦½”\%Wñ µ<Ó J?î¨à©£Ö¨ ÿykIÍz_0.ŽY™t¤l(!«îuŒSw%oõuKFŠö“øe€a‰`¸MÀòÌH°=ØŒrÓø¼[PŠ´§ÒÎ߯¤&Õ’å÷ˆ¤á舖çèPÄ9¢`Óa}–#šÉFáˆlЕ¨ œòhc‡ÛÂAcÄÑ05FPcÄÑ&€Ù€Ù(261eù'@¬}3ê6OÈô>; ãT&¸ãì#VªÓäÚ…A¯ûpæ)à|•¿ý­~vñNSHå5;Xìí`ù €ŸŸëw*º÷‡^9#>5i+xè!þsËCœ“ùû0/=¨w~HÍ6Ù²ÖAÿŒ7A¯-δåEŸ?Ÿ÷Ì‘Û.k¤bÄþ3§ÿ4ôâ\Tþc4ùå £àVK1§µÔ_YísÒþ?Hð%/˜¡F2ÆrÜj­'eéV“*-ž‰És¤ÜR]/§C_­%&º¦B—Ò1›&r×ä=w$ò³Ïûš‘-b<¬Š÷6]þï {½eÒRM!7£{ˆ¦g߇­Bzw´yV‰…ãXÝhû ¬Gí}¥ÅV¸Â@ Ü+%NÞJNJ©˜OêP¡’ â£ç²ŸÌ°Ö~­ßx)zÅ`§AzÆnJ`œÑÁôŒþ/¯nFíDj5<^Ï;¹H¸÷8"U†=”éo‘éV¿ß˜ò®Ž‹•ãᨲM©ñëþN¨@×â/A Rª «ˆŒwËY O­˜V‡Ö[Gdý=ÛÔìZ¤no3#–U1—ÈER×XüJš6ãû:ôÊDê‡À_þü¼!,D̳ϔOžzœ6í 3‡lÒñ`tX¡bêöX•g„ê'€ý-ip;ì6`#¬GcæX°#”c= 6Au^3oe¿_ÅØ×8T4­ûœêýhr^pç!Ábu¢õ“™íÛ©öîÕ÷íÛ‡¸pó¢z»»¡.BªD±û:ÿ@šÞWtá‘ù-Ttzêò³,øô—ÿ9~¾Ë¯÷“øùü¼?°ç©Tû™¬hKJBs#˜yùïãô)Ǹ.ìNÿ=ß*­^Áž4ˆ#ËgeÕüøèø¶ñaù32¾c|G>G©þüpN®ìè-LòOMWa’,L²“UIv²$IàJ’ä\I’¼+IRp%I\I’¢-Ia¿Üp—YL»åJ•Œ›æ°+Ì?î óoqEJ¶º"%Û¬#~;º§vXçßÔNëö›ÚEoŸ[Ný|S×Áɇƒ=Ö¥7u=h¢ÀÖFÚu%ízu¥X3>oòH]ñQ'ζǴŒKÔˌًb0TÛÛ_6Ѱ=ž¡i±h¢MÜÊ{.ì÷M+à%ŠÏ6ß1^¤÷ƨYÃfäA´Ù¹Ybf~ܪˆÒÀlÛ†Èw71³Ã·9ŒýÀm›1C§¨²aÇ¿¥N|˜-NµJzn«`ÝÞ&xŒP¡Ôß±òï9u;Zj´)$!¨šÜÊMîÁu·UÐA5Ú´ ‰LýGøAEC¶‰t¿2@ƒf=D“°É2*_«±ö -ïO¨úoøÉ9¡Ý׈xXadÓxrîqôqB•u†ú•ôËd7ýY¸€êÙ›²0lnàfö#ò‹?c¹-¹ÛsëíuƒiÕ‹”‡bkÓi>å’­8@ƒ­:a].ïJÓ%·ÉÚªv…Í«#]¾í€ÎÉÄe )˜[ Yìr¢Þä_ï1—ÿu–Bõ}€àDïùÿóAç?`¶ôFC¿q{¯Õú¼ÊçÝv´èE\zA« ˜-3¤¨ïÕ'¢-ÉûÏA§>’p–"8Kx—I‰¡Öß›Ú,G¥ÂŽ“uÝÚRâ%ÇgU€j§Ê¿âB[scÿZ+Ò>÷úÄþ}Vb6Îbñ§Áë°öÍ?îMB¹¶Èúkj–† #~p½$R¯1mŠì€½fZ)ìTÁ©ÇR#TVÂúu°Û¸_UçÈ[ k**¤2M@…p [zþ‘— ½T¾÷ßNøÒÂݘ$l!ÛÔæœ†óîÏx0:0<àφw èŸLù£XyÆR¨vÁ¼³ `lc²pÌÕFHJHTKêíÎJµ‘*‰Ò Æ7™”=FÅ:ëŒwa—t÷n¡¸³9¶6YYª,µ£ÙúêF¾/¡3[’j˜~ÈÖRñî2' ¥Þ/»í‹ò¦ýQ»Î“Pžö"+ji,bà섃îâµ"Ú€âaW dÄœÑP1-¯9Ï }ÿEîÌ&’æò6»2ñýFù:"ˉÇ?tòÔc§FCQ_­oöÈÑ càyBy+Kœùw#‰ÀOíV«£DÒ—‚Ñ—ÊÑËÿ¶ß„ò?Hƒ?Xt®Ìü0ãŸvÊŸë¨; Îê"Dôÿ°!(ø“Ò§åVäëE¬^±¬Á}ÀÜ‹Îà>œ£èx$Á¹8UûÓV¦N™º{Ê]UÈ0Ž4Öe¥åÉ~v½ðkèêæ î*Hú®ÕÕ±„²õZhÐOÚ–­Ú½ÑRÒ—^É¢ÜYϜɮ\§hoÏèðV“ÊSøØ!ó!Q® ö~’ϼߘú}·4¤«ãÓÏ ê qõÉ×à>àîQ|³„M¡X`ˆ¹ïõÅz£Úv뤋u)J•“NmÖ‡íàÚE·‘ © nSîÄTÌ“©;) ™Ý!]£ìYìº^õKÔŠ£¥ªæ L´âI9Ûo·Ñ¶•þ¢µ¤žî¸=Îë ””e"ÜÒÚÒZªLjèÓ øwc†QEøëKûmqÝy"„r Óú Û ó ·‡z.XÎ'¥üo` EkZ3)Bp¾#Ý}T4r(¥êuÇÏäjõööÑ—Y°¾?°Ìš*¢äÖêRûáí°­X°NäÃî«Ðe}“ok*™èL%;m2yÛ’ä)’†ÿô£¯<[øo1϶äÈ’ºIC‚þšaúè?)ø¯ÒüzU!_ÌoïàãOG‹-T^—øôýý½Ä`¾TAHsá²ÝHávGÜ\ÉsO,ì’¹k(®Ë`FODQ¯¦7÷ì‚é‘ÌÈ;)–Ú}Is[÷Í8-yÁhq{û~ÞÅ æ­@ª/<Ø4þÕ!—}ΤˆÎS²ḑµ}Ã"vIÏÉV¨ÉS¶Üm]©˜áT}¯ #/—•ÃÛNÆ\ajl<"•ÿÊ=à¾Ó¥—s9È͹~ÈgÿܱSØlËÝ,ÚñžœuAüþÀFAÓõBÚÊŽ³™þÿ_J«ÿ9üÒ¹òÿtUZXЯ¡,;@ÊAÂYl«¡_–þ莠Z”ñ¡ºËjÇן‘OR F<ï‘d.½’ ÝP• ü!íJeÓ`¢,þù>m6ÎÕe8óÔŸyÓ©2½”¡×–`Y.–ŸC)ÀUZû:uCÃJesjI"ÊNcoQ:¢LÑÛµ;)ËýG íÚ­W¤É &‰R‰O¦)*—wÚ+5”q@ KÜÙX-ai©ÝZj׫¤.iyˆI&7­¥›<¶¯—±AØî}ˆàþJй!zžåÂÅj{®¿iMcÒÅ­ƒÎ_P€)|]¶6Bƒñðþc5†_´ ,m}-ògºQz å×îµãOQž¥Ô“±F1Ÿj ª–ޱæ»(Ô-.u« AÝæBP·»Ô.u§ AÝåBPYâL¼³èJ§: Š!¡A¥°±ö¹˜«¹çóÖ„»;"ªxK2 ƒ¢,×AŸÝ—BùÑÿ$0 CøF[ÁKƒi+xOØÆ#ÆX¹VI0rßÊ#rÉ•›é• ¬$0¸}¡²îGjê¦LáE!Eeá³¥Ûc¥b°–·žášgU˜£1R¼DÏèòõfã¾oÐA7¼éPºÍÁ¿Éo ¶:ŸkÆÜzJͰg¦²™·ävcâg–Ç€½¡ù!»oéHŸ¡{XrÉÕ;èšÈ¤®Á+ÌæŸHNé œ¸ðJâÊ[sèƒ;ÈAÛú,ÀhHwÈ9„9eÉ–üX°'¸%ȯ“Õ°ËϪŸËù|ÚîJv·Ù®WÅ˼”p¬0·a|Ü¢(Àä^ÏýtCGŒÓÛ1?êG÷Ö§O•²¢±î²FÛ[&HI–f}—Y=€ãã/ÝllVOÑážKïAZ~Þœ³_qÛ±%Õ1˜hÓ³1ÈÄ~­´œ$Û€ÂÑtp6)C¦ÞªF¿üÂ,š”ì3ÒiaI¨ý X¹AK&R]M;sV©t»‹ø õ%mJ¹_Ö]Þ‘³d€OÆýƒïø,.·ç ´V÷x0ÜŒ¥uvÐ;lR>CëÈÏkÉ­æè—:owŒ¶éZ  P\=M®ÒY婱èzP·QH‹ 8Ô—Fsw Óòrù¦œmÊ­ÅþÖ3ØæÖD|õ OHsÃ9ddûà:¿Õ6Lv—r‰Ô h'³eÝÝä|ŸC—À²"»ÝZθ-R|«9gï¹×ÎZdPLÑJ2/2ÊùnC¨[*ó’ÆÑµ‰àÃëðÎ&þŽÚuÄWyeÌÙA´ý;8>+tIÓE’ *øÞ‚èpkœ1vÒÄ3¿5i7À½m¸‡êaí ¸c(àlN… éÓ^äùÚVÓÙ™:?×l0=s~S? eP»²Ûv¥ýÙ »ïï Øwyî:ÈeÈülÐÙc_2_À“2?ï1L=<×¼)ý½?Ä÷ÐÇë“mí]&hü°üîmÅ“º½É^ÊY8_i6êÍ…½,ȘMùkÙŒa¿ €wò6K8h4C¨+ª#3LĆ7Ãhµ|}ÎôDþ ñ¦|nìÎÙØƒså“Ïœ¨œ}öÌ™ÓågHÞOžÖ`”WRG’µ‰MÇ[2R¡Åxb—¨yqTàLß¡ÅUʹ½ëk²ªš:bkª!}ø(wž JÌ;rÇGÔ†U;å[qi¯CævTmèfx µÒ™eãîÛÒWˆ)}û M¹ÆÅàæü–ܹb0žË£j°HK…ÜmÁB*·[rù`kn ó¨8<"WƒM¹-¹ÍÊ3‡Ó<óÓžŒú$‡¨y v‚ðDÔø.Ì'ÁÖšˆ+Zy|!oâ O‡@`•ªñ4>LÔV²\ÄÚ&Çí6xVð7K á‹îz_ái¿|þ}ƒ.ì£p£ÀI!6[Èi«·*xV[õ0"’ñÂiOÁ1†Z÷G@v¿4™ªÆõmߘ­í—³RU°|£‘ÿÏÙ`ã$3ŸÛÇçfµƒ½õ™x²³ÚaÒF—Xƒëj°x-/0 åÆœóU16m’fF“ñ`ßèп¯3¿GZýŽAkm22çZùû Ý 8S÷ å…Ö6¹É9×üA_Óò³HI¯ëü¿ËÎúñ—bç²w:± ?«ÏÛߛЕ¢úXÒòU— ¶žNû”Z fZŒm!‹àÌòc,Ž1¼œ ìCÊÕsËw¤Ö1 ©¥†`GI2U3;v»>%ùD:jH‰ÖDÆckE¤ö–¤ÄÖ ?ïsÜG‹¥õu±Þ(½ú¾AßèØM²XÅdu˜õ¡v ÂÜ€jŠê•©I“RQÕÝwÉið2ÕK‡Så®LÎvOˆÞ˜Q©#’Œô=h賉]b|Xœ=]ã¹ä|™©®ç|×Ùë\¦×}úÙ” ´ÇŒWȹâó^œ#%ìJËÓÎÑ$‚±°ÿZsûø®5’׆¤sϘ" 62ýèiûKýïöFgM]'mÿBÒíž:É>9¤þp²”w圑ý„HZþãð“áÎïöÒ-e_pWz…£®@$L;ÒóñOK ×cx·¿<Œèåáá‘ñÂðØøðð=Ã[äl«‹hîõÁ1þZC+˶ÀÑÎW[à¼( ëÒJ·V3*y›†Îj8¥<˼÷'¾°ÀC%¸\›{CŒ:ÜivÍìÝŸÚžÆmpYjGŒa`ÛÉT+p1Q.$‚+ÛžÖù÷5¸:v×íj¬;k×›sº¥¤Ûì[DZ -»µ—ncÅ8»¯uj'j>’¡±ù<3íò?i¬Ñ†ÂgŒö½1.:pÁG4Ò¼àæ®;:jC²²·«‹ 8^^z<ÝÅö½©ìŽœÓ0T>ÊÙº`Ôx)¯i™Ò¬…žñiøæ³”ÄOµx²`ä!ÛB\¨Öp+Os+Fõ€õqR.lj¡oÎ9·ö~β,~ßÛ€)¸lûkŸýO’¥^×ãNšü?\oT|ï;IýiáWÝÌGllç`/áÜ}5ÂéÊ0O=©âæqsséͯBo-.DÖÝñp“¥nºòB1SDRCÙQ[ åCx`¯ÉÉå•V<‰w&íNH®µýëQä3ò¤§È®‘ƒ¥Þw0ãô褾/5êpO¸ .%"ùæþwÜùR¦ yÝïî ˜ƒOÚMIø‡ü×úÎ>äö§gñÙ&Bü£°{Ú»f“„«Ìæ¡ QûÐÒ~£N s»÷gʵyÐÏÅ|«ÞL.ïsI%ûöï¿Öð'Qé>ñ$Í®3j²õóxMSc‚4¿!^3†Ù)]AÝz­ßœçÏíc8PÚ¸¶÷½TZøgîÛÅmÅÜ×€Ø%s5Äd¨ ÓKi§sôjdÝ×y·0TÉEWo?fKËiqhU¿ Øë² ™æhâ.®¨e{XãW|4Ç!|’‚ ºz;ª;'øÒ¨m£}ǽ!ŒêøgíRm›)c) /áå?däwò3×hßAæÿt¡Yù팾%7úz‚ÎI îAG„mFcrã’Jz5ÁÕf¦–Í ÊoL %ïÊnÓéuÚÂÎÆ%f6rc¦R¼¦Ô¥Tdž‡JÒ¦ÝT¬ä7PÇ "y4¢‹{ºÒ]{OÚ7ö–&2-²=+Úï·»«¯ÛAî ‹Zu;äóÕŽÐë*w‹¯–¼Mú]µ\/£\mb«îµzÔãÒôtšNOû'bA³•fèjâ2Â÷Õn‘==YÃIô°"=ÅsÒ3%Pø²ŠÄùI+m¿Õ©ý4ÄfæOk›ö޹¯ÀõYiahÈÉ?ƒ^Ôõú5ʯ*àØXòÀ…“眿Ó{^ñ[ÝÀ(õ¦´ n4û­Ž•ºP¯–¦15Lá´NÉïøyñÞQÿœ:@šµòÃÎG¼“"dÍlrQZ‚íÖ¥9h'¦†‰ùŠIE1Ø,Ñ]Ü^#h¼?xÞIüí'¬aT«ñÓû<h¹ôv™ï®Îò•¢-àyü¥g]AVìG+3pÌþªT«‰¬N ,´³‰nÌ[êã ¬µ›à¹TD”ú›sË3Fþ?Ç:d0êçx¬nâ€ßÈF Gy ´Ôâš­•Wºo©)j­ 66YÓV/žod5™òƒ å+ðy­ê!Éÿ?@~@ÝT¸þ°Ã‚Œà¡IÚY/ƒˆ^è,ƒ(ž¹Ð™—b5*ØhÊØs»| ?è:ZVf]ö˜>”/ö›Ž?&_»nˆá"€£mùB0Ê*¾Å\õ|w7')™ְˀȟ|ïˆúêìu“ls½&=™Ð^‚« 9l€Ég¤\Rû\*fìÈév—ô!S.^¢Ìq…^{‹CÁζF¤/ùÖ6ÙJÅWl=Ažå¹ÕïpÔ~êøKï,âmÌÍ%îU¬õoâŸs§ZjgOnÜ׿Iú¯ý'ÛÅ)Á'‘‡Xõ®†Ìo¶-ª ªvÆ… ¢‡z¶ký®³÷~­ šÕ_†’˜ûÿ6÷5Ðqå™÷g4ÒH#K‘lÙ²{ìDHJl™$$ÇŽãXJâÄ–+'Jb‹ÑX3²Ç’fFsG¶d*(°$@YJ€mi) ¥´å°Pà°°Û. [-ìÓžåÀîö–¥=-té9 Kw¿çy¿ï»÷J ?{Æœµ¤ë;wîܹ÷ûy¿÷çyŸ· AIu•ÇÝIs¥7™'hÿ›¶ÙôJðCÒçJ[¢]Mû6çñ§– Îj»ºü“Îuõ%1zñvø%wñcF‰kuްFôîõ,fÞjÖÜd¯½Iոɿw'ϪkàNÕ/0JE þ13™ýSÖRX5À¦YÙÁ ›HŒ¸€±9i;àò|I”¼ÒgJÅÖp{.ÀãCP ¦Õ>cSq]n2—¹M©e“?óSðE‚Anc˜‚¿cTðßñƇÍ8åÁ¹Ä™‘ðAa>€Ö© ×8w¥œÃ:Ùµß`yP¬R‹w'Þƒü’‚Æ•F}…ò”BQ^Ê·o öäY÷5ÙàŠ$ˆÖ‚î„9"kª7ènƒÛØÍµôxµÍíñzÔZ›v·{}î.·SíSÇ{¸—VG².rð„(KC¨ìëR^+‰áúã:¿þçP‡ßçÅÕá ß@e¸XRZ,P,æ]“Çÿ‹Q7¹©¤<_ž+€÷èK³¹ Ÿ2wz€šlžãâ€.ß0.þ îǪÖѱaór¢Ï¡i–Â’$Þ]Fa²YÆms™î"ˆDÜ;È¿g“ʹä²Þ„Îö‘Ò¸—ê¥RQ4ð2JÈWô%uÁÜùÒÕB%¦œ0jÿJ.¼\]š/òKy©X~‘@lõ-è yŽÙ|>W¬–4WgÁúó‚X¥Å¥òÕª·™+)‹à¡„º/ºäÂ’ä.l´æKùJh{xZT,m0¾m¹˜õ\®õoÑ5¯å­B¾†Ï¹äàÄ|$¨¼ïVöq•Né°kø¨ÃºÚ³§a Y·½Ÿ8C J§´®ŒÈ8õ»¸h·ÀÐÍ›ïB»è2_»|—,„C:WT>‚j¶)ýqQ IIá—èÝ´vþ“{¬‚ŸÃZ8õ ?H¹23¿Dê8ÜZD¹!5j+%ÔaÖ©;2l)æÆ !×—:<.„{GäWê0Z†¼žý26Ì0f-7%¹B®#§yÎ9õ:¸à€vXj䡆¬KýoÇq«Vð‹«§¿ˆ c¬EÎNYÜî7ÞfEP#×£:xÔ»ñ()("_¡a©M›¯ŽŸU ÀJØö¨íNµøBÓCU=ËW<²3B ÛY‘uM" œdÏþW –9üë7SŸo˜Ûf÷ûÕôš®Íß˜Ž»ŽìÄ®Ž26y ¦ßw¥Ö£ûþjÌÑb’§¬ñ²;>ˆôޝ¥´ ³Nϸ­G-}1X†I-=†Thª-ÕkÕ°®£Ò´Éó3JÎñpèÌËc­6;>÷~u…?·Ïîm¤ŽÂê±’ÕÚZÿ„ÔFs¸¦½‚kšk4E9åˆh£+‹9²p¾Nœh«Nqhö3az|£Í"|Šé­›è O8öl|hpŽIa9Š‹úãx+¢l`™_íPöþUC1ˆ¶Yó©DYÎe™Åœ¶÷šY,>ϲˆê‘þ[ÑÐè9Ülé9­.ø—QãtÑÎïJfšÓ»øÇ!’f>á,W"TëèÔËM{Iš÷5,<¥4+¯Ÿ4¨ðÊAfÛáÓûÉÙÏÕÍb‡¾ˆ:}A)OÏh‡9×5´ˆx²*ÕÊA$‡¬žšR„Lз"F¾” ‚p «Ì”»¿E T€]ƒ:Z<³ÀZžž/˜Q*I^zÈrU z4µ;ðU…îèæüãtÖës»<$z°.„· Ý2rÛð±[‰„W//\ØxlhèµÕóG¦†ofB5Ž9zlõ~õwô¨Úì;ºúڣñSoËï»§§äô,ò€ëŸ·{S”å®Ý>taDm‡o»5|·£CCÇÎh»ÿü«NÝ>œ².‹ƒxëj©¾ñ¾[[Áû„Xl~†½2”î¹}8ñîð±öu»ú?ÞÇ=ˆ1üg]x?‹<öâÆù_‚–­D¯õ\¦Ö·˜ÒN[ø›vÞà¡ÀS‰ñ?Óé”äÝ6| Gºx$cRî»Í íæ„›Ì‘s¤ˆ2¡ƒéŒøaê%ÔîSÃãYé…âU¤o#Î*úÝOâ´™!WˆS}*zsv…{t¾¬µ>*(bÐëya°%™Z´'@rï®´i 9ÔW2†tµE“®Æpup ž”ʒƯC•ƒjùü@8Åùx€°ér=}fô‰ScAÅH½x'Æ£v:Ú2†Ä ƒ·âÄi4®×Xb+…çfôU/qJ3'/°=›ï‘eê@FIÓýn‚ÝŠÝ1ëH­ƒn é× |º~$*‹¥ójØsÛï½+;_¿¨#™jhÚìtŠ9Ë55èB,2aîhn@òŽs=b/äÐ Ö|ɼX×Z¶Uc(ÀCÍn¼/¨+ìÊmÑíS w3ÿ6ê_[¤élH¼Ï Tƒ/ôlµ\iŒ°„íÐ@}X”¥ÎJX>%³9Z•<-€‹¨¾ÈªÉ &¶Ê–; •Ç"ãùºšçºÒoõ1“ÆÀÌÛ·9T't›Ù>â$2ählGvœM…‹Zåü«RÞÎ_U†F¬:lø¨ºØÙBànTIîD7q²gé‘\îÀÖ#æpîŽÔõWkޏÒüÊHê^V´”Qõ6Ç1uá&Õ,W+“…zE‰´ ŽúÜ`–ÇÀli¶ê*ƒ—eÌZ›êUŠ’+ÛÕ_o¤Ùü颓¤WýuÉ55G\xVvj;¾aÙ‘1Y°„óŽ{ÝcaëEZ³EFÕ,Ö´Ÿ£É~•–†g\|ý5t¥À¹ÊЈUôEbÔ§šRç‘C®ÇÎyÀK¥º¯d0þ™ò„lümlXZïªuÃ|×N¢%HãòýÍÖØ1îÎ¥4µGéì; ¤%.Dñ«ÉÂ7Yµ×ð´h–¶˜•vŸÁ­â.Ž€5ÉMCo¤Ì'½Õ \?R@ù¡aËó_HV¥eíZ¼›½xùz3Ò%é>l¶»ñÄ7©~|'6ýØDLMjcL¬c¶YÔ\àá”#Ê¢ÑæFn?-ñ¨>&#íþó®(E ëw0ðÌñácú “ÈÃû/œQÊ#ÞÊ^l‹Ï¬w81ODf烛¿èê¤dÉ\Œ:Ô7†F‹É9m±«ÔàúëófïJ‹T|(jÂ-°Ê"½ýø/­þkeuÕá-ºo¸Õ¥@$)&ÊsÏo2ÿ´}1Ög¦£xßXì´õ¶•0F‰^ F"Ï>Ä? Ÿ« ¥iæÃÜGÃæÎ³%ï·§úÿΩxÉysS¼Ó_"-‹Â[Ô✘üþééÃÓÓ‰ºðÓÓò=á”zƒl2#¬‘Œt>Z)^•Xis KàKeÅùA"´õýó;r暃|ìBƒS‚¶-ÞÛ­Êyv˜[/nÆZ‹*Áe¼O“êR½ºTGª°™p¡¦“P8õÑ{¤ÎÏúŒÌÀ6Ëæ°š2;¯6{i2zÆ.-=(-ÁF¯{K”@jšW‰v ¦"±kf…á‘çA%¼÷­Æ¼ž¤±1eù>e…0eˆÕ‰ÎP+Í„¢P´0o6ál¸Ól9óZõ´3V¯SkkÊ„7ëZç¬õ¿¼Ñ‰E1# %6ëËÄ-?ÑéŽN2"€@!bñJʰúÔx-ñøò¸’õºÓ”,Š-Í…¶<)𹇸Ye'ï>*ÖjTF–æ7]’x)Öø-nĉ–šZ0^8Æê¥…êU5Šwçgë…Kp¯>ÙéçYÊënÃ8MóVwC6 ’‹÷G¿¥nÓô»µ‚Æ²ÔÆ·|ã{iK]L½ÓXn‰Ê¨kËnC`y“!°ìáÕ²æj½|Ùi^n5d–Ûx¼ËïãËnór»S¼…åÕ]VUï1UÕ÷³Âº‹ÂêºÂú.‰ÇÎnÔzÇÎÍNq;wö˜'Ýažt¯Sìç[9§¸“;ûxÂ.^SíìæÁ[xðf¼Õ)îáÁ§¸—;/sŠ9î òž÷™{‚?™â¤¦›¬+Aâ +NUëJª!­¹¬^Xü›HÁk‡LQU>Ó¦;Úfš]ÑË€ïÔ²ZbK²»#H®)óVŠRºEûW ¶È²½¼ÔÖ”D'Ï©MkŒ‘q-Ò£†øDe®R½V¡û0@a©àkäλCËëBdÁ¼wÅLœàä ÜÂB[b¥DVï°§ÒÉË>Bùm/rªÙš#$åû¬æèo³^DüPeÂsbî=†V‡8-’¨E5ùÖ )Ͷ¦Ì›ëm15U%,µžA#Ó‡¤M¬žo‡ÑÕ uÙOÛ…Ægy>j¶¬ìÑÅ£V gn<ÐLér!¼Ì Þ {EÞèç×ù½øvG]Ä Î¹u`‡‰¤w}w³o¼}_ü¹nÐýÅÞàÍê _ú¹n0õ‹½ÁœºÂŸþ\7Øò‹½Á½ê _Ýä­¦UýÒŃ˜Q*é„¥KR[~ÈmS4Ó`'Äx7ú)PŠçkx ©æÚã¥6iêÇ,3ên³/Q°©é·KñßÅ؈ k CÇ)܆,…Û݀ƬZšeÇIIF¾X p -}B(çJ+âxç twòéö7ûépÁÿhýÁžðŸõm}‹²Q5ÄûV§aÖ­ÙùÆþö­¦¯\>¹ªÄ á‚çQÖØ¼&¤ß¥.ý];´¼.w›g1@6¢°âİ]H¢³”†ÂIK¿S8D%T¦‘Ò¨ñ¢A²=Q|•æ„|º6Óc´Aè0}du5²ÚL|žéI@rÆæ÷»±Øþ ¾&Nq=7ôׇ݄ Ô½X‚ZZ—¥ró¥K…™•IÿrµÂŒ—W¼âåÉ7ôÅFrOW—r …I7¯‹ê— WËL£(æBð÷WëJ=I|üd…®âòÌÊT•–0)~YuCó,¸yY™/yùHîd#qõõ’ w@Ô¨æÊ—DÄ®¾c[Kj¾´Ù½‡É[ ѯíÁÂèaæÖÃf€Ña|Š­ó¤Vnú͸£jõñš²hS‘¶Ö· ËH=€ b˜ÁgÍ<½ªš=€ª+‚1êIÚå0/!><¥6ßD¿V¨Wô·˜Éõ}ëÂsÅ…—j˸)/ݺ˳¡M+¸~}àz«\ïàZ~¡ts4KüèÔÃíEÕÿŠqÒÕGhK¸‘ñ°æIü…„’k–ŠD¾jqÄ™,²Ð‘€çå ú¢Èb¢ÖCB T?ßáàšjd¡ëG[ž.‡Ðäu¯Ì].±Àºº‡Ô‰Àº‹çLPSâ Ó6fnC›¹y&O3Ř’‚Û Œ 7¥[öýÍ61`[ÛMGj™Ü¯l€·ÃK‹lNøb¸®#ÿÚväH"ê"w@5è=©ë¦'–ÿÆÝèÔ§ ÀûhLà™ØôèÔ =0p _FjÏë'5:ZÇÁ=s&ÁB:q÷×É›r?‰˜Ž ?¬pê ШöÖƒö5xÀ"ßdB0µ^üÌã œÉÅ{ÈIªWPºHj#^ÂÛÁ™\C¡f¼ŽFŽäþ´óYù¹ƒ,§¦ÈçÕ9p“Ê"Mk”îÜßôÌHù§Øü6ïņ) ¤Ÿ}§G'Q\$övòºùB}®¹ÉdâÑ·¾µ]û=ÍàBîÂ~ÚY;ܬ—¡½µÍ¬Å‰¿äX:~¦ªè|oWǪìägvÖ„¸ûC‡¯ìŠN´@{rÏN.Rãµ…ãu…`â´6XÕIQµuÖSê/æÃ‡T>ú¤ê¬ÁÀ,¥O’²" U$NKÐkšñÍ%µn†ÐŸ•@²c¯f.K¬57[*4@1PgA¼è™ÎdÄŒíe›ÒŽóeü g¼ù¥Zü“f Ý„çÙCyï~æ£ì’mæÆÿ3h_ 5Y0Sïp–÷&áˆÂ¥Î󤻸WÒÉ×¹I±ŽOù™ØÔ'Äĺ§ÝÚ]PO7ÄR_ë8ÚÇŽXÒí‹0s&åZNœ÷l„ÙွG»IŠºöëVhpeƒà{<–¶ø¸£~Ù8¡ ~ywAAÙ‰ƒ5+ÂÀ2*–f Kó£Æ;LÐÆdjˆ$ Úá ‹ò©öc”1 ‡Ê!¦R½.Ù;¶Ì¼jꦋ–ÂL£|Uén÷µ[s–ˆû.Ú]›@!³x>ñà4œ„E¡z­6ˆ.šõ-D²Å©?¦{Z^nc}#4kü5d?E2@÷Æ`¨ùJëňÀ‹° ¨|±D{h <¨~k+a0hE÷ûœÞÁW[§Xdª5=Iåj·!u_Éê^?cRÆÚáõF–ò%Äé„MÖ˜ˆá›4Nth Ž"L7<ùx4­3îMÞFÛú´ÚYé‹ OuÃÀk¹jÖmgq ,‡°h%쌪JxÆÇu†àìì糋­Å® ¡½Ÿ_’8‚±(¦ˆŒU aêg}ÅθŠéøX'?ÒìVA´tÒv²à}jþ Åp£cgÄ1>'­„:±‹š7â”Ø†Ñ5„3Z‚Ý€5e³-U`‡]ª°Þiméâ|y†xB’·:²S.øŽcLêÉT†ØVÏ{‰zM³cլݷ˜ÏçíR¦½  îcɹ`[g]± AÚ>ïÛŽ+8|ò’c%ß!F ͸Áj"dÐÔqV“Rôh áØ„>çÄàö¡Æ¸Ã¸ü[’ óJ_$8o4 ÿàš£Ç"1ZÈMOÇ4¬éiI+](4Pyz£€ùÂLc~…w?=:jsû1L¼3‘™¼Í5ÂÕ"™bdƒÔúj¥™¦¶ôõmóhé6¶ô·ßëóì0²«Õ¨Sšâ$lZå8là§|Wµê¬k4×8nQ·íѨm‰ËÃâ3@ (vš0’iä-”ÃRNøJXNTVq´á@D$ËÓ>Üe+ºˆáý±¼œ˜D’Pck6®(@™ã¥¨I{˜'½1©·¶Ò™“•»¬áú c«+‰]jc˪áSR†$ïy>Èd½j Ö”y"06oñxSÿ[A·÷œ®nj}"°7Ðj„ÂGÀ@¢‘1vÆr¦q³èWDc'`>ÅÔ1â½XjŸkj\Ã`41Ÿl i7ç!÷%èbcXiQNë‘dÛÅ š*&Öz·ËXf#NOW+¥éi™Â×^¢šO-ÿæv'QA0Q iÎ%޲–ü»ýæ1OÝ­¾¦H¹äˆQ»Gs˜ÔŸäºB¢ö4v^í9‹÷#\¾üqÊÓbK\3UÑâÀKý­ÎÙÅ*_Ki°ª6@ÔˆÒ/]œ Dîó|WÈ_µ£¤ÝàÜP>,m^ .­~'×H»®Ña <ýòi¸©ë³îÊNâ#;‰Ÿ#ÌnûˬMVzÔ4ÝÂi:Ž¢dgwºº†ÓQˆ?ü׆GUÇ'‹ µüd¥Gsai~vÄÐrEGèÉÅ’G%f6TJÊ@ARÁÚN–L*u2ENÔu 4ŠÑÿZª,-”àL– öo8Úd¢CG-Z3sÆeŠòK³Jåi¸ ¹&€T# AÊÑëg+>E†”z®I³£lYVRµ¬Bb°}®öõTš;Éa÷=‡Q X½´›òàõ½Ýë'uÊ.ÆW·úiã^§›ò3Lªèt[¼-^»(Ü ÿέ(Ðû½æp#GpÑx¡6ÄÌg8?gÎÑþâßÓ‹¤¨(hÿ¨Î¼PÆ´ì«¡ Ãúº³ø¨^)‹mŸ"GTjíÄwú‹icЇTÿVäL²ã×M™Ê‚â‹ü–¹ó5*ï´¤1ÿ(KeÞ¸d+‘WkT«óáO°É…P­å™[ƒ#t.'ºMW‰TƒñëªÁY{[(}àž¾Ñlþ‡¢¤ „‚Ü—š´í)u¬Äø dnmøÊpݘ;Pb:G=ë˜5êývNE\DÏX­ž+š°å†áR‰ñuOëÊ6UÂZð1O/Š Õ"šÃ¶ÒÔáÿQuÍ?ÄðÇÃ8n——RºœC»VÍÒ¶‹A?^ ×.˜éÖkî ¥(wiå£hkÉwUGN<…:wÚhÆòúDÏAº~®ƒâ% 6K‹ñ3hÃOaï{F´Ü ‹ú uÙ/ÇmGqí¶DœèEO;œà˜²/§ÒäH6ÿ~ÎWÑ|m? mØšæêåzrÅ:`R¶P7óÞžwâÞÙÕÚÊFëà¸PÂF¹±Ä”fÒ¹­äf.*—ÔØž+­\«Ö‘~x)¤æ‚3=W³!/[ÀÒ_ÉEÌ“´ÎÆcì tÆG#Æ*a1Řð/hÍ·]1öfP$çëí6ätuΤ&Ì»œCÒ' £S=†]t¨Ð2Ú“P“–·Tð,5wÍGû›‘f¥=ãÃøÎuðX½—Î1.ÀăâMãú_á%R¬D@A7¶B†ˆ,Z‹¿á™ùEgü^ëôü06,*J¸9ç¿‹c¤…GËDQGtBpîÿ{ÖP³T¥ïFpö”C¸¹›öí̶ûnWwW‡ÔjâO:ÓÚÕÖÕšÙÙÕÙµ5»%Ó’íÈt¨£m™´:7ÉdZ³ÙL*;”éSÇÚ F€êde¶TY`6ºêAŒ§ g3`v‰é²¨kâßà‡Û ‚£QÙ†Ýn`Ø“Ç6üÿÀø@.âÍ…•ya¼9=vîøèñsÇC ‹¡ó†L1ïðBqä6¦&?paxjx£Ï𜓌†>håú™ccÚ¢ÄHÍÄ5'r‚$ÖOET¥˜Z&=¨˜#k­­¸ ÉS<'ÅNÄü3%¤JíB¡<|ÑDûx¹:Ÿš`Õ‡1Ú‘f !Öטs—߱ˆ/ËFq8%–Ì{Ö5í­¶ivÍYßxQèˆt*˜Ôù͆l2¶*uf„L+/‘Y%ÓË¥ð­Ÿ' fiˆ®(š@ YÏ«P·©9sÉeYrp¦˜ÿ±&áQÏäƒHúR©!¶šo¨ÌH•êb¨-ŒHTVV7'âÕNT+NçªV/”æqÇð}¹‹…g¡™£GÞ1x 7ˆãƒÊÓj*^-׫RçHÈùLõ‘œÿÀ…Ì2 Ç[y¶LÙÐ^¨R‚²Y-æƒdh³ír),ÇsÒÑk÷Ñ€“¤vžæÂG^¸óÂ]wïZ*b@(¨¾®”óœtãuZ‹GÝç±/¨ÿ­?a1ã$ž}þ“¾V}@ýNÆ?¤/<šøæŠy4u“³¾ÖšÆEdžîtAúÅjµ’2 ªÍ›/ðpåâ|¡2' šè±e5àŠ1×ÕP ·Ðàâhß<0ˆÞWz×ÁêìA°"¨3Å ÆæÄ™ñs'ÇŸ þÜ€®'ÕÚIŒ dù†Ñ$ÊüÊJ‘6ò‰3§O§3žÚÆÉsc§é”?7œ>9~üÜ™@Ðן0ª1ø¾QZÊ@Z,¶wÙ GËžÐ$â„p¦PÉãÑAVÁ(q”Þœ³íŒ¼özÏlqw{}nû« "ÛåV!€ÙH ÎHFa¡r R£$µDÙ˜ã&šø#œ3÷„Ž­Ã4&&&‰HØp£''Îg¤/ý÷žî¾3ÇO<6vNúÒ¼ÀÀzr,˜8yFTÞS'ÇÇòc㣄lˆ‚·ˆk}öÚ^PŸ0¶àõØûר»à$”9tOh¦÷¢Cþî¤{¼®[¤šM°Ý²C²ª‹nõ{Ô±w£¿ìÉ«ôÏR+]ûÈZ¬Í)e4[œhíXêÑnLëF´š¥~i]‡‹™'©ôº¶…aWñÄ”\zQ§¤¸Õ•6.à‘ßÙ~¨hЦ Q.qíú1fL.áïôt’}£Ã”é0(nßbr9n°4,9’'t#ë»ÍGzœˆ˜ØÑ3¹ñ3çr'ŽŸ:•;÷ÈɉÜã£gN·c$¤‡ìpçU>Eu³!7p­/wXxŸ2ô2îQ/ãîð` l‹°•Ö‹Keb© š4©OµEÃCºjP¹š(%º†ØD5à ?¢’GÔ¬l†ï%Á›Ý PDßÜaG þunDl!N^TÝ=! á^Âa)H5Ò¾Ÿ¼ÿ’û¶Ý @4þÿ”û®È°·eGÓÃëš´~‡nLiØ9ê¢DÌ‹ù-±…`+Ô5×䎒ª^Òå>â AÖ}ãgH•± ï™EK—ˆ %Ò5ɾfµÝê‚/t8‡zð-Ö‚sMÓ´:Ö×ýwÃÌ5ÄÓ>ë-s;?Kwû &Óýî×Û t6ØzZZj~¥5×`Vî4$L(õ#Ò+ªBÅŒ5{$J3E‰ƒ ¤UqY)­Z±tŠL1B3W‡z)Rôžô}ÀÕ¾ ‰‡œ¸»¯YM˜ì‡;Œ¯Ùë¡–Ó¦þ„ã$²Ó#B®(°ºÛ`5ýGxù£Dç6ë6!A¯÷IÚÍtgÒêÇÏdÕŸ·qŒv’¥»4¨¹A|­h`JzúºIñQ]½wÂ$ SõùÁÃ¥‚’ õª®½’( Xž‘ÿ‰èÞè©DPimŽíGÛ¤Ío%ÜÇ'­×Ckò'C«±wÄvèi^=\>/³·É£K2™+[¯~Ü®­jmêw;"T¯EÁ·|ØÌUCs-ósMÃÂvjÄ媔ÝÚ« óþ $›EÉT̽ÖtðÞj(O8[ P@§Õ‹Ó–š®³~d}ešx½rÿ `B»Iø·oNòxïš=!Qƒí3Öíî úšÄBþJ'^”ÈÐÇE…e„ó¡°ß±øNz3¼_ýÒïKh²ß¸Âx±bÚ„Aý AíB¬ôËz$ÜXÕÜP¨:’84èŠj¶ «Y£†¼x9ÇàžÖçLë2¯,\S½˜nú4Ã:0´ÿ¼>2µ_¢íˆŠ—ä’úÛÌ%çuê²½´T¯)-£ 摳tͺÒÍAj%|k$—;9+Ȭf`é˜Æ,Ô jæ3¨gl˜;–·¼kÖX$c4„­›ôùñ¦€,ј~qæ2VžÛ)Q Èd uÂäÆ[H=•dLH„‘\¸Lc9g˰@— ¬y¬¸#…’xîë†l~ª1ù¿Ö¡Q>N[šÔ§]tm±×ãÝäSI0‰,Œ“Ýk%¹ÄÏÞLç?=7¶f*C\΢ūæÍ8.&Éæ«a¾ZSOIgjiâS;‡²q56ä%Ñçù"?ÔÔF¹MµòßDvNÆõ½Œ»Õ§R¾TQ£Kì®B£tI‰Gv^Bœ³òZ5ÉS¨j±=½ceßÝžsƒê>HÞ *ç a¹Xú±µ²á!0·kÍÙ éÒ5CÖ$é§G–_eêj–ø«uN¯?O­æˆ®Ö-9x˜ ¥•.Õr—æ« ó9s˹…B¥p ‚¤Xš/_,IM Y`jÿ`X¸jËÍês™Š©S¾Þ‚Í€g¦ÕWl×ø˜eÍ摆ÅË2kÞyY3TüŒZY08cU‰ž³3-ìèÜ9]0X#ɘç+ŽÇë&gÑ\þ½E/&â[u-›o5q5G³‡\ÉN Ð.ÑyÙèÒH·˜25RÇ\ÍÀt–`‘š V%¿V­ÏA(‡´&Š9èIšSß„˜žæ§Ÿ=™+\-”Y|DV•sÐf—*Z çÁ Öì,ƒp:£G»›EÍáD™êÜÉù u6Iø¯Vç¨~¨aTª%–õ6=#1=®[eS;Dß’Õ;}QiŒXLbUAÃÜR%RoððEµÈêF¥³\Ï!…º^çdYþ†àëX<è¡!Þµu‘[‡HÓk41ù4« îòfl¶aJ`² 5}Á#8†3ƒŒëÄkutb/–€ õàs¸Uêw¯O^ê—s©O4{ÚíIN»¼ŒÓ¼§(Å“Q´3ëv{šNÖK§:Õ¶ßbŠüÅR‰9?»“|ˉ~N.IÇÞkÁ-¯Æ^6cóŸ§|Ð5Õæ.-5ÊóÁGpôsØ<‰ ©s‡±÷MÇ‘Z¾DŠ“©|—û6ïņ#Ug‘¾Êà`y¡|ÏÕ/Î>}—þÿN^k©>¯D¦\L8³)ùಒJ>%¥”ô$2Ÿ‹Ñ*:Iè!C9Ut: û¡gd˜Eg‡öNSEæ¡’ID“”¶½r\ÍÜêÚËJ«¯h$˜y•8+o‹jDpð ³.«g$UMùj}D&§êçÃÕúiÜæm?ÃbÑú䉖`‘Þpi"Ì7û¼ŒsŽø±Á§eæÓ‹%t£Ìzð¼ñöHû7÷6Ï`ƒ"4Á46l.Ú¡ÂýPQBG¿ õË`Ñ1Ù·§åó ]Ï”Xº$xž·€Í¿ÄæíذÏ9qoLLøMl>€ÍoaóAlþ6 læ±ù66¨Þ&à®KØü-6¿ŠÍ»ó1¼o0ùšŒÅ ü 6Ÿ±ƒÝtÐ2¬C7œ6tMˆANR/辜æJûVO¨3ÞÂÊ¢È{¾ÐíñÒò 7åùr·ÓWÛe ù}­}3{Sê ©LkÚ˨-ý·)ä­tú™þ,Œ¬1~†Ð8ÙKû¾Ï»ñÓ~—/äb8šõûÒ}¹¾Î¾]}ê[;Ý´ùñ2™L6Û¥>Ûi?3’ɨ£í™T6•iéÝÑ·»ïÿ8 }oQwÔÝû±ÌL[&«>ÓÖ÷ϱ¾õ–:ý¾m}½½ªzý¾ŽŒ¯¾akÿÖ¾»ý¾›ûúû¶¨µ°=›ÎnU-éuzÙa´h¯jn?sSfW&—íÈdÕ+~žO–ʶªïØÒãéW~Ôû}©¾×f2ê~í;æ»­ê§=•éìkÉ<Ð{Ÿjü´gú3]ªÍZ|·'óPKƒ,ÒF!pkg_resources/_vendor/__init__.pyPKò lH¹¬D}œ"pkg_resources/_vendor/__init__.pyccþÌËe¶»)4™ ؈‹Y€D C°HÄO$‡F»‰¤ÒÌœý¤”Ìâ½ÜÄäüâ ]C=CÝ ³x3ýÔôtý‚ìôø¢ÔâüÒ¢äÔbýø²Ô¼”ü"ýøøÌ¼Ì’øx½‚Ê I6¹ù)¥9©v ûŠAæPKƒ,ÒF›~ÐF1,pkg_resources/_vendor/packaging/__about__.py}TÛnÓ@}÷WŒ\UÉ8m/ $B„E• :¥ª²6öØY±Þ]öR×Ϭ/ ¿Ä³sæÌ9³ã\ÀJéÞðæèàæêú5¬•d¢‚ÜùºvÑEt·¼Di±/+4àŽKÍJú™2 |Cc¹’p“^Á‹ˆ§Tüò1ôÊCËzÊ·HÜBÍ>—¨p ¥jµàL–wÇ¡ÍD’ÅãD¡Žš^STŸâ€‚Îé·‹E×u)„¦Ê4 1‚ìâ6[m¶ùæ‰à÷R µ`ð—ç†lz`š´”ì@ ë@`AÊ9´v†;.›¬ª]Ç KÅ­3üàÝÙ feä÷@£bâeYÃÇežå q—l»NiLÔŸµ úI$#Ä*Ì+G<P«QÕXòš—äK6ž5zB#Éh4-·á"-É«ˆEð–;憓L¥QmT EQ{ç E诌v°JÏbŒ²þÄmÚpé¨@–4ŠŠ‚ A•ïá{ôÄEá¸D'!°¾m™éçÐ>¿>+7‡Ì»£2!šy°e\Ìééòç°œw~(øtLmIIL;ó“54‘8:Q2+e¼ã‚îí0Ô¯=5–0Ö  %ƒÊ‹hiº)Hiź×lqÒ :qJ®ß¤×Ãél(ž}“¡Ãä-äª!÷Á¹”«¡øÝ€øÏǸNf1Z<û;¸´1\Â_9ÑoPKò lHö©.¤öó-pkg_resources/_vendor/packaging/__about__.pycURMoÓ@Çmš¦iqƒABÊÚIU"„*‚#B•+8ìÅ8Þ³ªíµvv«æÊßâgñ˜q¢Vxíg¿7ãÙ·³þŒ–~ÿ(` è¹úZútPÔˆêˆÔ!ˆÙ‚<y²òääÊG Hƒ Ð1ŠN@P ˆ!È)ˆÈScg †ð\ƒ|7³§4­f#³ÀM òšÊ;•éº5Ö9¶(õFmwB¤µºqÙÚ7…ciHR–9í*E¯qÇÐ×un·Ä:î­~ˆÝ)Ë¥ˆ:ž{·1–讪s]=$WºP ráIÇ Ón­.7nŸßæÅm^ê¦Ä׾«"ït¥V­®·T½‰vy ñ¥mœkñC’”Úmü*.L´Û6O‹PÖâ]¼@žõ«iòJF7ί×O¹r…kƒ/HüL¿oTômçømôs·Îè"žãYgno=º˜/.£7ø}ÆÕ÷]X{ç-­3åÍH†GwýË+jIÊ[”²µô¡ÏÀñ”·(åv¤\lÿ^¬¼®d²’]\ç…ÁûóÅ<^ÌÏïß/³åe¢Ê2ioËÌ*4Þ Ú§FûØ”„l¬Œ§ÎÇí¶;k#}¥>ñ¡Àg/Ãi0 û ÆàPKƒ,ÒFXÕç¶üŠ+pkg_resources/_vendor/packaging/__init__.pye’Mo›@†ïüо$ÅiÔS£\ÛUQ#,§QTUh»t?Lüï;°ØuT.ì;;ûÌ;³»€µêOššƒ…û»Ÿ`£¤h+Ȭ«k,‚¾ƒ›1!œ·ÂÛ&œ”ƒNœ@* Î #È@M-¾•Ø[ ¥êú–„,²‡©Ì ‰ñ:#Tag ÎïYÕ×y ¼áƒµýçår†XLFc¥›eë“Ìò1YoÓlûÍNéϲEc@ãGšÛ,N zöRŠ‚¶b¥A4yϪÑë É’l"0ª¶ƒÐÈ”ŠŒÕT8ûnPggÜïuJHW$Y_WY’EÌxIößwÏ{xY==­Ò}²Í`÷ë]ºIöÉ.eõ Vé+üHÒMÈcâ2øÖëÑ?›¤q„XóÊߨ•7dz,©¦’û’ B£Ž¨%·=êŽÌx‘†íULi©#+ìù¯©8¨µê ÏkgÆ<ë+mAFµÜgîuÄ­iÄFÐk’–Èr„žç¹(”³ÿ7ðÇagJçyÄëòüN½ÄNPë—óÍza\× }òÂ’mÇøŒsš|üèßkž·AÀeZ&Áø5å…—sa4Š ÑË â—Œ—g·atæÌ&ýöŦ—WýðßÁ_PKò lH15C Ži,pkg_resources/_vendor/packaging/__init__.pycUQ[n£@,ÀÆÛÉrÿÄ$ÒÊZEÑjO°‘&ÚŸù™`†QÍ#²÷Z{¬½@zHäU”¨žî®*ÈþmÊýß?¿|^=?Ÿ¸#½Hºô€NÀè<…ÎÀ3$2…ÌÐÏ çàsè<‡^€/  ðz ¾„.ÁKèø z ¾¦Éä2‡\@KÈr…ŽÆ6kÝÕ=åÚNŸó îàT/«ƒTÎïtÝw¼¾½ÙÝÞ\¿ïÅþ[Õv]5¾v¶ÎÛ´®¢tƒ4¶ëæµîÔÐUB¨A‘§Ýxšþɽ62ôí˜ÉEcWé]~™¼PKƒ,ÒFgG½›°å*pkg_resources/_vendor/packaging/_compat.pyuTßo›0~ç¯8%M'FºtS¦>di§¡UÉTÒUÕ4!bÍØÔ6¡hÚÿ¾³¡Q²~û>÷ÝÝcXªºÓ¼ÜY˜]¼y ×J2‘Cb›¢°Á8Ã-ÏPÌ¡‘9j°;„EÍ2z ‘¾¢6\I˜E0q€Ñ¿'†N5P±¤²Ð$ n àŸ3¬-p ™ªjÁ™ÌZnw>Í@Åã@¡¶–š¾¦]qŒÖ ÞY[ϧӶm#æ…FJ—SуÌô6^Þ¬’›×$ÖÃï¥@c@ãSÃ5•¹í€Õ¤%c[R(X J+5RÌ*§µÕÜrY†`Ta[¦‘Xrn¬æÛÆž4êEÕ{  V1 £Eq2‚‹$NBâxˆ7ŸÖ÷xXÜÝ-V›ø&õ,׫ëx¯W´û‹Õ#|ŽW×! µ‰Òàs­~É] 1wýJOªdjÌxÁ3ªK– +JµG-©¨QWܸA’—‹à·Ìú“¿ŠŠ‚B« Ò´hl£1M]~¥-°­Q‚êLû}H¥ï¹£ ¡Ö\Zº 3Gà ә ¾<ÎàʽGûÞO)—…úvñ®®`FáËÿ‡/’[ößÍÉgOŒ¸  +óh¹ÖË2µ]Æ‘X( þ3ºed’ª ïÈ´BË2ÁŒ™¸·^yÜyO1üs©‘Yr¢'ïýÌàp?:¹1†ûûw•[çl, ÉwîûN”48ž#s~"+VT.á󦪺ëÄO\I20îQ8¾þ˜Kc™´Üó-³”še”š[ƒ¢¯v siYf&þ”ß³ödè…[®ki*±MÓI&L’Uô£p_~êûF®8‚»¥‘l$=å¤G€ÁQÜM)z¡>äáÌ¢3Ó]êOÎB˜œ‡ðó×yðPKò lHBZºoYô+pkg_resources/_vendor/packaging/_compat.pycµ“ÍnÓ@€Ç^ç—@‘r!ÈäKã¶@Ä!$îrÅ¡¹l7ö&ÝÆò®ÓF ‚(ïÄcñ̬“cÙãÙÙÙ™oÆcöûawôëÛ—¶—‹ÏÇKô•o€Ô‰© Rí¹x0ñ@zpÝ ï'1ƒz5ÿ6yÖÔÙ‚òdf­Ydw«Ç ø0y@!Ïý&¦Vã3æ…˜ê<©Œä*-òÒ˜6Ñ©¥Ò*ÏÌ#\¥Ê ŸUYdÐ4VT‡¢ã‘ƒ‚”>-ªì-ز~:”üà—2ÿØ\|uÁ\;°F+äG˜‡`B(º¼>•R9ƒ©Ðr%BëÁ2WhI¥Ö0´ž¦ƒgö¶zíÑST$P‹ïq€p°Ýá¹ODŠÝÓ§CQÁÖX ÀšÁ†Aí:ömïÈÑØ$ÚÐ"ˆÐ%ë•Òœ µ!ÿØ'CÅÕFoKkãè1Ù+•ÄÁ4VÚ Såúöøôdxzr|ûnÄGo9ŸÅbÎK©óªŒ¤øRfq^…ˆb®²yÀ£<-„+Óœgò†óW”‚òƒSív½‡¬œ[ZÎÓ<®\†´¬‹£!¹†í !½Ü6;ŠFÒŠrÅí×¼ç±}3«BÖœlGWs²ÿ°¢¿ôCÐ$òýÌ=§LÄ­ÌïhÝÛYeª’zK{!CèîG¯´!×¥,é?ã*›åvãóÅÙöýºv4¥uÄ7’pê¶ñëy"cx´¯/Q:õõ}=0¨ šÄ3·ÇúNßk:=·ÃþPKƒ,ÒF®’9µU.pkg_resources/_vendor/packaging/_structures.pyÝSMo›@½ó+FöÅ–N£žõ@mGE°dœF9¡Ø ï’ÝÅÄÿ¾³Ønü¡¥‡Ê–™÷öÍÛ·C˜Êz«xQ¸¹þôfR°*ƒÈ4ynœ¡3„ž¢Ð˜A#2T`J¿f)½ö~ Ò\ ¸ñ®adûÒ`|G [ÙÀšmAHF¢àr^!àkе. •ëºâL¤-7e·ÍžÄ#Šç=…L £nFý5­òã>`;Á¥1õídÒ¶­Ç:¡žTŤÚ5éÉC0‡ÑüŠÄví¢B­AáKÙlÕ¤%e )¬X R+RÍH«µUÜpQ¸ enZ¦X2®âIcNŒ:(£yÈ*&`àGDøêGAäÇS°ú¶x\Á“¿\úá*˜G°XÂt΂U°iu~ø ߃pæ’M´ ¾ÖÊê'‘ÜZˆ™õ+B<Ë ]cÊsžÒ\¢hXPÈ *Aã@j͵=HMò2b©øšfº?CyN®äâ8oL£0ŽíþR`‰–ÍïÖ.¾á–Ö…Zqa RKê8NZ1Òˆœ n¶#™üÄÔŒoèÉ0'z…µŠã‘Æ*§ì…´)yx€Ž!%Óå»[YÒ]}| ¬Ìæ‚´î^¢ïY¥ñ‚†àK„ìÚØÛ0ê:(jÔîÅqçWŸˆ½ ìÅûeÑëÃJ5'3½"΋wÏ(Ä‚b·ÁÃé:Îá ¾¼¥eü;@çý¤«¤s?úƒtŽørtq9úƒtùS’ÞtžJÒElÆÎ/PKò lH¤¯Ë/pkg_resources/_vendor/packaging/_structures.pycÕW[OA>»Û E@ñ‚1Á˜˜˜41Pˆ¦Ñ„¨Áh4&}˜ê}pÜîN—…½ÔY OÊ¿ògù<çô$ôÚééÌìÎ÷9s¾Yçïülýϯoô?–w?,ÐßÑðñ² ˆ-hYÛв!v å€åÛ  бÀwàà7ÀV«ªH~aÐ]v—@•¸»~ šÕ2NÒ¤UšÕÜÆÊmë4Ê’aÜM3cfE¸ê0MÌþéfabd'OêcÈ­2¡$cü2ðgؘѬVðéžÕŸÊ{š³ì´fÕF£!ˆY•9ÒC½ZE^UZ`ÕÎÃȯµýP›ÕØõR½¿²¾¶º¾¶²ÿª.ë/k*jÝÝ@fJ§yæ)]“{*ñÓ¬Öu½]7“ &µÉrÏä8fµ{Àž‘xC7“òÍc³k†€à;„ / q,ºš ¶Áò¶«·Ù çq§( ‰]= š^Ê¥,èÇ>ívd1@ÎÎ.bõÑ´b"Œ˜ÛR³­²«Ç^bì‘‘òјÈ…Ö1h1;_÷ñ*)—ÏÁ{:^9^v0^ìÑx!°¸_mÜÄS¦ÂOõ"Wk)§ÄIý”òÉEœÏrš;IJÌSµ0½UIpUžŽÿÔö5ËÕ”0ùÏÆüÅéù8@Wál¦¼ÐÇ´*pM¸§B4ÉYî‡G åócìÕ[„­—<7Fb¼-¥ŒS?§.(  h¨˜£ŠX!q—*R ñ`„ÅURa©¤å×4{É®8£_q›¯£Æk´2\|öÓä"€WòÅ9a{Yý¢<Œw‡oÿúúooÕ»ƒ7oŽÞ¾:V¯ß¨—¯¾:|{øú¾}­Žþ®þ÷ðè«¡2@&˜Æ\Ï ÄL„f‚ô:6ÆCàBDÉòYà¤/ÁÈÿ`eò,½±c–³$žÕÀp#îXœ·Y N,×jü³Ã åd¢Qüžp*þ %BW9`9R>n ±N²¤ªQõzk)s©«x`HŸfj®uÏúøú ûŠIã›×ñS輌–¥ì†æpO=þ°ûñq/ px‚ÁVù„>„úÞ4m4-òżßsËï "´ûóþ`¸z°5û]cÅÔà5@ÓVhž™°MÇä¹ ªK¿ÀJä8±U¨HÛÖ ·ìà‡ÝGÅdžˆ8£øyའ»ÖF Ö„‹CNð›öQHŠ OAÚTõžÃö?<><û8د±ðàðŒgÄÖggðW¦/ÁÜø›»Ák÷ž­ Zãº8¼­O¢ì4¬äÁèö,ü±¿âÅ5FH nVVx€éÓ¯CÏøâR7þüÐkµ:Ò14Gí±)·6H»ª£¼:„³¹“m&õ(“ZîÀÝÃ!À¾jHJ)É#^•4]ã‚üAÓµ4}´Š¦SSÕÆÁ‘vÞæt¦«ÊèñY Žq E¾^i,ÍI>?H‘ˆsSÄæÌªWçßð7'Š\¹“V?8yÙ?uܹmÄG3÷þ \”}^»e›»[Úú—yx]Æ4¤¼¯ãµÝ¸[H^ ] 8Uއƒ Y$÷#0ݧ¸mh`¤Ñ-¿ctIm`‚­xc»uh‚"°m…‰Ðˆ$©iΆ… Ã|_ÿõ¾Ü©ÿî¿øö¹³ûýÑèöÑèöùèvþ{»?¬|Çâ¼ï-éäû÷åéýQ?,J¼ðXÀzþHªå 8¥œëx>Á\”UŸmVP½”èÒ“‘žŒ7ÐQO,døÇŒB7<=ÎÈJŒU³çÝëý“ 5‡e øw¯Þ|ùúø•ºÅ/‡9zýæÕ˃ãW¿ç¤m¾zؼû]ì—ùðU>p}k'Ü¢ÙlÜýèfïŸ;‘øs›–…ž—øK,>™›ÉèµÑÝ-†Þ¡%xx¾š([b˜Å°6i¿…1ûytØ3ø> d¥ë¿èršßâ¡`‚‰¸ NµR'§˜ XSÆzŽÞ Ú=ö‰Àïèç>~­c—K·ÆÒæj*ÄrŽeRθö0MÛnÝ6åÙÅÁíÛÇ^1æªlÆÛ9N`qHíŠu¹—àV•æRÃJcui4,w™Ø”s½|[lÃiBO…×/°ä$NèD!ñÀº¡ÔšO­öªú/žpÃÊkÌ1\uEk+Z$k¸uQµ{z)+‹=˜%g ){o‘‹Ž@p‡a£ÊþZý³Â톜ØÏ@nI ¯bG`‡ lwÁ¾kšÇº‹-£•6Œå|« ¦âœŸM!‰sôÛð%¥œ; 58”Ø´(R!‡M§c4JêM)øÀ‚ §…–õ±¿nm´ãW/:&Ý;Ù}òß§Ÿ=¼“šy.RîÃCá÷ÿ9ءѫΘ02|¤ì)yå;4Ï“³÷Ñi[‚©oÇ·ñmßêt>ƒ/¦Ò·ÿw•˜eû¼yDZJ›ZƒNju¯'/«µ ‚ŸXŠÝ"É›>¾w hßûˆqi¯éà3,O³Z ÜtÀèxõ ÏÒÄñµ{؆SåSÎ=§Sî’#:T§Á¥G`—úÂðã|Žõ8ºCûvɨ}n×ù+m¸n›°½ƒŠï?;ÑO~rlÈ ê'·½B¾ñsÛùô}ô~‡”`M¼ò&«ô5 èN¾x˜ÎⲄJœ±žÈv¥´L’iR¹P\4€-ͳ7Ýzåg_©¨†¤«ßL³|æ­Nõß¹H‡úŒÌ?Æ.`ƒ´ê–ÿ ½~þIz¨æÝ½Fºï/@àÜq†µ1´äh°Åת\Œ)P ü±Dϳ[rVù “>Žà¿;öØ.k$Wc“Sàu™â²t±¶:uÔ½žHÔàI… F É•)#òýøLÌêݨÌ^ðëÀYm8!/b¹¶®‰#™uzgussn§X¾—¢É)óLFS†4¢Qêûi†¹JRHm!zeµ¦ B¶r¦Ì• +]JpÕc ß2«ÂmO•Í ˆX/êE?äIæ×ô¥ITùá§¾ U`–3/Bæ½®/Ç­®÷ÐàWê:*+]T%nú=\e¯[ûŠ;lûïazƒ †Ð}j)çà]pij=ÒŸxp²÷äé©Ph‚Š“‰ðŠŠ‹&LFÎ0f²9„Òö3$îN¯UÙÕ拓@}3诈j†dézÔzŸ±pE\÷P+›×IH”œ×Ãe-Tè“MÒšrγªßÄÒx%Ú}:aàmðaë«L sfcô +›šè•¡ËCA—¯tÆ—£â¤ àMrº~~ÀÒ¼Xãìù]JUçÏV,w°0Ó³Sо1—ùßËŸ¤¨à\»r…2‚,8€ç/ÿ àu.ßKTµ¨P’ ƒÖ’±"Êd+ÍNÅÝÚÅÓh¾ƒH¶ ìäo]Þ{uý€ä/Uq–Pêüûs_l>Un¸ƒƒîÅ'Lÿ2Dî“=î8¯ÂÖ%Q‡uº«Üœ[¸Ì‹ Ò'žÈ·È\uZýÓz1Df&¾@¨¥1ëD t*ݨ¦š×–†®Ó;Ê<9¥Èy]µ±dŠ(&Ó¿0|)—Ó„ '9*"s ÆU-2tBð> UA$ãáÏÍjdßÖÅ6œƒ‹%'Ãjê!LlÜêaMéDz6@µwQŸ œsñ®úÂQË.‹Œ™ »½ ÃOžñ­3§¾‰¦‘zþ_ÑS[ß'àÕ·¼ü½Ëç[è~Ú¥Ÿ-ò’^l—%Kåçýº*×.u9†N¶¨%£ú¿®¼´ÑÚÐCWô7Í+ò@rÚN¬#¦4³=Í®`s´ÈX›ëëÁ;°þ†Ûý-·gZÏ o˲=®U:M…‘¿Dþn5]ä¿‹ÚÿPBpßP ]oÝG P¬ö…䩡ݧêÖCÏø·5Š~^§‰šŸ;Uô*³¡|Ÿà6“â¥5Šœš¼Þæú„ò­e Ð/Ãø‚3ê²ÆæœÔ0¯vHLajD”ˆæìîº(~2Ø¿(ŒÖ ¥ñÃévg’ªíZ[á*ú·eñ>'#dËÖ²ü¨ëYÁ£¨‹‡B¥ýjL·Î8ºÕUÇZô¾ïÛ¯ \S9í:­;b[º1\$JL${­ö䪸±§Òãø–ËÜëñÅéˆk¾ôK•ØIQ6µaë­e« uÅ=Á;¡£öá~eñmu‰*ƒÖ[žÅø„½·þÈú¨‹¨÷¨¹»lØRÃ6Ëì­©Ë|b}Ç&ª&#Jº,]¡€§®®[lç'«Ú†GXI^÷½h<±º]‹æ7‡<¦¡D › ÉLs‰‘!]dù²î@$Ú’øáµ'+*—h6s/d^¬ù5îö•¦í"Ãù'î¿#zÊÐb+S";Òx/_b°Ÿ‹p‘•Jš•Tl+~ ú¥tÖºœÙf2ãnµë(µºXllí¨xžyÃÎr¶wõîjö¸ ÎÑ1Åv¥|z}ÀÛEv¤‡ ]wž†)«$^¤º°¬fd¼¸9ž%ðÞ ÖI©Ï¨†ù¢´wƒ½æ¥M󞎮d¿VG¸wewL–)%G]Û&_TÇ7*Íó  ÷-Y£Vôé uc?^»6nØK)Ý IÝH—ÇýYDÿ²0FÌue^ú-©{üÀº$j^¢˜øØW¼Øˆ¨2{œ²I©§\:ñT-ë<çX6F αã±Ï?ü¡Fåû# Cc5Ë—Ä"€ÄÒu³nÌÆ ÷wm¹F(9^ï@ ž·zÊm––~‡Ê è Þ¾Ÿs·<Ü/¶Ÿ”H .0·Ã¶­F)»Ve›Óñ[œy$_p~ö<«Ø´µ—óêÆÝPk”w‹äÔÆ@§K}Sú*ÚuÎ’v¼ÜdŠì'~yƒSÛ€ïÓ7íÒÚZsåY¼Kׇg퇵ÇûCïI:o®÷„KºCA¹*5#q6[ú÷Š·q¸ï9wÀ"àgÙŽ™2¶Å4Tf¯Supô•Ò—y6õR®ôjsvl{†¾ <ÖŽáÕkàcd9®›×ðÿC@¶¸ ‡VFÜ».§(Ø]Adw“Ǻì3R2GåDDKjÛ€Ë3K²–¦0öÿ¶^È´tÀ›Ñd':!‡ŽŒšš )nï·êü:…rONƒÍYߪÒm ËÄu·zdìƒÊ´< ì0•39|97P 1‰6#ü2_Ì}Z (¥w^Ý?°tuoøÚß~"Y],c£Ì$cÞ2ºV/›/×5s4I&3Å ’}nãç»/MWK˶T"ÓN§…Ñ“æ#<›!G˶oLg_Ç®¥¯ëyywSZˆLˆåûîAøYÙíò¾\â¦òß÷†ŠZ#&W–[ÇS4åñ•†0fÓÖ儺ÝãÂ/ÈwÃx»$GwÇGw h½Ãk˜BØêRÁnÒ­ÿPKò lH8€pj_.pkg_resources/_vendor/packaging/specifiers.pycí\ÍoGv¯êžr¨¡†"%J²l¹ië¡>(ÉñÒk-)Û²dljM+MY²iÉãæt‘lrfzÔÝ#’«¡±knlyã ²Yä >ä´‡MrI€äC $'_sXä‚ÄyïÕÇôCŠJ‘YR,uWWWW½÷êÕï½zUö¿Lþõ'ïV˜úÉÀß+qOqÆ|øÇY•±gsœÕ,6g±šÍælÆñ™Åª6—aê:Ëæ²ú:ÇærúºÍõ1ßf~†UûY-Ïæò¬6Àæ ÈͲêV+°¹« ²¹AV;Èæ³E¶À™ßÇ~ÈØ&cïÏ 1¿Ÿ‰&2lùÃlÓ¢ySb„ùðx„r˜ÜÃÌ/0q˜rMîæÄ›¹Qæõã!óø(}lùó±M ÀqæSé'˜?B'˜XëˆyíIìôli( IK6$Io>«ÍD”ƒZ#Œ’¤òüà^a=97(¨'å…f½’@ÖLÀñu _/@'ðx±œ¬7DLÅWƒd©\‰W©zq,¿ÓÉMQ•ƒpý–Xô*ë:'‹ñ¢X$CpõfýžW üÙ†¨ ˆŒàw¯ àWCæ/ùîl ŸÅ¿ É€?¯Ö@ÖâĺgÕ‹…°Y÷Ï:;ìÄKa³ê;‘X€§Iè\¿vÝyá… T…l7Ò¢\®{5Q.'tS ýfoûèÖ+år‰(j’øw ™oUÿü¼ÄÉDÍ«„ñÚ¹‹&.^8·öÉòä çÅââùÆÊb9qØŒ*">_¾'ê~ox•oˆzÞ4>žh¬»Ø˜ãX=Ò>g!¯x±ØN)[SêKC)a±eé…Áq|¨®s²:ÇÒ99cëœ>ÊéÇA£ròLäÙò˜vŽ| ŠåØ9eR™}:s9—‡&V¸b/þ½† ÇM›%9‹_3\‘4£zì$KÂáþ5€†¢žx(žN¸O‚Ø1TqªÁŠpÂùeQI&œðÌT¥$`^tTrOÈJDªŽ ‰Eua¼9#¹íM°­øt¿@Iô¹\ï°=îõn¤óœ%/^r`„4Œ‰h7Šuë²;ØyWƒ[*G˜ì/öÊÚ¹¿w»÷w> «Â«·ù ŸsV—p9r€õ0!Ž'«á:˜Ê$= ²H8ânÓ«n#¥IC-ĺ÷H9"’¸[.Oì•DÍž‹?„LîP/ÄHR¨*ûÛ{4‹Ý(´…@¤s‘ŠÅ:Œ\]Rß½j5\ XÖidµõnØcUÎèB7}j¯Rã§i2+’}&HçX"MµïìöÜÐÃVéôpÓô¸*Õ‚:ôo¾BàÀxy•ðóRè»TAº{“a,>”*ֈ†ˆ)ºô1Ñð1›™°.\ü®îçB‹ài¬þ0$9k¸o8ô›ãÅlŽ'ø üf- f‡]À+Ê•¯Á|4Ü °ZdßNEãŽà)Zv„JѬ#0:'(CH*­50î€âÅ& Ú@#$*ÙòA´ÒL~ëBÕ¹"]èz1+²%1C#£MCc.ZŒÁËœµçnجe³øK,l= `™ÿ>á¬Îðé2õr–³h¯©»³`aµåkÉ‹>$Çl‰ø#ßÜjð\rž»aã9z”/ë!ä=iv•úµÌÅš/ª,¹æ€Ãš—^ŒÂfƒ®Ðä“Weü™åÔœB­j«/,#_ê*K=ÂŽA=HÊåÛøl#ãÃ<ÇÙÃüD† €¥¸Gœ{Ýp(»’gÑq‹È½Lœ¨“q´Á‘1*?ƒìJµHj¯¶á vù¬“¢Ëôý cцKãõð§tÿ"äÝ~cür ™ã"Uܧ0y¢[žzCöt¹Lšƒ”ð!5Ob|¬G¤E”6¤µÇxÎÎñ<üteiÒÉùbY˜³/˜š;fb2 Ãý‹²+ÔéçX/!iÙ{LÖ¬Kûåx—ßĉ“"·´ˆ£‘ÒëV£­§Z­ñ[V·ú#ÕjÎŽ.©è[¡NXZ3qvëîu–ÙY`Ñ$ãœCfß«ª7eix9¾Ž=Åû,>€tÅ2„@.’$ˆ9$^½"\švÏbBÚ‰<&oÖUQëBø’`½µhmaõCDµ"·ùäý 2Öc ¡ÝAC÷"&”sŸ7C¢Ç´B¸ñÙÞiõ”%8Öy›JÇ7‰vzÈÓtQ k €neTÆE¸(˜l"RÒݦ'®8¥èð*l컞Ão•¡E¦ Øe°™Ù£”hâ‚äø³¨— Ô©€fxÆ0œXttû:Ù<Ö6“øL”6@èEª™ñ#À÷íörÓ“¥î )¾RoU NŽl¸ÒÉÅ-G`™IÀ´µ±mZîU‹¿LµX›VFŽÊØbº+ý,:¦æœ ‹d§Sí´KFßÅòø/¥[ Íá(<.A‰º·à‡!~p†V¤/ŸpAlžû"Š2’$ˆS¨ŽÀÛë^5î¤QHÆ´rè×÷„hÑü)Ó¸Ã*ðB¦˜â™ ³_³‚Äü9(€/BšÁî*Ú¼ƒk€t•OndÙÚëêÙFN¡¾VŽˆÝ§À^ .²ìÇœEÏã5:ú«iÔ x °O½Éïþ~`ƒjºÉï>Ïàß-€÷…诰 ¤k£xqõÎú*•ú»UWòJ*S–&ƒ—4¯w܈š‚ø%í¼ïh&v÷  ¤|xtÔYvÔØËéP “rtìf°˜'ÁX3yÌc°‡'ÁÛwÍêAmVÔfuQ›ÕCʬöÑEA/KêeɃh8£Žßæ)чæêv|Ú\—^¾>¥§ÝË¥ééÖØtkjºuÒÖåññßQâyÙdâÏÞŽïœvN9·„³ÜŒ‡LPG@áuô(-žuÄZE4Z Y] —„XÒ‡eêç:ö<ç™*1ã™´Kªî“PµÆ‘K¤NÅ«ãR6¡{}Þ|ØLàmÙª¶«{Ÿ5W¤šÉ×NÓÊô4Œõ0)·3ǦIrªLÈdÉ«§MM'8"#á%"Úúô²¬Í¼˜à”1E6ú ʾlf`ãéÀE @2>m¸ˆ&•6.:Çz‰H/ü 3¨(ÈLÕ¦k¨*ÔäJs6ô%eq­_RþGé{ÉiÜîxúBÚÛÀmâ뿳6ÝS¯ìÝz墣¸7]NwÅÈ÷™¥Vï£ÿí F÷?ŒÆ•¤ƒð_!3‚jѯ0³ŠêWÈoèvDß ÛÃú¶@·GRkXp;ªoÒíQ} ß;F8|ˆ‰CÌ?®ó‡1^qy„ùO´s¨£/¨<ÝÚ‚Õá~:…×wÄ襗/mÃħœ¢CQ’uǸår/u@Ô"®x á,¦§åäÕ ZíR™Rñ5¯’hD. ì¥ÑúzØ„*â% $gv5Â’nÀü?®—2†8¨@B²Vâ~,âë.•æwbQTœšðêØº…(¬áz¶ü”î>Z0V*0¼EŒÛ+›#,—j¬{‰Fý:EdtRk{¯J/OM#ð–wpQ^HFˆuaŶ Ò¢¡”ùEM{D ¬›™dº)­³U`B!ð-a%Èa`´nrg_Ç;îZ{”ÄR=¬ˆÙIA|`wäë«aÅë&ˆJÐb0­»|Œ‡XEÞÜøÈ ,Hø˜‚®ºÔÔnC,@ü`G*„ÀtмÀѰ“a”ŽwV¶…áÒ¤Ž˜P®x`O¿÷r—^ú๗îœ9ýQÑSñúG…wnOÈËñÓTZy§ºÕ¾5‹Ê7"±ã;ôsåÛw¶·–êôZó­J+ª´¼jc nDâµ Bü»ˆÕñG®‘º²Zã]©Õ½?!ŒÝ:/žSk!ÉekJø^ šÝŠÆU–lËö>@cºÈÙû •k‚0z[ÝY½‡a`$ñZ¾»Ô“„‹2d $ dö@%-ª¬æ­™60 ×ë¢}»Q•¯ú êìi[êNQkBÅÛg>ðÎ}O‹¡¬ÊäŒcu§vßøÓêš{{âöiR‚†xñz=ñÖpšx¨\üÏt¡ž$ 8,=(dc;q …túÁbÄXu›¢Á@Ó,âòmw½òq§Rqv˜Hº´ê±i–3½sJ·”öœ34ý ÏGyN—ÑòÿCïlýé‘êRçÃ÷.£ûÑЫîBâj&ZrÆ÷œ¸9ã!AùXEäÙ}äì„üpBRƒ"Á™{I¬#LE=KŸèRY‡ŠÝ!ê0ÂüPÖ$[‰ã Dg!XëR KŠóÖ:)î:°Ç$¬Oos4RèëШ Eþª1¾ƒ`lÿé@1€VcÇh&ˆ›Më{®ÎëÏi„ ¼¿-¿VÿwÊã¡‹1Ê=&'8r¥}<í^Ñ~Ïéi÷5}=6í^Õ×SÓî5}}yÚÅhD÷ LpW›û¦ö±xÑ|D^´ÛTÙ´ AÍi·ãÓÑvr¥ÅìéJ2Ê ¹I©o3Ç„§úö"^Qü€ŸUÑŒ-Šb …ÎÏé|[ô Wh†–~&:¢æf±¸¢©*i¡§>¥ïéû‰@+ÙÈ] aHŸÒ¬ï(‰ÊlmgÊ!3͸.t,E`¥+¸(ð·fÕ¡KÓ1üÅc§¼ìãj9®düÝ#µ<û i9.¿üýn-ÇPÓì K'ŠÈÁ;‹CÃÎnÐÀ³\ȵ */_•×+ò)¼T'-©)ÕAM¼D£n&_3ê.=. áÚÔ/B¨¨Y¦-ðLn„Ÿä}ÙíÔú¢;µ2ÿ[ja‰ŒX{°ë; …s†Â}¦)cú`ªUÇ ñaé©ÇFm\üg®ö uP;SÜæj1NÎ!—Ÿb¼MEcÐ2Ô¹¶_Ñã_E6Xζ:7`ËLXul·’ƒQy+ãAoÓÌ(…Îïc+9…t-åâ}%&ÓÉ[ÀqŽ )5CC’:ÅÎÒ$9£NîLM+LÛ1¥ÒFŸ] Ë0Äöæ uq³…<ËÈÅKZRS¬qX¯b~ùä,=£‚Øõe‹¼`Ÿàƒxý«\|Òˆ’EÑv©ÈHü¨‹ÛVÝYLn`Ò^¤ Þ}¥Þ0y*Ù›Õû9¨uUÄYbT«÷r¿x¢8VÌÐïñâÓy»xŒ ‘Kʤ,)¨­äq•÷,ºŽ}|¸i ƒ†9[{§Ãйzç²°Ë–VødAEo(å,7ïm2ÿ;ªvzÈ¢x«$àÞA¢å´^"3@n©Ô±„€ÑPûúC‹ÝBCo“öƒ¬½%7|\eY¶~”vnØ4ˆ³Z³Üº{•e€Å¸·ï3ÜÛ§ÊäRe È{ðw †#<Ý” _ïÔΧ6rü-ÑtŒRé~‹é½¼B šçû4ÓÉ­±&C«¢ð{¢Ž…hÃ6ò=–ƒb¤)º˜fF äF:Kú*(<…*3…ö]"q ÆŒÁTö ™<)< é »ØÞ„m¦Ýi¶ì>l62Ëì½¶ö¶÷ãæÒ Dï_ÄMØd.uÙ„½5}¢ w¯à*ÃíhµÑ·f˘ÃRþ^59’epuSû×”ÌýD+lMô+8!‰~ç mRÝäwím°ÖB'.¸z@†…vjQÔÅZ#º\Ó7§ì„ŠÖ×qá¶bT^=Þ=^ÝbÀíy÷¸{“·ÃzÃT‹MŒ«nñ?±-»žO¶½µè^ÑOå&׋¨Âf•VÕCÒlq¾²Iβٖ(·6~Ÿçô8×·X2Çês©ÂðôÏR…ûé–¥ ŸÓ·TÞè,P@o¯¯OÜhµ·"ã*Ëk2°ŒòyŒ·Jë…X†¦à.;ŠM¡í)­â„÷D¾ˆ'è»Ôöí`B;·Ws¸­UHUßÄ3®EQ˜öD ÃÐýQ„@&½*—#”…“$ EúÍXy~Ü:ÉÑõRäühÙ<ŸÙ¾¹G²Ž]´Ç£!ÇçÖå ¹ëãs†žÓ\ÏFSjºûœ«üBt‹Â8„ ô¥ÂìócŸ‘•/w‹àù$!èo`[žUúD[Bà{\J«~Ÿº¦(;ÚEdé¶s›~/„÷Fx¹´{ºœx‘:|€Á/©®V¥vÚñ Î^íã‘aÌ ÔT¶À ýC<“³ñx }ð€±Lð‡âÝ`kgµ¢º3¦V[yîÛ¡œïïž‘^CyŒ¦Y¶¶)×ûxn.€çƒ¸)‰ý ‚s~A΀ ,Ù‡%qvù9»»HmêCqŒ¾’GI|…flüK´p—ÌA¿Ä²hý¶³¡UxÁæPSÓeÊ™…‡³[O18ÐÉoF¨‰ÉŸ‚gv òuv9Î@IàyÔØÓF,^î…VÁü# ÈiÒ‡ Y<¦àižÉb¨Ä ŠŒ•³‹<—â9>bʇ™nfË»Ï-ÀS‡¼bºþ8Ž*@ ñö¿›³ŠGòyÚ1w4?(Ξ*˜[./4“f$Êe\z`.é'µx–µ{‹iß¶U¢Rv"ñŠqmKaȉø1SNzçÕ+¯½‡ásy -E(‘zQäúyVh ï“Qè5£.õ„x2¸H"~ùKë˜Oâ1&økò'íÑÜ3/nŒ¾Ï~͆‹xĉÿPKƒ,ÒFð„ß=l.*pkg_resources/_vendor/packaging/version.pyåZmsÛ6þ®_Ò7±‘;Íݵ¾8©›¸=ÏeOœ¦Óq|*DAjŠ`AʲS÷¿ß³x¡Rr”6ßN“‰%b±Ø7,ž]p‡½PÅ­–ÓYÅïí?a/Uγ1;¯“IÕÛéí°W2y)Æl‘…fÕL°£‚§øãFìÐ¥T9{œì±>Dn(Šÿ·jÁæü–åªb‹R€…,ÙDf‚‰›T“9KÕ¼È$ÏSÁ–²š™e“,~v,﬉ʾ /ðkÒ¤cÜ <«ªâàÑ£år™p#h¢ôôQf‰ÊG¯N^ŸžïBXCþcž‰²dZü¶jŽn/ KÊG0ãK¦4ãS-0V)’u©e%ó逕jR-¹à2–e¥åhQ†ò’Aß&LÅs³“óˆ}wt~r>ŸNÞþûõoÙOGoÞ¾=9>g¯ß°¯O_ž¼=y}Š_ß³£ÓŸÙNN_˜€™°Œ¸)4É!%™PŒÉ^çBL”¨,D*'2…^ùtÁ§‚MÕµÐ9Ôa…ÐsY’#Kˆ7—LÎeÅ+ó¤£TÒ›h5gÃádQ-´i}¥+ÆG¥Ê çÐþ@õkIl¬Ð2¯0!O‰i¯çf¤*Ë„yTúG²ºR*«ÀÊvÁdC.RZ³ôKžä™Ëê¶×ë ‡<Ë Ì!»è1|¢‚kâ€E.Jéë+1åémãÁI~Í39ncOžìÕÃfÌðöÏ’@§JßZ%éã¤wRÔV0ã.y„®ëL ÔX1èõŒš­Ùýw<[ˆc­•nYúŠYÒZ“%GSØÊjºdåL-2²ø„vŠòª¯Ôó‹¿Cø%­a±œ!#‡3^ΆÃ~)²IÜшÍP2¼·qs^V¹Y¦ÈßÝÉve[ä­¾! ÌGcÎJÌ:`%{ÊTÈU|®‡-¶â·ÏÁö°ÍvúY¤}ÖaûYLû¬Å5ÿ,Â~ÑÖS7Ø\T35n,€ÝK'2Rs^VtòzîÍðlÐ7„:UÕ 19γ^[f»Ô*F >^Ý.wfkц(³×VºîˆeW¹®3r_˜'VDXC›}†é¼Àƒ~0?p8mÜ„Á¬æ$-ŠÍ³¢§¡Ò¿ïý?‹œÎs^õijŸÄ7“c'Ë·…V8šq¸ùEŠÅðd{ÁºF°µ§ù+|ÌaµÁ©ÊŦy²âØsgá†ùß󬼗Ì­8ô¼Ã2f{@8 -Z$ôDúÓ[Gý÷ã‡ìŽ]ðÝ—ôå}rÇvcœÎ .øîõù±9ŸÛŒáÀŒ§fW ç¼ïßÁÀ¢Ô÷×R,ëß»ô ð…g» ¤õ|ÿ(â† Ô âWUöK§:“8±ª§ÑÇL;ìÌj)”LEÕ'Ò™÷ڹİñR 3GIæTå€Î Ì$ꋃýK’;ÚÛüÕ“¿ÿãŸ_Óšºº±Ñ1_Ì…†µiN–ˆÏ&á­8…‰iòUFÖÿz•"â` uôeÄš9V²ˆ „ |Ãh³bÆDÅ¥ÀTrÌ+T ÈtMÞë5¹™'‘wZ˜pÂØ/p¤ëqªÆ‚Ê©´ÙÝgHš"aG)€¿²[L¼Æ$;DZC¥ñªsƒ¶P×ðŒàÈ^ÂÞR嵄M˜˜L½^ 0)•öÍÜ4pì–3 qpJC}x ftbŒ!5VSR|äêH *ªÄ., †÷¼˜œÅ@ßVª´8ɪí½'ŒÐ%긹)¤*~´iJâjŠ-ÕB§¢L‚­ÑXª*”ã'«(pƪ¨ µ…⟮ÍäHs}k¥1Œj‰Ëî[·=¢ÍÔRè~ž¶&$a8RÛGÐÅí×bŽ‚Œ²Bm*¶J•P~Lp\Ù|Ì… éfÂiBùv±‹ýF;ôK—zºójý“BýÆf$­4—ÙíƒÐª´~¨ºá-4°¯ß¯†YÀå~ÑöÜglkå²Q¼£BéÛÕô¡-ÐÌ/7É×Fr'ÊÞ—1 4vQf›G3¥mýoªhò¡+ù²5×€hæQ„XÁi{‘âæ+mõ»ef§ƒL l«^«Ð¤É×ÏÍŸþó•ð½ÿüì©ùÙÅÞî7—ã/âçë|W{j•,‡³§.œð|Ÿ8^_Æë8øð+Å”öwÀ Ñùìžå;¼@¿ëøn½Ø¾O.ŸÏÿaö¬ÏïFwéNïL2¾£d|‡¡;wœÆñÖÌro·Õpã«¡´Ø^'¨z¶N'Xv×3æû~áPÖ»ö”N´¯Ó¦)+ìCî`Š;úôüq×$ô‰7Èä“|úµöÙä&ÐC'ü¿W‰|³Wc¿‰Þ?$bƒYŸ¶óÁoÙÖO°ê µc!®?£zÍ*þ¾ÊÇÒTܬ—ôÑÑß—p´÷þCŒaèo®odˆkÈ Š'?œ¾~sü∠¨ÕnûRi‡½£¡ÊXþ¨t™—ú”t²!3RàD­ç¡81g²­ ŒjI)¸NgÝJË!A3¥U;r‰%Z ßyó°(ŠÔ5‘çßHó;ì¼RZ¸c[SkZÁX™}6öó“ÚU¢ïÐõM¦<„ úFþdªÕ¢è»î]“rë ¬d{ƒP]ï‡öØ!ž26$ô°ñMÁØ!sÀæ8¹!q:Ä‘‰ ø®.ß:Û:`m²gÔb¶–*oSµ%@¦øs"˜ õqlŽ„5a£5#?"’ÀŸÏäšJgRÌG$0©¢–~Ô"¼l‹·éá º¹@~Ô°°Ü€ö‘ n‹ Riº„Xßáp•F ]°‹yî!p1y ¢æÞa¸í¾q˜ô¾ac¥Ž‰¶j²|J{åžVOü7Üs )d„5†¥ŽÜ^˜ýpA²/jÁÖ0óÝ› ð+ä™DɯJæFÅ›jn(Õ¬õk¸ÀÙLÖÑ î¦ú‹²;õvîSo+IÀ¯%f 1lm)‡!†­7˜šF/ö/C)^ Ū Cw0KG6ÛÊÚÍ¢`°#É«&ôè8¿#‹E*ÛIÓIvÑæl[Æ’Y±…fãN7ØGC³òúÔ¦¦ßµþ€| Ø~|±wùg:œÿ/ûú“ì¿¶•ë›î>ñp刦¡à ’'$^{o’´œ¹¿Ñ™Û´‹GJeÝ=EX¢›uþRWyÍB4);´-b¨2ªoy`:û¼‰ÐÔ$-¥»mצS02As¿Ÿ£ï1óD£’vW±&C7˜™æ…í¿ 5 hQ©äÔž3ïXÈ* `»‘H7y¸1D/”5§PÏäðÖ©Sº>‰ÔÌôÁXÊí+óz®%?ûÅ÷Ëz Qª¹`K¥Ç¥·F†Y9¤²õŸ ò7×LŽ^aXqƒÁª™‚$KÉ–`Ç‘àÁm¥{A±ÃZh2òDh-šÌ¯Ò!‹L‹¢Õµª5ŽxTˆ,œH]óFëçA³‹úf¡yÁp¹‰‘N£N’ðJuŠ R£Dn2UŠv´²­ÅÜDáÒvÆí;ÜQØš"~~Øòmð‚rû‚þ-JÊ:ä–:ô›­VÞæ¿a}‘L¶ŸìíîÇݳoVl¥0Ýè4aû°Aq¥Ë°”×ÑÅûd¸{µw}úíñ¾Gð–_!ü¸C#“W0Ê(Mö“j)2jæÃÄ$`Yãý”"á[K„B1`*]ú^ø;…ï§øiH»­×¼ÂId9–S¤fWÙ’VýTÿ ¯›6ØÍåxkŠ&˜·fs…ŠëÀúšƒ6ÝÀ¸z@eÝ€5-‰x£Y wÿCu’·þ ¹¿=Ìi²]=Ø&c×ê`Û¾ö8aç l€šÞY£5ˆ»Í™4¢áü0ìèQ®–ŽD¯Ø-òJfNZ“Ë)—!ÀAÕÑÀE=u‰•eåx™ o×…ü#ž^Ù˜ ²T!-¥tß6v[Óõ!¬q¶y¶(k=é*‹œFiÍ•TaÚXò&ôàh•¨öq(­ÎeCºÖqæf:nóØÂļüdR˜c–°“2Í=v­LeÃ,¯çÏÙZ5½È„»É›ÁË™{©Ò´..2çXº"²rPZ°Í>WBÕ6–1…¹!߭߯³¹úº4Šzo!é»7³¸áÿðvTìß*ÍK‚Ÿ÷wœÂfsbqw ˜…r·EZ½ñ·Y¤†ƒµ÷×-K‹6ŒÓX•ž6-±yÝq£€\·¼Q}ÓêÎáâô°­r3ç‡Ôk…²´Ÿh ³}ÍÄv „÷è­;ËÙMJéÇ?q}[zŸÖ_‡  é8bÎŽÏê—é,Ù.;" Uß/:æe W{pëù™¸‘©šj^ÌdJ÷ÛÁÌÓµs§õù £pº¿ê$ÌT>mŽ--2Ig"oDSdß‹7œvxÇKkù¾nˆÌùÞxÕKäãÎ÷~í\<íò¦amVhwã ÔûïÞÿPKò lHøÛd9+pkg_resources/_vendor/packaging/version.pycÕ]sÇqf÷´ÒN:‰Ì °9c0„ˆ/‹„ؑɊ€-—Õíè´§½Ýcw%Drz1®¼¹Ê•Jå£Rùyö/ÈCª’ÊSò+\•Ç$Ý=;{{H88É "¸¹™ÙžÙžþšîž9ýë¡Ò…¯>ûq¥ð¹öˆ³8àŒ¹ðŸ3Ÿ±&g œ55¶ ±¦ÎtÆñ™Æü[(°´ÞÇúTÝ` suæ˜ßÏšlaÆÀcèígîs‹¬ŠLX£Ä\ø?ÈÜ2s‡˜;ÌÜ sGXÝ`ÏàÐ?Ê>gl¡ŒÅ[æÌÝ…=Ïûd w3Q¡Þ=Yï¾GŒPïÞ¬w” ƒ5v1wŒ*»iþ=ÌÄöá{/à×~ø:ÀÜ7dë |B´.,ìeîaBdŒ¹oRža ûqYé»Ìì]0Å8½¡^z”=Bdî1ê‡YSå0’l¾úÐÞC&Tu(’ ÎRúk‰°½f+Œ’Ùãzë^ì…A2 V䉽¼Ôèšó8Ç‚@oË^à%O“>u¢X$ýP»'"š`ꊺS{ªz†iкã{®êB4îÍZó·?š³ï\¿{wÖš£¹m€s‹VX[¡¹#á ÞƒKpÅ:}·"‘ð;Œ÷Úã×Mü`ÏM”¹I¨<f cm†¤š¿ìg…„³Õ‹ªŒsžhêÑÇ ™óU FĆ¢dÂß\¡™¬³î­‹À\—šqTª›Nàš€ÉZ˜Â¨ÈtÌË5߉ãËÒÅ<2Ã¥†¨%4]˜袓3]Ñ‹“Ãk¼åmÞíÅ4—cQÍ;³wÌóç§³ÇôŸæV}S4`Ž„ÀBÚXHWËÈ8‹Í¶Jâ‚E<ÅÒšç»g–\/N¦šN-Œ7&ÏNOžÜxï‚}áüQ¯Ÿi­ÖíHÄáZTñpuÃèLË©­:uXÈ…Eë©…<;Šs#¿™¡óa>Ä3S¸Ü@¶¡Ð†”,„5OxÆ·_®¤Peë~âÄær¸¸§ÍµúÌx%\ó‘?ËÀ—$T„’Ä ARgNSØvR¢F3t×|löSÓ k¶Ý¡Iσo›Â¹5¢KRÆ·ß±Oåc+îäiô9‘ +:*?V h/±Ò‡V+`+û¨Ò+hÕ°RD*#A2-Ò”¡VKjpRâÆé ©áНPÅ^O¥Ha+þrOÉ–2_oÛù¯i)úºZÂn&ñ‡’§tz¦¥ê>—ãgÁK`WY¶\Z ­™„‘ʰ÷ë»â;Í%×™¹Œï`]ÖØ®…M0‚°²öa7ªwˆ¦¨·ˆDx?±íK½!;ßJvëoô\”ßí"¶u(Élî5о`ˆ®ô†¾Ú«¥ïµ×‚¾â±m_í }û^-}o¾ô­ƒüÞè } ¯–¾·^ú‚ýí }õWKßÛ¯}ßïçè«§´Íèû6“žGŸ( ‡€b¾MAECÇP>ë[t‹ÈÓ„€+ˆ'¨ kö¡Ë;&·›-_4E×ciàÖY4áÕÉJèö–HðpnƒV^á­Šh[£XìÂb?obq ‹q,ÐÁ·Želc¬×ƒW*¸ôMø"ßÝndIæÂ@ìÂfÝ–ÿ’ÉsHb4yËñãÂ’ˆ^l·"‘¦ýßeëÜ ÁpŠmvD¢tЭ²®ýò$§°ÀD©e+ ["JžZg°{ d“õçÙŽlž¨rëlžÜ4+ù/¦]ä{Êl›‹ÎäObåÁTÛœœ ôGì(pkÝOÈWXöÇŸ¤‡“ "ªQãZM¥”i5äÞT6|d`ƒ§võý‡‹l“ì¬tžÚäUmR¥ J/‚×è:{<Âé×jÌ„½zÕ`Ñy\Ü«a¶{``Ÿ†¾}T¿»ô=NšˆxÏfS”â&§lúì¹wο{áâ{—IË:I몢>$èÕ¨Í6%$%b@™ƒÈNZ·|/IŽl –ØwjääÙM§Ez]È4öO–=ßï8Û2ÇíDIoÅ÷/›’ù’øÒ¸­Ä‚ñ1¾KÛÍ mDÕ†ôšÚ"3Gø+FÛ$pªÎئÆ6~™Ë¦¬ýŒmSuÖÐeÐý›È:“Û8ÁÀqŽ–±„¹WU½h@ãñMv˜žB~™Aöä—yÈ&AbG߯ã°û@æ6½DÓØ2zçÈã9ïŸðgQê§ÃsÚlN¦bR1þÑë}e&ýð ¨2J¸õ@¼'^²"Ï*ÂíkN 3û›¬—OîùeVIMBd·nö\é'`Ê/pntâYŸQ0ø^ÑÊPŽêðÑFyY‹¥§éöõ«2i~õ2}§õêÕ;Wè˜ffqzòÒÃSãWÍÿ3 87Ã+©ÕL'€9L¥sœØn†ÞŒEõ§k.°B3ßðú-süd:_)ÿdqÒ~0õðjW_:¿íÏTöR»ÖŽjmÇo­@C$NµS#81ñÒ“Šnǹ*AÁÆòòk‚%¼¹Ýš€²“jB;8«^Ükûù!]í­&+пÚ@Šv4ñí‡ç¶’ÿ&^D W¬+žü¶ôy›ÖåËqÁ_ÌÕ ¥DN!0YÎப„_N›õ€d uÌ$puÚUÊ¢Z4"Õþœ©¨V„]NØ>0û°£º vϧûUœ; NˆŠê„¨ÄÄ`.¶-S3‹m‡¨™Å¶ÃÔPÍ 5‹ª9‚‘/DDòÓñIªÀ÷ñšÊRUԲȕKßàiDŒZcñ4º.O=y}Æqï‡íÑ%X]º£,`¼•ïÿžÞgE®, '¡1€ëà JBÃê’¢‚ 8\Ö‹4† :ƒ9€2Ö[QÍ!?œƒ¯äàGÀ(ziç¨ /™ñÿ ƒHé2ÈCª2¬*UQ•QUÙÅž”AØ-#tAçÈ»Ý}pzÙ<Áê ڃ讀…~kæ­Qº„Y9˜ïá(9h*kn•¾%´Á1^ȳ2,¦¦É•òzº©ÅE˜òJ]b£ÍüU9â³¾ƒ«ÊöX´ãY-°Ð‰—'Y0éÑJ;™«Ÿ³Êj2 Y- —½ºGÍØÖÅUcáDµyØ~‹¢š¢…k-ëCìûx‘ìí¸a>øƒ"ÊÒ;9Ì€z@¯Le¤YŸ’b ­—ÖFˆË¸â¹ŒâˆB§é$µ•Þzýü çÆà‡i»¸Á÷ë?É«\çeð.±×dý`AçÅìß–”Á¥_ÙšŽ‘ŒÀ{!;™„¡ïkÖ|ÁjvSezÐuæ+èR>ºH1 ùÌhÕS¹Z.C |¬§Ïç™!íS6 Ó>µuµÈ¢_«q}4ÎÈ3òガ{@ ý£ÚŸÃh­å-ƒŠjÆÓAÅÜ âöƒJjÐ-5¨D[š\â`ÕRÕt¹ v* (üsd×hóA'{ðß8)9¥ý¥aâÆÚ¶tl[Âþ·k±öZº—¢ñl)t'h ­-0‰br ½¦ÀÈBqïTþ[é,V&‡ðµÒdßV¦‰BþFè9+~v«)Ïeö?è¹ñ¤ÕßqîCd¼ }?¢¿ å|Ž¥ƒŸÖ3Kåð´0»}'múed®ÌS,³0§ˆãò²¢¦XEûâN™hÌÁíQJ³*_EkÁTdOMt·å2zo¹vZÆ; `a‚_¦P¶ÑËf©³£‚ŽØýˆc‰D t­‹â$ Óy±Þ$9ÀCsƒE§‰×yA×@Љ 8zÎz„bηóÎ.Tu•ˆ“7M{4ðW‡½Z|°­—eKn0·ö«ºž¿XP6l) }ÉÚ²2d;¥É˜>?õœ&w­eä¹µäð'q)ËáDþg:hWéè ;?Étyݳ͞/,JRÓýëYëÆGó³”~¼ý½¹¬Ù›×çg­{L; ÿ)ÞÅâž7 ÇûœƒC3ø ß­õ⛕Be¨bT ÙIyfz'-\´Nù~ð Xt0M8¹<ó&ÕAå0| .ô'©Sf“„þ!vî¥ÎARÚeôJ±“†'ZjA13 írôì€ÜÐÍ­ ¤Ü?“"*JÒÆæHm‰l.Y”:X±¸”‰‰ÝbM¯¸Ç¹Ãù”<¼{D±£ °Qie¼HÕ`­¹ÔãÛŸÖ'0åyžsʼ¨—û äéGáCº¡‘EY|0eO>ÜÅM²Œ[àêO -ïa$jídeæé÷ ´ãáaeÒî:«"6uß÷V…é,Õ¦ÎN%O„¿.èz>^ÎM/1½ ÍêQ8zÚ<{Ú<*ŽNÈ á[wÕw$z'Òó§ý #O <ÔƒbGžßmu¥š^ìzu/yŽkrûíy¢¿{û]ȶ_. µ”'Ì@$Rw'ìX´Dä$açü°JÏ ÄLy—«ßÊ\ß²†‚„Ÿ~%=“6\&éYIéQùÃgZ'0ܤ¬[j9éØ)«T´¹ˆÊ4¸©‘qÈ [Ø‹,7ìgT§Þ‚êý-¨³Ouþ^‚ö±` –™×væøÁyå/é8<[6”¿Ðµyå/é¹é%^-3<’-Ä¥žûutIo…§—ôº|eRž‹©òLv\RyC.:žšp°œA y7Ø&3*HåoÈ=LwããJs,½[}ævV}¾è¨KÅA) c„K¦Þ‡w'8ÐC“ ^PL-7 [OVp×>›-…ÜßoLÙõ–‰xÈÆUá=Fü9ŽAÿöó’´éò[+k¥">Ò«xã/ý­ÌòXWaÛh‘™E‚G;%Cßô²ØzŒOjê º´k5[™•´mÇ÷Óáàïq\:"¥„©•Ý™¼çøkb6ŠÂˆrª´ÝÉŸMÑ@y•ÁÅB`1ƒÅ5–ÒÒ™'yLò'P¸‡Yx]ƒ ‘¢÷ÞüA‡üÑ rš"‰Cär—µ‘ÂÞ‚æî`¡X3ÆÞ7xE×ùÛ…âhñ’¡­Wôâà¿PKƒ,ÒF(¸,©setuptools/__init__.py¥X[ã¶~ׯ &’§Žlû4 £-šÝ¢@Q,¶éS°h‰sM‹*IíŒóëóÞtñÌ H ÌX"Ïå;Wúîîîóƒ•z°ÌiæN‚•´nrRÙ’õÚ0ÅÍ£`xhõeTâ™Ñ¾‘GàÔÝÝ]QÈ˨cÚ¦§Ì¢nµ·«½TBá­è¾l¨Y¤þ‡¾\øÐ1nYŸ·äô?‘·zø&ŒkFîN®.ܵ§D_[nEÖØ 7NkðÂa‚!]¬‹Pâ“»!%ÅÕ öì£àn2bÏšGášiIÑÝr£:›˜|ÿŸ$ðÛ’‘'x00=WdXÓp¥š†ØÏçôÇÊ=+—Ñ{Ô‰#¼ô˜­£—(¿ÜV½:àÛžù£°eñ…¤EؼÄ[4ëAQµvЬ#=½aö=@õïØ¿zö$˜™öÎé?3`^W²OØ=³'=©Ž`©NþfnÉ®áÑþ~=Ÿ”{`Waß#tìtˆj€…s-X'œhý)'¬³Ì ùQ] HmHj]óîýd&¾ÿuÀ‡›ŽEóÙÀ/Âúüèå³0iÝJ=¿œÑ"”q«¦-[¾¢UP‘} D¯0•>~…†»ùß<ÅE¸“îüB'zF~¨ZLžNˆCYÃYâ¹US'ÕnÏäŸËûr¿‹¬èƒlý '™qFù(ût÷![£&¤Ý“t' ¼àÿÖise¥V™Y\HŽ9 f§qTRøœåì®5ÚÚïGÅpºÜ±JÖ¢fÿûüïï­»*±Ëœ(gß3 'IèFѹà‹G£G#¹Lé–+†Ùëàøs=«Q(™$ ,âW -ªW¿qØFÒ÷ ùЀÜÉŠ.3óF@£®%Ç RÄG0N(,>®Ê^ë¼ê‘'ÁšÙØé˜¡…D_² yÈíâ«tV¨~W/À>ü-–DÒšQIWÚYö(ZÙÃ#{$“ºf ºÙÛ òȤ›¹~/q¢˜ 1ò“ÙÂu\3»“À 3Äp) :Ñ× ¡©äYÌ]@óŒðÁ ,’ÀYÀuœPÙ4"Q Å84…áˆùáš™ˆgDj+@‰"<8ºý ‹¾DIW/s(?kxñÀŠu³*Ž„!Õ²%U>Yv»ŽšPeAfÄàl…™,h“²­kBɯîãînaÖ䥸¥Éíà¾iÆkËцšï÷ñäVÁx4©±g+í–4¾UI ¡ U‡Üì Õ ]ÀÉvSÞ¶x$P×u,?H97\©LøC9G|ЦUøºÓÂ¥K°Râ-ª-í#ª»xæ4õäúòýÈ 3%³ô©ÂF#¬gð’–!aо,–Ð6ÎTY’‰³…ô9bTA©ãžµ'øÇA_(ê$µñ •·:è”yÿ@ŠA€¿æNJK9 Ã-=m Ð0ŠT¸–p•š`ù-ú!­ÃV¤„O€W¼—ڪѓ®ùÈžº3¸Tåòò+øf0_ì=›}ˆ›¶õWçjÁµ×Jé'%‡³=Pß=lì7Ä„…îgoQ €1±Cú*Ÿàéý«–C•UA7ž!(^ïé/Öjñ/葊þÒ‹Ö#†±ÉQÅ/ÇŽ³á!~ÈÌ! v“®ÕÊôh-úy+²µ>:oÂЇ65h0OJlãÔk¯´>Û†J}²}ãÂkÞ´YÌ›%ä%¾ £‰Iš´1káAnÙ`\•®i0‹–»·Å®«sêg¯„þ?Øyó}=ï“n­S)ïÀ0ÂÆ.볡ŸË>s£Ö.‡Ù_shØü¸@‰õ˵)瘨šV‹SE«Þüí’ƒCíŠVæqö翼ûa=Ô®ÞÒlû]çGób•7ô•¤šv‹Â7=ì­/šµ_Æ%&Ý4›ëY•v²iñ}ÞJ5tcðW ´QÇ¥-mXlPnéBb\©ñ=øÆÇpqËöÇh«h"Ü{•ÑïÏO ¾cï:?mûû|q×'*3δ –Œ‰ïnU=ÏûoäÎóSâs±Õ¦*,8Ú„Ó ÝÍ*Aœ%WòÑD[£úñmi ÃqÉ~¸±«½tK ßße${£ºÓØÑE#rôW¡„°ÝF!NÅ&°æ€JOžm¸‚–4Ðï‹C?Vs Nñ~‡Ä¯¨ ¨Bµ“¡VTGæRp‡1Üw¹‰B~·ÁPB¢fn1'÷S¤ö—ϧZ6WxW'þÛ_н€<¶¢a*y¥ËbùÍþç“Ã![Å"ËÕÀ8KXWyóOxB‡ÙÝÎEЉ¾~~÷ðeË|ÓÍ“7}ІBÖû ‰èf^ÙøðPWÅ¢¾îØ–LžeÂÑe\¤_¼êè\ߒÓ^>ç…ãô†t¸øPKò lHMb™š Osetuptools/__init__.pycµY[sÇ>³7],!!ƒ06ŽÇÄX †_â8Á±Mø’”Š ¶)oYžŒfz¥‘fg–é^\¢*(›¿ø7ä% OùYùÉùN÷Ì.†J¥ÊŠVÛÛÝÓ}úô¹|}NOó_‹óïþó¯_Ääþføûõ¡G”õ¹ô(iPæQß«ê ê7«z«ª7Ñ?lS¿CÚ-Êfh8KýYÛnS6GÃyêÏÛ6Ï}Žú 2·CÙ" Qÿ˜}6CÙ —©¿LÃãÔ?NÃê¯Øg³”=OÃÔ?aÛs”¤á*õW¹=OÉs”0ÑEJŽQ²DÉ2mÏPÿ©Ú}vOSÿ4Öî¿Dê õ_¦ä8móÞ~AÉ ©WhÀŸ§GD‰¾êû”œ åKïɺ÷Ut힥þ/I5i÷5Ú=Gýs¤˜@‡z¯ÏuL[­§µIµÝ„+í¾NÉ)zÄÖH­É£.…k`ïv÷hª¸±oT®Ó"×¾)|³£üµ$ÕflÒL¯ùƒ¢ô³¨ÜV>Wâb8ÊÔ¾çeºÅCxVúoþÛè²>É@½×‹á0ÊÛ±ÀE\ä÷TiÂQdvlïs\ òadâ8ÒÊvÎMóÒmV³×§Öú7UdÆ¥2Ǹn+Žó(©dÂC îŽÓRM­–fF•ƒ(ÓÊ´±seÆ£ …¡h°Ík˜neJž0Ïñ^´­´FO–n½eŠ·{ƒt_isË>¾ÉCUY9(þ‹ìq¡†­°v¶-6'ÿ£¦è±IªÆ¹Ù–f«jvdV»jÎÈÓNÕœ•æLÕœ£àvw¼cÏ=)/Ä-çrø½ŽF\íÊ8öÁ‡òÿ % :lM5›tؤˆ´]ÓzÕaƒ~hЃÖ–) La¹v¦šGí¶èR_kB-¬¹ÜüŒ•êGYæß:0;EîWbfsç‰?5;iÎfVªØå¿vG•jm~Þw®Ã×;Å8Kü-åëñh”¥*ñ#Í œËBëK£,2lÁó~7í©žÿEðÇKÚdê|M VyÕO /Êü0!g®LɹC4•ŨL#£ü¬ˆ£Læøú 7Ñ~oÂ’Ú³qÂL¥à@³ ª0~Íï²3ùya\35Zeƒó½)á¦ùÿ¼7´çûŸ˜Ôšž¬=Rq:`\ô‹<;¨wL´]‰ÜI&TÀß³(Áf¬ü7"“ @¶¬P¥ù„ÜŽâb³J wÇlšYº§& Íç¼ 1^–Eµà„×Ö˜‘ÆüAZÂÆ™SÞ8Û|~PQûl©qjX(n‰)Q©üR ‹{Ü9(‹!‹cbcfˆòm(ð¥ÂptG aØìz¸øx…)o-,\⢴àÈK• d!øNB “ìºbXдü´± ÀãL ŽŠ äºHÝIFFc#\»>m·`ë.àR ý[.„‰Ë[8^zÃ(.ôþ¥7¯ôÞ¼riÿ½wÃwß¹¬¶·/ËÖMQdúr¦yj°7:±éWA G­œô–øcË»ï8$PëM.¶Ü<Ú¿|[ßü„ºíJLÂÈõu“4e@À&•×Q2hîÍ ~w‘rBs×Ã,ïñÏ—÷ß‘V`ïo\Ôê»Q¹h~Tù×.%]õ²i$…Òùš©Ì ~:Z4e—7ùtVûŽç‹5/ÇJ* ÞǤ¥ŽÎÝ"Í»í*¼ª’geQ©€=«É4c6m×Ñù&–Y!úv$L:}5œS6ÝW¿ÇÅc^øXBVŽ‘Ì€#ø™èê{¢ï=4|GðËõ:ÔØÀ´oƒ&L:íïuxú7Ääí&½*nÊnÓp“÷³h¸•DÜ=+® í·+“a¶6¯Âí¶™ÅØè ¼<l)y`öiñ¤5C Ì즜wês +Š=â8«NƒàÆa‹Árár©8PŠUp›oT–Ö»"Ã,á7Pœ8"áhXÄûÛ*ç“°üà+„ t¼¦gW»‚춪u-—*ÒãÔD[™² {’ÅŸ /8$?,D%o¥áN¦béWÀ‹  +ÄUša¬Òœ¥ixóÔvSµaS 畈9ZÑbÂÖ¾†lIR•Êa’ß°S ÄÓØ£,ëú»iDû˜ñªŽÞ%´1ÐÌögP‹=ͪÐÌ0FÙ 0L0n1ÛˆcQI¡æcâAEzrBÕò‡‹Ã¶õ‹VþÓ\³­Û”Ɖþi‡{Õ9Ü)8œI¬ŸyÞ“Îd´ÈØÜ6hÔ†ö+ïÕÀm"°=zÏØ©4ÖqK#,C¿©9°G²•ØäÙϵ™·xúN…\  ®>Ýü¹KÇôÚ<;SÔa—6¯'‚ ÃPb”0É8Cg‘ÖCÅùd¼Dîö@>ec×»\C <\|BVž¸Ù‘ø˜ñÉE'À´“§—–—æ–æ—ZÊ·nÜzç­+Ͼ:Àþåêà=yuàÒü&Ò|¦v¯‚£–uûØÙìÚÿNö&pbí}¿Cña%Þ#–ìG$WÎ'¼§¥vqZj Æö†¥ßvÄÅ™Üa<’û”ÀÆ q…øJxrh/Ú#ØÛ¿ ¹Awmë›gèë†KŒ`>2Ž›äÝ}™C‰Zµíº‹1gÈvWvqz6Ôró¾ÙK±µ¤#¸M9•÷îK¤²'å½£“-ä÷-U±YcÙ;í¥¨ÅÑÌ´tnþD:ÊDQó'"jËM‘çP.ˆDDgéwL‹(™ãô.˜J£,ýV…±•Y Ö±W¹ÞCÔ$sÏÍJ=1Ôã-׫ƒ©ÊW‡Ið f~z¤ùOÿ U‘çš§½^wöIo¸V1†I;ß”«È'[à­æz<äl=*·ù—3sщ¬qÄ~ãŠíŽ7×è4æ:uŠÜ©åT§Èfþô£äO•#6\²´× }[¼¥JŸP¶éâØ?ã»à+­¹³ëõzµZív¼ªv;öн[1¸Ö­jx~ÞáuÚݹ—M)«áÇM¼Sˆ’·•ÛÁ'Ì:õºÞ(#r}Tò^?‘U”È´Úl;ÐYHXâ´¹‚Ž÷«•¬m ¶ãß`8þÕ6þ²§œÿ5ÚÊ»†»S¼‘kåÀz%«Òèš5çãΫ[“ƒ×‚P¶5¢’²ïý²–W¿Ëæ'4L« iš³™0F›NÁñþx{µÊ+n-›û" no½ÓÖëïu[jãX·‚¹“èâç® àÓÙØñ‰5yZX×ëz ƒ kŒ>Âvíf9„þNÿ ¹Ö(Ë^›–òƒÁ†.¦,AU^‚î•7<Γ…¯E˜v&¾Wc¸>Mð ‰ðê­Dþ Ù`û¨|Ïœfû}ʬáÒ ¶ßÏ]¼ß¯H×~‚cϤeœ•­¢<„„:c¡¸‹/ÛZ(goAÀ§£B=Á(^!ŽaH’ÍÍæ… 7܉b›2® Ô¼Z'jRÁ.'a“Žt]$øø ¢¿D‘1†ÑŠQauk]ô»£0ZÈÉ".èQ%—“ÌO¬æWÔ‡¢œÅ¸¥ßàQµVJµ%‡‰Šü…ÎÞ“OíY6¤Ê¸#Ø(Ö•ÀYÎQkÑ\‹ŠA…¾ +éŠ>gº$ }ݧˆí"`ÿˆQ³($ÁY¶÷ À ]< H3ÐC.°YˆqÈ!È Y2Û6M%E‘z7PΔV/Dݸ+³âÏV(ˆ,@‹Iˆ$Ä(¢'ZyTœ IÓ¥LRKÕzw–»ä7“')3=ºÅìD¤ áÊ è¡&êÉ;FˆÂ;c@!4CðÀHŠv¿ÏVÏP*àt é‰I]¡üк¯#ˆ-ñeŠ_‡l€zÅ݉ƒ7AwÊ}Öåü_vh½Þb P.ÙU·ÃÝVW,³>«¤´ùZm%6 Ì;R·Ž+×fdêÑ‘¶Zpe}<öûq3ƒåX©ÝíÐXàvTF®LÑ—¿´)„É"GÑ7R¦G„’ÓÃ\ˆo;ÎsæÚÿé·ýD*ÝvKÅ].·Ð`ÆÚ±ùAÊŠ~°ÀXÄ“ÍjþÐgÆB -_ÿAå}×*F™zËžÛ5{Îâöº¥ÛqGéXçÓzJß=BûX¤A3om¬*ªpbô’çTáÔù£N–@]lC¿ýóp]á9Ôa·¥í~Mê7!úŽç[xæéºã]SqèÆ@ê¾øñf>cÆi ïC"XðÉl€n¤£A™màškf‡˜ÞRßýí¨˜¤*5ÖÓ}†¿*8¨$ÛqnãJÈ?|œu”>’x}O1q^å««Ö‰ÀO`æ‘0ue™o±¢žÕèÍ #³(‰“ö×n²lƒküs˜õ=š`W_O`…Q*9QýD²ðEñ L±HÑBýþ—XfÜt†×“¸d> xµtÎþ$xÜqpÑ}f/’Q®Ì…)t#TP—²Íå°¡ì,çÐð*³‹C‚fÆúZ%ïvÜÁôv€Œ³1Q!¾t~£Gì»ïØËo¦Þž¬œ†„ÉO0”v('+&|FÊÿˆ/AÛ |²ã=}î¿þŸè3À~>ÃóŒâõÿ'~æe°¯@\G@ÆÉã(ñšzÑòÑcíis]7ˆ•ަãÁ°³Dƒ9·ËòþET–W'ÒÄohPÚ‘>á°ÄÕ•å'}Q øÅÄ=GT¼>œ} γ· Ïö#F¯E}ðÇ¿n‘ͽP6χX>“ÊÁƒ‹tŽg0âs”x §ƒË+YïüØù1 ¾Àpø°ú ÈÉ•TgKp ”âf1GñA n‹„¤0Oªør>ãÁaj)†ÀçFˆL%ÁëÒVêœPsëîØkl€b¢×J]ÜðÎ,vƒŒÕ.kÅ çHìlñýiÞD½É ?æü½€«×0˜OãóÔ€.ÇÉã냓_ÅòØAÈü½ÁÂÙÊÎ9DÇψ£ðàî¡ð”M8-Î}/o@uJÖPª (¬h‰ñb÷ûÝí‹—ï\6{i1½ž±·oß²7ÇÓ£R18±\C„üWÚƒy8G&äþ£W4!øe€Ä˜7ÔÄoês)K _Jâ¦ægQˆ¬ä ³xT ¾Rí‰K‹¯ÏW«ù;pïôåF:9O¥“yaõPKò lHq¯ÓpÁ -setuptools/archive_util.pycµX_oÇŸ%)R¤(‰úc9±‹äêÚÝJTÒ?Bê8nÝ8Aû" ” ºl òx·”Ž<ÞQ·{)Hµ ô%€?C?Cч¢  O}èWèK€´}ÊC;3wKR¶›>TÅãþÙßof/ûÅÒî_ž>r ý+à÷gøUÿć Ðħ7nܸsàæÁ-ÀAšØ>nü 43¦œ…fÖ”sÐÌ™ò4çL9ͼ)£œ—KàÏàÍ" JÐ, Öð`P†fës ËÐÅeËð àà×ÍEp©Ò\¹DÝ%x†úT¸º Ï4W¸\áò*—W¸¼»°e º¨ö:M߯®’õ;øx¤=ßÓžTV7Œ,9Ò‘íh/8°œp0ËŽœCï·’z¶Vz çÄÁÐvú­´k¶éÄv=ÿB“¶£I“+»vìë6hiRâQI'<¼é~Èkp³Q$ Zn„‹DJW¦2]'é0{ÿÆ¿½j»¸_*Žä´_¯`ãûa Q^lûMoø!êR4žzà)㨢(Œ&þAý?§¢1Ø €Ž¿¾ÏsÕwXlì»Á¦¶&XúPN6L‡²š¥…æñÑjö@¶ZºÄ•AèÆ>U \uC§ÕªÒÊÓ‡º‡NìùîNÇE5kÛ Õhûí·jo¿µ=zg·µû£yp°£¤Ž‡: }µ“®Ý"“jÃq=‡"ø¤iƒò¡ŸLjßûÔNN¤V$¢ é1YÃ(<ˆ¤R;ÉyYŽíûÜÿwÑdG²F1»†…=³J à!ãUäð¯«ôåšFB¯Ó ã%sd¥1 1 £}8Ͱ úÉá,ãu8ÍÁ)›}šó,ˆF°9- _‚è=B-þ?FJØÇ߆fjÀ)çž ¢Š}>Yõ‡90¹¤Õ&ëéŒÛ–­vê¿ä‰í- 7(²=%­vûeo·K% ÿÚf»Sx´-OY¶ÕÆ¥í>áR‡ècñ@ZÝÁ*Œ#GZC[²½= lŸô˜uÈêæÎæ¶’C;²µtooYvà’|:µ±ÒrÀ"¬ãCIËÓ,ëØÃsíHà ҭYyˆñk+z/æJ…ØsÍ„©VÕãCÏ9´ö˜äÑP…›eÙŠËa@(…3½à6o˜ôy¿ö°«Í{ªúÞEéC[³Ú4lõ5slÒ(V´\L‚QD$‡a¤­ueYfÏ­°ËŠLyg‹t;–h?éZ)h‡›¥¦{‚j°,Û ð¢9¼ª–žqJfè^×Rñpè{ÒÝJ¶µ­ ¶å`¨Ç–’G± ðdQ5㨑‡gd´ç-TÞA`㤛‰N3q™êÀ âd‡'+Oœ·™w’=3Ñî•ÞI𢄱再f­igb…9yRDºÉfÌÐ`z4³*`GäñiOíŒÄ6»ÙÆèž¤ ‹sCŒP´z‚#<[IŒÍž’Ì#"¹rthãn¢ì* O¼Î±ÿ‡…*‘ëÞFUÙµÆa%õÀKx^@—ÇížeaôOÍ¥ó<ù;|”¥0r6gy .L^ÿ(g8›‡Ñ8ÃQwᬧ8-ÂUL)¯¦ËÏÁé<µgx‰,LÛsiûÝ££ßÁiÅŒá¬æ–hÌÙE._‚«§ ¦iÔpô'²·žÚˆ +$³Qdz,,™,¨^œ©£ÆÑ/ ©ð>ûú=>n$‘îºÑ„t·Ð‘ 0qðéÚ“'Éá©„ÿê„2õ5D3F½ð3«%œGQÿ–zE·&wДÉììU)ÏÒäÒ¡ÒäÏÄšlñN`çöcÛïs¡zAœ†ýV’·±ÿ;áp̬© ’u•\¬N¨“Ö)ÏdñÌö,°ƒ¤Ã\Oq‡Úú"_2ªºüìò¢ˆìyÉyÉ}dÝ ‰s«b ARɼ)*™;ø½"ÖD>“%,UøÐÞ-ø<˜ÀgŠLм¥L჈JF<_¬@GèœSîõ/ ú z"BAÒËØHÞ}ºuQK!méç!:£û,tž\³WâtmfÌÇ‚ñ—¡FÄ ùuž êéD¼Ž>]æaˆˆàþL…4\LõÂ:¢¯؇ž"Ÿ¯¨w½e‚MhàõìWiB…îˆ?%œ!ºÏŠ®ÐÔǵÀÿF2ûUò-õ%L2F¤÷¯ËÿÀ¤Ãª"]‰€Ä4 Ë1ÊJûkž21¦z»Ý¦Ø·/å4Ф®D} ”1莆¾A£[f’¬éåÔÕ$IRë/`–l§u듾Vc´wö<_P9š˜+e‰±kf×çMŒò‚nè#B‘<AiEÙCOa¢¥ë4é*=®™™2pyT}’IÛåB8Dhòq„Ÿ^LÂçÖ-¼¦FÜçbìg¶y‘ ×',ˆ´ãSý¦Yȵµ]§›$GÒ8ðF,ÖëÄÚÜ£.‹H—Ç$‹%Î/‹Ì2⾘½‰ØC,‹<~–3‹Ù’XÅÏòB~Ê%ÃE9ãµ t€Ho›x ¯t…ºKW¨Ix¡5# QG4q.âóP½•‡QŸàøà‰#Rª(ª˜'†Àå¨MȤ¦bÚÔ/6â‰#Ø{eæ7a‰ÑS‡hí#Rw‰^"VRãe–©œ¶Wˆ¦7…^Þjª Y;ÔRæ`\`Ú)pËZJX Ø ÞºiÉQPnL5øŒWºÂü†Ë¼¶ÏÒYB,Ÿ |ö®²…¯1—=§$ GàRtŸÅÕ^Ÿ¦¢qô‰àó¸ÆçñgAWÚOÄã£OÅÑg⨠øßÐ×a¿!9å 9}5%'DÏ~k'üÓ9ùÁ7ÄUi6û_¹*í¯¿i–Úy¥œp0¤ñ|ÅÃkÆLÕbãWF"ý6 }¥âBúJe/yÕ”ã<Ó®|¹g2»ëÛƒŽkßû˜d’àY~Mß•}Ëkº³õmC…íˆ_ƒ%ÉQ‰³~sæ{žáø!e{)ï…ÇAý‡´Æmz|ùµ¾k’"OùA?-©ñ€Wó½ Ï׊"eM(xÄ)Z!I˜¸‡†è?ÜÁ/Î0=ÈA/yƼFk}Ì'9d>mM'PÂöAÒÄVò1Ðû«W’wšŽ…l.+‚nà{ƒ–«ôÄR²þ& ƒºE‰KëE'yF²Þ!‰…,2u…®?™J¦Œœ]ÌÜoä6EQ”™Ç)Û»É쾊½ÙÌ:f~+¢JNQ/?hµðêÜjÕ¿K­?™ãuzܧǻ4’¢ß°ÐBÿç÷MŠf+|fé›Ô_ÌUv!‰ÒYã |s㌔R}rã¼üWŸ ’kù=~¹Ia7Ÿ+‹ålYL?¸#Ùâ\V”o”¯—o•·ÿPKƒ,ÒF.}ÝîŠ.setuptools/compat.py•QoÛ Çßý)PŸÉòƒóV){è4©“¦-j»‡=!ìà„ ƒ ¸köéw`ˆ±M»h‘¢wßq¿˜u½Té³ÎØh2C•‘’ë,ÛÿØ¢•/Ti&f¢•èÃåÛbá ÂBÂ,c-üV·‚OM4ÕF1qÅ´p1ÆõÀ¸acD4ò K>JѲãž(M•ó·JvèÑ¥úü-¨ÂÚ)îΆjˆíæîv näB€“®>$o‘,/þIuä²&\§„>ä[ßBæ½ÓÞLÇ©0Ìœ´Õá‘éheí%&.ùdLÏY=%¸ƒæÝ?=í©‚K²Éõb<¡üôy€›¸'âÀãé3‚7±ËÎ|»e—.þ|ãt\Š#6çÞµ]úûïÈ«f¨Ÿ,X… ‚5'þѸøÆkóÖ8^ö–mU1( O«ª'æd[] M5† |âÆ»«eº*ŠËžŠÂµþ“RRèûÃo ây&4Ìævöv„£Ln]Xk“ý†Á.‰;{L€PÕÂÚv\0-YÈœ’¾Ò&¿¹¹‘CŠ*Â4ÍM_ Â8ÊÔ»¯RÐ͈ª £Y¶n<ÏÛϡ뾞¹#ו¦,Ýi’™\2\€ß¥;'Æÿ‚¿—¦™ÅβhKG-£W2[6œÁ[ë a×oð[\Ág"ÁÿÁ™3T³âÒ®æ`®© ³ˆt¿KˆJj)‰k_´±Tca¶¡o y‘, £¿>N13waW_Ñä)lã$ßèÿÇE7ïò¼Âù*Œ]Û1#mihMš_ðveÚ½¤M=)'ðÇ ¿™9M{rSo²„,û PKò lH4nüÈ1ó setuptools/compat.pycµVÛrGí•|“,[Æ7n†ˆ»|“‡)¨T‘ª¡üyQ­´c{Í̮؜ò¯Ê¯ä!ÿHº{vÖVpªâ Öz{{zzfΜéîqùωêæoï·ºÿÊø~‹oöG Ä?€(t„`¯áx= ¢ ² 51rÒ_=‰¦aç=bÔéc ÆX/ƒª€®€¨€'ñS…p>â"ã³Rƒp„• 0 jtD¼|²)SÜ7ê èiÓ¶¯jô,ˆYÛ®rÿˆ9ló¤ó Ï‚8Ç»8âÈ‹ .‚\±òˆËï|Î9>7Ÿ˜Ï/™ÏKÌçeÇç<¨û ¹E¿‚½ŽÌ³ÔÌÉ´Ô’~Ô׃¡øS2í¡1¥kL©áyøˆüb^ùeó"FzôþžGøM…CñÒ¤Q¼óý]²¸÷)åÅ(ŠÜ)ú°ûs;¨‚b»wÛÝ$”ÖD"iRR±Èî£èô#®uÂ(3-t“ìÝêíõÖíõÕw÷7Û›w×äÎÎZ&M¿g’DekÝD÷Óêí3¨oT ;aðh‚f£)ÿ3ºšC·£’N 2¶ú%íÿãó‰¾Éã"s¤Ûít Õ$»!Œ-7è”zIk¯¢xöêÕ‹—2}+Sk;Gaéž’ÔãË7}™™gA*ç1âIÓÿ)Õ‚€ÇDNddН>¥ƒ™+X(»hè§j=v‰ ®¬§"c‚îu=èÖv'…¤'cFL{þ.M“”où?Ø»Åoú‰‘ìÆ³ö3dlØ¥ÎÒ RÄZµ~l›ù {t*¹ŸÅTøq“Ùåv#•ie²iz+·êË•†é<|žÄrñAµ?în t7‰Y܆žì™ É V›3¼Ý>“ZŸO½IØý³$Θ&AÙëS­ñÏ’ üìÒô–܉öxP‚×H¯pÓ£æÞ{tç°’@ÃÍ•Iƒ®ìÝר²Ÿ#³{h´…ƒÝ{̧”5t>×GG˜gõcšl„¦ôêÞ´Çpíýˆ–$-ÛÏŠÚÉ3qåÂòEIÜŽâí„Ý^üt'ÿnp%é`ÁÎøvÏS‡àš(Æmåà±e'{šÄÛÑÎ *O)W Ÿ.Ÿceˆ5bk×h…•12ûXš2ŸóvvÁ¢ÕawUØK†ÖP4^2yGmÍ'À†VR â­äJÛì÷¤¡5tð«%¯„jýbÍý8êîºbQ½²Œ™”Ï®CeÏ:¦ ÑÙ ¬¹Ht•{6l{$*#u0>™¸hY”é6–$É4ms3³\øSŽ¢(á8$[Ld„Çs[]¡‘!çjÑ•1g¼?¢‚¾´÷Z±‡–ä›iòÐÚ»:7«ñ·×±N—‰u (|®åtö•|D¡”aÒBÍ«•êÞhiÄñP÷¦ð[ágŠ[ôTØ6ÂÏZ›øTÊãŘùbDõAÿy´-x†*¥¿PKƒ,ÒF•èâsetuptools/depends.py­YmsÛ¸þ®_úÆu¡uÉÝ$mÝê:¾XIÝ&¶ÇöÝ$u=ˆ-œ)‚%@Ûê¯ïî$HJrÛ™êƒ%âeß÷Ù]Z­+][f6f¢ÜOøj®EmV¢˜äµ^ã:óë—û˜œž]-Þß\\}Ùå×äýÅç˳O‹Sz¸¾øùêý‚~~¸ºøûâÜÈ”±U…™=ÊÚ(]¶ä®m­Rû‹[tg´Meµ.L{(ÕëJØÉ$IDQ$ ›³Û ƒ¿’ÿlT-yÌx®Ê,Yë¬)èñ^Zÿ”¤º4V”—å³­EjÃÚän2I a 󴎉òÁÁÁ «jYã¢QV2«Ù²QE¦Ê{¦k¦ð~Qà“ íjµu 7'D"“9KU*›$‘‘E³R¬e̦4Vf‰·EÌœ¤1[鵬Ľœs‘ö#¬c ç纄ƒ¹®×ÂÒÃôxÒU¹ßaÊ0Üd¢Ì¶ân©-8ðñ·ç#¿ìf°›Ä6·¹¿mmM7x§g«ÀöÀ@—'-¥$áAJ´ö,I2Ð IfM• +£B§¢0Ñ4ðÌdáŽâŸà´¼ CW‘צApíÄf]ÒV‰ô|õ]ßûÞÅOßy±0zê·ÿÁµcÇÍÑ¡áì‘H3b²›VÐÎßí.[“é—íݪg†q¿Á™iò\¥J–¶Ø°¦:²úúç¾~}†[~Äœ¡Q|Âò?*ƒ-£Vö›9;hʇR?•Ê­Å~œï±eÐÀ/z5CVÆ'œMaçù~V¥í˜•Íz)k¦ó6ëeÖe,Gr€, ÷4{x-E®'ÎÓÀ_œ1v–“ÓsÝ”YÜyšÈ¹]·36¯]IæQL{töJ‚1WêöTG*xçIf*™ª\ÉŒî"ýGQ4’¥¢D—Œee½V%0|Rv¥‚ša/vÊÝ •ÝÎé(°HS]ˆ Â•žz¿k1nº»>Z"„†r3YSÀZQ9ky©Cö7UU€:Á ³¾g'[ ù@ÇÖ›mÊã*Vˆl¡ì¸ÜôAŸn]Cü9÷!YFœ-úÊ äJ›ºþ?É…ö 0»GÌP_÷H:pZÈÆ½^øRî´B¯dt…f2¡š£‚*“þiaäüªdIé*õý”ƒETM(€¢®d-¨fª’áU¦—¿ÊÔ2޼ËTê E]‹MÛÒC؃úÛîüåä—ErrõñçÏ‹ó›˜-¾Ü,ÎO§¸äˆ-7V0‘ˆø’ÇÈl–jÒÀLÐÏY!Ëh¸G›•­aóµ;ølÑuYêÑ"­>­T!ñÜŸ€P¯¨è Îÿ[ؼd”®~œdïÝÃcÐ]~õ掽ê=~÷í÷oßÁR_¢ûÕœý0$Kœçó¾™¶1e¤%þýÖwä³B—÷‰ÝT2z÷öíï¶ñ ÀŠCÓC# !v¼C9ʦ"¿ W7P.œ|ôõá·…²­ÄƒPúkc,+ÔƒdBeÖ¿6…ê ˜G•­í騆@@uAX‰ÚbÜøg ÀØˆÏøtàs<tÃG¸B«³JWÑë`14tØY=Ç@XÆ Ö®¨2×ø5’)íd¼7Ÿ&³¡‰[ñÝ7dà-oG~7: ÔqÀÂw}·Ÿ‘‚ø©…2²_”¢ƒ÷¢ä–<ÃqPb‡æ[Wº;]¦^1¨°÷è®JÕ©Íz©‹Ð¼½y»u÷dÎý4‰ †¶Gc‚XßH1î(ûÎíªß‹¡};J™–ûå34ý=X¦Ö š’|@·Ä]WÚ$Æt4c‚µZǽŽoâs‰6€Î¬ÕO`ùÐ8v½N³ƒ¾e+àEkCno"yL|¡ùø†}öú€òèz2θŒ„j9+Dox‘0I¡ÉYôû)±2ªbkq¯Rö[†µqp–Êȼ}wðóé0ˆ;vîýÄñ.˜yˆP_þ%¡êQaòvÙGνùØIÑ"òªL[_pù,S>}¿»YfôZZŠÞ'jË1ü#}ò¿PÒŸ%b!¶&uKlYEÝ[6×m´±åˆaIl•İ,¶ÊbX[a¡‡#âªÖÄVM?—D\ñ5CÏeVDXaMlÓðS-MÖÅS!žqo«!Â.‹·¸¿»¶Øu„*á´©³EMŸrïnswX÷½ÞC}J½^G¤ ËNšHñPã.!f¯ÇG8…¾’\ÓÀsËxÐæc+d$þPªg¨=É\ɰ˜‰›ã†üt(G>:ÀDð`ué)i6ôUzã"“ Öõ¥>4»2ôƒ4ß_~íÕ•×^]ÞÿÁåÞå×/ÉííK¹Tã‘JÓ8¿Ê‘LÂ|et`v%í¦ qX­pž·êvÃâ_{Á W|œâ€¾'´>Ù®q¡j­aÝ>°Å³]ÝÐmc\þ*c\³ÄŒãØùÁíñÒ4\èhÉ}tÉ(&/Ó Å|y1ï°oEÉvÄ >1…@ãX^+9yк°›Ö+° H'@}ç˜jbô¶QÂäQ9âÐØH?{ŽH߯#ú”Ä^¹PÍ"×r·evÝróñ`‘LT|àŽGË*]ÈÞcG1Nö’ôQÒiC9Þ·&y@cy*cE1¨5þ0ÎH?1UÍÉì¥{!°Äºú®å…];Ʈ˅º~¤.‹-ô¾8¸,”ÆŒV”->qÄcú+Ár‘½r—mÖ‚ î>¸/Jª,öfDvOX{îÍ„}ªųP_È,ÁcÀ]XŒÕßwaêÔ³:õŠ©Y—þiÏÿ•vU*×ì×MÆÃ¾ÌÜtPø6ºÚ€—ÜœEk ޝÊ?ŽUkfÆ5?]égÁŽÛ"·¿“·\²g3pÅu¯ Ü$UÔ6NÂ%7ÓÆ¢Åé·úÍD–é¡v¤k"-£XâÄo_‰a’¢×DÔ¤·ûÈÏÝ|$ƒhÉÇBþC?K7ð,°/ÝP*™ £„&|©t¬&¢¢á(Íœ=N6wRÌÚ¢ÜÕŽ öƒ Í8TPØ !SÛãˆ8$3h哱z Û¦}øÉÁ+Kî8‰ež»‘‚X­-³ê‰¤|<Å´#5¬LÞuÚµãvÄ^QW¸Aœæ:(_ã}­gYšyµÂà¦|g·¬YûëNlab•Gžª^ÿÒ‘×V!€´®'—Ip…SÜÏé€\:ƒéŽö;‹…BÜ÷ÂIºjøŸ(ï™ðVlö?¼Egz‹K_Ù"h‚]8¡àºÆo0‹0{÷Ý»Ÿ„S^ú˜*JÇTÁù8‚ô¾-8Ç4ãû?¨'g­ñ*ÖL(kX%«ÃäÍ;¢33ü`ˆfaLT' z=mÏ¡¸xõz[/£h[ø ¬ÞCÔÅœLH*VÅv¬æl½R/7Ï5JLH°Xhœ7ÿ‡Ð4ßF&2â±Åt9e6|ÈqÅ"ÑÕ˜¢ Å:óÈl‘¨/… ”U±ÿÇ Š4ÄÚþ.Kx<û¸&kAÊ"û³i%ºüÜYS­R•hò™ç©ö¸Îmuñ¢P ÑlÏÙ—â°Žx…à3ƒ©ÏÐ|îˆ_Šdé‹W™Œ«ƒTݱ¨Ï]zÝm7 ŒÞ‹dL®­Ž–ülû•Q«(ãÈ"} 5éHf>³«(qƒ4$€öwe ÜZœìèŒèô³Ì?`üsÞòÑ•;ë½+ÞÕo¬wn+L¹¾y{½³¶¾†Vöeýç±sø\1r¸FÕNœÊƒ 2;!0xËhY†˜i+á·±L<,ƒ‰Xœ&Û=u0’Ú0`ùÈ©7 œ„AýE¼bd:àÿ#•ñ¢)<ÂnÃ)Ha‘éˆßÓã‰\²ŸŒw³ ¶4g=kÏ[M0nÚ3vþ`Qi-Xu§B5öWœÙ_ýRL%í¯ö Äe?G¹ËHG»ß¿U°§Ò'wB¥\¥tä=„ˆÑ6Œc»È˜P±ÄƒyžcÚ„‘01“§©>ç×ôw÷ÁêæÌïGã\¹q´'Ýþ•©Ìµý ‘ ¢L ºÏ¡˜Â(#g…‘Ãn…£ÐªŸ´ˆþwY£»˜ëŒg£®ô¡šÃ£ùt°f)ß- ±›ª É™Ò9jÞ‹ˆà¡9¥b²½ÏmCÀ•=ZW¢dž˜SÃbGsœ¦]·šV›@.™ÐqÞJ Õ çIO‹B1è” AþÚ ßMæ‰[L‰ßdJì%þì|îÚãìÀS‘›Ó²H9»4Gu‘üŒ»V¹ëOvë˜Ó¼Mùí ¿ý­ Ö¡e)G¾M`t¸ÛGB·;+öª"ûË9Ík/¡'¼i¢x9½jšÔéì!ûlÖ½KÿiLÖ°0Ó\Aÿ7)ƒ&"‰âI»aóQñ!pÓÒØk¹ý7gª biÂñGjC•ÝV~0ì§±áæÞ4ÛF¨ŸH S™3/—ûtäSÑÉ1ÑÎIâ|ĈY\!\óö#"lúä“.Ñmß-.p–¦8=Ë)^œ jËE¹rÙÃQk—hÆ«7˜3#…´â«ªE!ÃðQ{õc–ªm•á¹…å²™z¸Áò`ÞŠu¯‹dÐÚˆy Âj޵H ¹L\£AŒyžJ|Î9Më•ë´Í9-–>¹ ùEJ/ó p]U\„ýìwä®q#U‚Á€i°ýŽÁ4Bœ¶·µûwÄ'ö‘ß&£Ùí³Ä2à\á&‚¶í_q?öïù/¸^.Ú«Ämy pKÓ¾»Ig¹n,ð,€f2=Êl'% Yжb ÖxÔ‹øpé)²8ÿ«âÈ1âæ¥Šš„° cDd û¾§­ç›§HÈAÀ‘õè”økVñ6£ÓécF¯×é~NIbªSêA”‘¹û4Áv‚³N™õdUCŠ€,ÒbßÝŽÓ¾³k ]ÄÒ‡ òÉò…Õ/¸|Iˆà¦µNt¬OM{œ!ûÈaõfÒ$>p[ÝÛÞz¯såÆz‹}—i¸z}ãƒ+×)ÍA9ŒDíÈ`;÷+|DaX\‘®Ðܬñ"^8ÃÜdÃÑž"¤¢£coM34vdl^ÉéÊ}ï­‚²1—££ÏµÃZ½[(ÜBçQ¸Ï|éhLÓ¦wÇï¯o\Yë­ntº·u2ÑlÞûáIú¬ü×óm›mÚ%ûyÐ5"lû,è9ë%«dóõz‘\²õobW„l×6µ‘½lšp èzD,&"ÿXˆýEñÚýó [ä=Ÿ°óx‡T ÃÖùÁ÷‚_—¯ò/àpp:7}Ed ÑËÇLÓ‡’[µ-é@ä?ô£ØïÇœ‹æ)™é(önNrƒüÍÍM ]­¸èKE¬•o_¤F¼Ì/®ÈÜ:D«¨¸ë¢Ø¡ÑÂ0Ø¥™8qÔa5²OÕùó7}C‘ÿ—¯3kÞ$ÅrÔ(X¤Ž%zû&=õãØ\Äk]èÔ¥ÁÈÔß®D¤}]|BpQ¸)ïé{ÿžYÍŸ ³ŠêÊ®+?f,=áB±3ެÞ5Q0V¾½æË§¹XÌXEq¾bîsô—¬…ÉR8Aò>EÁZ{kâ«Åè£Ä §å|6oë£{×* FSpŒdΙwVë/6šë§ÿPKƒ,ÒFÍ[]mg&ø‰setuptools/dist.pyå=k“ÛÆ‘ß÷WÀT©@J dYNη ïNK‰êÊò–¥ó£Ö[H ¹ð’€»Ë¨ô߯_ó¸ZÉNRWÇJ,.1žîž~MO#Ëòí6Ë¢Et]v}[.÷}YWñÅÉI¹kê¶Z¥¿ÕþÖÌ×›¼­Êjcþ®ö»¥jÍŸ #n»t[o†?®j;¼óë®þˆßNÖm½ ºGÒÒ?Ê»(s;ª¶­ÛNw~­|Û`ëø4‰Ì¯gÛ¼_×íŽ?‰àcž½Qý¾¡³ž¥Ã_úºF˜U£ªÂÌóúÛ¾„‡ÍVõ®É{Ýj™w !¯6ItöÓakÝ즬Šú¦Ëº}ƒk„5W›¬U]½oWª;9iòÕU¾±€ÄÞ£Ô<999)Ô:Ê6ªÏö²ºTÅtµíf§´ÔÉdrÖÖ½ZõQ¾É˪Cž˜S;·¿T±Q¹†‡Û:/TqB½Ÿo»:RU·‡™¡-,³ª£:µN/uÛC$Ü®®®ÔA€ðǦáÖeÛõ©†‹þ½¹,·*xÓ,ÛÕÅ~«²,íú¼í»›²¿œÆw±, ?Ð!¤p?Ây–ÑCXBU÷w h@rÇkó²SÑó®S­á¡©yJÛ_ƒæÛVåÅ!Z*UEzÅËCô°DqzÓyFßZXF[у¹añ¼Ç3¡/=Ì çI¶S}^ä}žÝ´e¯2d²Z×SKyú÷‡º½ÊÛz_QÙu{=xúïÿÍ£³C Ó?‹š¶¬Û¨¯£gééÑåýºlëj§ª~¾­Wù–FSÕª.ˆsê¨Ë¯QYOFß0EeßE>lÀ|YkÔ4H€9³¿,»T]ÙæKà‡¥ºÌ¯*ŸWˆ2‚p7}–Ì¢?.P¨¥× º18Óù鳋èø8úþ7s™c0ŽÃD&fþm^§ôKú© ¼SÛuB;Ô:\€ÿ€M Igÿýçù«×/¿…]+,+@ þ NAϨo•JÝžæ;²mTƒ,šÖ¸ñûËô—º¬¦z¾$ŠõÐñ þ¸‰qù£é¶ˆÿçíËùWñ ¥¬^Á©×—“Ú%"¸SÝrƨñ{ê2ì7•i@ùE€µ“bé““Ä/,BÁ@ ¶*‰¶¨ShwÀ¶Y]e,C‘¦8hå}عη{%DéÛƒ]«jbõE-λ= ºíÔ4¾]ÄyÓ/')ÁœÔ¤ ýÚœw»º]©ÒÛC£XÛ|=ùëóž—©ÿôDÍ@h¨@=l£Ý¤ùRëPÚ81‹¼S\zG¬‰¢é`}ØÎ&Þ£)a(XÞLT /3ã!2DöQ´·~¯Úr}`A@ØD¹{G d^וҬíÑBpÇÌÛ<øg ú÷_ŠÛ\`_ËR:‹Ìã´ŽpF k Oƒ°d-¥Ía’ 2YÊ`¬™+7Y‚Ý—M¹5ÈL²†£]Þ4¸ÃazS½ÝľJ® 6Sî»nðÒñ”èx5D÷U²2^iÚÆÉÓÙ ÒΓçeE@e»¼½Rít7ŒŸã\>yÅ#¸6CÄ£F“Ç;Ú¡¡jDc {wÓëÙìcEÚ'ȰØ'TìH´¢\áÍÛ˜ßu§˜(,n|¾›h¡ÄÅu® ”-ŽÔg5mý 0ã±Ã±$D]£V庄†éÄœ®âY‚ÍÿÑçm»‡-ô2ßvðÏç ÂýT³$pÉãDŸ-­Ýï4)'ïp¾ÏÚ÷ʰ£Ê…}Y¼£ïÐÌQ«Ç‰ƒc§è†æ=)…³&Vs3­xyWz,sO4 {‡!éÛ±fâ¸ã-Gwê=9XàçâȲ1Y™ä®°°ëÎÅvÖs9/`¬2â8çý!zG ½w9ð“)IC-è¿3_¼¢M™5hTÞ_È:}PÄ"!‰häîn;`3uì!š%Ñé>BFykëUÖÈÄùÑ•‰ÁQvÄœ`À3‰ ”ÜK¸MìT™x0‰JÍÐø‹ÕŽõÚ×Ïèón¶õ’E¡#V‹ÃAfŸ ÿL]%°ÀÙi´lU~åµEÚƒ :íÚWABY³‡ ÏL¤ L>vï&‡5ܵ'ãÊEÛ$UbwÞä¦Ü«¼-0˜ëª:~6FÚãÛ ;':nû¶*Ý¡ë9mãŸoONῳGq¢{d¹¡çy8‡–ºîÒÿ ¶=ü¿®¶‡¡7Iç‚›÷ªÐæwj`Ÿœ€mÙu^45'ö÷¬u 1H,’¸VyA¿$Â}ÿä•wÇÞ’Ù)á¢KäÙ"ÒBÈß'ˆiç±4Z¯AZ—×j{ˆò¢è(.²®·ÛúÙ§R7QM¡Ý|]©ÃM \’·›=ë2à'Ngñ)ƒÅ¡&Œ£ùÜS)&œà¨V bYÖ ¿²( ‚êȦÁŸQ¸7—ªÒjX RƒêÂŒ @ÁÂØ—Ú2 ¬#EÔ*0ÏÊí–<|=¢Ýwû¾†!Ëü|ài)'$"o@úÀ`¯ÖÑ¡ÞÃpÝ%â æ·ŠC{d´24‰¯órKXÁÙáì™R79(P‚@+°Å‘Z$¿…k‹›ø7*ê› cɆØK Á°^"1âuYàÄVW@&pÄA13Z|æÉR.b I¤Í/tŠ;átµÞÄac–…Á,lNžÛ!,ˆ5”G@‘µthï”c¬tGºÂ‚æD©f»Ðæ&¦‘ˆ¼¥a†¯'ÜubPUJgÆi7cÈöGñÑŠç€`«=˜ÕÑKXƒºÍw+³ÆlØS½Käxt xÚª7oñdiRÔ+ÚÂÿ±ø<}¢g‚O@5¹˜Ù€”À‹½:¶CÕz±À°@·ë²P$8pzØÏ›|Y‚wˆVĽ<ß„ýâ²ç@xâ¶ }R]ƒˆ$wÄ`O›ÁCÖÕ¿wÂM²{«f À‚¯¸ñ"J‘«”aDFbB#“SÞ5uU¸ÃŒS²îqÒSJ¬æ+-ŽãèÑ£B5àò£†xôè(ƒÉvÒ×n(çàê%›‡õ÷°N$Ø%Ì#T ²ë„%r#Q–Êa†ÕvðGÄ‚ò >ø¥bÄ3€JHsY`Ägn ˜KÐ=u€u‘HÌ5ï[`tŠÔtØ¿;€û…žlí. Þ•`RXΠ°>R“äÚí`‚»#þX$ÓÄË’0ë.šv§Zª­À°"ëtÛ—°éü<)Ý¡q"ãûAÁºP­»¬÷Û9ƒM 9‡€]SõìÀ$ÚÚÓ[é°[‰Ý"š4žÇÑtWV{]¹©\3ñF‰fõ_™ k®P8*MC|ŽÄüǘ&Öû~IP7ÁšbxXvŽâej–zX?\*:_Ìõo¬Ë4ð&'Þf¿‘^H âY4ð ²&4´õ–Cd† îB²B?¦x2lªÉÂÛ@|£øD'Ö;(b³ µÆÏÄí>`ÅX2[Ùú1¤\DädlEìääí¾¢1i.|k°-ϸ Ú1æm,Ò˜qâY‘ão5 Sá£ûÀ$lˆQƒä1l[<ÞhîÝ˶…¿¯p#‚!Øb4"• Œç!-IjܾM•q$ç8ê ²NT¥Ð‚öðiðﺇÇôq—m úÕŠÍ–¼ÂN,+ü-2“©¹ •¡l¯ôjÛk@N"Ë\æZ ô`—ùµò®0 ,ÛJ·‰ût2 I=`$%ÿÝ{Ó$# 2Ô–ðÀð‡ÓÏ­ó¬âvAVW,;ÖȇG >ŠfÖsØ„ E?úÂoâ#dñc|œŠ1çqg±C&dP«@Âï@ímÑakÕœ£°nL< ¶d#µ»Ó—¦þ†ú`2‹Ð,:Ñ.Æô¼ßV‚É”ë-†nªÍ‚2‘L+_ý³?Pk;½nw™àòʸÌKs¹”Ь%,n Ÿ›Ç[/TXò-Òeè:º|ý´}8ucm>lÕÈrL²Ç¸RÇôׇ±wóÁP¹@W<õœÎ„ÿ5(Q% €x G±D€²/úúYVÔ+:yÅŽM¦üƒý:lD×1À§X;ƒáŽÁ•Õ9 :n{òÑËjHÆÑùÑÑ×òe‡ÿN›'ZpN±žÖqæ˜Ü=ß…ee¼hÎV98ªxÛ!äeï!tö®HÀ«}Ëw$R”IñÀÕíÕ-nÁ©7\€thº»BüF^›à^WzYŠoPÜÑ oíTÖß²ÛGÒ:X‰×VóÝ‹ç_ó"….q€¾,22*Ý¡œ¼õçåÎÇ4¦¤é<ØLnrÿ8\„\¦Ï÷ÁˆˆƒéO¼<¸ÇîÀ¥´u8­„Í<åh¶ûÍæH®~®âá¦: ¢¤Óçß_:åÃ\w@‚SQŽ^ćgþK}ƒ±R}>œ¬P[E1f.=X¨I=*ÕœVqú:ó%6£óÍF»á¸©#¦Áé"~®ÉjW Aòá IU¶1Ñ`du›öuFY^ BŒ`?EÙŸmä’$[¹éúìÆýmò20g¹'ô]ܭڲ鳼… }z»ýã‹÷³ÁÆ`Ãh-GV¦~+ÔZÞ¨B Mýñý~WŠ. Mx7·v]‡·™€æôa6Û·[ügÚö¹´å÷¢c‹ ½ï|Æö!¢TCu@ÑLñ\ÙˆÒ[Iü—1î{rΡõE„Ч¨«¸§Ã ñ]P tO׈ƒ)Fƒ.Étðg´ùùéÅô^òPI¹%##»£Ó2ÜnçO/ä>Á,zÌí# {!½9¼'QF"à$õŒõ­i¨Åf#{Óå³!GIÊ#ðüâ|r;¹H܉Î÷D1d¼OºÀÕŸ|{“ðPsXHÂ<‹ #Æ(Ú Ã%].“Vƒöͦ5 ¡üí<óÜÀg`ìáf—¿ñ¸šÛßÁÊ(øî±q–ŠéH¸Çgx'xW„r—Fr±‹²Õñ«î¶_‡nåó¢ˆtÎÃ'ÛÁdD˜\“ߥGó„ô¦ökUkŽ©Ô&ÇŒH„'E…V4©s“!Qù6úx~±µÕ¥Ýôˆ¬“1(¾jR<‚pwëfz#w¤° ,I·¤¿Ë¦síËj…´XDq4•ÙPƒkÃÃE<|"öœžJÎܲå!“ÑBtøC&þ’ȃ“A§Mæ ©é”\ã9»Æl¨'æè3ŠÓzóx³¡m„<Œ%[ÙŒÅ0ŒUÕçÁ(¨\øìBX&~'Ž]xäü <úx¬‡?šË¯áXðŒ­j7–1ˆŒî³'r²k#8”ÇÑ7[ ¼›þFqìÎÛe¢—Xw ‰ÖÛ|Cy_”)Q¡L+"Ú*Ñ”ó^ö”@‚Ûyök7žž*ÀKÙeúd˜vâÀQÕý`Ö©·³'ˆwñú³‡ÍË*põ=ŠÅÓ™‹Ó·èd‚R¢$a¾ÈŽ8îjvêõz¾<ÌK>2œa@5]6|#RJ{è|æXê:2DGñ”hΘ!-qDnÜM™ãÈÔºUÆÇ¡óó™ïæêx"Ù¹âÈoAPœ¥ ¡ÝIµŽ0s£h°Jì4Nû® †cçæ~‹sézñ+9:s#N†ëÂÏ'F]ÆaeK€Ó]6*3¶XÝ…´ô#g¢š¬nºí@Òý:dùYBNÚº¿ƒÚøÑ&½Îÿ–4rÉ¥2Ù67Ôˆr´®ë+'5T|lëXì‘í`È%°ºä ­· ø>‚ÊÀ”ÓÛÌDÇ`¦~„ ß(#–bÉ0åÃjënïÀT¢÷a$žÄ„žÇuí‡åHÐþ;^íSÇ´rS_“ès¢í­þ3F=ãoûꪪoª‘Ðýæ¾; kõ0Àb.eÁ;ˆ«×ÞC!é;ž.¢ÉCI»X|佈 é‰òs♣ödpoÍ© 5âWÑøùj½V5’äDe6+ZBÆænŒ¬¤Z UºP¶E˜…i^â°!ƒ!©Az~nHBÎ~pƒÊRÇKã#Y£õÛ´9H5%q?g±$a^|»Y‹#¹‚±íÛ§„²Ñ„Y.ªäÔšÌ]øü‰óý·9ì”jBtD"®îNF¹j沜Ìp’ÓÛrA™ÎÞ“Âà%»…w+3,¹ôÅ=Ì@Î$”ŸZÒ¨9& ’D n>UQ¬¹>ûQçBZ¿ÚM˜$Ê›©$ [P håÎ šý9øÌ£Á„Z™“Ÿ‰ íµ&·þy]׋w“eÞNN῟¼w|1š ”(¢9Í]Í’ ï4è›H \¸²»õ„øO,ÀÍÄÄ :éwÙq[oÊm=¹ã°½§Aå‚-g›zâ˜-“züø*Ì›¢ŽfŽDÒcá=Ü Þìz¶]Ù­¦¶³Õµ9)QXPþåﱌWÎ2ÕY¯TÅÍ6÷äq³¾5É*êqœÆI­'8ž˜Gg6ƒ¥6Á‘n<êƒcáLUÑ©Ö:?²q+·¬>Ž/†zÅŠ™1xÍÃûAlšÿcaZÝ´óô^P;í‚Íæá(ìtÈ ³êÝÅ­dô-ž¼®M\Ãð¹î¤µJQƒ'‰²-<×2¬',ÈxöŠ‹Ñ…ƒ÷¯Y,4p„põÃ],Ɔ2ËS/‰vµ5=Ýë邌¿°Ðsóá×Råâ ©"ÉE”x*‹,.ÛÀ³­¯ /8ÿŠ‚N»SÚÔÃ¥I I”ø5zÈû×àLªÞ¡0ö!÷8iúؽÎÚƒ*ò¬$Y%Õ™^«wP%r;è‡&¿òŒÇ“S6&4@}âd¨ç0d‚÷òD<v:f•ª-ÃʘùÉ9êN¾„_ðle[°¡ºE±.\ÇËSj÷bk‚|ûÿ‹ùÿÿ'Ûåq‡ì ‚¸îÿÌæ©„ËØwˆ¤ù{š^ M»;¼81騑35ÿy®œ„ÚÑ›ó.ÿÜÛŸ37°+””õÆhs!ŒâÇèRˆ·# b祵>hùòm?¬`,NüǺ’Ô]Iº2þ[ú’Ê ŠÆþÕ¥Æé¿Ê¡´ÆŒçPêŸ?Å¡4±õßÀ¡´¤ü J}:7t(5èÇJi1’{xûÑ¥gzúeìµÎ3Ò]4”Óf‡ýºÔ¸‘÷·(ÍôÇ+%¸`e3q|¼…&F@¸ÁÍÌÏÝÆÓ~¡=h9ûC)RùÎó~:¯j8ÙÜM,ÇÁüHßø±«ÉnúèCVÛÓ}:rø©n‚¨:€L,sW&khïùç6!AZºy,^j”}ЧôPÒ‚hÜ„³«ÝæC„™Çþ2¸1pO¶sÉ&V²ÛY`mØíwt—µ¶?´f€t''S.ý#+sXed“M÷$6xæ.3“ÅÉH‚ò(»è©ÎcJÝ£Lª‰{«Ö2"<ª­«w¦l‹S~îÐB~¢ÎÁYë®ÀùŽ%ÈÛ€EÅï ñiôšž‚Ò{ÿ>¦‚ŒxS/ÐÏÝ$€oÝ*ý 'ºšK‘w˜òÚæ”y\Qqˆ_§ÑÙòFr»£¨U‡wx—ÎnëÊðJ4Ué&Åùþ¶/UÏäþ>,•Ì>er '[RAË0©åDçóœc)µ¸ð†‡tÙ'kˆ9¨¶c|ÖÓ€ý„Ò3m²¹ÙD8½ÕÌK`Wh‘LQÔÀbf:IðH{a4hq1Ÿ+Çó† eµWÃqX6ˆ½'d¥Ž°1G‚$Ÿ^x­ïaÂËuhœ‚0¤úv*Å÷ñÛkÔ0éÃÿ9?ÿþb6 Ã÷ha #€:xº0ážÕm¡‚7š°~¡Ò-'c‘¶[é-98Úœê›F¡;Ï/Õ¶™«F*‘苟‘t×g¦ÒwpLLÔ­9ýŒò(0²®%MÐ:üVYcò¸è¼+˵ŒÎ~ú‚«‡çàJL"Ê=Ò…îo×|ÓÅ»^ VÞP©ƒWßŠÚÆàÞšš…p—µ uà×á»r:6†é[`½WßþÐb.jxçé7\È×”@tÓD<9¥®ôëùWt¡YÞ§Ä©™ü®š4:cÓ¢s†¡+Ìò>#ÜËž=û2ukW—š¤˜ âkÓœx¥¾|î¤ßpÁg˜©dYæ¦WïÐ1¨Æ1‡¸¤Ä“Bê7,-Æ–b›q¦¤ßˆ~³¾ˆº!»”Ûè‰Ð¾‰oÊêÙR®ïç*ÖïfñöW¶Ü¯×ª€â?sÒŠML¢øÊ 8£á%ðÕåtÆô Âð2 @sGdý×ROCÉÉÛ`ðXßÑ5j2Þc‘''"]v´ÄòŽ-ÖÈÂÙý«ùzѯ¸œ¯ÛóþÞÉQwöŠ3ýðéÂÒRÿÆ‘¦‡%I1ŽøWiûW²+®ÚIi>•Ãwæá½9p Jü†žˆ„vQºr˜Ó°þŠEÊøêˆ’÷—1ÿñ²ï›îôÉ“eÙ/÷«+Õ§u»yÒšü‰½wö„z<ùÝWÿñ׌˜ÝT1¤ ê -Ö{J\ÓÕäõwTîKõ*|j³Ä(‹OÐY×/Òó ªr¡P¯*Þ0”oü“ØÉrÓe¬/It¹ßÑ _/hm:킲š‰›e çVÌ„ ¢ºŽm;Šð¨ÝÌãÿŨBм-,ôE÷yÜ iãå:%ÓË)´éÔ˜>VÎõ[44nÊn8šv$3½ÀPÛxò“û5œJ¥¼L*k]® *¾Òf†Ô“Úwjô)×+ÓMô–éN“u—c³Æ;ñe1ÁµiÓsICF…o€£c`ÔÊD_Ò9 ‡—+l-¥S)Û^ §:xT /{8nýb°Ú¬£(…iÍÇŽÃIµüî$S›Õ+žèÜI37¯bS0XÑ LÍ·Ìäº^¬½Ã^'¸'Á4ˉݣî<˜åt$},\|œëÓA–[¦WWÙÙwX‚“aõŠ?suP ›C‹oòª#Kñwºl¹‚öæwÊ;ã¡“Ò7s,køu”`³"Âwºl9úÚ‘Ó¯ŒM6†‹G°‘¹a¿ÅIÚ>*;ÛNNMt ‘º©@s©¼íÀ<⊱js¾GP»$eLNVmÝu«}?¡¢³þ„ÏæÊ¡ÈkÔåÒ¿ÀI`‹Ó™ëLº(¬a¦¡ó¸½ 8›+CÀ°ºWVVsÐc§Ãz¶XÞ%ô¶tõVܤÎR½7Qè7˜w:€j®¸è?qxÙ—\£’˹‹›×¥«„·™½=|iªa|}i¡ßl!ç˜îÞz;+Ç šjø‡|æêE§Ä6^ôÇCJ~ÿ…œ®ÝÓûC½w¥.nF„×”2Æcü|’L–“‹˜Pñv¶ÙHq.Ð.cÞTÁ>¶åSlezS]<Ô´en*)?7 #úê 6°&‚ê©8~lêß%FƵ§Ý!i|­ÏõþÁmÌé!#¿"2ßäö):MRv‰>%×çæNÉnDl§úýõM¥ÏŠñžñ‰K¹þÐè- <Í/ ÂÁ¬†wªõ[@ ±i4û¶Ä‹z¥ÅŸ®Éz·e½ï ?Q¤ÅÒâŠY¼Ôç¾@ÁPL:°¥ó/ ~˜¶à×¥ßÖ5‡@%¹Ä77‰qŒí”ªý/ÔÌåŠg6a¥AmLëEÝQ÷lâYȶû«ÝZì#/ÑÑF<áý„º ¿ÿ]:ñ/¶-À8?0ÔþsXúêj ÎÌvñÌ-ódДOu°šDÚÑWæý7rU_#_n·Æ½JÆ }}ôˆïo9X§`Õ°b©ÿÜuÑØÅj¦!§Z„üÕo`MÙ…]–ßÄ܉_˜Å¹ñ'P.6ÁÒ¶‰˜)áב¢«ƒþÁ¢Çê´úcÒÖk¹VWÐ6•^Õe:;ÅRðòÒù t<Ø…‹|ß$Sö|hdbÌ_µ'G±ˆÜÁ¯ 0F™ ù’„Èñžúå’àB`¤cJg;X³~ÀÝ?=­D¿›SI‘ݤF ñ@¹zjD„ÐÛ«´ žN¾[©~•†I„ötex{x°ÂgE¾Ñê÷ÖqþÏ‘k}ÁN£²æîî#×ΔýîÑ' þ‚)Œ¶À´Þ\…³æ’u<ü3;ØO m1N HnÛ²ªH$¬ÆúLª¥8¤óBœºÁ76pñIçuÃÚìöôÙÍÚ“à¸äª‘¦¤ƒñÚ-íßX³×T‚·ïXpwMgÕ©‡gû¸¿“sÏ$âz„yC¹ûØ¿‚8•ô ¤à"Gðý2Û(c?¸¼=röqP[dmÇÂ]4R’<¼.º¹Íd.Ç߃ÿJçÎå öŸÊko Ò!É$áï©v7=#+Œ+ŽR7)u\Y{‰E+òîÊ÷?œ¤`îÚ}IˆŸ3áfY£ª¾jÄ0(Õåä1mÎdRw±§Cq¯d̵ݷn"¿Â÷©ª£6])º¥àÀ8í]Âà+-˜&˳üÎ1\£D_‚’­0 3Ì}“·Ð¼êùÄ<’bf^hfBþVp@g<©–GÄ÷^ùD¢ôòNÍ &YGžöˆo¦nŽ™óšº9nΔÎë¥ó s^Á=Ý£êæ¤rð¹ª:ÇT÷¸ºy\u§ÔÍ)ÕV7§å»1Õ¹OuO¨›'äsMuNªî)uó”êžV7OËÕqÕ™QÝYusV>SogÔÍ3*:£6Ϊ›gUxD½«ÔÍûUD?“ꮃÎÃ:_<§¢sê®RNt^E¨6ÍýANðwTx”O<NòÉC*<Æ's*<Î'«pŠOÞ£Âi>¹¨Âûøä½*<Á' žä“y,; M£<…+Ôñ'nUÛ—T4®6äx™¨vE]»E+² ¢£*ZPÍ£êöÏ:+áiÕ¦]›±/bÆ7ægigóI:\‹³5ÞÂŽÑD—é°=§v•Ú †LÚ¶ô=|ÅUŸrÔžR·+j¥¸ÃÅÙÇõF@F×gèóçÕSøpc¾ŠvÿF’&yÔʽ`-ˆ{Yî¥Ñb?È[ë4R/_¼ÐLÓ‹Ûôe' Â(œ˜ðèß‹,ñ¢^6H£Œî r¯—x =”–žŠ¶sº…Õë&½Íh‡Âá¶¹¹vœfùŸò’eX×þnÌ£­ìýtXÁ`yF×ì#‹¯,¿ü/ 'îÑlq™0%"€òò4Šdlø—Æé'r€ÕVŽKf­²1úðÆë//>½<Óûžôia1›$ãÏ´dë|²‘Pw€¤bé0!kŒàQ§Íí¶›aœò³Ä‡ÉÃ[÷Z¬1=çL:Œ=¼1<°b‹øÀKʸ•ídL±ïD)È7å×ÍTÐ%Õ† ¿åAä?ZbZ{¯¦…Ç&ã|(Ó}ˆË@Û K#ivõPšÃkþ² Æê‡šS­ÔÇ[ÏG NT;—5No°°A 7K°·GPZ¬Nf—°DÀWzO¨jN NC×ÚUµ9¡Ò¦r‡ö—€y—Ÿ'æmh¾£Þ AôÑór†uÚ~>{’þ\L½î€ˆþ*An¼‡qª!„òjçiÖð„myókINõÒ<ïÉ1 HDú“AÚ"Þ†Y¾ÔËÓëË|Œ!5¥%ÄHƒÌÇSLn_ßéGÂJñØ›Ag ?2õÍe]å’Ï ƒó0Ѐ‘qwð$#GÔ?œ ž™_Z›ÍbE>€612ETyÆ9圥¿‡w²RÞÉO`'/`‰ ù ãfEe‚îØísò4º¦·ïuÞ¾±{n_ÅðìËX¯(Û;Âryˆ^{Ù¨ÍÄ#:½œô¢œ—ãâðVú–¶~"³{»ÌèèŸÆ{åãIÿ½84p°XÌ[ác±ýK‡†['°³Ìy›2°&Æù1‹BnŹÀKÏ ?¦yá¿,´è¶¬ÞÝŠr¶ßÅÙµ[»ŒFŒ\„L‹> N(Â1]™™µ¢QÈø¶YSé,Î7ýª8¿ËÒ¹¤$ÎÀÌas\¥_R´i5µ1¶LwÓWèüö—ÔíYü¬cÖŒv~dëzA7ÊúA‹ØbÐÚ ÖÀMÓ;‡Ùc#´ŽX`/‡ˆ!K4Ã.ÛGI:õ2PÈ}ÍÒÎ2¯Yb8û4ø×‹þò+˹J_v¨ա®C²”}Ì6´àÑô­½$¿êõ…¹ qå¸çñžÒN.Ï#üEl ð‰D´&†O9k¶5J3”1gýNœ ©Çd‘|+H{ÌG€oêe}&,Db¨ÕÿºE}jBv†ÁnÚ9æL1ÆßçN:ç‰§Õ bãÿ°Omßpl°BríÖºú” ÜceQCWÄpeTLAô=cZDÛc?ù£†ÑÛÀ4—ûj l¬ 8·§ÕÊJï½D[ˆ)‘% „åg˜°TY¼)ȉfI!ÔDÖYñºA¿šBûË`Épt5Æ1;O‡Wz|¹,Ò3éf”^õ²?M74†l”ˆP·ØAºãm­'Y$¤LpÀ&‚iЀ¬L¬4"`XÒy?M6 ¯hÉÁÓ}ñ`²~ÔŠÛ1}³´§Û.+¹\ȵxB6‚Zä…„PZ|VþºýÎá¬ùÑ‚?a™2r®{‚d;Ë”ì"ô`¶Ð9dµY¥è=O˜Ê"ñy é›Ê¡¥‡Å†Á(a6áw±•Òí<3²PâƒNÇÀi&¢ Jv¯ºo‰–$4öò=ë½A˜ÛãÍaäÏËÌýg &úWÕÔÁŒâƒØ¼Uö_T‡)N•ê3ª$Ì:§ÝZÅâ“•?0ìS…oTÇÞÞgìðûd‡iËE 1;éÐNº!SaºÙ‡4c'™A$ýPÖlNi©Z(ÝZ,Þh:öš•‡û'Ðê½f§ˆYQÙÚ´æ,ÊY ‡„ìjË–&3J¯Ìrv7“ŽÑÌлGU(ö(Îþ{­È³KðCX ]¡ÜÐ&]™iÑ„½‘i§±Ú^ayÁyáC…¼€û*w°<Ϫë´&;ÇA3„í;+·Ï³*èº6.¼E¿+ª“Ç]–0´ôÀ°ÆºöïE¸‡Ø2áý,SÎZ'YÚ±ÌÆ¨ƒº‘ö=n¹ù­x+HC˜ëò(íeB >ª¬ÂßÊ}˜ZÄ8@ú®Ò§B*÷" ÏâðÜ(è¹4¡æÿ´:Ã>EìvJUŠ:NrbÝ/3\k·ÃÝ~J’%æ²Æ‚·+û;^XçD-¡‹ÎíqE?+%å<èS[Ìj‰Ž—.g7Õ°0Oâ¹%÷åÅÖÈìúMz¥Å,"zäQ8²K%A^ŒPÀÁ4b¢Ý…åƒEu Šÿø½H 6³¿¹†ÏÎ4´ÙO[ÂLë~Bdr¥ÿaÈÂ÷ѺH±;G±#çœvÛÀ1†´Úï:êf lÇ•˜LoF‡“:Œ«8™€{'GÅzNŽ7Éqã&™2n’iã&¹Ï¸IN7ÉIã&9eÜ$§›dƸIfµwäæžæ“³Úáqó~Îj¿Mx†OΫð,Ÿ< ÂûùäAåߘ‡¨ž}qjD£„ñÛÓNVÛQØ¿àžÑŸ WÀ^ìþ¯³º§M¿ë ¶¡gØ?avÃÚæ—xóÊ}6˜Üˆ}¸Ý&¹!¾uv¼ 36›¶“N'ÙåèE[^ÂÞ˜ ãmF;[ ÑŠ ]ˆôB¤¤ÁP2©qU†å5FeŸ†·¸8$ÍdôEDã-K4"¤ì0µYÆškõ¤´sÃx,ìúYkk=êÁ+ €A2¦¶5ÂÌvQ±å®b:+~… x ¿”süÒ{¦Å-‘$ôèf]¥_fÏíÖž¤Ïx nÚsM{tWs‚Ú —Æ&‹Á.³9ØÌ¦£)—ã›æ'…šÓYÐŽšxÀÿ1¥]@É”Ý*¬›pøÿbŸÎêN“@˜Mkt‰{D8š„7Ù„ÛðnY€#œìÄ04u€Ç눭jÖ €#\¸êMX‡c¬‚eP‚„ºq*h‚~W™P’± NÕ¹àœvÎÓ„ñ²¡xÑ5 ¤¶ÇN…ì!óŦ„r:ªWh{Åj¸YSÙK¥8_›ÔK¬ÉÃUÓʘ¹Â–âäó8n°Œvú.Â5ë<1¯`uÞu ýš¹›[ÑwEÜí.)â±£ !CMÿ i€ãÎñõ1¸îÚþœ±S0´Ñ%¶•VMdAô4ÛJ]'¿¯¸‚‘"âÂÅÏJ~BmœÔ 0¡æ§¸£ÓjcFå³jã [Ý·œülq ÎçÍ +×õj%yhf5ïS6ÑÐ ?0´ ñÛAÚk º+´¿ª´K ‹Äq™BhúIßG˜˜¨?ÿm"U–iG LxšD^2¡ ÷içÇ›Í÷Íph¢Ç¯lpzH¤'ΛMñ®àŠ¡Ÿþ ÓBoÐ]¥•cê»ÌçB§ëž»Ž;ß,QZLVTv0˜èˆ}ûjij¢ëÚÌe=¸ yT˜ 4™ 7Ù÷ƒ@7^1HðÂô4@)×{|(ÄÚïÓ£ÿm|”} SNÍ™äŠcNÿŸs޹“D¨gœÎ)>ÞïL;gÜs.¢´ÏнðÿWèΣ•“ÎYœW8ˆßÕ¿LÐÙ-"QhŠé…£Ã÷Ó‹|biô.¼taƒHÚëiÒŠ fZÛF›À€ÁÀ¬ƒTsar ú+âVô@èH€ß`öxM-5`«pÈ‹ŒÔîÃYhš¥ºäXÏð-Ø1á|C!îˆbÙgCéØl"Ù³:þÔlÅ3ÖY2+™àŒ5,0Ѥ|³}P‹&{ÁùØ,7Òˆ…ÐbÇG*¸\ÆÌŽ=ŠqyA¬4h…€7,ÌlˆPWÑ\8ttŒ:­Oöã’|°ýñ/ž/ü‹ÿ8„orœÛ©•"väA¦>YÒF‹b+Û)ý~&y/z…Ð×î@cí­ùŸÑ4爄7‹åäÖ9¬ƒiåucÉÁBŒé$Ö—´#¯¤I.;0|ªÊܬfР ØbæRÄÂNè¸ÿ“ôè Ž `öqÌ!Æ1éœt<ç„»äZ€²(þÓûQ\ ü޹^ÕHŸ‰ž6f$ñœÃŽÍzdbJ¡aðbúÅ%“NP×Á Žþ0VþPÓ9/J}ü-ÃŒÆ*€KHØéî¿ôâµW_ZÊ·s͈ì6Ö’"b‰â¾«°ñŠž]òÏ ç¥ÿ³Hk0‡ö;ƒµEjhib"{ñ€~Òï2ãã¾г;ð¹Š8ÈÁôÊ­\¡V>JÚ'°±=B‹ÄƒaÔ‰Ø~Taùº, _Æ6¶)Rk$Í”I"%6颕cº‡K>Ø®p!dŠ”èd7}“§ÃÙ:Bnƒ°5i›Æ È0Û><ž„<´¡Ž—LJÒÍ äcÄô×%p.…µ˜1 ܦÛwÎêôD‚º5Žo"hlºj¥÷¼c"àÞ"drR«ª;xdúYS1G9®qŒýS6Æž ôgÆXAW8 ]kû2VT/fy„ ã¬x«ô³ø‚>>û³Š~V„œ¦¿£éêƒ{ÛA÷@ýNèãÙpBÕ´öˆš¥{ YÅÒÄäžçz†¸ÂÐR×ÿá$B<0úãj·ŽàÚÌpqxB3Â|~’§øÛÓ|œÁ•»Î„𨷘¯hÒŠãqÙ`üù³XoOAÿ@Þ©kkÚoÈú ƒ±dõ±L­ìP÷ÿ2®e¤Mã~Þ Ò5Iß)\ób±A&Sˆ¬L‘Âh»9H;̘AÏ»DØ%(ÆÕ&¡_žqh¸Dõ3°q¶ÚÇõm¾ÛDi§iØ6Ö”ÑdºÅ­`I¢Sº›%i.Œ9;‡Iü ¿–Ea$b_œµa콄W¸ xAÏ9øT¡¿'œsŻ#en<í°LëfÌRÅ¢ºýëZ[ïÚ­¿[ÄiêlÑ ­\¡W5+2ƒŽÇTlEÂ=íɪ‚éRƒÙO€vÉré*}-¬—h•˜òfC6Ê!„n›mWŒ)wŒÙ;jrǸ½C? !@îzîöEE?+»Ž6ÏÍVÅj'B ÝXÚƒã1Ìè'ó°ÞõbzÆë{¥äïµ>aëí·.F cTóæµ÷’¿€6.¶ÈØ¥ æ’$kÚæšBxËóÇ fõ¢µÁcn5 –.%h”±"¦€@5cóI–ŒaœLtÂHH¨Æ‰b@ÍÕ¦73ù ëk$…üŠékGô;síxé š.Kr£XéZÂzIaÍÑ÷3Òð ¸_ CË8=,ú)zô³Žf+ªR#Ì9çz úÑ"Þœåå÷늮¶[@jžæ+UÍñvÍWrÛsý$ÝUpʤg¼®%{Pׂ-Áÿ“v1~÷ì2f’­Q(釷jÿ’ýšccÆgH!Ÿ¤5³©)vÅXŽƒ‹Xz%wW2´t¾¬7"k…lè€%ñiät$A6#öp¸«L&ŠÅa&årçáÌ„ãë#öÄ!ÓêÌ3F‰ÁʵOí¦=ï1$Œµà=ŠoŒC{ÁkÀ1ÛÀµAo³GJ¶Lú‹vÒ?SªÿOèÑ_™éPzÑÛJ„H ¦›®JŸ.&~vCL$œÞXäÈôTù–j™{Œéd‡ÚÚÇ)mh?2ä8ÇNËèú†F)f_ ò½ÅÉÛ@Y­ÿ  ?' 'ÿ¦Ù…â¶ÿÐjYÓ?*5¨`Cj¹üÿ£Yóõ!¨AÅV~5Ètz äÿ—aju€æc&|(Dë·éÑ×h>ÓCšÏaîš%:†)],XbÛ)ñC)e­Qw¥ÎP©TSƒZߟ8#¥*ÿŒ"PMè7ÔïßQ—ˆÈj’}Ø5r,Sô“.KååúeTB ÄkZ­«5¶]^½³ºòcEÄ&ÊFÀApV|A“ø³`cÂÏŸŸ—xºNU‡•`±k îJËUu¹èàöUµB ³qdHÌØ“˜ÿºæ {u(d»m¥#õ~ýµ\¢t­É»\Áý9ºªcÒjùÐ%ñÄ.³ QâÚ:1ŠVs¬‡^@³ ¢¡ÄV²¦e/l§+G û?ƒ]ä<ŸÇáWpø{8ü-eÂ8Ö;Ѷ @³=\ZÍá¸bøüÙ1Q`[)^@—jÌ¢”»ôÿ¿c`,K[’ŽƒùøÿÓtÝãÀ®ÊØ5þ•CAK$á|ÌÕE¨ ¹N‘ JGgÚw& I»§IÂ8Á…ôÆÅ§MÎêQ ‡}{ŽÚ¾ßöFÖ+Zl[+¢üÅÿ`™£ª PãPX n¨ÛWØÆPÕe÷ÄÈ 9¤Ær¬«Òß/€Ó¸öœ‰Ë Àv~™œÁ•`,fmؾÉßéQÌsÿuµGÀ8Áh@mÿ*`\×oÿ‚¢Ÿ•ÜD‚òœæ¡ŒóícŽÜˆ×t˜ +– ªzŽf³r{†ƒ np¹àlݱúvà5Þ¡ý¼ê½C s•øÐÞ^ƒË›! ˜‡¨ÅrD{Á÷_+—8Љœ)6tÒÑ!ךP.ó̦‹‹áôq“*âÓ€“ÉI4èI†mÖJR#  %P&QÖkä^l–*vô¬çÍGKkKèïö ŽòÆ%ISe.“’,S䫚8 ](ƒã#%¤G'ÖJU $`šš…ldšÛ埶ýq¥ÔŒàìäºÁÅ0°8P9‘:÷ phw›’¦JdÅDò2gý¼ù¶ì MV7„ˆü¢AýA%>Ì… u‘[Á= µ@Ï¡ÿwðùë†FP·þï›´”zÙ ©3É_‰Ö8¤"ç:׿ÊõŸ43ì†XP³¡«=Ðj¢æžw/RsáU-9ËÔGÜ)ºVwJRÓœ ³ÙWè°}^s¯þ°ýÚ­£Ú;û&—uÕ_;ª¿Ì毙 ÑׄhÛMmÖì¿ |½vk™Õf'y•³ÝRœ õ!ÒÓcžD„CYÖÌû$þÇ2ºÊ£/„QË:D‚³Œ>H‡OÄœ„vßK‚/ꉕµÞ8y þ6¿Ãn‘ÆŒáÿ;þ½‘N˜'°Ø"ÞSŽ ê…ü‘alhZsÍÇ+4øG¨8´ê÷þ¢G¿àšïÊ í²üpŽ™ÀXë†{,:öE3’­ë¨ìœ±S?‚A‹ßÑ;˜wÌ`[k&¨…x!)~jßr‰œBÀT›dwï}ß^U·ºq‚óI€xÓßPõžãÕLçÇ™ñô•)î‰KKÛ]n§9®>sj_Ç+’«:òônõ€§ßb›í`°%&"Èä\– é-J–7G»Òï;‹Ðç,ï0tq~qq=êôm*¹NÔ6¹pž~Ü]Ÿª?T?S¿¯>Y?BWªõ£õú_¯Ÿ¤ã,Ýu}¾~Â_לÿ¸L#V¬\¦1ªèx=UUEc*ªáA®üŽ‹wǸRcÅTj¬šJc¦RcMWjôµúŽê×Üì/¦»ÉÛ:£÷mBÌ–Ô›bg<[!…úÈ !y+ÆÄNè-ÕØ’irAƸ]TO^¸e›4õ¿sm4336!¨"ñ_è" ;Çïº^ÅJH!NLb<²4Åøö­Ñ½F‚$ÐÒ@L`ö=Ç1n§ÁZý‚ÁÓ”ü*d¨ö—…å¡5N‡Ë˜I€UÀ¢¥¶”µ¿×`$¢O^«a«Š •ýY(·‰˜oØRw©©Ü ›JgxdÃuÏEKß߆,óh-ˆï«b*±=¶{ëgŠ!HÙL©`džûr9l"cÛw(%c*[(u­ØbIw¼J²7jÔö†o nê†Cý— ÂÈ™¸î4†+•–·í[ˆÑBøzŠBªI‰N—`å ÎZ‹Ë„È—Ë+"¢n©%}ïå8»\ŠÆäv¬é‹ºÖKRnáõ¡¯$7±´Y‰õgð¨Ë[*+9×J“,k ò9.—VŒAœ¥šW€5y+@ Eë’Ì€¹-Y˜ŒõF[Ù/—¬š%,+›?† =l©µ4²HŠ*ˆf h†–«û+±¡®*—þ—ê°­œWËÔ’–¦:TCÙÔàµÕˆ‰5÷¤\-CxœÇRéK ‘Úâ©2/“UÍÐfq{¹c~'Jp.5™µß¦Œ{û|%ßó½Jq™ñ2_,‡\@.DßTnÖ¾¢vÙ[¹“ ÊTȈñÚ"|p[s s«s·â2B5‹H@vµ!H5‚ÇEá¯{ 2¿Ä¨O0ÔOãÀÖ|ÑNŒ÷×X 4Q&ç²® [8zÁÒ清wotk†¹¾Tªmä^ÀÅ­@üoóV°#š›þ˜ª1–¯ ñ–ŠMb¡¤Ô(WžM¶zÆ7†Ô¼‰òÎå;}ƒÂÓRãÿ8ÔfiêWÛÍ–úÜÛ–™Ò—¤ÝògªœÝ Ò8džX9)¤#S}1Cé_»cúa£ì¶5ÃuÓWTí$ɦÈÀâL7p¬ì ‹¬mÃ&­ÀKbó!òÂâî8¥"ÈYƒ ­á¢ù~±œW’ÿ÷üŸzß’y-ik³CJG§xe¢$©°ƒL‹kzÔÁŠ”ß9D%-Ä[£¥æTÂåvB•B* œÛj÷JÕ¶RáÙýU: WY9ê±.ÌyØ‹—”‹¼ö 1ÒÖ-ªmÓp»ý޵’cn¢—£ÉË/gÒÖO7Ç@ãZ,bûÝ{,}ËRwF4~}Ê— ® t©b2s&ðn”“ÕiX=aV”Ð8Á€öE<¯¶²1ó–*–V+=¥ŠŒ¸Ç÷ƒS\ÊiÚ÷#×K3Å‚S]¼4³Ç5/,¤Hõ5h1£¼‰üN$¯ ²Íañ¼äîfQçN¹ú³ŽTúm L[ãø8¼hÊJ¾`ÙüÄ´‹Ò C¯ÌfØxYqIN“}ñ¤[ŸM˜0%éâÅ“:^éö~Jôæ¿:ï²"y°‰Ú÷Q/ãWpámV·—ò^¢¼±lãê‚î†>µAH:ç˜H ms¤"ù+$Âã5C oRÃVÚ/ŒÉ[$Ò/”ÚÓU^†ÞÄtEø·©/nâAIœËXw=@ÛܯlЦùÒs{Å+6D#«qçéêûm²E¤Ãf‡€åœ” (1£Øþ ]Ìøí1Æ:bB t êÅL‚6ömš‰°0–ŒÓê‡%M]ê _Ì41Þ\1R SÝý}ˆ|Ú79-oˆuK¢8Kg'1&–§N9ÚÕû`Üèéío+]Å®"’Í 4åžQ‡æW]-#ÕÞ_s§ê5çĹzµ~º>=ðAíËBž¦¿Ì³PƵȪHª´±Húî$kòßãj8ò‘üà€·àù¯âðqgº"II äR^÷ÃÛFöŸDx[¼'»îN:£ÿ§ó•ig†þNºõJý8OŽ»t]§3øð¦êõ™ï¨ï¨.8Ç*ÿPKƒ,ÒFñ¿÷ËŸqsetuptools/extension.py}UËnÛ0¼ó+iIˆ«{ øÔ¦‡¢§"· hje¥DÄê×wI=(·Nt‘Ì]ÎiÕÆzp“cjþ´¸~µaÞ½…å|ðJ»Zš Ë«h­±7Ðxñ88eÆZkz¨c?£ça…—6 ` öîE~æ.Œñcüae‚ã?‰åusõ†¬»b©SoånD©„V°áÒô£ÒhKÂ7ØïÄ r9ùÎ eõ…=wwwéý }°<Ú€ Zøš@ Å'\:Ǧ¾J™‰85µ^Ì)õ·­çSPºá$TqHxo§¹f|>@R¥Ü‘T«B[â†æ|q¾O8$MOE®ö\Õÿ3ؼ¿´†‰£‡‡ô"Isg£pŽíR¾ í1jØXˆ’ ¯NJ+?±¤ç8Y¼ÄÙíÔeŒIM<°¬ÌsÎÊçÑûNxµ, ¥±9PŒZHÓÒò8]–@@¢HC•fxA’†âÜ™`%:î ×b8—u[å­­“›>s/)ðª|±lÖvàÍuÜw^XréÆëqÆœVÃc§ô(;1(׃ÐÚ¼ºŒ4²3;XOY{‹Ÿ–ý`³•>±lѦRŸK¸¾¹=uÛîÙ~‘&Ù:ῈsîT*¹œ \3éÅ4»äJ2C¾Þ6LÆ)Š 2 ÝM-DZˆíFtM¥ãy…#Eäý}HæKžØÒ]8QÞv‘ÑÙ·žN|I…³S>‡]*'ǾV]ÏNÙ‹±L™û`U­þ©NVØ©¼áßî<­~ÓHI‡sÐÂfÇÒÜ¢ÄHaAÀDD¶vE“\üÖ G½mßìÆ­û’d,ö”}/†fwÅ#Eÿ uoš@ƒœ7²[xz7ûùªPKò lH òŒaj< setuptools/extension.pycµUKo#E®ž™8¶×Îc…  ¨Hki‰“H«,ˆ!8 ´‡ÙE€/£öLÛg^t÷dm”\ÿŠ¿Â¿àÄAUÏ# ¸„I¦ÕSU]õuõ÷µÝ߇ýÓ_þ6„úqñý _ý'þ3H&íœÁ„5s&N3waâ5óóŽc˜ É&¤]˜tÑ·IÒ>LúÀd¤Ë{°ÀV‚ìÃr ®c7à° r&;u@a†6ÉŽ?La‚µöZë.™ª´Á ™ß§yÔ °|gPX—ýDû>º3‹üåèv þ Ÿ1Ã鈳…C0—&(³B˜p!£Ê>Ä!ÕçáG.‹"WÆv”\ø>§Ž>£Žzp °>pucæ wÍ– ˜qàåwÙ.xÆ…³>¨§ÀË|o<D™ô1}Ž/M©2þJ•’Ç3þ|myÆC‘ñ)R £± Õo0þ"Ö¦4q¢ÇÓ2N¢@®Œé¢{¦ò4AŸéáGë²›ûå—éSc‚ªnøÄ# @ølÎ/W¡,Lœg†â¿‰–Uë¨Ï¡ÍNË“5ÎúãÊÑ4ºãT„¹^žOŽWž§OŽä|~¤±…ÉóD!™i¬2.Öf@˜â\UþmJJ'^‡¹Îë²!óX ¯^ØJÀ}N+ÞÄRŸ(Ï,%]ð_Ž xzs=7 ax©¥æÆá#>‹œÆ/JžÏÐ\¬Wµ#¤*^ýZšüH=±VCKDä r£Ø'¶\2¸`°tÈÌ9s@=!Re. P.@â,=À/;¤• ŒtáÒ³ xÌ.±nÙƒ+‡„†ó W‘}“JÿÖp«âWXç¥ q¯c³à„œ·=ÖÜä·ýf!¹ ÒæID6/Å\^/óW‹XóT† ‘Å:å"Iò×ú:R”xZªÊŽjJÖm²BÉÃ0ÏÎ%‘»-=- Å¢s&•Å`qÖîq»ú…±´"n†kjù8, íØ‰&^ÒÂ÷GDfŸXa¥Ñà²ÄE¤Xœ|³2 -é 5¯ÊÄ"1”KIC5t9µ°²"C* [yH´LfU(–²RªšHòòw=Ü(Þ!QÔ= p·A&0y@åߣ"¤èôm³öUP»Vã™HeÔ‚Oó¨LèsÓ~Fyˆâx ñÀö©§D„¤Ã:Ž­øM¼“èG¥Äj´yŨMî ó–O¬ÆhÀ´]k I­‚Ç=ª$xOï# «ÄÊ©ÊѵžÕSoà–éÚÐãöé0@ÝEÐìAi´`jÐR¸â X¸¬Ôe’w]}âZpœf0ÙÌŽxýêNæýꉿâ©Ó1#°…& z›½ˆ *°{ìMÕ|G3¦„¨¶ìÉü¢t~l@L(ZPì±xrUÕl™Ã:a³i•Wà4eþYg°— \©,<êgmîÒD©¥Ïâp}_ÿN>ÄnL5Äocˆ³ßŠË¤¯NÓ ÛëÊó]ÇEyJd.y¬ x,DWâ[otC^ÊêÛ§’öäJæçñ}+äÓŬ÷J<‘éº|úõ’Áÿƒæ·n¸sH‚xé¿Í HÙXÊ™C–‹–ísósH/kc<È}è[ Qüü5­º³¯.ý™çͰñpˆS Y3@­ß€H@l@ßAc¢ÄMè7‹q¢Ämè·!^‚þR1Û„¨ýø-máL~¸ø©o¿ÒäÙN=kÓ‘cQh¬'S¥Ó8üYúöwa&÷uú™­¦“Išé‡–eïØßWÕŒ=J3{˜&/d¦Ã$°ýt¨¥Òʲ¬ã硲ãÔŸFÒΡ’Ê$ö·1¹}eè—&öú9þ»ß³Â¿ñϘ‚î ©×.¦¥( ƒëh\9 ušá¢Çiémœ ¤öFa.3å²4ö&ƒáÙ ‡ú=|x*=Õa¤Þ𬉠u¾">D#‘At N„‘à“x¡›¸Gå4¤„%ß“÷»”!ÀXÀ%~ ø] 5€SüCÞ€Ë[jÒ2„ƒCþšŒ’ш·«€'Y 4¹œ½t(G6êšÓiù»§>©ÊwîíõîííäŸï{ûveì*©§{T»QxJ`z2ïM.`DÓãå»Ò`x7fy}ó¿vCÙ†É(eTÜ™6™¥*륾\¦K¥ÛÍ…$OTøòt¼íì+ày±­Yîe i5ÏK±ôj+E{o‰ŽÙ1]Š\w‡QuÇÇuwHƒDp_ˆ²/ÊiÖ b– BŸP€?Ð\"+L ÷Y²-Št„,)›ï° ÆRÇM¢ïZÀ6^‚<[$]|×.î È~#øÆê5 tôl™|®L¸ÄX+5—CåD{- qþ’.èU¯‘-b”Bt**§¤C­©Nl.”—Y¨%zaÉ”bç¥Itá|š"²ðÅ&M˜Ó©’aÍMrœM%W»\õÍ8 ý>ñ]«žç1…œqI(}û_È|M}YJÌŒ_MÅŸM^ôªd™jn£ùØ”fV cQzõBų2k7c1 £Ò¹ Ï@e‹,Í»€¶®HÅÁÜ ÑÂë¶°ðƒ¥*ÖÅ]c(ÊmTeök]fÙ*×TÀc ÿ0˱ÏîÀ•¨ŠÑ$2ŠJ£B;·á„ž4©ÞПÊôä;POþ·»' è•ÜJî2´MÝ_m´`¢<®”&xe®e⻬G¬cës…TQN›=LYH³BkM)Y›¬CÿªÆO)x—Å« d¡‹ŒlˆMÁL˜óLœ2|É/6ȵYÁÆ,”Ø>$ð°éëyBÌ÷èÁÁ3® ñþ³dgT\?? ø=aÐ ’C½ÆPÎ÷‰C]­ÉàëÂ@묀w{Þ›.IžûQEÓ“É8}!gÇÓSºùó9ƒl‘¤t™”›i> È+ÌÈ~¶Ä*v†Ãg¿0u«¦}:ˆ”ä¶r©¥Ü[oã@¡(·fÊÊ;޳\!ï‘á·Vª%¿—õȲŸû”oõÃâœîÎz¦W©•˵oV}Åò¶èݰÂ=*Îâ/–*œ[F«~K¬[Ö?PKƒ,ÒFaà²ìE‹setuptools/msvc9_support.pyUaoÓHýž_1Ê©²Ó—ë!NTª´€Ð T]Qù@P´±Çñ’õ®Ù];˜_Ïì:ÞØI[Ý©J³ž÷æíÌ›±ÕíÅèÃËJi 7¶¶\˜¤4Mú"UeÅê þH±²ðÞG½ÑZéV1c&“ZV̦fpI ©g“I†9øÓE®ôÂT˜r&øOÌ=i<ë8¦Ó©ÿ¾qÑ×2µ\I\>$¬‚Ú ØÁX&3&”DjÛ²æ"Ê 7­-”„ø3—™ÚPR´³Þ2!`ÉÒµcSš¯¸dt€k8¡6J—À“Ý“¸©,°†qÁ–“ÑexQPùHºÏJ¨%¦¿¹ûüŸè¥ÊjÄ)£¥S¶DØ7@4ÚZËIŸ'THúJhdYû(6“ºÊ˜Å¸aÚÄÔ|6ë@2³$r¾ ÷°=I¢¸´¡Ìpy /Æù»‰ùTø äôï'\®]Ö’žþ(ï²… 0¹‡ãJQdj¡1•_-/ËM›ÀK± 3~#s¹:¤ÑŒÓ«ï?ö >€+z¼Cë²æšÖVgglÍh}ž5i§òüïè€e\Ãÿ'i›}Gáá“_PKò lHÍÔ©fCsetuptools/msvc9_support.pycµ•ïnEÀgïÎv&mhhÒ€@+P«» Uø#Ä¿¤E0ÁI…"Y뻵½öùÖ¹Ýsbä|IøâøÄ7@<¯ÁÀÌ:礢Ë);ÙÝÝ™ýÍØÿ{iaû÷³oB¸ø Ø>Âf¾@1Y† b|Ëà yéÁ`Ò×1–0x"}8ÇÙ"¾ÇN"ßuŠ®S" Í YVÿàWŸæcۡþwŒ²5(AºBæš–AúJÞë{`}°ô pÎèÙ⟅RÞ/¹2nþ@±ÀñÛ6ìñN–„VéÄp•ðH›Y›êÐŒÃwC=©X¦ÜjžÉmOrcE‰X'’çÓÎZ;SqÄ;:å{ÛÓ ¯¨$Òdžë$žÜ­òÇ"Žy[„²¦SÕU‰@…쉱Â]Ç=™ÐÎØ3áÊðD[.ÆBÅ¢˪[i˧üÚõÊ5¢ßÝX·ElÜ|–ŒÈWatp4Š„•€±HMƒÂn—P<å³½šºÐ‡´ ooo¢ê(“éäRW¡Ý—Â|ˆÂ…¢Ö¦[U‡"ÔædóÁýêƒû›'ïl·¶Öd·[3Òf#«uljîØ–ÉF#Úêhb_EîÂ- gËŒd¨D¬¾“Q+¿yiè‚P¼é^Ûª·ÈB†šÒ²Ž¢¿È7€¾cå”Q§L=âaŠþy°zêÃd¦¸Â‡©O¨žãÒÑþŒ¡ý#¡=yÃm ®l|Æ®£Ÿæ»~ ]˜-¨FíJiéŸ(‰â"œ`Z€~ ú×§¢¢³RÌ•e˜‰jÜ‚f‚¾,@T‚u¼Á9%Å¡n6Q6uÇ‹Tn˜/U˜jƒãÃ]9ÞUãÃýÇ:Qy¸ѱîÉ(ûD-Ž#•šEèãí‡omÕu$]bâbþØÕ¶° B¨r…§A¡¶”X Ùu°u¥mEœIK·û\N¥)>,áVG ­‡mܹç:}­Ǧ2|ß­©”r”Ç25˜¡ë¹b§õÉÇÍGîØœ8OF©Ž²Ð¢' ÂÔ]å”>@]^&c¯‘I¶ÈŠl™ùÞ*[B¹Ìèÿ ¯ˆúÛì+yËÂE£ºf~£Jz‡ÈD é5$dëg|Óƒ„r¼"Z„ѯÀ5†”¥¿8n}èDÜú èTŽÈK­c3[€&HÛÀ#†çVg¨­áÜ¢êÊÄ\y@Ä"¨M÷õÉÿ¡\XßD1ï+“aqÛ¹w;à¨x¥ò(S©ŒxeÃÜ­*z³‚*-W–wR=ä=kGïÕjb °ׯáÈQ»õv…Bî°˜•+JâÊØUìîæp/‹Æð’9‘v s?8/åVÇóò$tx ¥1¢+Ÿ34dy‹Œ½è ñÙÄc­±[~™-{·Ù¬v¯]­çOÿ Í\§,ølHV/ŒThgÑ!ŽOwÞÿQé„÷‡˜l±ü€åuØÇXbWöÊ+åµPKƒ,ÒFº+‚á -h—setuptools/package_index.pyÕ}k{Û6²ðwÿ ¬|R’ ÅÄNÒ=ëFisqÚ<›6ysÙíÛKÓ"$q-‘*IÙQÚžß~æ€/ŠÛî{ž÷å‡X!Á`0˜Àh4z³}óR$y*Ò¬”ÓZ¬“ée2—"-®óe‘¤Y>F{Ùj]”µ¨¶•þY˜_¥4Ÿ›:[šÿÓKYëÿ]$•üòþß"©ËìboV+1ÛäÓº(–•P_¯Ëd]íñÇõå<.eUlÊ©4ü=ϳýõõ‡÷ñó—ïÞ‡âyVÕev(y(ž¾üáÉÛ¨OyQ®’eöIÆë¤^„âÝëoŸóGUÊŸ6@€PçWYYä+™×¡˜ey§Ø*U2“qž¬¤úy%Ë $0uϲ¥äÏo&ƒz~ü·ãW¯ß¨&î[%ëÍÚéyU-ãj³Æß\[G¢šËbÞúɲ,JSà¹~Œ¯Û EÓb40„Ü”K‡ÃP,êz ¿€6ÐÛ|þòu(¾{ÿþ áÎíxÊ:)+è4üÚäúwþÓ¦¨‘P¹ÞTòF€qˆ˜‚øïá´HåºÈ€ˆŸ­œgÓEI8ü *ÐjZ¡Å¿?åY‘ϲùìBÙ§ù`°kYÎ’e%+竤ž.ô÷ºLòj™Ô²g½=üÒ……\¶Žge2GŽé«ðg·Â\Öq²\Æ ™¤À„{{Çß~¿xûäÛïx/&ÀÓ„-ð£_zÿ”óùÄ??ÿW2þtoü—8:»ü‡ì}÷öø…[&ü¢”³ÓÓêöÿ9ñFg_û'ÿôFT‚Ï!ìí‹z‘çUb!K ìù(ä*™Vž˜–›4ÝŠ‹²¸”9ˆŽ¼N>ŠE6‡‰?_ÔÀc{oþñæeüýó‡nó4@Þ£D “4<ÚÇfïGðãÑÝäñi~ZÝ9=õ¡”ÿõQÕK9!$,#úx ˆ¡œüóë³;§_%SœÇ“jQ\Ç«ôáÉjýUšÍeUu€,ÉxvöóýÃ_¡9øLM¤`ïÃÛWñ;8ß»Øz@Ô;ÓôìçÃð×àÈ ‰:±ÂÞñïx÷òõï â(ª“2šô÷âÓ!ýѧl ¿æŸF1©ìíÅ4¸1T:ᎼaÑü2OåG/ ¦¢ŠgEã+šxñ~‰¯³<Ë«Úc†÷`Ér]Ïp=’aðñ Zz÷úÙ_ßÇï_~ âZ¸A ¶Ã nÔk.Ê=?¼÷Çz~8<6F%³¤âHâ,¹Ç, r0ÎòY¡§ j@…V5]HÒë²dv#[æ4“”ÿOYnÁ.PBךÀìY8+åç#5©½»^p2>8 4¿rC“‰Çæ `4—Q.k,2ß´%æa­}ñã?Šl¦—{-" 6xØ4èí{"cÒ©¹eõ_èšû^xtÈi´‘²%€¡R%iR'šøFNü#“ˉ’»+lËJÿû³…ƒºB !.$È PÞ$0Ê ÝcóÞA¥¢(x°ì¶ï²˜&Ø.#Í5êÁ‘غXA“N·Öp0kú‰°Õ.Ë|_lÑCŸÜ `c×+ ý޵ÂDFPѼ,6kÿ h0n+^¦2Ÿ"K8²©5ñ±ºÜ]C-ýƒIÆVÚq„”Š"7 õ0Íô+G¨Ïç¨/m饋)&VòâÁϲ¬€±$éÙÏ€öš|ÞØÌ,Ô4µ˜.·‚”Ï>]dóM±©šá#ú˜âjöœØÎI„¶ÝÍhœíDוá ã®Â„ñ[]úT¹†é°©†‚V]^Ô¤a]nQ}º!Ã6Ýkð³øUaê¸km—e÷˜üïË­ÃN…k™£ÙQ G8$S*²žFª–‘Pǵ1Êë Kd(ߣ%»¼N•=»9¥vŽ»-zOΰ߹ÕQ2íÎTí~úºs~£ì·LÔDhèzª*L{e†¡ˆë… A~àß ÚÒ„°¿iô÷˜ ¸ËŸá½]¤Õ<‡tœ°ÙÍI'2€æG*nÞ6¤üVæ²/O$èæÐô•l „J3 ›Ë¸ˆ¯?€æ>B<רŸãücBWÛª–+ÑŒè¶Øð`60~SpÂù¹)‰ZÄÎÏqä2ԪРò>ŸãpÛÐã,`Ìsù'Ý55éþPÄS9M6 Vªb%u˜ z¨4B4©¬tWPÅÁCFóHŒ’4¯À¢¬E>>ˆ¢{àŽä\æÙÇñêã<³•,§Y²± P•ß ‚$¸Íª+2õmøŸ:#Mo„ß´…c5¦ÀÙh„B㺣‹ F „êÑ(ˆ„x™Ó¡/:•¡‚‡ú©Zoʬ«M*=Ú`esY™g+z‚4êò í2ª”sY€#4ÒDݦFNç4– ¬cí ;À8±—H€|+ò 9›šðÿ åH‚¬b$ˆÕ6ù2»”Ë­Æ®P¦SBa7p½I2g5Ò¥´«Ú†¯k˜y ã´*`ŒVˆy±™/¨ MuY/—›\˜€&¾m¢gŠ€ó‚ÚaènDŒVY° ÏicQKÀ¤œ.㹂_‘ÍF6:þ "žÄkt},µ mé±g pT¨ø!@J¿”ÊpôÖÛÓô4:MÿÜùµò›‚}rxtئL^’¬ÖS€š€bÇcÀ&[ ˜Õ-“dϨD‚_&ù\ú!ê1j+¸s`5ÅÆ¡mďо¸˜…~G‡cx'Gë³ ór r#r–pn~¶ìÚæ?­º–¹Ó6!@sì‹T{Cü.£?‹´˜V¤O6yœKlO 2˜~ °\(.åÖQœ¯¬\ü^ŠîV„:s(P‹2?X¼…O8`.MAœ¥ c¡…H‹‘vËÞxž>}úìÙsú öèxüX<OÅ3ñ|°T˜>yL#Ä”n=, ¤©d­¢+ø"NÒ”^NðS3*tYË5þȀ⮠ÏXÑOŸêÇñ´ÈëlË8…¦aË~Òú Rà|eFSŸè‹ðƒ(è6Ü&.¡CÐþ°s4I :âÒõ„ †—A盋ŸÍ;WÉd™‹e@ÿ^&kTå¸Ì³ž' òJÒô@T‰äý¢ä~Ú,kVÐ\€@‘ïALDˆTš¡ÐªŠœV¿¡UƇ^ ®øn-KÿvRÎmoß¾¼Æ_Ö)K®Ía¦S˱Rè½½·Ç¯:ñäGþÉ?ŸÝ>­J¹¤°²U>»Ðçàq7¶¼käw˜÷¾q‡†‹uÐ’3føËŠƒkÐÍȽ€b€Ér2Z€Á‚ßF$®é•ŽÉŒÕGV:Ç"ç! ŽÛ‡·¯*àD¶U+¹EˆެoµŠOÌ‘K  åäW~` вR³x•¬}œïäàR5<Õª'ô‚Àñî<Ýro  Ö™ôÛnœÂ   þ€ð`0A-Ä0yõj™J\ÍñÝð hhа ô¨^<þ-Å7Hy°ïðÅs…%Å‚¬VÁˆ#w. /ÂÉî4|ÿÓd|ࢩÃ7ÔJ¢Š§Á¡tGbôÄn~O7q ,†6(h5bE4æ%¸»·*k¹þ7·Ô:'Øÿ‘R„'G÷ÏB½Zé{M/8¹w¦KíASÓ%ø¸˜…6Ô³…œ^Â`±'×OOÀr5å¢bÊeYÁ„ùGÆÛ¤³d*i¤¨ò¹ªç€¤y&e ja9S̃Kk¼t1|^@1´`°zh;°G"i1'ê­eÛ0äV8Å3np %"BW¨¥‹¨¿pŒ ÿ³×Uw´,Þ—Ù4ŽCQÖª·ü´„A(£"‡BÓ@—nĿΠ°Ú_=$>".܈Mµ¹{¬\ #ŒN7¼›xÌ"ßLÍ.»(´ÁDaÙ³HGÀ<ÿë71òÁW‹äàøçððþ¹ÿŸôçðá—øçáÁá/«ôa0ñZõåÇ50¦LŸ$㮤éå» !rgyVDZ"³iœÓÃ¥îfʳ:ûÄ!"µŒ[ÓíK”ªf#”ZÊ¿wÖEÎð¶÷Jù¿þ ÝpI&Œ|nŠkMþükp‚Díõ™ô£ô‚µ5 a€Šµß\á^ŸžZíML?mÝ$:ÚF•‰¾+ÜÇê-ø&%’CÙÿ¦KNn§äÇ©\×âo¸J:¨¥«ªé**Ô¨šeHæÕ×cq…–»YéLœž^ãÜå¼=[ ¸ÊRv¢f'Ò-—×±réo²†ë6fËN*Ñ)×$–÷%•+zç#åÎ[ºm½õ+ªE ï°úSMÞ™xû¸ëV5¾Uy¸0ˆ#ÓaZýô;Tú¡ù…á =©—ݘ‘)KªÕ!@ßTÑ›¹¢jsÑ“œ¬.ÒD¬Ž¬]·ªýUú:5z|«Â­Vس•æÞð~x„]VØe-)TF#¡2f+`T ñm.–rL74þò"Û¬V5Š«Kcè¶×ˆ,`@ºá‚5îX¸U©ä Àä ùU@ë|¸°§sÀ°‘¯QÒ²?)˜ “K-ù¦GyL¡¶„ø0Æ`/ª0ûíVŠíTBÑuQt{ØÄ$«a"*KÒ´óYì%Sìf]ý m;ïÓ$R™Á„—³©”¸þ’êô„TV8%u÷v ‰ËÅæÈuÙ—ÙÀü\.ei§p˜dˆZ¸âu˜Û¡M í]`“)Î:]—¶ v5Š•õ?n1˜²jVˆ9òàt›‡Ôjƒ‰jöògH€ƒHÑÏag‘™²&b\nU¤Vi¡•I_ÏÖÉ:ç‚òkÝì]å#ky˜Iàú’£¿©,ŒAm¨ZµYÑqÒÙûО™º ³ Ý6gëN ðþ0Üâ.h"x_t¢+¹ÛVŠ ð>£ýUKmQùÎ ›NãþºImÚõèîÒÚ<×ð>·G€sÓ ±c$¨ÛÜq’¦â_ŸëÙ’„ç?¦ÂãôWó/WÝfI&+› ,IÔ«?»½vVmÕò‡þ¶Oû±$Ü“%® lÅhŽ% PÙ¥ºZkÞ48 ‘ï‡Á%±Ú]–Ýök…)4wÔã¥BÑá¥CÝvÒ>eÇĸ>ÛF#ÇÌý—ȨnV_ ·×ý4u…¯ý¹ß< qËÂu†.pÌ}µ˜„¢ (üËa lž¶ä½–ÛÝÜ44†ˆQhïqºÑ3JsJ Þˆ2#S¸¬ ZkÒ6»Ö65EB§FÐR'MaÅ}ÎBR ÌÅïŠÕJ¦Ph¹µ¬é®ße|©¾tµáp-=˜”Ä“r)˜Ÿˆ!³œÓoÌÅ Uô×£!æ]) ¥YàoleeCYÎJPŽ„âknž2UÑNU;Ë´}°Êªj-A ¥ƒØøÆxîÆôÈ€ê &|ÎNhšù:°BÏØ G‰¬Ô>³ý‹Uµ¨Ö±äµœ‚’\­aÞºœû ƒ‹+ºk'c ¡ç\ë<´ÓÝ•ØAÞXoªÚühñŸŸ['çà¶5JZ Y€Tt:Pû (»†˜h¾á"~j„œRd Xo0³‰Eý5ü,’ï•âFik Å&ûQ¤]3µ)ëÙ!ª§ý@NöĹoí >?'Q+ä4fD&¡°7’bB!±–Xs %üc•E‰»¤ÀÉÿ9€ün¢:?§taÀá76ÛÔ¦œâV­˜‚–A7ÁUU–J6uÕ£|ü£fô ÃjÉRê§ÌàØ5‘¦ÏŒJÈŽ“,KUjç— s³¦KljbNn\“k™Ì0çÖ:åJm„ÔlDC=$¦Â]šËh@­åÍ­ Ì”רVÆȸɧ Üs•FŸUm‹î€\‚Ù¾4y,®j&šÞõæ²=G¸Uhëo oûS‡Fñ¬kÐCS0EAœhkMÓéJ¦=‹dýÙÅÝt¿·½Ÿ„»á®b•NÆìÓÜ/Ù¨!Ýfd‘ÚÙJÔéÔá Ò±®Ãþ35c®àHÁ1áÃ(ºQê öÇítç2i*ûôڜʡ¨<**ݲ„¬%?µöNØöf 2|(þµ©j³Û½»j ]:[¼rû}–XoجDxkÇ3hE¸ŸÂ7wr7rôCùjŽ:"€ÔK[l¡E!n Bã¹ÑÅíxÄ:¿£ Ó9«„¾Ã§¡§£Ê±“©;U;î{ËCg !ªÀ©$û×ûCµß[ýÏ“‚}µ,Öqq©Ë’`b;ÐÝJOÝuì‹×äã“Ç`Éïj“Õ”¦ŠÑl³º/‘þç²ç–ea¿+äQea¸{å]•¥å–£r‰Vn‚¼ŽNâÎrœ‹Ù÷.Ñ&žPmákxÁR·ÊmdC_­™øìÎÆ1bÛ/ÁämÜ Ýhº¥¥KtÐÃD *Ö%-¢Uè’#«X 4ƒÆH+ýdƒðв0œkó†6ÕÑa×´¹ÝTl^Ô5šÊè8 ÚˆÑìÜØ˜x&Rèdág¬ÓÂvqì•rãçÅ€¾ïöñüû`´¢cÍ’Ì­A¥Í—=d¨LúàÆƒ0ÎÏ‹:†ÆU%éâùR¯I7³Å´j± ɸ±µÇ§B€¶©´¤I¶©ZSŽ*£ós;FÔ JêD~mn-vÚr×õ$8õ1¶2”;Q>Ëù¸ÌÀKNÝxŠ7NZ+­:t¡>L¬¸j‡Ei`fÉUw³²~ð#+Îvœ¬Kñ+íŽLy‚­ Z틽Éà®ÙÁUh ½WSíÓù­üŠÉÄ>Ô¬6Ü0¸nHMê…&égÖü8î–¥þZ …á,ÃOœæe;¹Å,…Ëï½%ÑÔÏò¤„ 1ó¶ƒiÙ‡±èÀϲéäê +«¥FL÷&Ï·£êæÓ "ëø(Þ՜ڳ@AÇãÝ7|²’‚DHʹ ÚM‚Ñp㟡Èzi£Ñ,ï"ÿ¿“ÆÃDhø¿uù¡0a µiG4X|³ýÍr 'GНôŸÿÒŒÒLŒôhtëÛ£Ü eë_É,|Ÿâ1*¼EowúZ³— òæª ¯Vh½ìdƒ²m@ö­_ÝÌL°ôÈ­øÞóã7oŸ=yüü+‡á°Öë1p-[Øh:Éuð‹¢qqј$åoêì"[fõV…ÔÉH”é’â¹4È2ÝFXf†e.©e[Ë—omØ#\8Bdi¼| ¢ô+h51†|{xÔè4ƒ*iÚ7‡výæpHÛMit8òJ㬪´q3nk7Àø›ŽVÔ¹ÑêP!˜€'®è` tvåbïbÖ±i­3ù [¤Ùf¯Aá´>9så½Ì}ΞL8ŒÜ ös˜#5mܬ3憗¼\¥º/¾Ç„ •–%y6-Às¸ÀˆµGÒ[ÄуïlÑ Â7·=ñ§‰©ž„SbB'ÍTË‚î!ƒúé9[{ÃÉ¤ÚÆÊ¹1§cÄ¤Ï »@}·p°øœzho½=lU辨"“Ô6,ð!¿¥› ¬ûî鈫‡G]cJï‰èɩưêu™Õ=G(â3:1ßœæÝ•@ªÄ3p¿U†:‘„~¯·ñªÀ%§jrr«< †`ìZª%ǃ'ì´’°yíŽß÷hªQþ«ühIyÒ:ìW?= ²}JY3\ëêÛ£~³Õïg´íËšÂËm#B:ákÖ³LâºMïê8ž –&ÕBšÄIšð H4ŒæÌ7Žó§Ê³ëÆ Tš‚“REqFP†,…nlTü&zhçp½D®—7*“äö¦×YÕðzz‚k†Gû€t‚q£ÈzY‚Y\TÓ2[×úø>Tt8Ê¡3†è´u ÈPYL–buû™‚†Ñî E9ðùƒDÕÏîÌí  ÏeÿxZÉnin}ZR_¢_ƒ{æN†UXÉeF Zî§N·—4 Uß­£»ðŒÁIãbm%I‘ÖF¤p; ØÝ«Ó”zŽ¡;"µ#UyÂÁÆ ’~“@ÃgUXº”×›üfÁÉ\«½Ì)wîÃÛW4Q®Zg‘Qnˆ'Ôq' Æý¤œóùŸðåÐU„‰Ögq®ˆ2Ë¡˜‡*B9(7I…êû‰sψs„Õé»>µÃ(•žÎ*²^ Õ UýݽBRùïîsû„Q„ep’:&–Á¤C1Í O“ô]Ô›êþ ]§¥ßÛñÞÞ!˜õ¡»TT„2íEŒÄû…Ö†MJ”× í„Ù©·€¦Z·ø ‘ØŽ^Ñj˜ˆÿ0Žwkå)pŠ–º´„Jw)`âÕ%+ä)c›ßÈ”2¿ÜÈÌΛ5=ÝÛða}ïE&Ùý®ÛÑ÷ý€Y&`ŒbЋ¼ ysz obo—»¢ ⸉qÄñˆ;¯6 "ž¸pˆá¼à þz³é^»3Ÿ¹j¢…}ï5àÈ– _ê¤N[׸Y{tzNؤáÙåeìÛ=`vÀ+e®r–u8›ÅVŽðé΀nl¥Ã@I×’±GÂnmžÕC­Á§¶%oК|1¿!ìÅüf¡£zn¬«éZgžíâÐÖ!@êlT’*KG²Ô‘Ã}RÇ󘾵;fÄ…³#¨w ›}âHƒš%p:míöš§­Eþº"sbOãkõÕ3xTÏÀxHµ;V{Q}C?°Ð¹¢— [dèÂ?r&9NpÛ[rwåðñÆyOP7¤K> ÝiAìÃ'šòÆöjsÑì(Ô‰Ã:Úìú$ÇÒ{D7çáÅzcqvGŒEðõ[y•”ÓôΑÇÇ „QÍFòÞ¶Ù0ÌÙ·IE?ŸÛ¬Ò©› ,ý%ô±NI/¹z±Ü…Y¿ð!7g†~÷þûW:—[]i5ºãnp{±{¢mè0Còz¬ûºNîQÇJ¹*pÇH¾mT9íX¹Âš*¹´ÒTJ™â|õ<{F"`s’´«9ŽôIßxj—K_6' Tƒ£e.Q ÅO!#¶é\˜fµËGò`EÞ[@¡a«ý»wuëw=>è ^à¥=†Õ<Å›ƒôõföƒþŸ_‰L_Zê3¬Þ N¬1˜¡á’Ãeh$+º¨éZÄ‚Á£^õ£Gm$ÆcÀ~qKAþ†°µ1}²¬ Z^šâ*}géÔb/Ña/‡„`R{íÝða¢W}r ÔÝrÙ²êMŠb›N¶ºÛ¬ÅnÈ&­£Á:S°”ßñ;&DSw<þi“ɺÄof‚=¸ØÁ¤ ÃgúÔxœ¯*E°åe[ØøS\H_|Á}Òó¼A-èßIj]g]^µÒkº°Óø›ÿÀ‹ùïSõÿÎðX«­Ï£›>`µY‹ñ31Æ(ŠxüÅøiày»9O£{”Ʋ˜«îÖgëèñæ‘ÁêT¦·6£>S»9N×ÞïùT>µŸo D+ϾL¦¸í |½…nÏdI‡|ù 48ÍVÉRßêµ·ß|®pÙB~LZešjk/mÞÑ·ƒ¶­ É¿ð÷}p1~ùxrš&ãÙ“ñ‹³;Á/'§×ÑÑ~}õ5ø{PM]±3]”¾Þ•ÒÝ`4ÅeV;ÙCŸ+¯ËO>|xdD<ÝïOëkÔ¾P‘SŠy>SI¿^ЕÃnnn?:æêþGçzN® ˜úøÍQÐo_ruŠBtìªpt¦ëÚVœ*†cqˆÝXƒL¨É£Æ/n^Ó=÷ "3–Rt°–ª›‹0G£ÑszÉN Q)kÒæÙ•„_P>jÝÙ0ƒïP8¤ÒªÍª˜^Ê:®³•Yï«¿“ƒ‡ªu’Ç­BÖKCE†/<§X¦º$ cªŠ$SñC ¤•"ÌŪN1õ×-Ý»©I ž¾Ë•œÂ½ s;‘°ºÔ1Z[ÄÙÛñ‰ÆƉ†‹Ö¿ðŸÎ 2æn+9©÷¸šËÖîïG÷­ó$UGˆÖ=n(8èÕWaÎV{üø1F[}/O»(·î?Ñ^§øÛKüa9]=\\üý×Óo_|šÞO¯¦«ÿ3ñXÚ¾ÂÛ Þ£jî ¤c7èšÅÏâ¢h è.Ü5‘CsµÞ6á†YBÝi ¸€w„gð¹}pÏ”ÇÉvp/ üývg ,Õr šãǸ²îý¦Òô olÌÁ;¢ýttSƒþ«|Í¸Š¸M_×Ó)´K9O¦ÛÖ?ÍP u¬?K‘ȘÁ…÷ËÓk&§ß4ÝÆPŸs¤wÛ qùÁ®qÖ0š€{]‚—B{‹“²Ì0Êbn¤²rŠ*š«’J™òu“C×$é1½«‡”lVFâC…'YÐiU¤ëÍz)ÝËØzî¯ÑÐB¡Áµ£³º²úé0xL ç:=Õ\ç*G§¾o}à]xмÞ-_ƒ ª£[¾é-_·Ïͽ&Û7/Ÿù,›ûüç ÊÈþOp4pûÏÀ™=¯hu Éßð~’rÚ[N‰J>PyZSŠÕ¥ÜVþ‰™·x8¼™µð3ª 7»zgä9`ƒØ·®'1­Ú†ç´½üÓlÆ]'yJá'ï¿){TuÈj¹»w·lïÜUi)IŠŸTŒb]k˜z[CZŠtÀ‹›N¶©\IïçA˜r¤Ûj’5‘3U)îêÈ ÆïDþÔÆfô¯§¼íÀ&y £à¦ÚYÇz§;ƒÌY'1&S!„xJ·åwÀY`uj™•©ªÃòë¢ÙŒ}cœ­{~B[ÜtGÌjxÒ€ ?W¥Q€Ý*ísñ¦ &} EöÄQÛ#QIã©S>)b½–ÀðJ/&¢¡º>.eÓÐÚÐ8¥i¢áà êx•¤¶ õï}˜ÑŽk]&$†×z¸:¢k2Ûk)Ýô¡¦F_N¤òJ¼jϤ*µ„87h²qo±iTÊë5c£s^„º9äÛ!P“‘уðx« Ž«¹­i ÆŽ#T=B+Þ®4çs:SG Íùl¼Šóõûd*^¿?b Þ’àÈ‹­:¯cŸ‚‚äÆÎ|½YK¼Ú!Fy‘k̈́޵7«Äþá½Èxp„ºµÖîdk1"ÝÜ)¿ úDñHuË,ãÒ ’ÖFÉM÷UÙÀoåw=*eÓ5ûZôJ­Ø'æ›Øz-ˆÚó«<Ÿ\Sm¡Aˆ[r’s‰ñCÔ˜öq ø˜ ‚÷Äb4p1–£RQ0?ô¤R*êh¬ÓÒíœBkô4©€ò#°i»>)¬êíô#ÝCbXů̮ȭNt/oîzËoº‡ðª¢x ¹ÊœõGØqîŸxÚ„¢ÁÏÙáfšÙÒß‹¯?Á{<=6äøROn‚Ò²yþûªòY÷Å›MÝšå<ÊdÓ‰ÒGº3ÚèBÌZPª‚¦½Y±°Žc& ôA“ñIûêè8\}R~ÂoúÔO>€Ú•ÌÆµ7QøÝëg=~¿ùýñëïß­(?Ë>ÆÕ̤?91u±ŒBÿöAÑJ:5zà-£f‹²ßŒgy .Tž–ÚdnîOÑZPkN»s4ÁnE@cÓĪäº:B3ls!„³½ªçÆhWÕ5ÍPh‹­Tûv=bšÖÍ,ýñôʽ͎v†¶nžè©©ðŸM&1CDY&=ééý[¸L(y„^©vnõd·ãsQ¤[+} çÀy뜼ýj¾ïŽ; a+B„ÒçŽôÛ·Ju´6o í5Õîâ¯êTGZ=~„âî±ÊA0üKßÜJà´ƒÙèÑ]®…°¨ý€·«¢ßÝôÑŠsq.i(VxÐ ]Ptxï^(F¯ÿ:êÝ­Ò¡FþÁ½! ƒšë›‚ðþhsm²¡šT¥ŸÝL#0)0I{¿ÚSÝ$5«ð6&è…2^¾ö' øÿPKò lH †Dv#<'˜setuptools/package_index.pycÝ} pWzÞëžÁ AR¤Ä&)€H€7µKñE½H5H‚ Ó `À¹ÐÝ -°±Ee¥Ø»^{½qlÇë²·*‡Ïãx}¥ìd]IÙ•ÃvUìØq¼ñ‘lå°c—]>›ÿûÿ÷º{®c' +‰èé~ýú½×ï½ÿ>:ó{]gì;e¥ÿËÒß‹ô~*£”§Ô$-åÙªj©IËœÛjÒ6ç5™1çY5™5çmj²ÍœçÔdΜ·«Év>Ϩj‡ªåÕd^Y¸Îªj§ªmQ“[T­ & ªÖ¥&»Tm«šÜªjÝj²[ÕzÔdªmS“ÛT­WMöªZŸšìSµíjr»ªíP“;T­_Mö«ÚN5¹SÚmSÕ]ª¶[Mî–뜪>¥j{Ôä¹nWÕ½ªö´š|Z®;TõUÛ§&÷©š£&UÛ¯&÷«Ú5y@ժɃªö¬š|VÕÔ䀪R“‡Tí°š<¬jƒjrPÕ†Ôäª=§&ŸSµ#jòˆªU“GUmXMKyîcDMŽÈu§ªSµãjò¸\oQÕªvRMž”낪žRµÓjò´²üŒZ8£¼.õˆ–ä¬Ò—[ùäyõˆÖ榰›ë|Ð\ö$uΩÉ”·M-œWh™/(¯Wy}ÊÛ®¼jŽò¢òh&/)o§z—*¼¨¼]|rYù/)o·z—Z¾ÂçOñù(Ÿïáó«8÷»¹d¯z—¶È5>šï¾¬¼g¸©WÌÀö¥]ù¯(ÏA þ+”·_ù–Zøò(ÇïQÞAÜðžU»©lÖVý“7”7 üWÕ,â•zcrLy‡•?Æ¥ƒqéM¼¨¿K‡âÒ[f$Ï¡í…×Ô¤«¼#<Èqåå“ÛÊæ“;˜o„ßåuåã å7c8·{Wy'•?¬†ùÆ©øÆÊß§&•wš›ySù¯+ÿ:÷ßä÷~Syg¸á{Ê;Ë'SŸñÁçépkåÖu§T÷¯øåÈi–Ê÷Ks¾ã5Ö«’W©ÏU¾Dÿ ZT;j£ÃÃ Ô »p‰Ã•W®^ùÐÍ;·‹£×ÇoG*­„QP™YŠ*z´… ^º>vÙ}C*l¥ëz#¨•ª•·ýb³Ís•ñ›wÜ+W¥J;]þâˆï]­?¨zͯGQ/]ÏVê^ÑKuFy¼OiÖ/ÖK5ŸÁWü 4ƒˆÅÙJÕç ¸v¥n•G}õõ«7nÞâ!ÈË¢VV‹áR³Ù")$Œ¦ª9¹Øªß–FQ ¯A#ìF9Þ`)¨V+3'ù|>ŠštuàMiØõ¹ë7y̯ܾ}‹Ÿã[ôH³„~Ô)Ku¹äæê‹KÈ—7¥Æ¢¥ÐxàTñ$æ‘ߌ§—NN–žßlTèårüt¥<˜q- \wÈm%Ê%š½Ò¨ÏVænaA24…‘Ì–ª¡/…O”êaµùɬ`qšÅÙ 4‡ –rLÍœKÕjqÞ/y´8áN*{ËŸ›»0øæðåáÉÒðÛLJ?X™:2ôløf.ðgï…Ï] ¿7˜º4øæ[‡\tè~øUtû|ÉA ¨üÀA*=p‘ÎÎÓÉùc¥‹÷Â#÷©Îà¥sQ%ªú¼:zÆ™/…ópoHž}ó­KSGî]:W*c3]ç‹5ïÌ¡R­ù‚W™óÈFGÃ* ÏN}øÔÉ5ê„n£ƒ{C!6$ýȈ }êÃ'® ÷QñHT FæÞvøwæí“|⌼]iÒÙÜÛ<Ë·Þ®×=™'ˆ÷u#,Î6‚"­HÔGe¼ Š3¸U|X©WhÃG;¨œVÑš% Þý´RÆ„X±]¯`=~«J-0êX³€ÖïeÔš­Öè˜U«„°˜Ú~Þ\Ú|y¥u¨6Xª½(52 ‹D ãáJí |û©I\ä6>aƒj¡ÍoçRcKk›¦K6c}›]­OÔé¥lµJ÷²j6Cˆ­ïzÁ;Z êÎàL)ô6W4&r38Ö¨ûGqrhšf# +3Ußñ—}s‚ƒÁUÀ¡9?u—•? T(HEa>¾;Ü\©üݬüþ„áV}s¸TóΞæÇåyy\ŠÃ®–Zhæ7ÝbáÆÆÆ³íV àq‰‘3øúu/|X! ÚÉW "¾Du®‰wq‡Ì¦‚±As˜‘Ëš¶ƒàÙø^Bµ¥JÕ;Æ»m¤V*7ÂåáÇGN^þÀÙâÙÓÇZQCKͨѨ†Ç4Å(V°…Gš+î!¼{Mf V·Ýmu[VÞ굺ø7}U°x³â}rf³~+†Ìû•öʽök¼S×ÚÔZNEV=Þ²´SwÓÏZ;¶mÕû´{î«Õvì>9_ÿ@›y Î;•ªÞÏ©à“8A¥öíÁ{6êP‡ØiÔzÌÂø F;aÜǘ<†º°±”}ÚQsþ­/QLGÿ ;¬àÈëëˆÝf…÷rÓLeý˜‘°ª"H‚α|mjµ …Ë'°Åñp›ZhÓk¼Êû‚&îQÆjikQM,~”(³^¥Ã¿ê9ôZ@²˜NšÍp3 Ä#…N4_ŠœZen>rf|B!KÄ?QIɹãÞàÕ•…!†Ê÷üzÙáuÏãÎöu8¾Ú(—˜Q5¸úòËÅkîå—_½:v›W³VŠÊóîa³Cæ‚ÆRÓåýƒÙtÏàÖš6@É+E%^k÷ñèÈ}qÓ—ßÀöGc ~Êîµv«¼•#°ÎÑÿì2¶o»þc€þ¨ê£IÌ^½:v=¾Ç‹¼ ¨¥䫨«\‡¶í‹9KëÚøoÀ¬ràiMÐ!8¾Ÿç mÜD†wW›‚vÊ£œ§Î—/‚c: 8—† Î5•²0Ár¹ƒÕ ™±Œ/~»š˜#®Ž—8<÷—ÙFÀÇžC8a²ÓÁdgn<‚‘¬.aÔ1Ó¥±AP÷€/æÄgƒF-ÞOŒ†ÝçpÀöq3f[^½{ûêØøõ›cãÂËúu:o£x3vhrÁä%s›ÈT¥î1SòA»¸ÆM³Éûì¢bå ÷ò>ë&‚±Çî§}¶ƒÈFÆÚí¢ómÖvA2øËšw@Œ Zâ¸t«6ãvÕ¸¢ãÓB:¡ï×GÆDðÀÓ¼É"zžÐ w€jŠÅ2Ñ—ɰÅ"¯8£Ã Án‰ð.?tß_áUF£|'EjŠõºcÞ¾÷7s‚‹—‰(âµÐï7£í~ôÍ“ÌR Ζd»‹Î tCkFÿ±äOëü>“™÷«ì,õQ¾\c£§°Í`?”š@=KuV@8‹®˜ø0ˆÌŒ.•ç…óŒæ}ª.U#A(R›jÔ«+²"+ g¡YVªT G¸ ké ~Á`þxÄÂÙ|-Uh£èýÜRŒ<ðT)˜ Y¹ÿ§¢ÝÁ ¼Âæ­VÊÆ¦|Ö eË€”ëáàÇàm™²MBW²!”ªK~ø]ÊÐж=™]ž|ó­‹SÏÝ ¿ºQS5udˆo]dŒ`˜bÆ=4ÖåÏhŒ.ìëèÔ×ô`UÜ3R/Í0!´…}¡w:4©~dkÐ'2MàNŒs8J-çAZ~šºKËM£SÑ ¡âUÖë¡¿ˆù#ӡЇ$%õ(ú7±ìAm3:uOc¬….#å˜% Ù™D³ïá.¶2*b¼HÐaýùýtX‹ß£èßÑüñAVe€!»F‹@Û¼záÀ|£æ7iY°¢š‹ŒX}À©Vê÷C"þÎ4ªL•À a,d,q”‘ˆiÅ= |Ã|V÷|4ñºåÜ¢{ŒÊQ2ªÛg‰Nôßö_ü Q³„õ†f÷ê•¡†¥¸Ð½k*ÕJMAšQ zèNYm#ÔÛí÷ê5\0“Ïù¨Võ|¨xÝË1ìQZIP Êó"rž1wùÍ_4=F¥9þ¥¹ä»ôrñ¿›ŒRûôЊ$€W«yÅ~íïb´ÚoõZ‡­]V¿5hƒŸ/ÐuÎ ŸQ°NDóú°¨Ò „Nª§°Ë4IqM²ú ‘¢Wæýò}?ˆm“Xx° !æ—ÐÆ$3Sb‰„$£Y]Ø 3|ÒFl…( nŒ}Ù©/ ,KNYúììùôº~ÈXšyÒÙRÙg=#WÃÎÔÏ :6’ vÅ`—„@Ÿ2}â¿k>I%g†˜Öû`p!ò ;é³V{$®96cHMK«³¼¹øÙM^cÞ~4´Ÿ‹±t–颵þµ"eD®+é×â5J^ÂѺÛk°2€I'Ô[ñ˜KwfK•j˜¼fBznKb~p?¬6]¢b%,ò8þmê% Ñÿ2k·Ôò’àš–$Ú*ÐÓ:О‘ÔÀ/Vš!I€çÀì¦ALË,Cq#áÒLU¢¥ˆöm.Yy¢íÃý «Ÿ1ÓÁ/`úæ óÌ&OT.îçWâijKؼ"[(ŠEÚb±Ö𖪸lçK¯Q.Ý5 ú¯áðNËBnãþ6µñ¯Ðëœ39+ŸËçØºõ Íøz„a„ñ1ÂðY—à‰m9k0G›òsy ¼Ýà<œä!㤅Q5Ë=—nÇRóÜ\ çK'Vépòäiüœúÿœu{•µFtñqeàTõ ÌÎÁRjßA­6Za²0ä´’z9­+!J"Výc'òä6K¨£˜¹gÁ«”#1±Y ™ž³z÷ huµÑ Qƒ2ÿ·•Qægzˆ·3MnOôlñ CÙ$v؉µR›‰YtVø³ºéçØñ&YÝ|èþøŸ1ò±bB¸?=âGrnÃJdÆœ‰ÇÌPà/‹X6ó"1Œñþ45ìÌú­ 3‘€+¼_qáÂ[$5€ï™à¯Äá«Ìª…s›<ìw”L¯ÈDV—5Ⱦpx‡[f‹—µf¥ê»Ð ¹¬ Ù›º†„aæžûu¸óäÑ?‰âê?ší ƒE>›oëÞ’Ïä31Òˆ2Ò`mà½8ùÂf Þϲ N;Ÿ·ñyŸçø<!IP?I98Ù‘ '˜ÁqÒ…f½-\+¬à(ìæÂ..ìƒ ·Áz“^¸cá¤^X8ÙÏ$œì@ïò-ôñPûMÉvõ® ß6oWÞÅnZ»›ÖSÆMk?+nZ{ÙGKÁà Ztò ûe)ø¸Á)KÁÍM;eíWþîhž9<¨Ý±&Ÿ…/Nà‹…“CðÆÂÉa8dádúµ¸îr«þRxí°\ª‡ÎCÆ|2—í¥±¥xß„çŽk®4+Às$RŒ4Ú$â|Ÿ+cÅÛõÊßDÏ?!¤cÁÒfE’i¿j4¦#iw‰‚³SˆiEibªOÚÌIa(M‹ˆÂ"µÃU¬ÀÕºÔœÔß ?ø,nœëÒbëYÿ‡RË¥âÌRÝ«Š3T£ •?¬Üœ\ºÛ n¡q¡Hd^Æ{ߤ´úw¾FâÖÚâ?¨Ì®ðêÎ(­¿ÿp“Q &¹ÃÒTReû¬=Vžÿ?Lû­‚æ1œØõáŽm6BóPÞ<…­R È‘¹CUÎG†— G¹4Ó_Ôdm‘ÄŒMðWÌ™çÜ(ŠÚYuÄ*«ÎLOømÜ1~¤Óγ*Ï%¼í¸Ï–¶QÛÞè9 ÖÜßÂz)騥Î ¬gmv?Hl°×úñ=Vj:X ¶•šmã3”ØiC  ðI¨½ PèRFÈO­ÉC}¬ŒÏl¸£x4üI —ôŠýì‚ôákx‰ì2ýìÔ.LÍïÖ·èÙ…]ìkÒÉZ/ñ‰»]~IE»ÕÂSÚ66:uB­u¨hpJ´W­v¨…§öc•ØšLî3j•û±Åš¾ÙÇÅ[Þ^³£ý<7FBèà^³Qç@JÇ£a‘”ÝòàƒpªL6ŸG:%ؽbçAŸGYÙV+­Ì@ÙLØ×‡-cªy] È9ç „ì$åúì,ŠKô«Ã|x7Â6RÝÐvÆ¡=ÓÀ¢§ÞH\)ö‹hÕª!Û&…™ŽVš~Ä ('ÙµR>!œÅ<{I2f¨ÌÕ_‰ÕБU>E—ƒðvu¡Íw?¢´ÚˆÞ¾8~å•«¯^e‡–fÐ(ûa˜¸‰¢*\( #DSlÜgÄâù3Ksî·Äï Ó%¤z楒€2ÅrÆ +íúÈ Ùœ‰VóBÐ×ú¸’Ç#¬„pö+Õ˾[C#Û Â†%{þð°´.^wh Ý&— §eÞ:£Èvi‹Ä@»®Å(Œ•±‚OcO³d*@®˜ìYñ(Êî·²ì1]VÖîe7”¬Õgﵨœ]²vû­‚ÊZ=„v;©–œn«ÛÎÛ» wÒÝg¬mÖs‚sš`„ü/c> –ÃCß 'Tr«keu­àス?n7èÎNäÂ\¬`dLjX×î0f?+Ž>Kj¢Î[W·#ÞO?¥4^8‘UZL”neëŸ`èºJ1¬É#¨cc(ÎÀÆ«°ÝWqø€Ùüþ2/7õa)¨ó¨„^%УTe§´v 5tÃýÞ˜)й`¬Ü€Ã÷µÀ˜~?lèðlû«“Ðå{Ò?Vä×ÜW›.`/[ÆÌG[¨‡6Èn’xû­Cv6Tl‹Ú5•Ò,hê:ÌÊKó…bÁñX´ ¯éeSÊl’¯ì{â„K§Â¾IšZêKÕ{ôÆR³ÛXÈK0{. :Źá¥ãr@Hw&‡y0ßsÀ½‹­Ƙøâ™J4R]9v›û`eA3Ñ„*Õph¤SÌìßcP‰˜%à*" ^V O÷óX“¶V„ËÙRTª2ŽÝoØüŃepŠ= Ö9‚þœ# «ƒbXž¥Ãr³8:5Á°°ÅÕ¹]-ŸçB£Ô«»5¾kÇx=Ú´ç1Cæ1Eÿ&Ûý›ðŒ¢hL„é† æZ`ÊýIþ™2|8 œqŽ•\?ã%í:ì^âþ”™]¢ŒÁÊ&ë¶®H8ƒ îä îb¸èNeìã÷ý %ÆéЦTL– mš'Lø5ô˜Äñ-[-²™³]»1€é#hø^µ|t§¥¡¬¸ûêõ9 <¸îþÇ,à½"ËZ8Ù¢4w)®‹#Ò²{ ›Ž8®Eܺ/óÔÚ1Nc§”Ä …7ÿ…8Mžø×»ÅS…•Ƚ²ù‚UICÄiZ²CÖ.9bq£]£²°—*¦@›^3r¯žá±2+‡°P"rDL˜²:@ 6@[‹ûT–Þî~§ ÞR–eÑõ]úƒë®öÏ´µ7(W§µ¼ÂèÎìŽÑ©yök;­kw0CÜÁò³ø‡~œq?$ü‚öò ‘\ÏS ‹_„; ÛZ"ª³{–vÙ_£&¨`Œf•¼t?NÄ8‰âß-ñQ‰aF8QíZÆ‘SYØÕÐsgøcÊhß%# ú‡0w« »ñ­} ¹V3¾•HnB=èašè=wC¬ù!ž¢Ä‹Ýf'U¹/äˆXyácuÄ;ükσ=àÎ"cʇ[»¸Â‹+«¨ 0ÜSzGiaÔ6&BÌI¦(úÎ6`¾vÙSµ3&[%F[ÏŸ--U…vYqVYðÞ?ÁaBiÍeó¾X¬è`¤D»iL <Щة9g ؈wì±öY»-qÀàè†8ˆ¸¥px Œ•Ìlø ±¶Ö3ºÇ1 p{Ȩþq&’c݇/ „kÞjìÀÅ‘E2ݳòΗÍ“ÓÚPÿŸ¯–j3^éâß²Ä÷P¹ƒ¬øeÅ LÆëpáP6w7  ]ƒ–¦îûžñø+Æ(pqë[׋¯ŽžWˆ¥™u‡ˆ¿ ´háþ~^i¦î?dÁfÄ k?¤‚>¼YÈõS&‡ƒ[ìîî~+CȵËêÀ†±ûmPÇœµ“¶Í6bBº2±Å$æ‹I«ø Y(ÓàY‚ˆâÜÄ¿%j8Ô;»¤†Cl=†¹XÏ(’_`o1Öb^áΪƒ(½Ù4ñ”'˜²ÁœQ›N‚þµñ­Vl›ËÑ•ÓNr@áÍxV±½€ Žh›ŒÐ… þŽ%®GÉuÖ„´Y-SxP&ûÇñ”eW«‰Òa¸¬zˆJ÷¡ y8Os;$ ,ã3–ìÁÔº`lÜ_Viƒ:s²¬8Üä™ûUjã3˜¹Ïí)ÕGó×iÇó{¸ïºùôNš¡ì社Ã;‹ž[Ç6ÔÏ%õã)ny$4²G<ï˧˜Ø´Võ s7:ÕÇ~_Òp‹ŸÔ Õ ‰õ}Û]‚/ ´6Ûë»ök½Ã~†þzì;6êÅÉýx ¡*Œ×³&î½²¨»G§†4ìãb^ÀùxZ 2žQ(¥u¿LíÓÌ·` B-^ƒš7Ž2‚Ðßnð)œ¡¤ÿOföYjï´¥¦¸@¢ŠŸ3oÊâÓš¶)„$ùU©ò`rÿ3µñ#É,wÞN¬nÖÚi•³ëgl‹ŽëQZ>§ †ÙZ5rzè³—á…qBoß(§U+ lÄÁ½<³’¶æ›ŒœžŽ'V)×ãÑíΉg,U¯kG'í´@ü\¸Tc‘| Ÿ—u[çE"½Üa£×!€¡ëÚ¥1±Ë¾c–RL¬?¨´@ªƒÄAlDš‡ùÛÅK¤‚WqT´®ü.TâT8»ÉÑÌWp7E8š|Þ2¾öÙ‚µ…½¯»ˆ°dƒáF±|_äür‚ÀMwÀ‘'2.Ví„°àž‘l‚Ic2ÑȬÝ8´§Š&8«s.l±ô‘îIÔ` ­ê¹1Q½|Zi¶X”0Ìp3¯=`°§XØš$ ¦üo˜ žÂЕ<¯ÈH9”Ÿ‹aÑîb¥k·Õ›éÉÄŒq¼4'cŒ €lc»4˜è*×RâO‡ýºîà½ÄÅÂLæÏL'`gЙq†‡1<Ö¼„CâÖ$“™H*¿læö‰¹u|‘ÚøÕ˜²óÖÞÄK)æÇ”q½§Ø8 š²%6V«9"_é°wŽ˜gD¦´›’•RòB‚½‚¸¥úá(eÅaŽ¢« Ž€Lãz˜µuœA±Õ*aØô ­{—4·Ääy$æ–~ ‡_mÁBp O'¡ü jã‹ ÛÔeõóÝi·Æ®Ï“ýß”QÜFÌ{‡?£bCªÖI­š-™ÒúÅŸk)ÃjZ›±3ù–SúÚ\ò”XljyÒôCðË'9$d¥µf[Ì@,5±ø3*KLt)ÿºb3D 0«†©ÊÝ:û;£Çî„Ò“¬‰ØX#ö3ÜJ“‘n>ÌzÇÒnÓ´œeÆSÓQ­éU‚é£ér`œ£ùΘXégÀ>Ï€yžžNeSAä‡HEeÉ 9ባÃ~¤Ñ;î£qkÐlZÀ-é- ½ã4×ẅ;)vÎÁHwàʈ?ÂøVw ÿZQ×<~ˆC#Žs}AyÑñÐÀâÖø9#v‰Ç.p l¦2·ÔX ©QÖ`¨ÃzpÔtTš“‘Ððë~Üc ©¦'‡©f 'E<24–æ Ó ¥Nið*4ÓÓ¼éi ÓˆOLfl)jÀoш+N9ðKp.Uõ¹°âùü&fiü#ÉêÑ ëd†äñ3óe×.næ·*G‘±Ø¹Ko)™dsI3œ¼’p¡è¢ÅÛ'ñ­,ÍÂq:•˜HÇRšm;4òåÞ7£Ì.ãpÒ£F°âÈn“}À~A+qc2ršÆ¥zyÁˆÞȆ°ŸõÓ©y§Á•à²ÍÀ“ÚU  ÁÆnf$Ùö"»K¯Ô×률‚ÝÆ¦ôPC]2¼RqÈ•Yp{N£\^¢šÞ¯^jÊ’)jUgA&ƒ5P¿IËD1®_ÜsDXë=6ýŽ‹x·`¸–ˆŠ¦_Ö̰ñ(Q ‰ »^äýÒ«ÿS•„m†¾ûKʘ— S•ìOðEjIÿ$<öýeü‘ÙÚ=kÚea1I“°ÉtÜÍoƒ!ü\õ"˜%g?Cb|·µ‹„“^;kg¬>á[­ívƒÎ«Ä´ŽÑÃï[­Ê!_þ†­ÄÙ„Žï)õž¥Þ³Õ{5Ë:øZP“ƒr•ùah¬÷­”KÐj‡¡,œñQ[œá=¨Ä›_¥¤‚vi×éNP§C?έfÍ#ŸMu‚z뚎û-‰ÿ-õçŽ$®¾‡GÜ"÷>½ÊV‹ˆXs›åµé`}«~ÌL ‡Œ3×ÓÎt·o°ÕvsQF(kœ#Ê8lœF¢n²¨J{¼Á„K•ˆ,ÁçÌ.UiËW±õ§S[~:EúÒÅNm)Œ loũƋ£EÕ}˜JÁ C00Á4 £ì³‹Ü´3[%RRá°§£:ì3Ã=ЃpÂôЍ:Ø€8çÅ)Ý„¥+Á_’$R‚Š«)dg„v/V• ²[7i1®nŽJ(þGSDÏOhº‰Ã }qðý´¡¿eÉ÷9Þ~¾ô AusˆDgñ§Ç°1ž³iƒj8î^S&ظm·³np‚ÂÚkì+/\o|‚´ñ§§‘‘IÞ!FÛ-ä–);cÝ¢rÀîc²L„LäF«z_Q I’¨3¨~ÀÄâN½jìUÓqûÕF³Ø¸÷šÚ2Ô»®ÀÛ‰û“Ì„åBÃÁÐT†¾³&sÍölhœ§§ãÖ$Ži(’¸ayÉvgÁ}œ·©æËœ°EpgË™ÎAA" 0€µ$ˆYþJã†hA¶˜DÉF’í©{W~¨ô}‰~?hЖáŠ-ïÑÅùŃŠþÕK=TjMƒm꾥¯*Hé8ÕM©0CäV¿_i6yw¤&‚|<‡ð£©$Ézž‹…%¶wÅ?7¬c2%›Jý(Î8ªd9-LˆQø:ð“wËæ³Ejã¸m¼W‰”å3Ûí~ú…;UÎ>`±0?ÖˆE­[OK²S%E’,ú@î¦ÇJÏ­2ë°Å‰U /ù¡ÖMb&5·‘¥MžOÈ×¢¥ü´™OãKW—P_~N‹eQ÷Íœ&ØÖEô…ûÇJ«Œù´FËÀ³!ÜBÖT”ÿ‡?ݬIÿ}jc'&ý8úÚà›œ½§'ÇÚ®n»`í²á¹†ó>]óJ·Õ™!i¯Þ⽆L=±Çpœ*ïQV;ÁÍ"Ï—6lýñTÜ©•"˜Ì/ÿ% åèÕ[îÕ+—o_}Ї¯‘ÇFî-²ë‡LüPÙµF¢¡yzX <a$D3f*ÕJ´¢E DH•ð`å"‡ZO )l¢:Ùõ²ÒºP‹H‚é; 7ÏÂR:ò’5p¿oÐWbøoÝ}î—̶yêqát1ÕoÚ:ÎQuì"Èmí86x§Ù"MKµ8|ˆ×upƒylíQkHõ˜‘Ä$m:ÛZp'ðá9¡š7ñœªs&xò\¶$"öÉ?”UíMø0Á”oáÝÊŒÞZ‡6¢W9£óZžX?nˆ¸Ièp¾ˆV€tgØʱøàø¨§¥I*=vŒüÄ%µFýwÂgÜ3Ù v#´BŸµ™Gû´ïJg3¬±@^»»*ŽåÁ4\Ç=æ?µ+Š6 pd†x¿c‰Ûf_œ÷$&01Ю|’øD¤¶÷? ¡…gæ'Yz‡dÕFII'ÁÄ\Žó0Ÿ7Wt¸mxáÍ`j¨“}9BC])Aí—ÒkKgSÚ æ „ÍV|hat^q¼R8ñd –P„y@gN"®@”žæ&ˆ$P2ñ Äca3ŠvBvšU £ c³w©îÞ x9Ljv¶² ©›ø8 ªXM"Óã„å ÒŒœ9IEÏŒ ²# N¼ 8UÚe¼LaMž"vhIÕëæ>I—l­„GX´Ï,/Î!«ñU#~)\)jÖÚµ-­²ç‘7XÈU£¹rÒýYC½•Èw=ÞH é/G, ‹!‡‘ ôÆ ú‡æ x§xì%+C:òˆ{uzÓ1û{ÔÆ¼­ûŠSf¬ÓD³z­Þ |«{¨¬Ç*Øûq'³ÝÚŸÉÚ9¶Ûôe2$Û:ôödW'}ÂzŒD>I‡òö]KçŒ=¡Yÿ½.ä%bëˆQHa2Å’ÅnžJòðP¤tX|rÛµoõq¯q7Á6ØÅ_ƒEz5§ó߉º€„¢n`íÉ%‘=†ö¶³¬Lx çhgEãÑ}bM­mQËÓÐqw,Œ£QµBÝTðšl»ç,FoáX/}ÁBôóz¸íoñÔ-ú›@…~"ŠÚ€\­±XNã j„¯æì4þÝe1c6šÒÁ;·+ܘíã`ü¯2(ŽŸ4Á$iÍEóa*OÇð .bɇ3Â6kG³]­,P–ÄŠþC iõØTQ}·Ò.ì4àU‹œõ"¬¼í» PÔJËlâ äÉÆûIî‚ù±ØFñXû—šý–Ò–SñŠJ<”ØÊþëM.L î(æ1Ô—j\eFüè1$±ªÓIèþ&Øü˜hI¼«ã¢Æ'°ç`{ì³;è/cícv¹< 6ÊöZ½œ®7G¬&’õîµÛ¬ÝV‡Se“Òµ5÷EùÍoÛ8CnŸ¥1çLU–d‡µéXi5ùƒvk4µ0ö›¬u Iws¸Ÿ¯l7ŒÒæµñ‰ºgeã LDÛa–ù;Ê"$©r¡c73àعYb䨕ŒÑ]ƒ¥}ÌÄÎÙ:8ÃZü”™¸8*Jq¿Í& ….îîǤ;8~péV.m³¤”Zþ/©–3`‡Rg ÞëN·ÿ v×%Œ–n&-²ZZÚ–n©Í´´-ÝÒUi©—[ú†¤¥·[ZzÌ€RmXÓäÓĆp¦i_3Naùq]€™È–Çò‚Ô‹µN%<‡ho´Äîtþˆs"Î¥œ¤ñx… lfgŒ r ¼¿ÙêÍ1]àCŠÄ\̻ߺ¬¤î5\¯³Æ÷†8‰ÃIL|É?ã§m]1b ªò ÉžR #µ¼TòÆyÔ7hÐ&–Êç[üÝ€å²ßd ªÊ$oZ‰íwIXØüù¡üq¬d!üö "ÏL8HEÿ&¾LõXöÙ™ÒBˆ6ÛQˆÁ÷Qðñ”agêˆ3ì ]rýàïyGα{âºÉóä¼rûÕÆ=H§¿+³Íˆš’¬ðÄKÜ ]$lrXš®g ^(`×Ù|¾ð˜…ä×&Ô“c† v¯ ÝjÕÁ:VÞá[U*°ívšW2C[z÷ÇÛ茘¼| ¶ÉHÐòrÆU÷ •d§Ï%_°Àg%$¶© f iD”ç9ë<Ñ›}Ò†¾À :ô bï£(«#Ûî± J‚$‰ cy¬ÙÂó¿É*.þâJòlA­uL‘¹ÚÅ|\Í:Aš¨öN¼Ù®cÒ»*|Ÿ‘)gsÚOiѱïñhWì*¥U~D¹ÄUJæ à.Tj]t‘¨ÿ5ÍÖïEÆ=ÇŽ%I\|޳Â;ÃÃø’è¼]Q¯GWŒ@ÒBèwF[Ã¥£ ŠÍj¬[àh‹ù4!¾ÖEª•­~Ú qÊd’IJ*gYù~³éE×ÃV!ÎÁ°^bdýOà{¡8)HäsD|§PK×¼ï¢Ë)i05à=%KB#ŒÄÓ_ƒÂÔ47;‡  u[Ƹ4ptË~Br‡X6$9‘X½> œuØê³žbÖ¡R¢Ö7kÔ'Ÿûh[ÿ%I…Ý Y¶a벦´J9K| r†ý‹Œj:—ÚÖYíYeƒLíj–dMœ-Û×ÉåH¢Ž•=ÉÛñ¸¥÷¤8;>/üsf±VϹ@â±ËL8g9o4‹ÍÀŸ­, rÚ2,do÷?¨Øä÷`“~ìÝâƒrX䱩ƒ¢Éì61nÔö»?¶¼`íÉì±7’ö¿©˜߀øì$‚„V({jaæÅRéC¥ÐsÖž‰DÐYzó*øzóT»õ#z Í#b°ŸŽ ˜RCøt áÄ<:l| \'÷†‡—*~$pÍŸñ¹bÒ´%Pöý`:-çÐ!iÕ Œäá!a6yg\´Œæ(ÆîIK¥ƒ×ñ%6ŸÒ¥&ŸÏÄÆÛ~kÝgí´a¼Í“„¶5óÿÇrï—{~ \ßj]l ã;Mo!µŸnYkzn©é _q†¡\p.þn™‡©É—ÿÜeÞw·]©$縎¯[/\°‡8‘¿‚7t3‘I$Œÿóÿ_Í€ÑÍä¦ øó5F7SÉ€%Øáy,̾<³5þu¥÷¯llNӺǩ˜Eää”.,yÿ È6ÀQ±ôÉŽÿâ-Ñ•ÿì¨ñ #8°Ü´À€änµŒLÍ­(ö!GK„d,fÝ™‘uøÌKY'ŽdHÂcpø¦8 áI¤„dßôƒü²9 9„»» Ç =…-ùö|>ÿ\>WèÈwòùnú?G%CTã¥î.üææ3…ƒù§óªÛßž±º·å{èÿL>Ãßz94xpd®Õå7ïy¥áÙËÃ×¦Ž ­¾yïáȹa:{áRU+ N)Ãcé †>œCWó{VC:Ф(cÎÄÂRùRŒ°ØŽ‚ï¸{”fNÊóAs^Þd>…YWêÁÃî”#ÈÞTP©/kÄô 0™¯iˆŽáŽH´öøD‘ÖZª~ÁTÉìuSÉâo¡Æ­ý[ãõs&[*ƒN‹ ~Ó×ÁeIÂݘa™–MÈGãÉD¬¿h+®XFaó¢ÒÌüÃùÍþ#kÑ$'XÆúhe!‡Jâ[ŒHàÒgï±6n¤.¥RŸÍ29qEnâEòçV+‰Í®òÀ§39‘œóXKéºH’–{Õ2™ Ø›mó¿ÖÔÛU$$Þ<7óGNZ¤>Å2ÖRû¥ú{àù¸'”nØqŸy‹ÈäÖ©…lx ‚‘y{[ËçUØÐ*t áÝ}`W@qè+ß÷#VnÎÅÉ2¢JÍ'Þ“KÃõ¥BLØä€²'[£êÍíø‹)’ŠS—nÚ¾Q+ʨM—o']`¿÷m¶,}òñ–WÍæpoÄgÞfm 4¾’Q&Aqo{ªwt'½sY<„ÍË¢Ô2ËÉ0ºóe“.$½+*%'ǸMo¦ 9ÊEǧ­m Ç®£P­øSñw…Œëœ f’¯k8'GN Ÿ9•ŠNõë€t~š†TóV'ÀRÝ!Ê‘Œ†âwñâED ¥6“ 6˜S—~æð|Öà°ww¬Z®™Ÿ™¸s¶üòµ·Ë§¼åÚk‹/ᢎ0 F C"×Ë%¸–œºÿ¶1pñð>®CbÜ1"DFñPœ N<˜s‡#Îáx<Ï8×Ñ;q|èmÃËÄmé`ÞˆÏØÆÒ)Ú&; $Ëó|ŠÏž=ÍLŒ”Êk¹?‚ž³Œ¢á¬ñBOÅ*ŸÎ¬D¾$á•Ç=]Òž”< ïÔ ¼ƒt¡`ìnúãá] |ö +U;*õ÷µèHô6+vÌ,–Ó,U‚çNˆÈjÎßÛ½CUÇXlüç}7AÅúÖZÇ—ËgÑuwò‰KÝeŠO¿ ¼ñÆæ s`·¿-Aù„>3ï¥Z,C¯ët¯o-’á=¡¨fó †ÈŠÅÏ$îx C4èY bë7I(`Æ4S=ž4S=”ú¤ØƒR>±÷7%1쮊8_ö$föžõd„ d1ü–ŒJ}–$›Ï2`!ÕØ•F}¶2VüU’“iÀz—aËÏhðz$Ÿ'±5`iË+›…Š9ì%exÏXîæbkº|CÕÖ±ú&Õ¨I¼§OÚ5Ÿí™/€éò“aq11x›@ÿ8áÚ€J%͸ç¦<96‚ÔíAç›lñØk+¬ Ž“q/K*á4ÁúÁ1v^ÓŸD.Gñ—.îû+¡»/^ÞVµð°ËÍRÝÃ.åÐDö[÷]Í…ò¡ÍM–x`ß#ÜìâÛ÷ãS'fíbO ~.•MftêYæ"bÕ•Xa6ÒÀ1©‹×Ȥ¥ÓIOì”pè¾eij¦?ÅȼD(Ò Ûù¦±ìIÇVXd&Æ‚aÓHMU{òtôTª%ñ¦‰—„ŠMrðól_!B™ô³ò9L*geÈôYÏ&z²Øn‘ÊOÏžáÇVm“¸BîÚÉݤ0“>²ÅÚ§4…¥yŽ’ùœ°Ò[̳ôÎÅÐ7ys‘4¤~ eí²rÈI¿!?òn,oùhÊèÔ¾äÓí«éª=œ™Ÿ L‚I>–ln_Å+Kìz³é¦× \ÉIÖIPÍQ3ÁVfŒh’H†Æ˜aþ”9Ú¤¥ Qå%‹1>Éòúz½í[föy7oîÆ„´$ß:ˆ‡ýÏãMÙ¶—dtÑ6'”èc ›A£I,î ¿/£[{BdiŠÚýΘ,Ùù-Ýù|;ï\k]0Ÿãûí&ø¤Þmj¨ÖpUÒy§¨÷¶ò>maò¶òGdþºÕZZÛ¦ÖzÕZŸZÛ®V»ù³¾6*¯ö`hrŽ‘v³s›ZíU«}ju»)5XìU‹ŸfCÊV‚FÎ# ëÅͦÀ.ù²âIŽ+&â¨3OÔŽ£ºX°·/ñTgÂÒŠ”z£^_ªùA¥ìÀ_úœsø°NÚ5嫸äJEòåTä`yÑޚΠ“wM£‡xß¿T ©Qoð$у·å{Þœ¯ŸÈððå9jNЊé2Œ»ïM6ų×Ü2ݽ€¶Ì³j{Ê€‹¸e2"Žíîë¸d ~üyWfGd0Ï+Š¼Ë—à Š¥¹8±ÜŽs°kh«Ù—å9ÎÚ&`–ôÜ癈Zf_0]ë…q‘§—Œð$ÿÌŸÔY":‹›•Sz"X‘ûHƒyr“ÂÊÏfLÄGæ™l·Õk¬6²n‹K@·µÓFÚôgXÏØm#þ#—ÙOæ°Ý"ÓÄŽã«ëÇ-3O ¥Øle¹ÎÂþg)+zìNc´h=F³Ö#µÈ| ±l¶Iˆ(<×ÍÇzEÓä×nßy¼®¸]— j®C-ÿ(7”×å£S_ËBy“ø§ùëAòðvÆÉk3-bHúL,gû%Œ7A¬ûkwoÕGTÜáÆ‡Ñÿr–zˆ–QâBcJîܘc¿’ZäWê÷8âÍ0ÆìßI½y=‰[a@o›º—Ñ—t·Â.¬^·:K(O2‰ãѪÍÈPÚhôžßqÒˆŽŠâ É=@ãÃ¥&¿Í¦R¹ÿÈ~BŒ0dÙáÈ2A0¦MÖÝ@'Ûe³ïyT»x°}Q{ÃᮜIcrs¦á­ð=>¡R<(ºŸÊO) §7?ÄŸaù÷ ÕUì+ÇIáÇZ® ?öØ/ž0¢ãVCi•9—¿XÓƒ=1.dŸÙÖ¯9TB8׋+úgb|ù“8pNzväcW]Žùï8p„ 0¬8úž‰QÜóqÓm¥0\ìæÄa|ìÆ$ Im7ûº3Ö«!/Æœÿ$ü5Ÿ¢~-êW¤ ûþÜp—…è4„¶ïgõýT²Çn·¶[Ý„½º¬Á·”ÖˆW4I<™ìâØ¬ý ·px_éô6¬wÅ øcåòu•tŠ—qkl˜eΓu¬`ÂÃþDImýã,;z´‚ÃVÓ¦…!3þ¢M\4"¹ƒØëÒXRAŠ[²zÍËRóÞaZÈ9½wÅ[‰ Z0J*höŠ‚”ÓŽÒÔk¶Îáûü1°hGk·Í•“gu×ûy}û ÚäÏ‹±Óv]’Qÿ{^Äs#²[Æ5ÓyyŽ‹E1JŒß¼ò¡«·‹·¯¿zõæÛ.8H6"æ8•âEø %ZÂŒpaד¤ÖY,pd4³ûÍñ” 4˜…Ý_áA "l}lù’TÙHí#Ü$<áBð@PÝ5¶>^R{KøïE¶ça@ Ôéÿ{ì»mHvÞcyú·1`DÈó™]V!“§_âÿwå; …ÂŽB=¿¿°-ß¹#ÓÝ›±ögúwöïïÿ’ú±œv>—ïÌg …|÷îÃÝGz3ùÌÿPKƒ,ÒFKóâT¯setuptools/py26compat.py}?OÃ@ Åçܧ°2)º  ´ªÚ.° 1 s{mœäDî¶CÛoÏ%j©X-??¿÷Ëó\=Ø½í­œá}ˆ1@^ÏÒ•~ãk@C½ERy:RÖM2>³R Œ2D ¡g}˜á*‰ÉXL«T °Û†LëÐËl þn©²Ñ2{ö°»¼\T‹{Xu"qY–û¡e§…Ô––yÀQ±Ùm‹[ÈùRe½$8†”áÐa  ¶LØJC‡pýÇ=8ói} o/@ø5 k•=…IÊÆá?,ô%zªQÜl׿§~*£Ä†<¤!kFhú‰mð[ë››5̪b>’øË'YõÆík§%œÔPKò lHÆ#WÆïsetuptools/py26compat.pyc­QM‹Û0;Ù›í7ô¬c];J6” )…–²”„½„‚W¶[]Ûr%¹›@÷ÒöGú³úZ6·žV0Ï’5óæéMçσpøûûe›Õ±ñÚ†~o,,zÀ|(=XxnßÒ‡ª‹x¬ ?mR¸Ÿ€Ãõ¨·ÀŽ6ÿkÀây/@Î…p*«†‘ŠR˜5™·M#•!K©Èǵ)dMÑКNU)¸ Å_».zž-6ÇHÓØJCó ÿø›˜âÅsLøðÃO>ÜÜzxœ»jý ûïjrµi5Œúd\Ó¼Šã´ÍuÔ¸‹Hª<Z·3&WÉ‹½¸s%5\‘ª‰}MVpFŒ$LhÅsªì¡àd©h^ñÚ›‚פ¢×¢ÎÉåìQüK˵ÑQ¼‘.UÓŠÿÇ›è^0Ãõð½ÕªÒ9²mÔs×zl!mEÉâÔŠ2QE3©W§gý謺 “á˘çy¬¹i#e©ãf=fn8èÂCd1J4ɖݰ‹ì‡O="Ä‘7†mL·9;Ó/îD¹é!¬îS$>~\Ò*etò wþìõõ±5î’„É,Iœuz­Íü;Zgñ S̉…¯\i!ëDÔK¹W~Ÿò+ÉÚ’Oœ¨ÍõOüÇ~<òþPKƒ,ÒF´ úÏ´2setuptools/py27compat.pyޱ Â0Eçæ+™*HqsÐE(ؽDû’>L“’¤…þ½II7×˹ç^Î9»Úa^¤),ðœÆÑºÒ:¨—Ð[‡êÂt€ÂiBÇx,1VÌ/ž±%( ­ÐºíQtè|9 ÷Bá>¸ìάH¥âF3šè‚{ÓÔp&c­!·aáÝ“Q @­h©²$ãy ÊÃeÚ‰·dºTÍQBÖ´d¤… ”Ç}úðÏÏú ]¾PKò lHÙÛe‚ðsetuptools/py27compat.pyc­POOÂ0ým Êòzä ãO CŒ‘ƒ^4ôÂek…m]ÖŽ°Ä“ú­üX~ýµ ½z°I_š×þÞ{}•Ϧ3øx} \6îÜò Ì- 6DÌñPw$m`¬+@k°È@J>ýxÖ>Ö}g,âÔW|Á#® 2ËÓTdŠ,EF&…Z‰„ôÝ!ñJ˜ŸEœeÿÂõØe½ÇZ­‰ð°F´àÍBKÓ·Ú¤~Ç·,Arÿô4y`Rú!;#Sy†t‘ó)Ë$‰}¬xŸ„ffà ש-¥S‡Ly8жD¼WS<ã㶮ɀ!,rÑ΂r©ÜØ„Ü÷ºn¯{¾»xƒ‹ ÃŽÄ©"’´èÓˆ›ªõëç•MqÚª\;þµ‡Çýœ½b)f>1ÕSûú¢Ou¶ÓŸ¬–q7ÛÕCqžGEày¦8YH3¢[ŒÆEâñd)~3ýS§'(0ŠÍ#vmœ5Q³v½Ö²¾PKƒ,ÒFÿ®5d®esetuptools/py31compat.pyTMoÛ0 ½ûWí!Nghl@Qï´Û¥-Ö ÅP†’ЉVY2(¹­ÿý(ù£všÓ%2#>’”eeÈml$Ûk­¥sh]å¹P*Ï!ƒ‡Ù]¾1º»üY%L•pûÙc9j."às 7Û ‹ô ‚¯Ù2]„ 2¥Ó¢@í75Â× V~†w߉ ]¼ál¥uµ“ʦÿ‰’Ê•\Œ-C X‹ç-¶?²omH ñ¬R±£/¹ª ýuôÜÒ"Ü UcH4>¹òem¬:/OG‡u2ü ]Mú ÉS– ¡çÇ> ÖaYRaÏà ý¯ æ›$Ü8C͇”vvï)[zÌ`Û(aíØØ¬ÿðmÄÉ Ÿáã©Ë€œšë¹7p¯¾:(…;¤tp¼—J— ÎpÃ:Q8¤AÛÖµƒÿB(k@î´!„ë[zë£I%h@B_ªæ,àH£Óq®ÃÝË"Ï%@žÇUqÐgoJƒ82¸2¹?8V>m}mA Rï8 hÉæXBôì¦wÌmž¦‚L Ï¥ÓÍ€÷Îõu¨"ñ¹¸¦Âpyö2mM$6x;Èl’tFJ¥#Äx™ÀŠjœOžw»¾må§„¥á}µ“åöÈýP TÆZ¹î$6>«íŸìGQÔ謁<ªÙ°»RÿÍ ìæ÷òœÍñ2ó9\f~ÿ¤ÏH–ÛÂ}.ÌÃÅâ.ÃÅ<âÑ.ý ±`ºY[¦ç s#´å‰ô:¶îW­5R–!°DW,âÕ`ï žù)yÏȵTÒ5¬Y·Û‘Ÿ¿(“ ZžæOÃvšTŸ Úñ&;;{zñ·é¶š½e3ó«} ÛëÃøÅ#Hè›¶ùèË¡Gª©pÂû»l£¿PKò lHï¬i6[k setuptools/py31compat.pyc­UKoÛFž%©eÉvÞ¨ ‹ä¢¶‰Haä`´E‡^ì‚r“†—%®dJ|»KÛrJzîÿèoè½?§—þ€vf)Jî]‚8˜Ù]ÎÌ~ßÌÐýgÐ;ýóÃ/XýZø|‹ö@Œ)@¸Ö„ bbf„Tv˃ԅ̃Ѓ¬a ØÛü<Ù†EÔct¬i§9Ö…° ,nÃo@/ä ~­ZgH}ÈzöÈÍ7k75n0‘wš¤|}ˆ» û0Åì|òøà¾O^%ƒùÂ]ˆwAÌ÷ î÷܃âoˆ÷`;à°pä>¨‹6©]Èm€Ñp!IþÅß¹ÙCu&˜ù4™‰ëHiÓ]­-#s5tÐË!„iv›S•¹*r‘&ã  ÇÅç{‚ýKï-ž‹¨OÁAý‘ÁFÉfw,Z ‰¯sÓA¹L#ƒ.k½TuýíF™äY© K¾Úà…â«ó6?}ǾãÀnšŠ7QZÊ•*T@kCJÚx(rt?¤ëY¡ÏPŒË$Æq¢ÍaM }ûòäøðäøåíëSqúÕ‘œÍŽ´4åÒEª–Õ«“I‘!v‡ËÊb¶CžÚäõÙ«ƒÝGq)³e¡"Uý(91…ªÊv]½tð;zùsH5Õ*P•"bD¨K¥KŠG¨ÖuŒ†týŠg=¾ú½‘ªâ:É–©ä¦‰Êã&,Gö¼5<‹òh&ÕáúÅ·Išrƒ'LÁc™J#y45RÝD*~ÁÇ¥á7t"JuÁ“Y^(É/F<ÊcŠ–¤‘Z{’„¶æE^ûIŠ|e]8NS8OÁö(V‡``˜»Ôµ‰ë# â¹½ªåí¼Èe@Ûâ¥+NŒBpf‹˜ì ÇZ¦Ó-rl# ‘䉂òÖž%Ïgëk±æZºæ›´‰×ÚN“Ö–rómnÙUBpréØä&”£·š6µ×(ª'Ô¡sÛ•s ‚îÐ̺"G3ë šY4…Vä8wÙ°ø“ÐW¥IR«ªÌ(¹¢†â]ª²¦åbT÷¡gy´w·[òvbª¥´À¢~MÍÚFE“mvèŠ=yKì='= Ëž°óØp]TBÐpÂ!²".S2;ÖŒ‹‰AŸî1 ñèDnišP¨Çä‰òi·ÚÌ÷|7¡i›‰ÓLRhù¢ ‹ã=ŽÙ6¨¤ ù ·è’SÉ®WÏꩌí†ìâÒïÄ.y;·×6R› Ìs©jʺ 8%V?mÚ¯Â%Ž’ËõIK{%y=~ÉŠÔLÛêXܺM:w’õd3}Ÿ²}f“Ø@vÇ´‚{”"™ºÒÁASBDiŠTûõFý­Ü| UîO4U­ió€Çô© ôáæ ûñ$'–É`·é—b<ÇAÐðè#g¨Ž®¥Ò8%q°L Cm*~~÷êdÛ5eÙ;«‹ùkºŒ~†¢ÏúNßqìÇlÐr‡¨á*;xä;ÏYÛýPKƒ,ÒF0«ÔÈËe6setuptools/sandbox.pyÅkoÛFò»~ÅÂnTªð½‚sP#q‹Mb8Îå Ç VäÊbLqÕ]RŽýñ73ûàò![y' 2EÎÎÎûµL±ZKU3©'…¹Ò[Y‹ÕzQ”Âý–k¡x-•û½hª¬–²ô ŠZ¨Î å×f²ªÅçº,æîκÈn·ÿys*¡e£2¡áî)IÖ%¯R­]sUëÛ¢^ÆÑ'¾áÑôÙ„ÁÇ‘¦®“õ¶^Ê*Yɼ),•ºøœœá÷kºÅ¸f)0*J-ÌbøÅŽi»èRê¤â+q5©ÕÖ Š!>gb]³7rª”T]7²“¤TÁü3Y(¹by¡ë¦.J\£Í/Ý}Be`;Rp€·RÝÕuªE=1`pÕ¬IÒÌËwµæuÿibn; yS”uQxÓ”—eš—ÄÂÁÉ\׊gõ;^åsùù`Æ^J€~Õ6¸g/ÿ]HPL!+¼§š*¥-f“«É$ –ŠÏ"C©Äø…±ëRÎy©g¬”ü=FiY%Ðß3Ò {‚ô–b%ªš6arÁ¤³Ô†‚Ô<¢ßh$ù`_„™¢îAÁWfGüèL Ìcû ¯<žÒãC’'Ò?5VŽT•#ð(ùA°'Éc0ñ?”f¿ÿÊÊ¢LT9(KB­o„Ò€"-ª…¼|vtÅþÅâ£{:Ãx~Ìâ'3öhJíÂGÓ1Žè8ÿÉD<>ªU4cpQEÓ½à»ÐÀ‡Q+4Ùy»©½ìL2£'EƒÆZ­D¨P‹/c\10’éd2ù¥ ‰½\ñŠ_ E¦¦ùF¤\]ob¤>´*|’[ÿF€ËgWŽEN*Y÷¸ €a)ÂÑ#ð³-D™ôtoQTàMÛ]H à~Œ€³.ãúñ¾£ÿËi±«÷§E‚±©")¦€ØšúcÏa_ËêFlþléÓE‚y¡Œ7‹gàºQà)@ëÿth5" ÅI¡ËÈîø˜¿ ;“Žèú$™§BC*';„<.Þ\{ÊxÝèeCZ»uOãÀÜÌn]8‚ßÙea¡¿Â < ‚A¿ÊJ®5{_™<Ìç¥8¥ì1&öW=}ŸTL¸G(3ˆ{ 1T(Å-…b~%«—ÓRt¡RçÂfü¼Â!:V«!e“7`vÆz»†°›ºwK‰¢ò–o5ÐR7ªbœV‚ c»×”P  {…™$c¯¢¤™Çw«ø­‚ý¨h@²J×É(-àÇReÐ$HšŽ‘žé¬{Ùó máwE ²IZ!Á:"DÓV¹Ç;Pºê©’½06É^£4 »-Ê’ìdÖêz5…*xYüdEÒÍCi @T„ ª¡ºŠ¥: ó*Mc-ÊE BËބП‹Úª‡Ëy°ÖF x0&š‰¿wHÆl‰–‘6,ÂIênTÕFÀ­öÖÖs 0óp?ݬÑ%ôŽ=-Óª-Ó߬D_>N¾FÖ/4þضh&¡D"ÃKD¢ãÝpŒ=¤cBòì3+¾¶~“”’çzJ©eßÔ”P,Qq &'˜}Ó¶­ºã^”q† lÜ. È,¦|MÙŒƒdˆªÄpr¡x¥Ñu+(UÐö ²Z’F2×ÞÀÒmá$©{Ú’M­!ý…«ºÆæf×pdr½µ›2_×ûbSƒâº´cºaè6¸œÍ:®â@‡ Â•ÜcpòðÒE• k[¥“/Ðûíà^Š%ƒ¶ªý¢¶ ˃XÃjsŒ¡x)›ÜÚfU¿Ž°„½‚ýóg¿ Q9¼ÎÎ#Hlih¾Ó \Sys X ó=Š5±î„H!¥»Òü¥}µ5º¾J¨JÆà¬L;Ý¢[wµouvw)0ªí¥þH’¦î ¢âפý>:Ý¢ó…À}”ck—Ú±ù…„¥ËžÔÔ=®lû$‹ª…ƒRa¢À1î“E°$Üg‰åiÛéÆÓÎÓ`Ÿ ¢‡ æaÂCu«aÇñŽ~•©ïúòÚõ94µ±[{´ ˆÜ„;¾áE‰ùéN4ijBè7j1EÓ;™òÖ:L%D®S.¸aì ¼ Ÿ?ÞnFYnpG÷{À·ÈÓuÙ\®+ýZÄ=Ý{lå‡5}XÇ;Øfê×ßFq»Û_îþò§ñÇ䯦¯­æ°"¶(¡¡6ª•¹‹aKï*ãܤ%BAü„pÙ-P‡Of6Ô†/„ƒh!o1Í™þ«Ú@Ûmªwé†F˜WR׌Cq#×PÖ¡•&ìb t-²eUüÙ@ 5é£@ŠæjKÛld‘ÃÝÀ¶º”¹ððÉãŸ!Á‹®Ñ7ëkÅsÓ#RyHEmÄ<±A”Ë¡Ô÷ƒ™\@¹« |•¡VÔÒ&ÌŠl2„~ äw4? %3šuÚŒCZñS/ëânÄÑD·:o¨)q6`eV›iš¡Ø@;róu† A|åsMAÍý†§h/:¦a¸½3€ãgиt—!櫟(C›ƒ5¦m¯ Y¨ãG³–ú.$–0ðˆl¬2Õƒ‘ ¥‹Û¿£Ü¡ÅÛœóì†2r7¸·óPïÚýø€8DÀÒz-ª<.ùjž­<m(u±X=WX½ Ãw…¶”Y§4NÓã®)¤äÇp;JÓ/*€ÂO;*í.®zâíOcE&@clè´‘ï¶Ö)ôUèr›.PÞmPÏšª2syùèjÈ*Uú=¾‘jµ5¶l3ö©Ñµï-l÷Ù){Ÿø€-v$}d¢Í#šÚN#7£¦ºlS¨ºÁ®ÃAè:ýÃ8)ég&ͤ5Œ^dzˆ¸Jûé·×¨«‹]1ˆ“Tê¡Öl:(`AÃÄÎ’kÜÂt²Í=Š«€FjL·kòE@hHG@tÏQ!Ôá>š5;f·w ¾™Ë$nK4³!†ÏîPƒU„·#ÖT¹Pq\ˆÜ9é0zv¦}3#Ú•;Hì ŠACG-£`ölÅ€Ñ Ëo>u»Í¹Èa.5óª¶Ðøržîgg'$N2¿ÖbV7i.AemŠÃª5§ DÃTÅ52…3yk €¥g†ˆ ×kÐ*›åºž=À0{ðàæv:¡L†l[ ^;Ð¥ò5YòÆvSŽ£=¾ ÞÂ"ùßÄ9_¹ !t¢À¼Ðƒç;»½±% ¥EnGôÈ~FG]V‰ËVƒ#TܽµY÷m{SMÒÛùÎúg„Ä¡¡3½ÁÁ‹±Côß™}[ƒª æÑÑw vÇü⟢‡8¹‰ˆÆ€¾Ù ¨e´³˜ÂF`ÞØID¹ØTMYº—¬ÒÓÿ¼8=»xõöÍ;왤N,Àì*|›ª }Žohôt[TOŽ2¹J²²U\‹*ãÙR¸AÓo¢þMTH´8CÃíátÝ{Ìõì8›ïc°=ð+¼°uˆ'¼ˆŽƒ×["̽uyMÊÆ– î0œ¡KÚƒŽÄNµv}î 3ï5¾Á4HÀƒ"«Ë é3Q›éfî'@ì![kÑäò¡-\Ç{« °o¹vÓ‡…{#¶:*›{«—;«–ÏÕËH}b“—Eqe/õ§k©uv{ïCvBsȲ˜Õò ɤFT4#2§Ñ]+¾ZqˆzóO )>>zÜZs”<°X’³æ‡È’cô >f”#Î`timοWæU°JKéÁŽ‘‚ŸÞÍ‚#ÇãÀ^3 Lò*©V×Âò (M‚°¦Ó?t^+±(Bö°%À?‹¢þªàL´?ò¸Ÿ ¢Ýôd‚€ù`Âá®zžt‡2azt/ZÙ¶‘™™˜Åz1Ùˆ÷_GŒƒufFº­ml'o¸§É®øºàq„¯¿olqÑ›‡öH4&ðHÕô=§ï÷øýÞNƒÎÎ,nâ^’ëjª•ÃíZªºÕ;†ZA ÂpßÊš&m_Âò÷fwÀªV÷²êØ$îaÓÔpãÓ¿`kvБÏM `­Ÿ…õê}#±;FHÎÃö #^8ZH´;›0'òØávAàÆ-ÇÝ0up8ò ãRw‡/±Yq¶jðôÛq%˜vO!DEJ»÷’ƒÙÔ,‰õÁjÏÚ÷Úü¼u$´µëlzع½ö<ÏŒÅR:Sîìóå(ŠŠ]ÜÜ¿zŸdKŽ)!”ͬOíÀ¥ »ˆ[|Ú9hÂØlÝO$Pó=,Å*wi†áñ´Ç1!fcÎ_]œ¦¿þ~òÛ»¡QÐhð¾c68¡ø¾dcI£ufÙȪIHáqû_cÀöò&&6¸ÿ@“H•ÎØe8eaœ^öG©pp„V`oÓçoßüþ{›ž¿üpNÎÎNß¼„‹ç§'ð÷âüý›ø÷ôõÙÛó“ó?½.‹:ž^M¦®K”JÝÿ~Ò6)'“6Wˆ›/[*Qš;oËÙìá»S7C¸óPíÓöŒý¨Tð5™\P%žÝðkÑ¥ úÕQÚˆ.Ñd+ú¿2¡ÒߢA»ÁL`ß8åzûÊ4|t*“#Ÿ¹#<6bãœÞ­Kh5.í{Íš/D¹m;G6߆˜ ºßâî|G»]^ÒˉµpëL ,í š_TèÀžÚÑû$‰•ì²Ì cg¥€¢áÿ Q+Û¼‘Ȩ©—hT@Bã žI×ðO(í_«]⦜a›ëð +ÙTøúFûRZc?7C7˜Üñ9œüPKò lHªQ§Ñ`¯Hsetuptools/sandbox.pycÅ\YpÇyî™],° @€‘”È‘H E‚¢$Ó¢LQ¢IJV"AÔ¨äõ`§Ìbvf93‹C+ލ²)'EÅU¹œË®ŠsØq*N\q§Êq•«œ8yLªò˜·8yM^üäüßßÝ3»e»ŠKÀööôÌt÷ôv£ô?£Ã§¿ýε†Ð?Côyž>éÚBøôg‰PˆZ^·DÍ2u[ÔlS/‰ZÉÔË¢V6õQ0õЍUL}PÔM}HÔ†L½*jU!-ÑÍm·Å-K$hæ¨hnÍ1ѵ"燷 )DsB쥦õa!'Em§˜‹öˆ²Ü%–‡Eòï²,êš#K\—{Díî´$½¢µOÔö ×eL¡µ_Ôö«ë>(Z‰ÚCêº"¢uPÔÒ5A@¯ X,ÐæèoïÒ8 9(špËZŽÚ!Ó8*ÞÜrØ´l7-GL˘iyTøå”X ®vp£oÔ¦…?!|zn2o:j^Ýi^=&ü]¨×3·v›[ÇMËÓrBøðÃ3ÂßË•“ÂßÇ•Ç`=$üýù`§„|X÷·l‘œµA'Å"uô”ˆ*bQ ²>ÅX~H„­Ó¢vZXò)Ñü¨§Ñ kýÂi¢Ô¢ÔÓL© ›(jå)ú@>è!Ë¢ùŒ%Ñü†ðŠæYÜ»øÖ¢ö¬ç„Ü!ä³ÂwÄ­’ø¤-n|ݦùÕžä>îïἿçAŸ+Ó‡‰áƒÓÏlV¦jÓ[ñ¦-ªdÛ©¸¤Y' ÂôR’ĉjßFÅjœ,Ñb=•™j¬Pш[mO_c)Íw‚0 ¢4£‹óói–xìŠùóñZ6ν'²‘ÅÉzw£®¿Ä¡—q”U©1éD«Ón”èj>ôù8Öêw/›%dƒþJ Éû“âfYlÂ,@{s@ÌÑzzíº´E³ÎwˆW—éõ†èjË"ù|wÓ(ž¢¦Ñ, ÅõÔ?u¨[ªEKD£ÛX·ËC"ù’Ø YÙh”I]æov]¢6GøÕ¸MSA%‘žŸát=ÍFè{E&)ͰD q6ÈO´C¯!ùéÙ8’Üþ ¹«Á €$òZêîbÏ{aÊœÆ Tñv+ö%·ûH¯¥ª$hg|»A·§yÖ ôÍvþÉyŸXw¦å5âtíÄ©ÇgN=~bíéÓõÓO”‹‹'™—²8Ó“©â·™ö:sZÝ ØA;Ñk¹bMXö*wY#V•¾@¨­Ùú#= ØíÀM‹i-ÄrU$‡PW7¦‰Þ®‚ð¯[st›*úÆuººÂ gvxuG νdqÅ7TÑØo‡ÆM½é÷xôXǧpÊ {˜@µJVÕf=iu}¤ h›0°‰»Áf÷ÀFÂb‰o¸ú ú?‹‹! ±…r³9Mó&¹œ>Â-%}iE<ãæ€P¤¥z}àúŠ”“’¯³LEÿéËf=¿GËrýM§±äd²Õ挊$Îj-9z½`­wd”v’®NÑ‚'¤ÜÍì4xŸ×|œºP AJ½ðrjyË’ê)_˜qxmé±m+Ö'Æë/òAܘÄAø²Ža/¡OÈ710aÛUú½;>š“òZ- C«{ÙèlUX[V–- ‰E™5V}FQc)žQH.û 7†iwÒ%} 3Ùu“í¢«kQ;h,‡Ò›奵†lC¤ç–'æÆÚì!*H);“,LRöÄQÚH) WóÖeÃ[ç#bݸ(‘)ÑÌãEq¶$'ÌÉ–¼ÌiÄÐwèž3/5%_iV­%M’ å5*ÖM…p]gÓtT×\tL”‰'a½¼ ;sìµNÔ“ø£‡»Ç{"\õÖSš~ÖI"ÇsüN«-}gZO﨓­·%äÖç%èÁ†Óð¢©n(Žçý­&^‹'ˆœ»¢ÝYÀ*™ÉŸŸ0¼¡žfrb)K“üE[h7‚8a¦c]ØÐ såšc¿ØË=©ØB‹²JÉrˆ·Ô¬ÑR¯CÖëÙ0_Î세äK?nP}ÏÑKSÒ·K±Ï]óëÇ$£·=tSæ9V,6!sä]!™œäoŽ?º‰ã»Ã¡²¹R††Ê¸]§ŸÌ¹ß¹@D‘k™óŠy‹ÄíÌã«A:PÄ3Åò8î¤2 ¼0x›x…¹‰ YŸ’X…{#{S&z-XzŠ–Y x£5Œ3¶tyF2\è¯R§U,“z}EhSNX ŒTÖk”çt\°ÁIâR0_¦Xs,9ë6¬aTJ˜§™;؆‰Å<Àl_g[‚Ù¶žÍ3LW“Ždt»Ç}Å“B+ l¾oà*þ%=—Õëë¹ð´*V¹´Ëª–˜% 9Cýó‚ þLhå°<(’Ýà–+™…Ù)ñC¦9!áMª„¬pZÑMcsãî q‹o6dáõ¬ØA±Æ‰Ä R\¬,ä~Œ8dè¾â‘Áû-¯í‚,8ÂØóS~Ôeé  bîÎ…=¢U/Vû†ÎФӒïæò¢4a•íýÛîS(>‚â4ŠgP<‡âbßÂÓôö 3‹ ™ÑÕRuK£ùáî¢è2ÀHù¿Ç•*ï2+o md½v]?UF´ÿçû´¶ø¬éá"5Ãx0ˆ]Ag+&ö—ü0ÒƒÅêR@Öy\q’‘îQ"4u<â^3ÃüÆÕÄ‹RŠ´àŠ”Þ§Åy¡“Å$$)YÓ¯n7:ÁŠGÞNV¼ÆýÅ,%S©û-%fs S‹¤§”zkŠÍP Hï—Po²ÃA¨ë×­%Q¨[¬)‘³D–A:3«$S2†²6¨²PÌ<®ÌÉØgµ²ÉD¿7žH!ÝÎ.ÊH®µ“s¿‡þÀ•Q²Flö •0¨&h?Oó3x§í X½Ô¤Ü­òRÅÄ ‰q|’- Ö~¾ Ís…üfÀîqÍè¡Lïw„±y‡ÆÈ{Úf—ö Û=eQÿií@!Ê.¾5ÎÜki ÷Ù£bn“…Ëèi’Œ(÷9À#9ʘl©ûb?×2¤î ­…5imõ‰n ¾×ì±æ7íì5´—ë$¸âNÒ*ªP¯“™N šÁ”Q iÞpÇ {¦R翞 S2ë{˜}ü_ïc¬£n±úÑÂ솰ˆv¨yT`™”±hzÿç¨6ȵg¨6¤e×ûStQÕH{'] ë 0¢± ¯¯]ÿÉ%c8VÑ=xdjÝç˜ÆÒ`·Iù”ŒƒÈ½Š&vŽ¿[‚CW¼åÄ]x+î£(ŽR¯+J*–!^«7sÀE_}N5„– %LèÆÞe Óï —£Ö¨=lm]…ä„óï7ÙŒ€P5€[¹ ý‘QçÎsê‘”~Z'ÔXž*f7uT+‹Žü ‡{xìgx¾è¼Þ;‹A¤ßyÁ ӟᥢKëgÊ7AßÍÏò Ÿ.:Ýèb#ïèô›3‡²õ¨b”ÒÝaxkžÞd3©…xˆ ½hD~ÛË IûÊ=Ð}/a£c…ËYÁQ¬’XÀÊU’«Ð¨G,Í®lÅäi$rA&¤bÉ0 ßÅ ¹)±Ä-']OgL=ç…a¼ åÏ]ÑJÜP±^º§Ö[­8ͯÝNâ6y0™ìêƹºP_²±7:ą̈hQ$i*©—¬ó0+qàÓ´Cæ2t¼Ô9ôä©Ù#“îîœN{1ñ|}‚[írÐ`Á ØÂYÈ@öœ…NÔà¹ú’üÊ„Œ¦ R³•™GúÙÓ†Lá\/!Q×…X(/Ö,Jš¢Ÿ ë:½ýo9µ'¬†1:«šâé¿vKl])iÛò–rLãý¯k½…{‹]Öå‹\‰i|Ñ»C Êû‚àn+_E6¯9¢Ú.»µ»õf úOÒÜÎé zb.:)Ê$xWù'aÝ,“%[FÞ/ùPj/]¼C&ö8¯7ç—!ðáçqtÖ’ÛáxŠY˜ŠÐŽŠŸ“?¬°¥(Gä¦uB†=Nð¡ÍHÔœA2<Ï÷xÄ+Ä…_Œûê(ž ½Ö¼ïû/t'´æÍ­I´>ªˆê³}L(÷¡}훼¨o+CËfª‚ ³ÚE¬´^gïH·´¼ 2ZLÓÈܽ†YY®E©ªäH¡¶oŽ\'Šdòß9[»¬Ùé½úbÓ›Oìæ:ÑæŸû&žx5_jûÌ" ¢T&™k€*ÅÀšºAiÞk,«4 Iù.ÇLKj:¬ã¯¬§¤Ä/‘Ënr© *4Qd(j(–cüä.{»yïKÓþt‹MØ8κǚ$í>i•öXcÖn+4+8Òô}kKlÑ%KG—t¼©bâMƒHˆ£2$ÖÎ"îWÿ[,‘™þgꇅÜ&d•sÀ/9ÄuKÈ,ªŸ½ñ‚ ¿9 9BdÆ· 9&’/ ¹S²cxµ6Æ9ÂíÈÊqnk!’éþÒåÔîoGNÜG©ïIä¹ý]Hiû{ºö÷"]íïGJzqò®3ü!ÆØ2à ú›óbHwˆµ3H9ûÅ¢}×NNXH1oîä„Es¾ÃLp'#?ÿ$–œØÚIbÑßœˆ;!s…À<ÂöQ®ìF •ÂÙ›C¬w*Îõ,Go¦ªœ>:åè´³'Î ÙŸ„ÿ ÜºaÚ“Œ`;Y‹Ec °cö˜vº›¶¶G’Q¬Š ÎãªQTtåïQÆÂ,/‚ºR„%µFU¬-NÝKf/y)Y?‰ŠÇ¡–*ãèŒ@ìŒ÷K=ÆôörÁbO*õh²ëŒÄÖŽiñ­ƒ¬•ml3èFÙ!”vc¸ÇSåÀáÛ4šRÉNöª†"¦òºlHºŸ}tê€ó:¢?.¤è¸¶‡âôík`µµGÀ&G¸‰¡®—8ÃϱE\`Ö õ ³(Ü7nÃÛŸÒS¯fæ=5JVÕÞpnTB CeOÁ¶šr:‘/'N¢&ƆvQèX#ë-·lX„3~ÜŽà²k÷¬Az´ºÏnƒ»&tð `2ŒÜ7&KÀRV.¨K$¨+ÖçзÙUª£Öã±]¦ÓÊJa½g ²˜>Ç'BÖg…^‹zu5LÒ <¿4}^;%9¡éw[˜èo ÔR&ÊܶzïÚ½)ë[BçMÉÛiyízÛ#÷u ÇO:i¨¥f¬Ù>X^UXÙÆI@®›öƒ³A-dºvY:ˆ&™‡-5âMy1÷—óuU´}þÞçìf½µ\÷I¸rνŽYµe2YLlÌš(ëÐ4oøP1¬hYI‡õên`”"GA”iOü4n`‰d¸eYssÃS7¾ 7Üa>ØÄw¬»pÀHÁAÔîd]é^¹lù¼·ÁýXJ žÓMéý[(]êô~‘{&wJÒ(”=?PÌoÜý% ¹ÍHÄјÞ^’t§k,‘îÖµx5RÑe(IÅ2p°UÜ7b¦Áý¤…û¨‘gÓR·Cõ:ïE[Jâ8Sé¸*t°›Ed…GXb=XDÀ88ZPöo>ô½Ë'ѹ|z¥àÈg?#78dz{ _"“þ¬Z2¬êþªÐaUͯq'û`Ø',5%†}ÀzðÃN»{¹‰ŽºÚgðxt`êcc[.–§$auïä·D‘·eò]D½Ã!Í Ó]ÜÀѧ+ôµE¹<´Ìɨ×K¶BæþPô\AÑ1¢éø‡OѪ¦èŽLÖÏöÑ2HÈ팙כÆ7 &…it\^é#®Å+ŧ@^Lœü…D8Ž8ï¦a¹gô‚*àËWUßLWNo™¹° ý„evعуK¸ùéh.TT0Iø»€^ºQP¨Ø…û5̶°e€^²Cn–}‚Œ¥ÓË›`)iX.üXöÜEˆn`ŠôúŸö›&¼ò.wÍ܈õŠ¡ÂébæœOØ!]Æþß;v× ›n”Š ùF„çî"ÌÍÔ ƒe„™a?w ¥Ô&m=99ÑÒÔ{d;†Ç¬™A»¬½6ÚªÕI«ç»Œ_±“+Q' U(¹¶eö¢Œ@NyöˆÐ?Éú{±%’ÕäH–Šwúå"\•ÒÈÃI‹£¼™pA%œX¨à0N\X|eœƒ,±I::Þ„[Ã0‘q9É—ÛôI‹Úˆ9f1ªXÔ¶ësµ1s¨b\ǧðâ„oö ì…qeš%A#ëb_NX8Ja;ig>J;'œv*;~|BYwʽý5Ƚº¿â7QüŠ/¢øm¿ƒâwQ| Å—Qü‘Ð9™ca0ÿD?9sì͵ýïpÃl8ÊÃ0e·¦ Tà–¥>º}@ÇT·øDÈ‚a‡9Þ¿µ£’îñ£ &€0$šÕ<óT“˜9 àùÆÖK'­†G<«M™cÂãÕÜëbwªŠ´¹¬)§¶ØÉ¼Íë°0/”¦OhðF’âñ¾ÊV »jå;À¶öÛ%ë”›Ïe#cw+bäð­’xÇ~oJÂìB‰»¾ 9•ó^1‡U>“«‹c~IOl‚'tN‰ òæ§ À1ŧµèW6‡+xº½5Lúκ-Lª5s«yýOâ;bJÇã9÷o„že2¯¾®¹'´âÔqÉe÷[F¾Æ2vÝDòPïæÜƒôûa"‘¨sÿ¦À›ÂUöA˜s¿‚Ñö·‡6 õÞ&´™œ]nN!e¤P¥b×]ÒÄýª0™™oåµ3ýœ!¸S¬‹žø Ï.ÍgwÓo¿Ç P輊¶¢2P\í2U´älJïtmgØú²É‘Ø&GY¯ð¡[wܽ‰)›lˆ89ÁþÅ7„¶‰q.¨ÕΤïþÚµwÿ²W° VqÄYùݾaÌõ`qœ±XÅ&$ë€=FfÆÎRžÚÎ}TìÛÑYföHu_eµ»·MnÛ&Kf÷¬­Ï›eN€—•λˆ¶îJ< ¨÷ÖNx½·»Ö£Ú‚¸I(oÊ_zÁ`6W'E&1>tïˆëÝpøeÇ•"ì\6<¬!ÙcŽŸ˜]–„ŠÍÀ0o¡¨÷@ä~*_Dßéå{øJ€0ßÎ&E·¯ë]4êðB@UîSؼ bO¾m—ˆÂdÕF*ÄÈê¼7Gª“›º·¼ ¦AÓc·´{'åwîËaØþ>@TgÏF¬Ñ}ì‰Bàê›E6,ÍØË‘\Ô¼¬<Æ}ÍB?c)ùÁ÷r`©›?ÝS®f]MŸõ¸vIûBdðŠ/š»Ÿ÷É…þZ.÷íƒÖk«3ú‚èu£GRÇ\—’ΤuiF¸¤%ƒjZÈ1ÔçT-•y¶?úe©ÊàÇtãmÐàÍ ;MáùäL!ÆØÍVþV¤••Á̶¡]9¾.†ñê‰P®ÈЉÓ•¶N1sÅ9cØ!sîKW/Õ_xùü‹Wºxâm½ˆd_ï-„Þbz¿  ú­›û¬ƒÖô„ØêÞ/ #Ô“¸µ,×S÷ûhþWýÒõ —._}éÕÙ+*žÊ±ÿjÎ/ʱÿlµè'H¼=ÆÒÛÙ±'÷}ÿ@µ°…S8’ˆð¼ÞDxÉK×_"F+…wqøxÈSRÌK9Þ<ŸÖ˜Ád‚4Ÿ i'}À1õd¸îª#šÍüzwϪ»–·ŽÑ‡ÓN›w\z!ŸæÈ¤yOmÉ õÞÌÔ¡å9Áàp’ŽÚ:ÇÖ Q–¨çǹJòÈŒOZ ˜žäᨓ-‘À6A<Œ½g}d’æ;.‰’Ô£«5D ñ?¼$îDØÙéx+^â”ãŒRÆXðý7æõ‰Â4Kêõïå6}UÁ›þ¿ô}}bð"ÖgW÷ç…ÑļÝí‘:JóY¡½yË*o_ÿ®Ðö›2gÔ¾ñ0˜çS\îkæí6Ñ”S»t£¿dxXŠ#³w¦§ÁÚÌe”¯p“:IÊñžVu:÷Yâu=©ä÷§Ôf±Ç3%EÊÿsC;·qÈÿ"#ßÏ9#ñHê2Y±¾Ž‚ýxø|]Û„Õ?çP;E‰ÏêuÞÐÈ™ƒ–:H©¶öó&ÿ|¿‹ÿP¡òÞRø¼{Wà ‡¼·[oy“ž 'qô(ÜÆ`Ø ²DO>ASši„Œ²2oY—îŸá1œcL½Ä[ ØSù-¿ÓPGl㤮þB; 2Žux*õ€úÉ€j ª"û96ˆ ÜF¬M¿ö¬ûíqrÑpè`تXãÖ8]—&J#;H‘ OT'&&†wO>4±·:@WcÕÕmÕ“KäÐÙ»„7¬A2}Ëöî+rõ+ýPKƒ,ÒF‘é À˜Ésetuptools/script (dev).tmpl=ÌA Â0Ð}OÉ ´@pQ´‹B1Ep5”tÔ mbÒŠÇ7…ÖÝðçý¿E®®YyTu^UÙ¡¸dj.OõV¬!8ÖèÓxhoÜ@}Ó1ú„Èó{4ž‘Øý]ÌM笈@ºç=ª`G¯9HÜÌ X0F}3/žZþk†G\á/kжsñ Öq‹œVš0K’ 9q‰˜üPKƒ,ÒF¨3´¾jŠsetuptools/script.tmplSVpu ŽÔõô qôñÑ vò ±RPÕ(.HMÖ,Ò2’‹2 JâósS5‹¸âã‹R K3‹R‹ããláê€â™¹ùE%ññêÙé@UÅù¥EÉ©ÅêšzE¥yñS4àæ* ¬ÉPKƒ,ÒF¢¶}U setuptools/site-patch.py¥VK‹ã8¾çWˆôÁë1ý¸ xaXf.3}h–ŒÚ*Ç"¶d$¥{̲ÿ}«$9¶ã̰°¾$–Tõ=J*Y@ÍÊòUk—î>n>²ëµqÌvþªÃÛó_/Ÿ¿}}þôò™8–ƒz“F«ü.M¦Édbëy€´ì«VÀ´a)fÏû–»Z›®(’w©žÆ•`J»YPä´‚Þü8´~²bzÉmßJ—"Ûž»ÆB¿Ûø^V¸™sç 1ÊZPÅ`ÊŠW $Ùßÿ5Ö šÇÏÿî[Péœl`Õ Bšà­ÊñMñÒ²¬e eÒÝõF*Ƕ¸©©ŽÛ,"dcþÀ=bÒAǤ9LšÑbš+ŠŠKÉ@šÖÐSiå¤:ƒGfö${ ­ÎÆ’ÀМižK%ô»Í(O70ý®h *§Í0AFP!ZèKOx»§q Qá—„ZÍ…Ï1.Ík/;-Î-¤‰Å”ÉnicÐO“u/ .°>·‚ñÊyÛÌ3×ÀEuÀZ% 9ýüŠ=¯øé2ºÜô83¬ Æ…?ÈõÓ›–bjµî©Êσk°¿ì)ZÅ[‡¨]ÆüValm¼á`¶§Ò–ÌáG½c_<èŸÆh³&9î—ë ðñ,ÿǸ›6üï:‘âu‘²hwÇ›³ΚOˆË«V[H—1S™—%6\Z˜û˜nÿ 5*q„T`lË·¨dÐØü†ÛŒ "LŸž¿Ò÷,¬¯•K÷iÇO@CáÈíÙÃnÙ!bï8ìÐáÇü+Òõ!¡nE¯íuÏ+K8¥²`\’Ýï|e,ZθÄ͈‘’þ„Vˆ ³8Lymg¬1µtÜ¢¢¸uÖ½mj¤“Ã\r›Pì17á+Fmsh„ž ê;˜ŒŠ.:|&‘1$X°‹­±Áîïã™ %'´ãý ‚÷2^x­›t,Á$£G˜~3ãQjœ/ ¤B~M˜7Ùû ªid0µ–Æ:ÜaƒÅ¤‰o M6CƬ&Aøw –5kÀ\ê™DºÐFu×üHÚ|O’â_33å¼ïA‰«kbÝ.ï("à5Ý$/Ö¸×xV2öʫӇ8$Ým´0^Èel ¼›çaÚV¾øhŘn³‘ô‰D7xYâ·Š?É÷øá¶´q`ó/PKò lHx×VìûÑsetuptools/site-patch.pyc­T_oEŸÝóŸœÿÅqÒ’VHX"~ I[PÊCUQ¤VB!r[¹@Ãqñnœ;Ÿï.w›ÆAwRixD}æ TBâ#ðÊGàKð Ϩ™³Myçì]ïÎüæ·¿™Ù³õw³¶ûÛ‹ÇC˜=ǧ8ÒpR?|  (c Éh€Kñ @ˆ {B™à Ž ŽÏˆà¤Â äòÅZ@. àKð-Š¿D‹„L’w¼éøePø˜\ üáÂíý STgÁf‰bT <ÔfAn1… ¦F`ļ——8À¿¦Áae˜þY öÿ„ùð[¦ÓW´n$¿Ãé+J1³H(š(¨ Y•…Ú´®ý&¨2»PÃÒÜõRàÚoÍ\âàô¥@²‹íy–!·!³gÑÈ=p)á)j¯A^‡¼ƒp J¦ ã$}©ð$«Í •hQüþ:SñièÍêa†%¢Á_á†=9@ø§òB€éPQ‹Rí¾KU0«³LU®á8–ð­„Ó_eØœó´¹Ð-Z ÅYƒé:Õzï°Í4Wf4âô/1@@É_ƒ¬·%"éŒ^CÀS 9V£MIå+ÜäLZ¨úá?ª½ 9rá·Í÷ã¹ÌVæy.©ãnÇ ÷aMW ýù-Ø/1þÕ…Ä{¼A& ‚°U¸$è ·ÓC‚‡½Þî}ï5>†–_=ºÿåþÁ½G÷M·ç^øÑ- »æÄñ&q”8Cwx¢M‰Þ Ïèô}zM¢³@…›¦{ì…ªkNt7ÑnÐÝ$Àfw©³@{¦Ž“ãèÑÈ S^¶Þ:yèÝK/RCïm”š*þèð™—D!»FÚð™ûQ¨±y(*pÍq”LXkžáÒšê˜×ã“pÙ™(Ð!;•—„î¤àrœc/ÐŽÃò(§ÐÌû r{"ÀB°ýäó$Á™4 ƒ(-ꢼ¡aÞ‰;ÖtpŸ¬\cW)* nèÿÅc*^éÑ?OŸèúdìü41r’ìÔ(N… “ â!n¤œð‰ó.1%)×I8*‹m™ô[´§x¥Óa¹ŒÃè¡ÏI ™ò¢!l‰””f,(®Äf2»Ûi#6³wùBqµ›ÝÀYîîÞ¹½Ž Žk£ò*Œb]¹ £ÉdâÎJ?¯dY ò,¼‘‹ßày2Ó°íš›)üJ°¼d!Ù. ø4ΦÍS¬ÄïµÐ&øMý= Ú¶6ôZ ‡ð1N‹\”vSdJldV$Ÿ± ø×"Ëý‰G‘†G„Ë'-ŽŸè#ö„…–Ë”ŽE“nË~$º¿Šk ¡ãá L„0Í5+¥!¬2°Dc6z‡–òM4ZýÐ*oÃ9Z}¯:5·á&]'k©MÉ7â`ðôÌA\<}@"ÿ¤Ï渿Îa Þ·¬:èÞ­„¸t/ɶÃÝ–oZ€›Fkáϼ¨ícÔÉo}ð³^äPIÙYìQ߯ÁZT‰ØÝ››ï^±÷7÷ÐOaE†¦œÀ8« g*t@MN¦2•§k¡Y{@H¡ÌC”Ø/)p€VPYDÁ$P* ܃˜>¥Ø åØ7O6s`Âø—µ(ñ=–)Þa›-Šå1Cç ñ%¤<ÝŽeÒB뻹ƒÚuWÐ}daðù_ñ—ï¼ …§%ô!¾ÛܬÃà±<= "™¿õÙxyx oºðY<Øñ?¹qÀËv@ü&›…È2à€G€/OŸy}t K$ËA°*)œy‘ÿXd“Óas+ òJ„ÎÄ~OY}h¿„ÖÐ6%X´®/[—3ìËÕ”‰x³ív{òW¤CÇW<Ý=Á†ñI¸‡<ËȈ6¯cîtÀÒÈU ‰”õ²L׌H›>1¼Úª0ìÔö)ˆ›|%pB™ šVò‚ô½ 0e¿ÆAü›ÌË9EöÕ?á(@üöÇ÷7·×W—wבWœ( ql›‡æF¶ýö"Ä„Ù5ý¾ÁN7ü† á á°™H% Ì×\xµØµû¡6ÜÑô¯„4«AE­ŸÑê'Nð  Œ§§/Î^Pïê‚«;´ÊpÇR˜P³)[ÔÐÐ}@B¼èf³44:ÐìY}!ÑG-„ Õh›K¶„ƺ#³›¢˜i@*¼¬K õÉ©ñÆ+öí7¬hAÙ j×õ„á‘My O)ýbvÔ9¹i]•æ8(Ñ öÈAØü_æ=dB/Ñ*b7e_Q2¶÷5•‚R9ÔÑA2o)1Û‹¥Þ‘É`£%w*.Ä,ZÐQ S &ÖæÄèHY;Ȇà—a¢¤Ú…ó"ú‰eïïÐ& b\íŒÐ=ËõÖÑn°ìž¥­‰ÇgÞcëz±ß4ÇìÓ§Oã&c¢ª+ô,)¢‚]Ùže¤eÇnS=ô`5À:ÞKã¹Ù¶@„–ýê5ôÿ•×Ýßo£ eè¨"èœÏöÔ¨}"†Á½›»°¬Ø ½áUˆ=æ´=DE£ÞÃWŒþÿÐþ‰ú†ÎNkþ°BÒBÜ£$tŠØfw¸Á´µG½~@1èe hÖ·‚Ry]fGx÷`Çå½÷i½‹‹_]ïhò`_ݶ¶ã¼6kjĈ¯Àìo„¬±ª “Ƙ»É:Êo’$´mh{mçaWâv3­{nI|-ãK¯úâL­¼ék„)ñ»'¦)à$-“–®gЂo§hƒQ÷äa{1°Þè„v¹¯³%HbËòå‰Ëð†è°åÓ–èOÿ€í­æC¥/úFîtŠ÷n§=Æu­Í¬·<¯Cƒwk¶Iat5"éÛw mŽ=ÓãEØŠtøªÑ0°WÚIÓ³@þÀ»¤È÷ˆ{àãM¹¬53 L¢LÉ$t"ì×Ô}R 1šÈ…À×TÙeÆ+t[^¦0O ê#i š†0+#ƒ_¹Œ†‡DXé©J÷;숦jc5½·fµš[«£Y=+Ò»?HÍ{vÒŽ>è¿to¯‹¡>jñÝ”º™ƒž#ñÕõí}r{ýoo¯_Q4Ò5þ¼IdÝÓèö{`ŠV«þL0õÏ3ºß½::h¬×µÉä« ×»7á¯~¹lH ©Å¯Tó&Ì Ý瘰=óÜ Èb?BDrü¬D‰:bÍÀI÷45Õ8”t¹BYO(r‰°IûÍ'‹xQð™Xù·öׯŽ9Ž£½¯N®ãbd™>Ù"¾íÕ§½ÁÆs‚+p|¼Äñ³9ߪ ^°v½Äþ¯åâ}o•°–*¦øÉt¡ëˆ ŽÙÞíÿë¼øö­}#Éž_ØJöÓÎq݃—ÌöÔ’®çˆC‹óQïø ËºOC³=GÙ°·Â>Hý´Òÿ=èR„†sÝ'°ßPc%V9¤&›Á-’›Êá;Ù3EsÈÏÁÕ%ö¬·77÷Á—ÈGßÐcŽ!¢ZèßÚM}AL‹+vuÉ(âWË)}ã@Б–÷|”&9r D ^öC3·_FÝ f?“ŽX‡ q®‰]K¹gFiThIÆxuw+þwéØ=%(€R\Ð íô‰—»ŸÍ%dƒæÐƒóô›µÇí!!þ?PKò lHP°ãžw 0setuptools/ssl_support.pycµYÍoÇÃ%)‘¡,Y’%ËŸ›ÔNeÕ¦âÔ5çqd%6âÈéÒŽ&Îvµ;”–ZîR;ÃHäK¤)Úþ ´è¡è¡@6·½öÔC[ @í¥·¢—^Ò÷Þì®$Ç(rP$r5;óæÍÌûø½÷FÖ¿GêW÷Ñ}²Ÿ!ü¾Š_µTð# hmm‘·KÐ.åm ÚVÞ.C»Ìíµ{hW W…võZ AoÚà ¶ÇòI5h×`9ž†²¬ÃzÒƒG°;ð @–ª A0 «ÈµA º#° Ð=BÏö(È1(·B{¶zÔ!x ‚¬– ƒ[à£Ù+~n>|ÞÇcL@{¶®œÄ®ç } ¶§ y äNáFÊ÷—7þSlïîNàûü.oü–eα^ƒä–À]È£ Çiêú´§`ûô(´7 íiè‡öqËñý‚çï‰çö9¦‡h&£d©Mð{6gãs‘Ïù­ÈÄ4MËã(Ž= ÉiPÁ$ÈÐAƒ„ô.RÆò8¨ÿŠ9 ãÄ“' 䀣(m<M›)¦‚àŸ {O½§iÙàó8Cmï,§™“ Án7'ãsï—C2WG 16S¹1J³È™p!‰cÉrgi¯iÝG:õTÖnúQ(c­Ž’ŒÓ¤gŸWvØë£Ò°e4:†…=A•Ò’=OûkîZ¢tìõ$kÔ!¾¦ÕÈ_ ¢î×h¿Ãø@ ã´fiÄ,DÝ®K¼\—5躽$Døj¨Š‡z+ƒ0 æW‚PéfÏóµuéòsÍËÏ]ÚºvÕ½ze^®®Î+©}$¨q”·«}:Z³¿Í;»F¬héªis¾Ev‚ß2™ì^xdÁ¾ha«+Èøw<*ÃN™0qæQ…[œ}T… tKäoD2;øAÌ(Cº Ú"ÈÓebˆ£ÓøýHw"‘Ú¥Þn…œpGdõ.Y!fØJ;t«„™8SÄïòZC ø®>çyùkú§ŒEÛ­å®0ÓžyÂ@·NŒè»[b¢­s°SEè<†’ç|6¾„eê{*CånƒéXˆÏÓ42BÜáœÁùOkÍŽlûøx‹LýÝö|?IjéÄv^_°¯^~þ{meL×¾Ú¼Òün½ng?d¹×ççY±ÍPêN3IWç×t/šO;>MýV6ó’™™OÔ¤æfH6Äç÷9u‘šIb÷¼xÛÞD³ò½4@Gˆí}`ß\jÙd×mUÁ ï}Ð|øE¦²_ºÄvôþ\12g:n˜?Mó§=K~©‰æu/B㬰 ¢PsËO±fËÔÄ6•ý”û£d·QÅ–×G`Ø9”ö6C½¦KLÌRù^_²«ãôÈóMÛOzýa’Øv“0f·ßXºë,.Üh-ò*ìγ4À ƒ˜2wo=Â$[n!f†p«xvŸvÃ3"ÙÑ=œ¥k¼‰ž‡ÐÛ§·ƒs;©·ª-Ãä0}›ÁÉ bÅPÂÇz‰ÏûJUTE¹<*ê¢^Š%¦¬ª˜ª4¬1q¦2c=cˆ¥g…_Ê2§¡ ÞCc!8F0`ü߸.!D 2\à”„ŒÞ‚­r‡›_¤|¡¢Àòä+$fô<ò |uÉÃ[]+óG±qð³Œ}êo°åç T(áÙ¥<ç ÖÐ"Õ¯.RåE>;¸ÈOXä3ÀÏòÆO0Oc»ÛaïG!¼:%P¹ˆ 8ŸÒ²*…lT2Ñ0eQ™^<8W{“'×i2ö#<Ìì#o J˜WÚû†zYäi€­×µƒDªøÛÚÈÕ–D2µ“æ vÞ§þïŒóiXø;n¡-MúiHH»·4áà†íN(#g„DR &^û’Þü;^4ÈR: š‚s’)"°¥bFZçTÞÓóúÎ$1ʘ$çØyj’ŠbbåÅüw]n3ü}H뙑ÁÊ¡&*”GQ¨TMb8\£`ãbB4°U“¢j͈ ˼đjéçPJâÉwæºAâ».kϹqÀ&Ë0訟+Jµ0‘(ÕÊ΋ð¤çë;Ú«Or4¿¨Ú¾ž¯Y™™Ñ÷Í|}mŒÌ8E¦&vØå\¾áÙïqyœ‘›Z9W£óRÞç¼üM¸Ù¯÷´:!Øch;Õ2þµÿ/0uÁ4ÂP‹w×â|KfÀ;|CE¹N7§±2ìÉÐgˆù Su%¨U£ô-®ek`MkšÎK¨Ý ¬‹F1³%Ãbû`8¥Î!èŽrÉÆ ‹åø ”±j¦‹œÒ}WFs”O2΀—uMð>sF*¡“/™0 0uq³ÃX¸ YD| µ¹ü6xI·è‡& Gô仃YŠh\(NŠ4ú~*1ʺ{FÆZ6ù<ê†×ˆéirçR›2bÍSE'ñsn’a,æ(€úÕS7S¯ïfë‘.,:÷\gñû÷o;‹71јv_’f*Ú½Zè ÙŒù`­[÷qöÍeÇÔHQ¢¤±Y¶Ï¥œ‘çëgäq¨Å„)ŸXR¿!Žg2:W~#C½Ò(ÕJUq¦d‰bxäqpr^+|kùA%B _íC%Q+³'åÞÄžt¶ð$ÍnÔ?F:Û…¬”ï–3<`åðŸ%eJèõGùân{‘„ù³däK|mj"+½Seðz˜Ýe¾µ¿±…ŽÁ×}§¡ˆ-¼Ëlq€Oøò> ,EL ¿”y¨;ç,YÚµu’0îæÃ‰ì‚«+²ë±1‰u§A\s„¶Ò-ç·S3¶jnÞ| Ä+¥¬N²F!sw¡åV¨¹?•«¨S4†û°?Øœ¢ÙæNÁÌ­äÆNÚ‡h"´ë¿«:›Æþ%ÞsQë +¿P ú^ÞC†âBÒùd1 7ØSœ»wﱬÝÍ0fñ8wrWâ[r·|ˆdÆ[d|¼Í·º{—ï¼àcg9¸¤ÛbÄtÚG šð‰õ8{aC !RN¢+¥SÃÇö|²¸eQPÑ^0O‘ЩZ[ç²øBÒ”É-§§©ÑÚ8 Ëè½hHt Z¢àO ùr|½w˜D‡ÞÕ±Øcvã2¹1›]9\YÛ^l£½*MéØÂ ;C:ú÷ÂE*J9&’zb/³*›-É÷òû¥ÙF®ÆD9âNE¯SÍ•FüØìCE’âpÙ__Å@nâ¿â€¿¹DCzvÖˆ ÉÎaåÝÉÕ¸— çCÅSÚî?ö49ŠšÁBsX>§Äì3´‘ˆ·èñ=ŽÓ#9°W>ÐÞ*Mºšô4 ç.=ÖòeY½E®›¡@öñB€ôHøn€kDNbYª›£xÆæšÌ.FÍL\÷³b¨ø_ñüu:£jÒþSá¢ÛÜ0P¨åÀâÈB—eø‚º)Ã̦_á¸ü>‚Ñ‹¦ÄúÑúQKÿZ}ܪãû¨8‹:±pt©ÎX&'!:ò¸ª8‚QpÆªŠÆ•Æ…©‘©§CXÂLýPKƒ,ÒF}¼ª.‰Õsetuptools/unicode_utils.py’OOÃ0 ÅïýV9¬“ÊΉ›8$à\ÒXîÀ¡ø^˜[·©¸ëKsÖ¥ƒCûÞ‰5tH’äîvðÐzÞa,Ð.‡57 Å­setuptools/unicode_utils.pyc­TMoÓ@µ”†”6)œñ¤Ѥ•ªª‡ hà$GU?$¹ö&uêìïš&¨¹Pþ?‹3c7=×òŽg73³oßÛ‰ûg£vðûçIåãàø€Ã|Fã+ ¸Xú.û¤L\¸ð@Ä.ü  Ä;Uˆ+ì¬QN¿UÅZÉ_|z-®]C“«$Ò±ŒhFÇGÚøš"nÑ ¸s { Ö±K¥pWúó}òÆ¡¸°€‡ ÎWV§ªž­Âu ²!!”€3Œé·\ܯgÙ~:6#·Ãô5Bnel¨"iŸ)’pÇc³DìÓÕYâІvçJg“0M~H[]&°+»utOŠœn–é¬`ÅC3 íU‹t`cÞ£¹Ì“4î\Ɖ±íIi3ÛÙÛmïíîÌû9uŒ´ùÔjšN‰eÛ$5í霄ÉTI‡2Mª-6Å–pÑ6ŶØž`%ˆ†ê½—…c”`!ˆdRÅ-U!öfGp+ˆ÷¡Ç_Û°p`Þ(Źeîû§ßÞ"ófþœ˜Ç9¾g8NQžBsަæãÓU&Ϥo¯B‹Fú£ä»T>ñâ'Æ/ÉË¡½/½®s…?+íËÙTFVÆ>sŒÊø7:»6¸RµÇw‘Õ6sc_àw$í0I%Måä>9 >(,à„æJ±c¹Òˆ`Vwh˜ÏÅñûÈ2ÒÕ+q ¶©ômP­£Žž³z6PËÈ)yÙSoДº ƺ¨&ê"X—פ µê÷+åš+Ï”_BY›(«ýÐæxØD«0õ38•섬=`¬«–Œñ%ïi%yf­è£`óž­Ç£Œš×fóAÑu¯¨ìþ+hjÑ$ @5±mPÀ²\›:&´,/• ˆïàùX0:šè8Oå;êFC[ÖE]lyëõõÆ?PKƒ,ÒF/ðPŸ%setuptools/utils.py]Á Â0 †ï}Š€— ļú#n) víh2çÞÞ¶nEÌ)ø¾¤åiQ!ˆá£»Ì¨£1f ½t9uôfQi¬äÔ^ ¤b >Táò‡@arEÒ%z¸£*ÃLø$À‡·(XSt+n#¾RGê5Ä­ Í[áV¯í“ã\¡ªsËŽÓ.ý#­jêºöPKò lHš{P»@%setuptools/utils.pyc­PÁNÂ@Ý*AŒ?`Ò ƒŒ11ñÈâŘҮ¸¸¸ 3M )ô¯ü,?@gVð ÜìL^ß¾™yèë¸9øÜ>d°;šã–Ï9å|8€Ç?¬ÖðÁ¤fG¬´ß|†™bXãêNºŒ9À\Á\Cð®O"ïØÚŽÝ¨½®•æIÆoUžPiá_4|õ©›ÐhŽyÔƒ¹È®pySüõºraeÏCô"£•ú´¿ø¨ÕjŽBÚc Q€O¤ø.#iÈY „\a@RV°&J&°'J{®«ÉòUË£ÈÄýÊP—B»í—çN§Ýíº%m›ØB’i‚ቜ7žWÎÒó¬z9NÇ´Su»ò;1¦•O }øC†qìP Œ»çºy¬à˜y 7Re0{߬ÖËæÝûh³XŽþ‘S¦{z 6\,f—Ngco°^/§ÃõØ{›ŽFã¹a´N­«~ÕäwêÅ6óíjĤœµJ>×XÙ1›6VJ*Ëf?PKò lH×Ëÿô•setuptools/windows_support.pycµSÁNÛ@ݵ!@ŠÔª*ù˜ 1µU… MP‘P¨’ H\ŒcoˆÛkvÇ ‘Âzë'õ³úíÌ·—éÊÍÌξ™7kÿ|Qiþx¸ ØÓ²ðÿˆ¿>DâÇYÌØÕ³+ÎB‹}C§Å„ÅB›ôGôÛЫ­àÁè®NÀQåO Ÿô `lÂÙ£›ÚLí<Áõø×lŒèÀÊA”†r¦ƒ¢*òdeYY¯FžŽ‘@¾ŽLEÍ*,_Ýh(¡2‘Z##ô1ŠaÅ¡; # õĤ¾ÛmìÕ{»wo›^óÐ77®g e¬ÝÙ²OçY&Ô³9¬#ʇØO†¡Dåj“À¤§­,öa$UbJÐs "ù[é(Oƒg/hQ ·Lãù*ASvÆ·ù7dPr» ãvIÒ€ìqàlb±‰Í&+ìž32WÙ¤T(kld±gÞzá)³BìÝ›-äoa±G4m¶°™NLäQýÀYÊhT–ã¡¿£¨8¸z g…¡H@EÄ#ÑpFQŒšrÂH‰¤š×+æÔ©’‰3ÈÞ»®?˜Ê¯Bb9«2qos¡!’©vïšûûƒwyì:óa|í$¹g(wP7ºŠõ0Ï„®c Yfº¨«P¡Ñó¢„Zíy†Òe´Q©éqlXŸ •Šø`¶ÑÀ»âŽ‹;é‰)˜³ç_½~ˆ«Öà¢Û28¯ËêÕÉÅŹy è5ø6ÚJIeºiÂèjðò_YázOÏÎÛÞq¿ß=;¹ì·½Ïg­V»¶…gÅ2¢ £Â#7w‹ÐË^å¯yÕ*YU^â¦ø.]½K îÒź;E)ÿçÁ&2ÌcqÄ‹·±É7íré7PKƒ,ÒF­ˆ©–*setuptools/command/__init__.pyuQÁnà ½ó¨—´R”˜´ؽª N†1ÂN·üý0I”nê8½gû=ÛØ‚1ú]_•.¯±Á[jZÝÜ'60ŽÉ)V2ûà |óAÒ"ØÁ¦¦]­ÀÒbüD\ZHºx: à§ðMðw¡Ù2"ûLL»É5\â‚ÖÈîñ¢…¡>û'— c±|¬õå'©•ÀœZgöRSjȵTÍìu=Æh'×U¡ö1af]‰Ú-´©Ê”sbÄC¶ þL¦”òCýžFO(éÕ²0GËfSÓ[]àUêZÅ·rÅó¯»>þÄIw…êÁ8]þõ Î¦“;W¯‹RÂZØÖ¥~PKò lHiE¢±êKsetuptools/command/__init__.pycmRÍn1ï6?m“&¤Vpé1—nZ E*„x„Џ¤ËÍ8ÁÅ»^­'%¹Âspæ!x,ÆÎ/kmù¿ùæ[§¿ÚG£Ÿ_?N`=ú<ßðô?xAþ`˜Öë€ À&à!àà1` ° xØì>ìžÂ¬c¾Þ| V@žÀ8ð3°)ŒÓxvöòŒk|v:‡:|n@õðy„\ínV; À]wi`û0xÁZ©Æ‹²Fy:äÝ=ORÏf{¨*óš‹R/ˆš[T.©:ÖÚº’Z¼×Ê/¥)<)kc&³1žº˜¹98Þí¥5÷Tg\9R¤ã¯5óù(Ï1Ãkâ(ášcÝ=–m™Î^ÐO*hg¥gÌ£+jo[ûbŠÕÌKëJto~óˆ=1÷]Ä·¡"¥«®|ï—ôÉã‹©±zyùÿ¼-‘2(•tŒä+s2Ög—çªÀ,²Üö7eýÒSoåļ$çv™+i¡ù©«rEr÷tòO,š©ÊR8Ïw·ø·›;Œ•³\Mœ_\^_e×W—‹W#9z9ä†;Ã5éP²ÿ†¤ÌøUÃor‡s«_GGB=ÑÑI»¢•tÓŽh‹ÓäPKƒ,ÒF=ƒ/M setuptools/command/alias.py½UKoÛ0 ¾ûWp Ûhb¬×9 ëŽë0`·40[N´Ù’'É]³¢ÿ}ÔöœÖÓ|P"‘üH~¤¨ZŠ*¦t¯Y£r*¥ XÛ ©á~8ÿÚi&øg#Œ¢Ú˜(ªûN 6¥h[«D§[Z1]”‚×l¿aí‹Qtî°¨YC£(ªh ê𫚦Dî³UøÅqüÍဧ}K¹†ZHhˆ¦:"ã{ØѶ¡Ï¹ê¦Ó ͬ¹Ñ,qHâdqãòøhÖ÷±s`>V;%t0šObr’ãO'mL‘ׯÿƒ'x·† î·“åE+ˆ{̵lˆR@FTP2å|OkÆ1iÌ 9,{ ú@Rþ$~Re˜Y+$Ϻ2)[óŠªR2‹ kˆ«s(á.ãX¿3…SHº*òb~—=u¾zEeá20‚ÍÈAšHÚŠ'Ь'Ò.v iϱ=2L‡ºü“la¶pvG";_;l2Jxà.Ô?•ÞÂfa;ðRcÞL3ôû‡Š©¢MMÅ 1¯iÊf—#3&˜$s.ð){Ñ–ãÍ\Ö 7ô„ƒ†òt ËvçÝIO¦èÅÎôl'~é•ÕÑ’ÕG Ï¤ÔÍÑvÍxÓ±’ÀIK3ø} âs¨Þ^ÔåÒÅ:WÈ&vdÏO ±èÔpl3CJ²]oâÎ÷T{nŠŠ•:M¼râ!=K\è©Xs>:ɸNãO®áᣳ³KJËùw¢d†cÂ̇³:#ÂCÙ¹™wG§ˆ ­[¢ 7ìº@²ìÂTšò£ fxR÷õYÝ=äzâa&ž·ÒyØ~ œ6úèÿ$$?÷¯.ìÝ=šƒÌNÅZô˜‰)׌áÆ)üÓÕ¹0ºù°)L¤%ä?ãiKºÔ?s‹ÀðnµÍ‚– MWUóHšûµ€—±ÅWðbÿ®?¯¯²’Ç/RæŸÕÃe Ø%¤D/Kû"ñzùÆho‡gÏ©™Þ žî4Ù7bGš$¸±ƒ"$Ë¥“.$ÑØ1WÐÌ࿆edoGjDy-¬Á8¬hèh {}#l' ßq¯|k‡þ`}qõüEPKò lHÁSOuô setuptools/command/alias.pycµVínÜD±÷; „Ð6MUµ¦¥àˆî¦U„”BC[!„CUXµ²¼öìÆ‰?6žqI ùAëðüâixî¹^§ ­ø6ëÉ̽³wfÎ=çŽí¿zë<ŠÙǦç=ú{j"úJ‘‘J1”Bbl‰Ä©-†¶HbØiS ›ä³Å¯B ["jÕc)¢&,GBü0l‹¨ÅÚbËíPðøoú¸’zæ 5±6¥‰ýÍÔÄyöeQ䅋ݘ9jT?̳q<áqΓüQ +—?Ž"¤EOƒž»8ÊWÔì¿‹ýl<¹(¥xF_!v[¢h #Ð?’bk¯-QwGbÏÔ™H±k‹âÞKSèß–ÛBÌ[Ô|[æF9AæŤLUfœq^8I`TáLƒBÇÙÄ8z;Qû=Mbã®ìî ·ïk´¹ÕÅn=nšˆÏ.K¹8‹§PÓ°—c±Ñò$t‘AnôgÔŒÊ8‰ÖF!;Hƒ0×ûý›77oô÷?Z÷×o­©Édð+§&ϽæidÑZÄLL¶÷pJ>ó<"[ r^¾!ÏÊžä½ðìôùs"i¬!Ò -ðˆCÄ ®D`K1wÚb™¸^Ì"ë2(ÂÄvkÒô@tæ„·åvþC0FãŒð'€ó„¥qÌv`œ8{šï*íää£t¤y¡œÙÑ´¾V¿ú»|ö«×þÈ´û4ªæBŸ?68n™„«´4Ed(0¥¦ Óï*òļªXQϷŬÓ@g‹¥°éSS»‘d±‰)îOʯ(¯™ ›´OîPêµ·€¬Ëš%Z%ãÓ%‚÷&Ÿˆ`@BÈÙ•¯óö¿ -Y¢ø$E¿kT‰ŠŒMdœ,Ï¥ÈD…س#ª¾GÍ×¥6Žžª08j?MrÀ:Ö›{ »“©Zu~ÜV™S²òúý*E¬× ÑEj(÷'ðdôXF‰Ê¼·0WÔxzK5Œ§‡åÛãḛ̈¼$í M$¯U£Ù•Ì”@# Y‚Toºû¨äÞ°ålãÉqh¡öl ¦#KŒ1kïºxt‰Õϸ4ïRj~ŸYKüý¦(~A.m±÷ç,êäo¯ °¤Q2ž«ÙõYDì öÓÆMG˜níhŠËG¼ZÂôØ:'(çô}Æñ×é´ë0Ï‹#›ÅRi~“ë㨴%ïVØ:Ÿ¿dëŸüè7X”¾bJÅ/‡U4ãW„t  ^RDÔñkEŒ ±ä—Y‚ˆÄñ¨Älƒ'Ê̸äGqh˜B<“‚¤ñy WSÍ[¬…º“Ç/ ¦.15Üa’‰Ð|ä¨8ð‹2«n0Ò;‹K°F±S.þØ­ºŠxï1U—¬®lÒß‚ ½ÈB«ýêÕËáT]–\¿î±—Z’‡AbÅžQ“üÓk…wî¸äâÔLu?Ó—×yY„Ê»tú9Y¡uN„\”KDíÙcõä&cÀ÷GT¿§^Q5ßf¥.30‹? ñŠuÍäÓUZ xÙÿb,§O*Ý–õe³h]´»½s·þPKƒ,ÒFfÔ@ÚG Csetuptools/command/bdist_egg.py­[m“Û6’þ®_p2GrCÑvRµw59]ÎkO¼S•u\¶sIn2ES"¤aD‘<‚òXÞÊßîÆ;_d×îÍ›"€F£ÑÝxº ‚@ðþØöMS‰tÓy]¤ë¢}Æw»Åâ/Dz*X Ï _våúØ—M-‚ X,¶]s ×ð†ó®k:ÁÊCÛt={®ß¿Á ®±m8 (» ŸôŽš÷<ë;ÎvØ·y?¢{VÍN¶ô§–›·Ïš‚¿… õ[œ„~lÌÓ!ïÄ}^éŸ=ÿÐ?ty«VÓîwYÇEsì6–îŽ÷Ù‘µUÞo›îÐò´4Ækqìx ⛾éNgˆ]×}wzÕ”u/;ùò‡5ëŽë\pœ£Þ:Ï0#̬ûþP®»\Ok;ZÁÐÆ.0õÕ‚Áß{uêïÀ×鿳¦cÿµú&ýšZ$‰“Ø4õ¶Ü¹"ÀýHäÍÞó™Xи‚oYF ‰ª\G±œ ÿ:ਫ ‘(P}‚xÁ?lxÛ³š†´äʲaUeš!Éú×Ù2¤¢ïóJðx±XàPÜ€6;4űâѶ¬x¸"QnY˜†¬¬™n°¤õ¶ÕKqÑ©h«µÍ’¹}|§ éw)¯ ñP‚ŒB9iOÕ·WË?K"j1ºAñÿÐÁœHqiMLX{Â^Š05f=? n#imiÁ ^÷šºæ€¤™­›¦Áäm–¹âÄ¿]Õ¬óÊï“À컃 ÞÉgœ<˼aÖ`ßjlòºêñÀ©×3ÕO™A”eøNzÙÅ"š! ó²©ù·°´3l™M±!+N@¿ÜØy4ov²°Ì{jœV¤]ê-n:kZ^Gr{>„1ËÛ:Ò†FƒM»dzñ¨·›*‚')ëW;Up±YÑoÁÚƒMÇ‘B^³ßèü[àùù@ÑQ€#`Эá' iš%8¾U¯ÃÄŠ*@þôKÌ8FÞ“Ñœà×XÏýéâÄ!k[¢d‰t ÿÚÿ22ƒ¾aü°æšàŽ×¼ƒ•Æ ¼mþhs~¬ú+v)â„8öóQìqΪ:|)e½Ä™°… ä®[žc,¯*–¶'bHH‡† ¶œ‚¼ýï9o—(5\ðÞ“%6ÑðVðcÑ,ËZô0ANûˆ'&Ë»æX,ßö¼cûÊ<+p´¹/ßsŸ oK »‘ üöØÃâj°w”Zï#ØŸªØ—í’Ä;!2l%¦fd”ƒ—ŒªLG!üxT@—ÝžbMüNª(˜YÅózRK}¹z|Lo©K]^Y—}™WåG®éG‚W[Ç÷áO…›@DÊ©ø­¨S™rßãVd‘ ZûMg©âj¤ÒŽ‚~eͱÇmšª–ž9nSèŽfé´¿gÎËlsÀ¹%IïÚ“_d ]Fèf²²Þ6AÌÙA¨H»]µ»>ÉèH3¦|Ðb°åÐ,Ãr`)z_ÔRe¿È/™¯~Ž'˜sÄpç±wК¹ÅÍ–¼ˆ†A‚'x†Z‰‹£‘'& þuvÇz/˜KFÆ€/ŠÇ½ŒiNÒû\d€p¦±à5ý}ðÈĆ1w' qÏÈ<õðŒ7±¢ù `££-heE“)‡žyŸì‚ý5ßìéìlá!ß¡ö÷*ÈA ¡GV¿CÁ–ú„X¦õõgÆôØ8Õ¬ÀHm>Æ]Ddiرk¯Ag7°ÖH¿€Ã§"ØïãðØšSÉÄV᪌[:ל°Û;ËŠ x; ,ʾÁê—‚Xox„ÝáÀaÒPrz³ÕŠ}}5Ò'®—UŠ|-¨3àøxÜÿôÒñiè‘“Qˆrƒ¦$«iLÝá«ÁNtls ‚èzqÌ¢%üWÈàíd÷9[¸%+#’[µG9ÒO®îêyûän–Òûå—_‡0íŠuy Nþ»ï¾[挲¤y (»ÛlµÆ„Æú¯jv)>Q ìÁˆâÕÜ¥@àè›Hõ\·F¶c|ÞþìI9u¦`¸ÃÌû[‡úªë/–7/¿ÿÑfµ¬ÈtŠvèlb]OãÜÑ =O8°$Y‰4•O,Xfû†«¥—S1­¦Š‰92œSIÇ«®Ž6|6ÒÓ%öhe ƒ;ÿ¯n2Þ®ž £åMÓž2}f}3!·, ľQÌ‹#pz¥ý‡>ðäî8Ç9‰v†²’r¨ý6;¬7E³äˆx›i‡f§7¦™ûðÌ•q«C¥¥v©ñç;×kS5‚;gĆnˆ…}¼ÅÍI—r®ÿ_â…ù5(öÞ—«é§\f¾åý)ÛVùÎ>Ϩvü‡ Rrdàû@M³ÑøŒrL¶àè…I?ÃxBVxðã¼à积_Þ¼|qå¤ ¥µæX(Øúä§þâ·zœd~Üuÿ¿#hªxŽ¿ü£~KZˆ€  Î¾çÝwEÝÔ¥´låª\ÂG¨Ñ;^g÷Ïó(ö|ŠÑS“ö—é”ËG`ejRO O‹½uøÜ;q¼L’—)&”Tplq&šƒØÍ÷€üò¾ï¢Ñá£óºPr{k à­D%/±ZN•r#m,vCb'{ænõ ²âµvÒ̸Hå¸vDX2Á ­à,å@€£yµ§êÚ âRL¶¨XvBQõFû…_‹Óy”A.If¡‰½1øsE@e“(xÎ+®Ï „Íg¬ÿ“}¬¤µ³–?àL^Ï*‚ªŠ?>jÁᥠçÈUÌ‹¼}%ghº ý°²™þ[ˆªòêôת t·îyÝ‹4M VÄew>±£‰Õc7¯b¬vXi1Íe¯yÀVu‚g‡¼Ëvºe-ö£Ì\è–kA@ #«(t®¸µ?çßÿˆe`^ðͱÏ×xoÀ0š,?¨Õ‡!ú^^3— è}ÃJéŽâ˜W ø§t1tS¼Mqãi ð,ýü`*JÔMÜ š8\‰ˆ‘ˆXtÙÅl“×8ç}›ʩ‰Zo¼t| aø¹œÉÀ ±A¡†¯÷ŽglOàsºŸDª¼ÏíÕ766m÷;Ú•TÒóË[Ìq¬ðVˆBJ,v6U’Ò úˆn\1qØÐùY~¥Â_ŒÁÅÖeýHÜOè¶ì–½3³}ùøÞ¸Œô›Ô 6(hƾaÒ5_F$©X°å†~çÀ½ÎшoI˜ÐÕ‚w}ô81KÌׂ¢™ðËÇ€X¾ìc@.æÚïbs›I²+º‹úè2BÑÇpÒǃÕ,øò¿ƒÑr0yÅí¶t_Å ØU‘•‡v>‰vU,©wC%OGú6(\R[]Œ ^dñ»ªà@*ï°mh'•‡NfzÕÉìtP’âàt¶yPŒé€¸¸Åv”Už [$‘×.ðä4(ÊQàü)–¢ÊÅ=å§tP¨Ù!sÈûÍ=øN™»ÑÅ€ÔUãd~q²l"/€ïi‡<¤oǵàáÊCHàQK¼CEÖ{bÙ)Ù§¨Ì8çt¦€É4š­Éy'PŠ”å!+a ;¨ø£iL”ÀFñ­$0îhC|BíòŠ¢îìÖ~jrpbAð‚㦢°ÀÝñŠâ>╲Ϙ¹sIðÏ)ÓyÞÐ…XMÐ ‘ý̦Ÿ6u‹–r¦û»> $ ÿø4a# ý45eü³€ôÌ•Å'w)(.Æ*HâåÓ·7ÿs]ÿòöúå››_¾™†­ŽÚña¾ˆ¤éÐ\MÑ4ñɶž*zlg 6"Y,\™!Z£Žh8W”áZÊ ½%û‚×ÀäÒiúCYòyŠbœõ3r>÷|q§²¬m„(×Õ Óóü8α„}^ª46Ùn 6ø*e2…è|r{µ|rGڂ쌜.õðÚ|‘$9£~2W‚Ä ïk§!¯y‹¿©’»Z}ß}1ø§ ÆmdŠLÞAó!êð‹'#ƒªÿdÑ7 ûÆÍZâ¥óû\=ò]¹aÿ†Tä èŽÙ°ÿ“¯'ÀRä€Þ¾Â™k a§okàÅ ¼ˆŠ|A÷XVúó4úÀ$Úê¾nH<ôÖâtXc9fˆ@,]¦#¤[7°Î飉ÛP±‚W…3ú8 žï¼ÃIõU”fjJÁ¥¸ÒGI7^ã7o”g–¯Q¹ ß°ÔJìA„(ði ð"œœÓåÝφx”!\ æ¡×T;T¿d“ó‚g(€Ï¡jEX¼ðˆ"$Gd¤‰t°©¨[a2"UÖ5糖î ÈÎ}u³Ç‡¾+°¼Üœç¹ ˜Ý„¿=ýU–í¥(™¦ç·crKÆGÓX¯Œú•0•üø†8ú|Q˜âá;ìþŽšJˆ€AÌ=]ÍoÖ¿‡æ.  '°b|JµŠ!€3ùWú°žÞB/„§ÎND­‰ó¡åàà’3P/ÿüÓПžž©ÿ äÃ&°ˆ³()í!€Ó=̨ª¼Xç÷ü}*xáôÁc6ÜTeèÞ|&¿MثӫŸ~cïÜ9þ}á+ÙO5¥å1©.!3S7oôNÖ2EjØSÕKAåFs±—uØ#pÑÉëëTÚe¹S.$ö,ïôŽxIG!A0^~·©“3ê¢.„3T8ìl,.ØÓ^Æç\©iøE}2$5ˆ‚nu½þPîî{PSNµÒ5ÕÞ“ôˆéë÷*ˆ‰Eù)޽´˜¹Âj>P\Í Ë/ÞOyWØüF¥ wJK¼Ò5ŠÎ9ØQ‚ ]³~l³¹ðˆ›×q!V(lj6ªCɉ¨O lÒ‘GYú\ÞïTÑ~ gµž=L&™œQ2£éšÁZnHá S>ÀëŒý ñÚpªH«ÅJíPß2+×á}œ÷yY¡žR €#nÀOÿïÍ+0¬A•’±¯)/ˆZΖ¾¤k¤&©K¿ GXI”USàè Q3ÈᨙTŠ‘*^–¼®?ð U¼`ôk2/AL|V£e“j™KÛ—õµt éfø®8Ù{/q?q¹0¼!I / ó ³‡ƒcZ¯œ4ë{ð‹}ô1Ñ7¸%¤3QâÀãß ¼m’ßXõˆn ïÑvM$ ^êD´YŠD¦sÙ¦ÙëB¤Í*|èvâÊ“-Ã;ÂÅzd«D¨-Q~™«v9Íž_ÿÃÓ·×ϑ݋°©×ë x—ëçî)1âø£K¸l¿» 4÷Äeeå<ûe³3Éh#V_bc-¡‘–öGîúü_žW~q65µ:ñ\q,þPKò lHBxƬÚD setuptools/command/bdist_egg.pycµ\[l×y>3»\r—¤H‘âMsD‰æÒ6Wòj*;‰eQv”¸´=”M{ce4Ü™%‡ÜÝYÎJ¤L­™6nš8nƒ>%èCÛ EQ @‘E¤I EŸúT¤A‹<(Ü ‚ Hÿï?çÌîÊNÑ¡DŽÎœ9s®ÿåû/£Ü—®üÙÛ¯Ö„þÓG¿ÏÒ¯ü'Kˆ@ˆ*]-Ø¢a‰¦-ª¶°pŸœhæE5/š}¢Ú§jó¢QÍ~QíW÷}¢1 šEQ-ªû‚h”Dµ$tyPTMyHT‡LyXT‡¹Ü/'DsDTGDsTTGE󤨞T} ð³1QS÷EÑÍS¢zJÝ—DcB4'EuRÝŠÆ”hN‹ê´°ö/p÷C¢1#š§Eõ´hžÕ3ÔpX|–Ö|V¬µ.‹|xNl—D²dÑ´?!‰æ¬¨ÎfíGtû–%^FùÆÁI.œÁ˜§E^GÍ‘oTçDxAl]Á)±5ª#KTÁ¿³ ‚I.”E0Å…EÙ"˜á#âJ0#ÂGÅ•êc"8Í—Dp† œåÂ%œÁC"˜#6è„.‹à<~¨ƒ`NÄg©òqlôjù"Nú .aºÛNã¸!+µ¸Ùô[Ae=ˆdê…¥Òs»Q#p*TvP™Dë»i·dô#úS&Bé8]–é=hÈUôv#Iâ¤lãá ]’°ß ½4 ô@÷Íí¶Ÿnª—stiÄêf€.×ã ¼µßWÊx”ŽÑe#L½uÌÃk7ü´'ÍtHi擎REØ’»IèQÖÒ8ÙW–èr£•&û/ÇQ+íÔ­û2D-=x?]^ŒÖß¼ØÏ³áQkÐsÁ쳉µ÷Ó͸åÝ IóȘ /\Çîb¨”9‰N{•;Zá®Û4×F´Îc¹XOYô\$^çe_âó¨4ýZ,÷–¿\yüòÒÞG®xWžºDçr©s€—ô^ʰBÓCßOU8Î1a©uè] 5q‡©êÇ®%ÕkÁÌW¸ ÛŸB€<ï7dxL+qG¨ŸsÙ×0«{‚7ïôÛ‘Ìc²[–زQsIJlæPˆ–ÀýV²Œj“k¸% ædÏVË}|Nè¼a0E¸q°Û£‚ôó¨ÄÀ±LQf¢…Èv#Jý”oÂV ïE†ØQSaËo†ÇtР趧&zÞœ™°†¬kĶj˜1¦Ûo¶ì9u¦´MŠDi³H2Ú`ÍÞ²#[|iZÒmNlåÅïæ$5µÖHK¼òz€ý³®H—–YrôŸ ¬;ž·Ç)MÊo{^yñjö6ñºßèmóÝ6b?UÆvy^ÏkQ³'©#÷åcN{{ÃKBï&µnéQOSó¾óÑÞ–Sò²ãð<üƒAç“Å:1¢nVâVø4-íÿ˜öƒ“­àìSÿQ­3Ž™[g°6+«g2¼Ç$É$êºG˜&ƒ0[)|øLq›*ñ½„ˆQë‹bµnnßÞÇ ˜ý=ßë^6!aC°~ Z23âñÑõÓga`ijÒ"Æ1/dòM@¦òOÀQ¤é,†'6ë»<°i´0º¬çXÿHñ“¢ŸB•5¸Q\Á³QŒœ¨ ¨¡<ûµ¢®@=£P4йdó QÌCÐÊ(V™á £–GŒZ5jù¤pWËs˜þYÕ$¤ vü–3GKœëUª%³ü%ÒaåSX—ó‰ƒæI39™rsH:Üi0'Ý ?ØÎr Ô¦ºj˧u%T¨ƒN;as= œ¨ål„­0¡ÉŽa 锉‰ýÝFzÕ™—‹òö¯ÖØ Â%EGKh*å£ÂhyÇo4:jîC:õ$nòä:Ó²%Îy; ÛKXOn[^Òuܼ-ÃÝ ^ŠZ2¥},É~pü$ÞmŽ_OÃÄ‘çÍŽ~ØPÛÚft7äÑzw5K\gö’¶¡½›Òœ[$@èiïnÒöðŽÊí¨½ÄŒ ŸÐ·Nrf ŠbÇ“À ›K5ÙØ ÒâU.+Ï2[+1/gjò¦¦ÏÔL¡_°f`ÁªªÌ2,aÕÅS´^¾ °JÍ90糀Țå*äÅ·tr^¼›ÒN¥]”àuIR©ôÆ–aã8$`WÔŠÒÈoD÷C/nóù¬`ˆ,IŠ]y·{´Ýÿ¥û ËZzë NðlƒhoDòó‚Íê±ucAlõ‹­(C€[Ÿ–FEóî æ‘:§¢y:ˆ®HbÑ[î‡Lëÿé0Ê8Xé_Ga[ÕÅÖI±5†rü7z˜£šA_çºæDÆ¡¬I0Né© ap¦“~6ú8£V=f=Á›ÌhœªÝ ö àϤ%»‰£ç¦ ZH'„ÂÌBt2§5Myµfà>EE²Â}DÎÝ‹»èÇ0ô³EhÝ} U}¦¢ ˜?¤1¨}ôîe´)‡E1iê ÌÑ2BêfìˆrÓ—iT š$/ž5¦ w?‚ËÏ›þ1Óc‚oÀÐfûÌêÖŒÞÖ¤5dCIž¡ëˆ=järtW°Îç˜Ì ú—ÉüŽeÈü  Úy êÂëBf޲DéG1‘‘ÖɨC[ßñîý5ˆ}ùö·˜ÖJ /Úc"¯$oѾä4ÀÞV5ªûa&ܘÌÎj ]µ‡ùΜò< *ôô©'ù=”' Ù4õdYÔƒò¬ L͢Ǽ˜©Û˜ÞŽeíä-Ín¼š­Q=Ckç5±vÿq‘2/‡¨mb8«‡8“ÀM/ÇY6ã܃®½P·(Œ)§ÕTFaáDä¹®G¤Ú~mÛß å§>4μdzÔ-?*ÊcM4¨pŸ3jSùÌk@ Ï€pÏOZ@í S$‰yFtÙÑpÍ8Ê™ÅNÂ)1—õßxá…¥›+Ï¿ÄrOÖào’rºwNºZcœ‘.À¢Ÿô€›}¬ä½°­€^iÑd8²’î¥Ò¸Ž0õ é{/•h^’YA=äû (QïîÑýÚ5wåæÊ W…®' ¤f §§ÎzèìJÒDëûNG;—+WΗ^•!;ÌŒ“pg7JBy‰¬†„Œ}¯Þ+/²¶âÆ¡Tx£ÈYÉÄyÃ@$²5BÆ äŒ¹óÐl"ÝÆgã¾Òþ\ø·H)4g¬—š§È •–duÁO`ÛhLÀó•lú‡­Ý&{e:(ÒÄå*.3¸¼lÔ¥‹€‘û¬Ñ‚IØnøµÐ}Ih³j}?e Ú¦µ¸7Ѷ‹ËÑ`ÞÔâö¾GŠÒg šÆ.ºrAÝî¬Ð„ZƒvŠqe$Ù?‰ân‹(k;=)2ÿ¡_Ó}¯Þð7˜®ïGmUÇææíªd~áÝÑ»ìGeÜ÷Ûžr}*Þô·CÞG²&· m„-o3'¸p¹Y\ˆöÕOÓ„­ÊòÉ|€ƒ'À³"8ëÄ»¾ôcƒMÔ®ÃáðJœmâ‚áY´¾pÁgÊFßKÝófçµ›K ô”™ºb5æ®Á^vâ£Géî€hNá§ßBŸ÷^ɲFØ%3cZVÑ£rî¦éo‰êNÒýYB3çìÝ Yù"µ¦Ò=³J„y&è ´+Q_“ôl”êq?N2w6w‘ž–òEzsšžÒH¹ +³Œû 6ú5Ñî°övÆÑð$o怈Ù”ÜsŠ—o’Qmž1“ÒO‚\·ØéäËH˜ÐMÊF"á* (¡>à&o¬'ý¬íœk,×ÙIÇÞS׈¯}§ôüfR纇(±W.õˆ -îÛ8%C€•»Xýªa9öOºwE†¹ÁÛÁ8}”qÊl“gŠ"ŠœÇè{‹úùg‘ùô†­Yú!UGj¢XYÐ/íòt¬P¦…g­ˆH •W•£AÎE)¬ˆé¨tË…¶OuÉR†•ÍûiÇoùýûØsÍy¤|[)˲R©°óÕýE#¢•°æ3¹Ÿ‰~?ì ÌMFÍ6Ãþbiÿ!²¨à±WÞ˜¥î==o6Qö 1G{B³Œ¶x'#FZCÂf¨rg>aæbA É7ØÄìI Ê„ãÅFz`ÞÛ¼“$–\ ÂÑæè XŽ ‚òªíâ2ý2ÈrØbp‡iŽr‹~}Òˆ*oèÁ&+7­OuZ”W ÌÈPÅÌE™a`áfÊ B‚›«eHß•”O¬Õ•IѸ`!¨GXÛMýu’ì§Ñø…jI NY Ny>Ytj~ D·é‰-(¬±à KÂ:A3BW¾£#ÒL`ìçÉ|‚NïÂùKëQë’Ü,EuçÓÎã¸t.^¾ã|Ô™›/›šE9çÜ.Ài9á^XsTÀ|¹½O°eQ:K5g®;æ˧Q¨Àµ„…†IZ¾ŒjUã¯KNïX¸xyaqñi%ƨ·í êK÷£_Ô‘ºNËóåún£±(Ë‹‹sÎÜÅgçJaC†%Ç k›1MÚ‰$³ €X-N U‹-›ô9*OóÒËF¡íâva<¿¶Í¨´kíÜØxÃZü.6¡Ž<†R=*)ÌñËп.GW8Œâ'2ôš~[1>e¡ÇG¨üY„”¯²ˆAj€‚ÃJSúœvÁàD8«YL¨£UŠÿj¯à~Vh’ ûÆ5š¬i,EîˆnPå‚@•nx"Ãí&#è°Íã“ætJ,pîÍX<ŒÆAŽGâR?ÿ…aÉt†þ’l²Ç­ýÍ “B‡³c"—,ÙEkŽït>CëûËBô¤}lÁ¤+9‚L©÷u¡œWJ‘/ß~Åèùí0N®v½Ézž_=šÕ¿dÔ»òuP­ûw® úY ŒnáÅ]' ì ì”Aµp˜.‚0AÜ)™!7kYa)ó!n^öì>eô8‡)²“í¬û%T#2澈K¿¡[á ý:Êž¡g60;g1†—ň8_€O´§fQÈ^8bÔÏ9˨ÿü)ªIRÿ³„üXU=²Þ穞$‹¯6|ïÚ_)Äñïi'‰ªbŒ÷c<öFÁõ xm–o? å¶*ϥߤ yñ’‘Ttƒ•_?»Jób†ZM1²»!ègmïIœýòíGÑUWRSˆ˜¨Î˜Ft<³óáÁKbMù×¶8\˜ü’&%åd#-¶÷Uh!Ò„Ë·ß…b‚Ǭ¿0kç}.°&,MX⚓⠤£~L¯ >&\ù¾ytªkŠ*~Ôo|%û–Ràê]kg£ÒÏZKh×otÂ×èòB˜’‚%:q„pƒ-dË®ë$h 5I_gÚW–нÇLþìpC»Ê¥A/2K]á‘S<ôvŒY–pøI8j+×nÝ|í†wãõ[7VVo¾´²ªL\æ!Fl&ÔRR’ZÏÑý$0£ŒŠŽe IÉ2ú½<ÑYJ\3#îƒU ×¹¿ŒËÛf޼3J辋 óïtïÊEý•ŒÓõÐÇÀt¦bÈÝæ VÁ%¡;L¿d¥ÙKˆA!›kŒ®g¬‹Öi[ɸÞ$÷aÔýT9,*ôÇ&¬ü¤Y'ª»žd—S~â\ÎB; !+?eFHyÌ§É cºót8šn•7KÙóˆds8‚A4Ã.á/-f—Ï:jè·²øø“h†T™×…ö¹ŸÇ–›¬YòòáW 'œ\`.6°ˆ¬r‚ô;Lzü[ ß~. «˜É‹ÅéâL1W,_¡rq¡8ÄôP pÞ2v*Á~#ZÇÑ™­ÏQ ±)ºŒe¸¤¶JAþ38T©59îÏrŽcÎøZ*ìËb¼ž¯Y{ãx}ùö ŽR¿fí¼Ú­ßÁék$}ßµÛBdS‘Þ‚ÌlÄÇÐHÛ|:æ}·›uE%"°öÿC#ßZÈ.-dÄÏ"—á#´5ÔwA A‚k½â„1Þzp ‰9.¢S73m°q9j0 ­Ø­³ÿ.{ÏéÃ9Bò)Žïð‰¤¶ÖÀºÀ†º:£#Ɇq,«;Ãb–J¯’¦õ¯Ñiî½ËMkú_â“f5O p¯õµ|» åXÒîù–¹U#|Mì¼…]ÉjX~ÛܲÒLÞ‚9Oã 4Àd•ñwA+4 õúÚNHš=¯ÕâJÏÑfnœ¼ú÷ž)ÔL!fè§Òz;îNå‡A€\v™ûF‰±(!ËÑ“tqOš¹•ì†|Fìb™‚ZÊp.ƒûçB;#” ×*N®ÞrOÐLï€ø Lttšéh†4Ë ˆ< ø¢²î i3M}4õ§Ý4õBS8¯œÿúR‡¾c†³Ãx_ÁÙ²*¥3Ù:@¿ãÖ¿p[]ªFYCÉÃ&b¨€ÀìgRNYUpÑÒ7ùNƆú~Œ™ý»¾Ê kDl¿Úbw?ü÷*ä舯ÙÚ–òg›/5*²Noig¶/·ÙnðwÓ͘ƒQ‹mcÇwLÀj*¶©ËaÄbð¡þ]|ϼÊïã92•T„r kzî6ªÿ—Åî÷_²Ie6¼’Þ<ï÷MG?39N¤%¾žòCöYkÜ+NÓnN[³´«Ã6®å,qÊó‚¸FÀš:0ÌW Áy:T:Öó„èÀC‰³²x÷ÓbwõAãèý6UÞ¨6uH ¬†ý=Ÿ++«BNPã/@kïÿ•@"…‘ g’w=Êb*ZPêyꚉÊ}I¨§mð×ÿœJÆ_j0¥Ýä@9‹þ:ËRYzœ›תû]\þÁ,œ¿Ewÿuìûs…­s¥Ë9q훸â2VbõëVq9Ǧä™ZŸQrÿc¬¤ñ­b “ÏÿʼndFÕ_;gOÚÃö0êá|q xbòGbt"W,އá4.å‹sÅ¡âÐX¾hý/PKƒ,ÒFëÒt>äsetuptools/command/bdist_rpm.pySËnÛ0¼ë+* ɨE4IOzè-ÒcQ´´–‰R¤ÀG#È¿w©ÙN`^DqgwfgIÑvÚ8¨…uÞ iY¥Û–«šíÂQiº¸mD“$I%¹µ#y8žëm´Ò4í¿?ŸÐQ#¸B{sa‡þ$´§¡Ö=h¯¥ÔG¡šmÒW¸cðè`Ó”Bíu@¢²Þ %oH)Z§@gt‡Fž â²ò’;¬Y_ëžÁwyä' †JfBYÇ¥ÌÀ[⃢‰ÅX«Àg‡FâT¼ÁšØûB´¨¾“„Y ýè 4bGjeÊ’äµÏíŽÂÀ«š(*MZ)3ô1ÉW¾ÝÑ–\0dŽ#þPx⤱t܉ÂX4ºß¹¡«Ü¢ÜCëÓäV¯M† ¾+œ.jò&BC&£å8ý<›LÏÖID-ÇÍ"嬢lù?,m‡U¹ÏM­~ßzÆtåÏ×1ƒxæ¤qÇÌàjžÙ²2›á™€gB¯ªŠ9R(¼ ¬lE-ÐO”™Áçi¿D}=Ë=—ô'LUb‹H?ØßÚ› ¿laõ†öZ¬^Ʋ¯Ìq“nnJñŠFI—º.É‹Üõ*,:ß±îãck¼ [žÒíV}ýkÄC õaÇï1 Cߌã\/Pá†óð@ÃôbðoÜQ³h\)umÀ0Aïú9ËÑM¸‹Ø Q”’N—ç2˜^¹t#CàÌgêÍeö›‡Cî˜QÿPKò lH6b¾† setuptools/command/bdist_rpm.pycµTOÛDÛYg7¥j)‚Jp`8,uvvÛ²BUUñOÜXP"¬ÖÄ3ÉN{ŒgÜݨɥÛoʼnÏÄ€÷žlQ+ÄzãÙ7óÞû½¿qôçÍÑÉï/~,XÿDð~¯Ã"á0ÃØ2`ËEL†LE(Ï&#ö’±+Æ~: Ñnš ÀGÿÏ©?q&µóyS—;ôÞ¯â; 0FçX]l2M0؈Ãóý3Õ4Z*îÏ—j.Zãù.Ÿ©sñLÛ†{Ë¥%£¹5Æ^èjñxDÇŸ´W‹E®«¹EKU¹¶é +Q*.*É!ŽÓ¶âuckÕ˜/„)Z#¼’a=Èø—æB¬oòž®œÆÜã­ƒxùá;<óžµ¼]ò!¤¯j# (_¸s~¡ý9o+ ! ¹‚'Ö±M¿jˈЅšã!>oc¶¬…×3m´_uøEÐO(„÷kìý'°¬aúDƒ«€žx°Œð÷0¼i‚æ§~'Úw–ˆàoÀÍÉ!Ô,=ÚF/&ÈuÚ’Ê)3OPE‹Ãf­6rL3ÎJQXw™eÇGéåç'ùÉ£1Ä;åÛÚ[kܸ4Þ‘"«W„¾…€(°ðfHe"=÷¶eþ±+x|ÞlM…BÕÀÇ«mBLx9`˽¾ôM„ü³»›I!H{lHûæç'l³uL  ßC”c&‡[yŸÉƒ^^Øšl~ Ùo§(˘!‡`™¼ÑÅÛ'å­á·Nì§É;4,.¥5w·a=„›¢«kV¸ápjÛ¦PGùásdý&=|Þë7™»ÿf›¶‚ö«eþëwix0h7ï/wŸ½éô¿Ü cÚäê>݉<­þ5%»_©ø5ž G=öéÕÛE<](¿5óCdfwÑ&ÈÒŽ¯È¡¼¿ªÜÕªÈçÚ( Òp/}L’SOZÔÐt„ u¹Ýᇠ¤ûàáµøˆÔ(’[‡›lõku½…Kƒ-y? ¯ö­àü‚Q¾ ßévP‰ØÑ<DZä9%›ç¥•­Áí¶ÒyN·P¯“ý3F0j*v1>ˆÃƒ¸û }Ôfm\Öûf;_ʲ?%ù[Ê’Úõ¤kÐS",~;ïDPKƒ,ÒF Œu}#setuptools/command/bdist_wininst.pyuQÁnƒ0 ½ó¨„B·ÓV©×wÙî(@ ÖB‚âDU÷õKPšÂÆrrì÷žýlœfm,ôHÖY”Ä:=M\õ¬ ©æŠ YàÚà˜eY'9lªe(m ‡Sþõb#|Ê"—ø-š¨^’CñWELC®):£Dxyž§øÃͳ“PvW¬†«6_ÀvªO´‹µó©®[7›oö¢Óf¬‘ȉçãËÓën³nêá aXÜlý’X–Øu-ÚÙ0`Ÿ±al»9ÿ‚‹Y@øiÐÙ]øcU —m. ¯ê9äî@W2)¼»+žXŠú>QF8qgwõ‡¿?½‰Çäô¹f‡Ìg}o[$Úá¼L Á¹íºE¡³ZáÒ¥Íaïh=<7h˜!Ña½£-¯§MçaÛ)6èð:¦¾rø¸÷Iº,½Úæå5ËP—Ÿø¿PKƒ,ÒFôü´€“ ¼.setuptools/command/build_ext.pyíkoÛFò»~ÅFF@êB³iûáÜCš´×AR¤Åµ× VäJb¼"îʶîpÿýfö½KJ²ûù'–óÚ™Ùy-WC¿%M+ä^¶\”u¿ÝÒ®)—û–7{”¤ÝîúA¿@©š}åf«˜Äªå¬Â¯µîw‡ WSȸí`}°{¨ìZ ,¢î»U»vd÷BöÛößì( †~þ]ÿ—X ÄûõÌ|í…ý¬í×V²Aö=3M@0¹ß©…TÁ:Ñö¥õ¡]t8Ìfr8\Í|.È)Ùv'‰ìÉ^0òö 7€°ê­à¶[GG¤]zO[N— =¤ ˜j¬Òm蜵¼©ØcÍ€û{¥ô ó ä:±n(ýÏZÜoÊ¿ø»ëoËo¼T#Uo?}üñý?ª¾ùüËQÎ笼f²Ò+Õ=f '^ËçÞýòÓ›Ï?¼›/PÈ-½cDìF 00üu­l)—i†ñ”þSDŠÈ¢~Ã}Î6ôžUƒä hòGÊ›¡+ ¶n…·KyØ1ø‰ X“Íf`jàTî8•à[r}Mæ Ún®5’ùuسã€Ó‹²£[F^­NfÔ™ ?Fꆻ•R(î† *å7¼ Ùç_?¼«>~ú-[(¼cöÃÏŽ 8°ƒªá@†Óí²¡D\ì90Ø;É`¯5 魯w·Å•±ÌŠ û.Œ¯žÑ|>ÿ!ƒ3FÕ„Àb«e? "7¬Saù_^¶hµf€í(õÀÎ,¹”æÈþ,Èk‡ã¥,lîaB# ï ± —ý®º ”~k•ì+Ñ務SËq DYZZÐÙzúªí´ÿW&Ðç™Ëü^0©`ÒiLÏ-zµç\9_À`+»ž£ªðË"FƒX=‰fÖs‹£mûfGå°ìóRìx+ó¬ÌbÈ­ïèZ¯2+¿ôm—䛫˯o'+p@°ÚPBró=Æm˜ðb£ÕáüÍ2À."¬“KbI…Q†!¿ˆY‹¡>ÊYiUï"Mán¼È~ ñzÊ¥ ÂîáÐ`RÞ„ñ¼r³ÜÐNí|G‚˜¼À Â&äRâÙ#C»ÞÈð¢Gáƒz? ¬“&‘|å‚Ñ‚Քњ+#ò‘6Ce±U rφe/صҊù16H3*8ÕÊüˆ€bõƒžÐ¹«Ž±F¨`z5– I= P2(€Ð!0}‚É@èHªP1=8ç£Sä çûÁAÜ Qçððärpâ«-ÝÅ{ÒÕAøüÆ"Þ¦ÊiEÛ I»ZÂÖB‹±–V]a([V§Ó‚÷Ûi€²k0²Š 8¹«K®9ј„RùÓçBˆ†Ú¦¼íîT\m@ ­Ç27 Ç.•ø¼¸Ñ!YÃ/3ò hyjiyðÅKÕïðŠ4àÆ?§«Xs°Ÿ}Ç&@°N¸¹€'ÿù¯Òæ—'ˆ8 :bb#ÈõhŽP*T½aõ]˜9Tqy‚8¥µCôÂã©ïX?áì·á ˜M¤~ÕGT±Aòçgdå¿x(«gæå?‘òc^ã-b„ÆIsoÁ¾-¿&-çjä ë;%dî=g)ˆõ÷ß'*çô¤éª¬Íy[Kñ÷óõà Ô“rÙX5OÁ8¡~§qÕº@·ÔE~HE90’Bä8ät½<ê@cÛ¦<5Ù1œÏK‘8o/´ ±aÿhCM6®Á/þ´bd”P­~ ]¥˜N‰hc:,‹q4N!JºÛ1(m5£lb3¸lò…@¶[Vç?iåp¤ƒì>yÞ“`æépŽKâ¢È®^›¾Bÿ*&«œYmê#õÕ‘ŠŠ„ÓÝ©ýÈ-æ„°%VmM›!jPíGèŸß½ ä=œè.“ª{A'×0 §A©jIh%¡jÔ¥fY–#j¡7™dxÈÇ$~æëº&—¿ñâò‘\šã '—û,Öv ZL½Zñ¾¿ÛïæãD3}û6`:‰ÎÏ`þòIã”Íaz<ûÊ헴ׂ,Ë'”[ˆ3:ä§·Sîw •,{@ìècÚ'%åö«ù¾Q%±šÐàÙÃ"äjÒ›1KV!J>"²±Ð¶;NüÊ0’]‰ (%X9~ErÕDÜSÅ93Ë“,„)*7†²)TSkÞíF@Fª‡>"1ÚƒòÀã[Pi©8Þ ákëÒ†¹úÌV³–=Õ4>ÑQ><Çî!J>"2f1¨aÁÓhOEïÜS™’¿»«úå…Æ“å÷(ùˆHp6. æÕwІûÒ(ó³2]•å ½¢=U M°„`Ô×AG|ôœÑ°Ãªa´XV&þ*=¯¾ÅÑ_%ÛeÏ…i'ýÈΨçiŸér0sÆdÓ>hÔБÁ‹šjjJNUö@¥xÏ€Øîðh&hª°â´[¡°J³°»l°£\ö¬ö7¢9é#œ@!ÇwúìQE½mÈSÇ„¾˜;;ñ²‰@“ù(Õß¹³ê¨Öž2ë|>ÿ¬ÝF{†Ï ÓÈØ$P›ÁñÐ`°Ä™”ÀÊ×Ìf±.G䎷Øô{ÞÕ^úé—ÂV„àÖr#K†w8¨"™P¢Âr/\áÿ²%¢ˆ¹¯‘Ä媇ðŒc+u™±&”À³d[_-9P2©v TÙ@+Tâ…Æ;ˆüž„ý!&£‰ Ã ¤»»u8E[¾°}¹*yEn²ìv4Ë€ê-GB¯¬`ÈÏÉhd°ë¾˜W‰#Š@ý^îör4T˜0ðVÔ!NUý `2õ8avvl»äÚü8¦%N—ŒÖ?öÔóPuìÀºHÕQé„j°[Œ Ò“íÓ_ŽÚ )üž6ȇ‰âÿŽGkv§6¬:mܾ£ê=†bJ¿ö¥ån€¾–y¸ç"4‡Öt0¶É#RƒÅÇevRƒ …ù U¼Gæ“OLzhà6±VûE›ýχH¬$±Žãœ'Úg^Ê ^ê fö“asЯÕ\!œ÷k(~W}>GDTÃÏ{Šs{TÐKö^Šy‘Œk&n$<Û`BôÔ4òËPÈ>I^MÏÍ”¶£ºÊlÒ6ãŠ{³ƒ½¬iA[pˆø^߃§Ì åÔD¢)½ ?C§8 ãL²rI€9lŒ“"ÐÏ{É’›'“ýÆ föGgbèÍtó©ýuÙ÷RÈî  [\ͧïæðoÍû%å1F?Õ,G}Ó^PU'ˆø×Àéàéj`¦*ðñ”¨®usð †ÏljYÞ ¦ˆNi¿¹qÒ¸U4òJyHÿrXLü_Ŭòáe¤®SŠÊÁk0ÃØ¢.N[…8>g´otJôEôŠÓµšpÆ–†£Ÿ©Å|qJåˆë&p€X?4€p+Õ“Òã¤jƒ·éDÏwqŒ¼ßQÛñ6^Ú÷ NîHùd‰Ês…žó 'É-ØòòÏIélqFF¯&m€£%úØ\]ž²a‹Ò“?ºTreÆœš÷‚åSÑ4 añ‹-á;Z˃t›x>Éo\ð»-ˆMrׯOÜoëÙ"ÞmNOã½X’gšÕ\A¶Š(H¶iaãˆ}G^[ž'ìË~9s}ÿ¼-êwv¦Ó›ë ާ!¥%°]‡MM€ªÞ¿ fÚú‚YOõÃWƒ.ˆ~ƒF·þÄ•ÚúaÔoÅã8§™JE/\Ébêø°„¹Æ±Háùèß­pêbÀ§2æQ<˜ ×°å~ >‰Ï@«ÃÚc«µüÇ/ê _Ì› ‡€8¾¡ÝZ= j7Åë¦Ô“ßêÃûï?¿ùü¯ãªŠÝ?(ªœÆŠHAÓº‰ÉÄ**´F}¤ªˆ)x¡‚ÞÀO~G©®ÔË/” ‡‡ ƒN™Ù ±ðÍ7ŸÍþïsÏñ9sëÉT_©f­º°±°W#RB=è‡`:ˆó¨ÀÐ$èÐ}E—˜”¥T=<ý–É ´áõÊEªÖç©2 3¥Ô'ë/ “hÒg/lÔñ=^ç8¨AøÚÙ¿úÚôLà¾Ï¨?ŽTx0'ÞºÒ Oì>êÛZõ﹤srw;œ/JT„Ø„ç™JéT펨gt¹jÿ¦YðwÇ÷Íú _ôÂÁ—½ÑƒÔ‘Þ¯SÐÒjÅÔ[šL$̾ðµ9óõæÛ«ÛYk°¥êoñ´£r’a‡=Î^K¡²M蚎AÿPKò lH™L ´+ setuptools/command/build_ext.pycµZ_l$GZÿjzfì{l¯ÿ½»Ùô&Ùdö²öæàIXÂí­“» ° íÜnΰ׌§Ûã±{ºg»ÛYO°Ü®.á÷Èÿ¤"OœN: !xB ñ¼ƒ<Á÷ûªªg&»ÀËÚv—««¾úªê«ïµóoú«ùovÈüÌðóU~²õQÀŠ"¢¾¢)¼—(r¨_¦²~w(ªP¿J;Uý^¦hŠúÓ´3­ß+Õ¨_§º~¯R4CýYÚ™ÕïS5h§A¦>G;s¶>O;óRŸ¦húçhç©á²]Ö¢,k‰ÔݸIåp™ë”þˆ”Ra í±¢ t¢ê¯ÒÎ* ß, WXVQ—U7i§I*lR0C©_hÊèYé\“Ñ@®ÓÎyBy^üE çèà æè°DéM^BWü… :x–‚y:t(ýž>o·æÒŽKáe ] èa‰Ê<€‘Þ½ÿ=e÷],Žß?ŒyÌ9zD´ó‹.Ñž¢` -‰¾µ£(¼@ÙÕh6^Å¿*žgâoyòu…ñ©¼@ñ«ØÄÿß4ð\ßn­1‹ôþ›ZŠky‹Ý£^øáq>jê$ƒ¡¿×‹BÝ4ËE>ð;IÀ©n]àQ–'ýÞÇáúæ¸ØêeùQÞ‹²·Ò41íQÒ½­ß¦¸x··›¶Óáh"ÿÖ{·ß~çëþ›ÞöY7ÌyŠx¯×õ?j§ù4Fnmã¦÷ÖÖØÐD–W! ûí4 ¤´Ó½8/a+¹Œ÷>xwË¿ýÞÝÆÛçFaœ(­Ó Ñ6³ìv ãnç´•öÛ…~šGnB‘µEvËÒöúnÀ¤Øì·;Iv¼ñåW6¿üÊÆñk¯ú¯~åzØí^ÏÂüh'I”]g"öÛ1°G²9ÊZoDíþnÐ~óe vE!üXÝ×Ðõ«\„Ìo ü Æ+AâPq P)CôQ©@æQ©BØQ™‚”£2 fA¥F¥YDe2‡Ê,„ •¤ˆeí‘‚Øó¡5°4e–U²D…rbrˆ(*¼øB¶ƒêÛÛÊ•ô†€;‹Ûn²ŸÂnA!—)ÆY/‰3·»B57è¥a'OÒá57ßc¼ìööÜ^<ˆÚ°ŠÝn•-šæ¼*(/¬šÅùº•‡Ñd~žøYr”vBየ²0ÚË¡„oP>}fðVÏ&ÖåÜ—TCÕTU ¹Ñ4mÉý_ãäfÚ2ÁÿYZmÝû':¢ƒô%!2C8ÒR¦ý*•ƒ W©Té¤rÑTÅ9LÑIU ¦ˆyõ &@Ee¨Œ^V•§Óc<ÓŒtq{ â{R£“i°$º`ITæ ¤°ÆyJ×¥iØÿ"¸Îaù¬‰:¤î¯ÿÝeÆßnUE\§ íÆb mŠê“Sÿ(Lw¦6êA:ôù¨[K8Ì£mözq;bÍøæ „AFL/@nò÷Ž¢(n÷Ca©Lô²b”Æ Nfõr;HX!͸A»sØî†>³¯(©$˜A;ß×ûhgÇHeG½]»ò. ¸ˆÅƒý8 ƒÌgå»+K~öòP¿VEe§˜È?HÂ@¼&Šu«¡Áþ˜³Ø•¼ØM€bý$•MÉeå2÷ø. ‚0Û>tt–vІ3UÆó*^Z5¯Ô"—ój‰ŸYµ¢Ö*·ÔK5Õ™A‘²•™?Õzÿ@´Ð‰æÙi¥Ä’rX¥ôO¬Ô(Zgar±äÂÆé>ñ3oC"Df~±)2r%œÏ ÏgÂÀÛL. c ›EÅŒlŒ¬`°iŸ±SßÄhÖ‡'%k–2œYm´ÀKÞ2ŠËV¹ýúí0B/ë1Û¶ãNèaÛÞ/rÚò%NÖ/Ûgæ*lº0s¤ µ?Áܘš)2ÍeY~\õâCÑ”ÁÁ{ï9L÷wÔûy¯YÑɆ™ áØ(ç%ö=°¦XBÄWžc—߉Bñ1ÃÑ hçÚoìÅè(Ï2ó¾jµ ?Þ£C}Ù•ŒÒUö€:i"¸eÏââØÝ›ÎZ¡)zì³6 î¢ÅûÙñ)'T Ц⠯™î')£ŠâC?Ù=à5C6Ö¸h¡tê´‹vó}Ä þ˜÷ô¾¥lÞhU‹µ|ÔŽŽt¨!;;µ´Åx~ßµTUWJp®§®ð;Wª«s¥zIœîÒªjоlœðâq:6?àX%š\\ï\¼ïtUDî²#‘©uË­Ÿ…]Ž,’œkxQ´W‚•ý.™dÊÖCßÞÎà­{¼4vsŽÖ‘Èz‰wñ’+~“›'nÛjoJ½#ëåfì¹&y~Î¥ÈÌa_?Ž9à©ñ–î­ÀáþT¬LóSB¸{GÝwÆÃ9 Iy¡Ø|ÅÆ€ÌKûô¨!“vŸêáe`’Ý0fYNßü0ë8¾5m­IÀ^¤NY¤Iÿ0fâ©zo‘‰?µó‰Åµã¡çcOÎ$#:z£ýzHºzùÓd·Ï_º¡ÒR/>!üll§£0l5í‘8…ÐÍ%—åƒ#6%µQ>S[‰Ï-Ä™†™CÆóC{:¤·æŒ=Žƒ7" Üÿ©$+·tªÒd…•´J Xçbø|u›¥®‰o ¶®X¶¾aØúÇÈ„‡l¦ƒ™q~JVJµ£+ôý exÞæüExnëh@4XqŒ¢ ÍYϼrßòÑ|6"ðWÀ ¶¯²› s6)Üð‘•KÔ|¢p;v"IH:j2ÆýÐSç’Éüí˜0‹a—H ½œí°è„cšG,â—ŸÀàšµÇ‚VÙבŒëû¬La‡Ú…´öÑı=µ;d–Ÿ ?"›‡qf9Ž[›Ô¸Þ‘àJæû;Êdô%AÏJ!}¦ãŽ\1:â–õÿŽ˜tû–h…r‰¨xg© òf±ýÇÎçï ¨ ÿ.ªІe«ÿ¼HE¹Z3 寽ƒŠaé¹ Ð÷,ÉL¦¦Îפ{d@§ÌuZ¦QÊb¿#.È[c¬r¹¶$Sƒø°‚¸•£]˜s v¹³àX—Ç6ƒ‹^ò·¸´P´Ìâ’9˜Àyñp,J‹„‘¸«]‘×Uyå`q‚uê.ÒCWãšì¶ò¹ ÎSpÁܬŸVIÒGexÁE ž¡àÞàY³›‡¬L,ë Û,ã¦æd  ‡eJmb<ÚÓcôû\éîY®¡oÅt¨ûŸìxYØÑ%}Ñ‹».¸ß’v¦.‡€îqa®d¢f Æ…ÎrÛQ¶ƒ¡3çe—Ý÷9*ÌB7£07%Gü “k/qã8˜s}7IØò¥íÇIWßÈ „]×íFÉn;šì¾Æ¯’G’š^’ïgWôˆ^‚Ëë57ᇽ? ÿ{ Ý"O×Ü ’ ˆ‡XtîOOBoÚÚèÚ×äÏ|%½*‹çἯÉ ݰöøF | žÞO†®h ·ÀPìäy݃ëȽ¨ÝÍx]¼M Ja,­«ÙÚŽãT†J¨ó àÎ)Ý™§Ã7DÉD ÐÙG‹+ˆ{7MÞ­eIpõjö‚ÆœÙäœA´iïÞ¯Ž°2M7±x›Q©@›Íh`IYF¼¤çþYŠ_ÍV_¹ÞíÕl^4ÓÛˆ—<ö¬Åî0/>qð°É%²Îoor»Eû[˜Ò«X;Ú‹÷í%|Á}O ær¯\ ,‹nc±Mr…'µÞžDÞKûù\d"ö ì'›(½Ovͪ{Y·N«ÄˆÄaÖYU£™™*ÚÆÑ›‹ †èÊAˆèíiäÎÄ^Hpø÷@ø¾ÄÍ—øÁEMߪ ¾Ž£Ê)-IÍ‘nô_— §Á ¥E¹œågI]T­kû,‡é¬²ßg·|&—ìr“(9g¹1‘T¬$>$¨—R\xqt½Qü Н“ nélhd8  *³ªjÓµÕÚl­Z{¦ÖªUjZ­æÔfjUaÐòXxæ¬-EŒ®hІSçKÙÔœÈÕýÉ´ÜÆ³ œ¡“YzØk/ë'Ÿ<€‰„ítNÐ÷¯y7½oÉ÷š¯ÀC6³57â1 zß â/É®y¸šó-WáîQWq¼ñ´íؤÝÌäx¤%ayCSÝ’ÖÏÃþ@dÈ­µãîœÁã)+ûF¥Ê¼…_}—·ó^G(F«ÒxšGîÃiʈ°Ó‘K,‚@¤¸÷uè´aÛùD¶}ŽNçÍ­™ÉíL_'íÒÉÜgȸ1riÆ­8Úi9ÅŠ9E¹z!>öŽ¡R`v[qWof{ÜìŸÉ·[cZK.qÅëVqàòìA/ß—‹ßŸ“|o2ˆ.\°üàý6ŠßAñ¿½÷»(~Åï£øHö–Xß%ëp¨KÊ|þE3‹¬nø×i”ªªäøÌb¤a ŽÍ‡H¦0¬}H´41LL™hg1.“"—_z¼“mœþ¾MgÊ&:Cœ“¶¢­‹1Bú?@qJã—vBŽÍQ’N²¨P,·†ù~oßðm³H6¼#N’pˆ¶Å%\óR/t¢p\éÁaò¾IÖ6¹dòIA$ c¿µó<õ~Ór¤œÌ©SýuÖüoÊ|w ¸jô+¢]Z(9¥e68uó¡Tg³\‚)ª–æÅ,9 Ùä¾)§VZý‡•2+gn™¯U]ûPKƒ,ÒF »G ësetuptools/command/build_py.py½YÝoä¶ß¿‚qpt·Q›öÍ€ÚäRMÒ —>ù +R»¬µ¢ Rgo‚üïá—HQës€¢û`¯(Îp8ó›Ïí&y&Ç^ˆ8rÒæû®ÃU&”žµèUýûVŸø¤›‘êÓέ-;[y>ÓÕ‡Yô¬/„*"'qô;¥òßÔ%|í†3Õmà¦ù³~šè¸Ûéér»#ð1ò(®çQK Çôâð'-ÿÜðg/ÖâY ¸¶ãÏ-5ù»Y?Mr²<Úž*µì³‹øa¼#Ó<4¸Z*Þw{Ò‰ž«=a²Õ\iu÷ó4ój¡ÀÏ “dú$†ãÍn·³ÜýµK¼sPÂ~9Õ1¹¹¹y?œèÐrF ¿­ N{DŸ¨&bhû™qEÕÔJDž„>‘‘¶ôÈÕΰúùÄãtâD¼ÞŸ%”Ž¢Á}l9Îg>€¢%)ŒR˪¨ ³œ»%«g4lý-ü™Ä ,‡‚tr"g §0®)šÜŠñ—^É=.x(ØJdÏ|ë~´ïå“"9£ VÜ 9€6 ¯b¼4gÉf¸H ûýàQ †©¢gnAäÈ'вÕ^µV"4k'Ú‹_x#GÜ¡Œy#C&fª·w‡ÍøTǪ$wvE J6¤¤L4h³bQæ<6wÊ)ÁßÕϯ¿-"‹ŽHÜpí™Óš†‰V7M iÆûôõ}LüÞ¦iæÞrf_ÃEî³ÞŒkÙÁ4àqkk€éþж Îøûõ½A+! DXìÛAü™x«åtAãGwÿtV €2Œ–uÇ?Õøš†]ÌiÅ%Ýo^Z¹÷eµA½yVDë7”Õgv<ÄG˜-I[›gO¾£½âÕï"1QïeŠÄž"|Iþ9ôtû8Úê™öôèì¬ |9Oä@·!PÊ8Åèñ„a^Füä¬ÇY/±®NÅ;\4oÜqi ®\7–Z¹ ïlƒD­düîUµà³i€‚j=5ÛZÁ®¸Bîî»E1{ú‹pŸuŸsË.¤à þ¿Õ.м¼^Á‚tÅÕ-¦7¿r“åª1tÝûàÿ‚7ÆñsÖö¸&æ›»ÕѯäüºÀ¶þxqb‹X96\l#Xé.PeL/Ábe”<„ý˜8é!¤#Œ‹ÒIºWS ‘uÚ[µà7d2@.SUA ™Ç8„É)$¥ $%Èœ¢_‹pà2Hx1;»ÓB°÷qlCÊUó%ù^¶(¬'Rào-_"jªI+¿(ª"„$1•Á «#¾qnàÏXídwP bIÕXeÖÿ‘b(ß–÷Q$„ð¼ók5öB—E]TUvú÷|8BÕ†@f¦à€L;Úš²“3äƒÜ5ÁHKwé ŽûzÍûƒánbyb}à–«±mBVÑpðñí=~û`l‰ÏÁPŸ°{VÞ.i€xHžÌƒ>#Ü/jß/V™W˜š&.®ØÚBX„Jœã_KÔ²Jˆ[$¥.\ºp,ŠØ'P»*”MqFD<–E±¨òˆò.¯ß A¨²${Ïs¡cMu»ö?­9\n`„]{Ü{ڞ¦µu ÷ž) jàvþÊUó­o%Å¢F£âQeâ1Á¸qËVºƒ«*7oR¥¾€3×e$)OòÀøÍª|ÃË\Ï 5xÈ"tªtïJ¸7ÊÛ (Ú#®×ÑgãÔc,FÍžHpsiÙVDSkœ|u`¢êíã0GE™×œŽ%²Q@éøîÝ…^s0=(#»{““@‚-ÝyPF_ÍÚžs°JÜÛx0šþÝ—Un‡ ÐU‘gîY–\áoÑáæçþüúÛfÏHíkÅâ›MC¤´ŸJùÿ_Ò³º‡*U!&Ð\N¿9XÝI¹K€è,—å®Õ­Ã1TºÐÉ^–CØ"§Q8+‚’h¼•¹F‡ ^}Û×À/µfŽ r1 ¥:^?gøÏ¹«×à~tîuàÇL^ôžj,³xêËôˆc4Äýµ uF¤›‡Ö΀Â9퉷ñëâ$r„U’B*brì Ž]i(ºi z‡^uâMØ'®0¶ôŸ8¿z†‘³{·°Ôn€ù~‰¦—±~¢ÙJYuÝw½úî›Ã­\68Àµ[ÇJ/(e;t…Ǧr2þ&H<·³È瘢#í]ˆlÄr«¤Cm}ÿyG°qȽâ0qú¸X¥Wü•‚£9ù¥{³'Åtøw±šÊ­T€ÓâÀì Ä_NÙ:%¬Fó!¢üü[¿n“v+Нv”Ù¥o~\C‚›<ôü|KÞÀ92ïÀªL“›œ™Ðêãàç>L‚ãýZÚ÷¹•Õä§žã,(çVtâBSýq(qNmÆÀaTM Ùàp Ú9>‘"'Ž.ö“ƒÌse;Ç®>7yCB¹›ß({Õm//³ú9A† \/ 7Ý.­RϾÆ2¯qžO¼?:z2P>$»N›4—Äð?I„®µ0¦ÝM‡IëÜ«|ö(a¦ãÉÿîWÝèU¶›Pß±$¡þ;ÑC'ô¿ëE·¦ö¯êI¯n÷¦ʶ†>/5@âûļò°¿¾aáò÷f×þžö2ãsÍìuð‡cÛ#¿¨ÖâÔdf1‘K8,¤ã“Îvy¾½SˆRŸ¢ðd³-ˆ|]‡à ~‰+@Ò×V#L€†›Çh˜ó°ÛíLç±UˆZõ»éÕ&tXñûè.¡¹]|ÿ€/ ògÉ.ürZ3Îø Ë«¶–p¿™©vPbø ñW²ÉÞŽéôé6ÍoTܘ_ Ãψzg¥É[Ú?Ñ‹z‹£Œ?|¥øHqÊ 7E¼vp¶;efƒïhöäíÀOoST»nU÷fˆb¼YT·Êp‹ŽJPOµû/PKò lHØÃe› y!setuptools/command/build_py.pycµYÍsGï™ý^­,Åß&qMJñ^Ô²Ž×ÊŽè¹"j–÷i~ k'ð¢•ù):JüúÌ;ÔSUj6’l]_u¨éfé#™«`ªÍe=Ü¢æûñ(N_VÙ+¾‹IVD¸øDtšI¯q„tqŒ±Vþ ¯Ð­Pƒ/.¾éx/‰se m\e^š©Í8ÝXžÇÊó»¿B&=]ôâDªÉ“»Šº…ž‰¦À.Ö‡qÝXâB-öÃnVŒ®¿ôââK/^½z+¸uó†ÜظQH5¨,KŠݬßSzƒÅÁ¯žÓGƺülƒoAöe¨6_ô³h˜àÞÍ‡Ò¯Û ùÖXðÐPNÝáýØû¥B«'¥BHP’6`PjÑ©èÔ9t±5î4 À€ÕwZR„R§)àŽˆ¦¸3-¢ŽEÚ4wf ÿØÌ{´­·ÒÍ0íÊÈ›³›žóÌ1=µ*/N»É0’……*ôXÙÞãXmzƒ°»nÈ¢ÝöèóœæÒ+²÷bZûQz¡7gž0oަl û2UžÊ¼9òüÕ¹E^lEJ3Är_dý,Q“ÇëCgéœ×Ër¯ŸÑ["©Â˜æèm|3)²Úx\xd/Mõ²]Ë/:_˜$ÙãÂÛɆ؃ÞNxçµæ;Jí–æÛÐeœò¢ÁÎãzÙ@æ!ö¦ÐuŒÚ]k\= Uˆ-Gl¹b—ˆÀý·ÅÜD€[\ÖÄ`QÄ‚k€Æëb».ò»¦Oƒ¯§DzRÃv˜Æ´ù.³1@Ô«d¾e-7Ëã 7Õ,›o&ñOd °û‚é&š5LªN1«ŒÁ¾Ú£¸«ÈøÎã =†š"#½™ƒ7-s°39ù•c±VÇÓXo–ÍrÖ™q:N‹ÚijKÕ¬Î~-X®[dâùyî9ÜIêñ|‘‡]𺓠3'_6ºÄ(zÕÉû5£DÕO\}¿jjMµ…š[±5{DDOHbÚf^þ¸Gö xJS]`w³ÁΤ­öYD^粫²|g™‘a,?XßQ²›E2fm€9Zcë`½Ûw¨é’íícJ´“Nb1Oû¸Çžåí0)¤Üú§¬#ÄfÒ쀶îc@#tCª ªÁ<ÐñAHU´/º‚%ϲ·=íTÝ–3Mß6µ§úWíºÆ¹V,–nK ³íŠüyƒ+‚E–ëˆ=bW¬(wL 4ToìÙÇç!5ëÁqÇæÍw$ÀœP©<Øoû¥óÆ _= »DË|ë5ÙÂ:$ªÓŻꓖµt€ é¨tú]ÂsUÜwÅ^Uì‘ÔD~[ŒI²Ê¤ +ªâ^²¦—Y,§ïÀ Æ62æë¥8ÐÓ“Xf&v€LÉ+öêb·M\ú‘+ôH4¥gAK ÑÓZ{è‰ÕÝ}$õ™ÂeJ/!yÁMÏÍi/y—ÜH¾ %ƒ ¯¸:ç‘A+Ébì”(ž².-$¶C„÷h¢Ö l¦$œ8W0¬¬`“@dÍ­,N9¸Ö/Oâu&£bÄŠŸ6‹‘çŒ&-ð26ÑÜggLj` Æ9ÕÄâ¸â—cͪÐÁ4ß/Ï{ô{ÔŠõN2{µ `gݙʕÊlõª{Ñá´0kX¨ý´„Úóá‰;Ùµ#ç]l“£ÏœF·€‡¥‹lÕUØ3—äJ$è\¸€ò„qʈy‹£A§É€T±É ØÔ§sæ©WŠŠƒB£Þ¹}+…ksFúsŠ óò¡EV)Ⴝ”EŒ‰R 9RD>ò¿‚fÍu4œ†ã`h"Ú* †Õï¿"ŒOCZW0õzQJæéÑ+ù%Zæ‡X¯ÃJ>霥Óî‚f’ö$ÿ•šÑçFŸK>÷« bÒ'”÷+ˆ~éÁ/¡<Å„Múƒ}× -G8æV œ`T8žíÚÙ Ã;Ä ˜ç2Û7Å^Ë>ßÀ-PuZì(õ#M 1°vm±5%v›)Ï ú[}Ø«ãôõœï@¨C–}8Ø™g¿1uXÁÚ7l33@YôpÆö‰ jì%Âõ³|ŽÎˆq¾Žx¶Œn9ŠÑ4Ñ> ÿ&𝠓ÓZTó&%KQC"üÚªqHþœ87~Ap¢ªKÂ}†ä3Îúž'ŸT§/ãhjÒ#ݧ‘Ø„3ìŽv­/.r^B7 T£G¼¬Ô%àl—1¢ª6@®ÝyøŠfºqP[otþƒ …ѱôàïŒQÆÅɪjIÅa˜Õ*Ú á@EÝóº7ÖÛÛwÅvÃôir¹ F¶YªmÇOˆÝ6ƒ–áýðw´a½-ýv°5?JOæ7]†5BÀ›ÎÃDÊ¡ÏÖ,[H]\М¹õ”Ù8¦Ðß*§uPù2ƒƒÄi/+!R—Ö?¨È¿†qÍÙ~_”]ºÃ°(Ò\&”¹>’þ5a"GÔZ *Îð›6QŒÊ;¦ðßLiösúÀå,•ÚšxãiT zÀA0’½p˜(mS¥ï„÷{ü„¡íB»Qfä8èö#~ Ç·=íHsùH›Fõx™¨wôÆq"Âz¼*™F‡b\xÑ‹î4l§œgéªîìDê†òO±œ¥É ÜVîv\G`!ï¨4«°åS‚§y"EÕ‚ÇrF¼‹ÈÊxQ²ýûÂfÝ$+$«}ì—™ 'ó…S*ÉÔÔÛþ=̾,N˜Ü¨ø´ä·Âuªª{ž9ÔN9—œ¦[ugˆefén¥2KÑüáÊãE!l9QLpº9A@LáľLú¤9q¼¯Hxœ%:¢ ñKe¹C¥”/(€Üq©€NµMÁã›ðD!Œ«Ì+»ãâAkߑ٠jÐYÿ“g™ò—Å¡q\UÑpak?Ž” [ú­(‹*g(þº ‹*Ø{ÓÊåÏâMÔªègŽîèØþ&‡ñ5ÈS׈¦gu›ž¹:2ùªX¥PÙ>‡*´<]‹F\w‹ã,Îë@Äs¿aû ¿kúÖwQEø˜Ô9r†÷vœPzôÿfx>x[X«0|5)ÿ5aò®^ÚUw“y¢Ç/ùÂäŽ=tÜU:Ôɳþ¶Ü)ü»X¹µOõ:‚gzÝ"a=Œü7ì*…”)SÅуã-óQV#‘êÕ‰'|¹2ãÔÝ Î<‹€É­iEÀU÷ à’¸ŠàÒ ¸DÀ)$çïøï£#±…j+¹³ï@Gz*˜"¼fñ 5õfÝmµ[§[õV£u†zÓ­ó­JËkU[uæ»Ê$ßýà=8I6ÔY‰¸ •TDŸS\GCœ«èú6Ÿ³ ÇÌ>tÄ8öžpØHåJ‡½‚£h¯ý7ç€ðá¡Û梢›ÇUþ*F¾;õ(oÌ’¡‚ïV›·Ûåƒø\)Æ×æç±ò73òÄÃBy×Âäq¸S\óÖ¥wãz!!êi¯Vx6¬GŸüøþÅ8&°)ð‚w-•”¯^Û¿¡b±|F×µJa4ÛG’è+Ë–JŽÔã<°aE2¢½r7ÁïIÍ— å¸ìGžwh™¿[ý ¶¬’ƒ¬7N9úUÈ}¸¢Ãq×8&@« ÿKûÆÍ+í+Ø~Ì ö+>SA$ÑÇÈ#aê?f&ñ:Wäˆ;æã»ýA–+ ½sl6ź£+Üoà˜~†›ufI@ý¢ˆÓÄçjÏüñ¿PKƒ,ÒFÜq¡êÒÒsetuptools/command/develop.py¥YÝÛ6÷_ÁhHjdõÒ¾-à—ëµ@¶ôM±·h‰¶Ù•EIí®ï¯ï )J$%ï¦=8‰83œïùrâL®ô y«Jü%üÜ ©I-ºG&uÕS}Ú:GÒŠctR2)…œþåÞ‹¯‹ùßÿî5y»i…r;¶b¿±‚û‡c%™ƒ¬Y Uòý€" òôû‘iÚPM Ò y¦-ÿóôVL½Ô«ÅùL»¦dT]*Þ)MÛÉ`ÿÝ#t¤þøÚ);Ól6›º¥J‘†=²Vô™/0¿Ýx’$ù…i2ô¤§õ=2rÒ1œY§`c(¦jɛȎ$NWÇÆ;’zlä,–ެƒb²†U¯¯Fœ½#w†Ÿ,º‘()H2àÏoî Ñ'®ˆ ƒS!É ™[ôøø~n4TŸ^ŸˆdÏP³UÇ×%²´¼{ ÞNÒî­ {p(£Ý5+âc0$ÔOGc¬+Hd5œ™ª¨<è,÷m#ä†HrÉFöT1çú‘C—)ÖƸáÃß”ÓEó>æì<´šW RÙ¸ý*¶¤š$Th–O ”Z‘ê¨!W*/è£!{¢²ƒó^²šjÖ8ïÙdï¸æ¶>Üide¨ ˜€Ñ O!p¦ºâà D×n E™êYfŽiûD/ "Ø_*S‘;’–)†ÍžÍCWŒÉÃBs*¼ÙÚß¾”îºÈZ$Û­Vä<(s‰B]BeðÇqZ™^ƒCÊMÄ¥À<Ðgµ¬äFU, ôœ~C~¤xSã¡3ýíŒ4™›º!æ ²€÷}ÜÚe¯=îã¢l$¸– XJyò÷Rü štßy©?yÆõ®}ºì)%ƒVS3LÅú‚¤_¦AD{ %ÚNF³7m¾ü2%_¬è5À¬Càä÷/ >Pèo%k˜}éó¥ºKVûü3’ñÚ¥€x¡)"n\çf2æ‹MV®eâh55¥%±>ÆÃžÎ(X‡Kü¸—@ÛF}©Ö2›²s†ã)`¼ê+-¾N ²"ïÜïä‰!À"H†‡F ŠjÒ 4yg’çvq~ @†åyÌjì‰0$´ØÂ¿V`–dq£<ݼmªþú÷ìþ‘¯0Ý OH¸XRŸ›W°ƒcN"fûzµ±Ž‚KKÓò}»âŸxBØ3d BMõ©Ö»jë]­îfM^óÃÄéóª»AÑ¿ïodZþ†Š˜vÌFÄ&[‡MzØú|Æ?!D+ðnR̳£–dXe+j:nlWhoÈǯpWÐra‘ÀtïYV1Ú3wív‡ò;×'1h[h£÷É“ !ñ˜ø¤p/Ó„oôÏI‹÷ÿWZ­\q %tÉrT’Ùv¡O°¸˜%n²@¶Uôá­iÛ‡ýRCS£}5õFè½kØËƒÅÙ«bû^!w+‘‡!jÉÀC¿œ×çqŸŽ§´˜t÷ $€*°h&Q­8–Ú,ùE"Õ[E2#7•'Eˆ r‚ë°yÛ<–— Bzê€È´g]ÉKž¢zƒVBd²°îÞ‘ä?¬hàǼu+ — ¡4ÔTÍ”ò];¢™Y°Fø3šGá(ðºªðäa³9Á9—ì¿ÌZóA!ZCì••?3ûQd*öböY'piWÞ@޾,ç°Ã2ìD©Ð¯Ñ¼ý3;C{ùŒ@ããˆ*ÜÈVãÒ¦Ñã'—;8`ˆ>é¡@úâÌß@êýõ 1ý1Ý‚NyÙ]B÷¯ï"!CçÚ}äUçYüä’%? 3Mµ)ëÓÛ9„„î…Ô¬/;-ó…( É.¶êåªÂò`è¦Y Á«RìçžTÕ»ÔtP‰)ƒíæbꃸ¬TØ8#X޵#}DÁ@‚ÑÈPúÄ`ÛÇD·À"e\è ïÍ"­³šÝ’‹ìö6;ÄŒ[‡A`l pty“¬À]ôÖHhÌ.LW Íl^\yN„ @;7 XïTDúúI$È5ÛÃv‡n³(Î}äB†[ƒIøÚ‹š® †'˜!=ç€q6Œ Äb*Ø1ÒúÒ:ö´UúW–ëƒv¼hRk¡pb»mc%MGnËe¿¤€ŠWczwe¬å½òÅÃÿ_‹Ì»&Ïׄf!ØîðUæÝM™©åͰóÈßÒUù° p ¢MöÚÀZ8ÙJÉì¼ðT.|ù ´ý PKò lH‘f2 ësetuptools/command/develop.pycµX[oI>ÝsóÜ<¾$¶çÒˆ ï’Ðjw¹lÈ"&ê`-­žéò¤Ç}Û®êÄF±Öˆgyâ•7„xEùð¾ÿ`ÅOpΩêžq !Û]®ËéSU§¾óS]û¬ß¹ÿ×OžLÁüÔðù6>òÏXøgA[0¶À¢¶ ‘ q Æ5Ý®AT‡¸ãÄM7uo¢Œ[`ê+0^áz¢6Äw î¸ qÆ=ýN¢>Ä«0^ÕíDˆ×`¼Vé\‡ñ:+ VáЂ  ¿8øp¼AÇ\tø/üZXS=,¦iòLäÊË|õT÷Ò£t6´©±ŠÅƒPªB…‘ü^ž§¹º´ÜõãL…iÂÃZ©”†ópRÐw¥.Io‰ÙlŒù®Ü3 ROIB=uTêL„SHЬÔ="é(LŽœÃ0Sš‡:ó÷iOßÀâÀ ¿ ¸ ¬{6÷ÔQVÒáFTkp ­ÿ˜í`ØÄÒ%À©:?É ¡úX‰‹H…BN6V—wëÑzÔöÂTšÑ[2=÷ó;³\L}%/eJ šJŠèpHèàB~‹IFÁþ$@XŽbšÊã½·Þ½õæÞñ7ï{÷ïí£1ö¥PE¦Ò4’ûÓ4Žý$Ø7S²Fa^$»¤‘6VûvÇzÝv_×Ô@&³ÊŠM@FsaýL3õ6¨Ti[ŽT𡆭r?i"´!Wô)³Ë¸<¾ÁÆ U¨}ÉØBuØ ¸U„R?zîŸHošf'ÞažÆl/w½4ÓÚÊÝB-_|ÅPø°¡hÕÍÒP]»šÍrŠÆ°`nAþ>¹è©ÍMÛtbOÌø{j°…/|bA<\'‡Ö&UMrqchR¿R´]Õ:0ïãÌ{DÑg<½…¯Â|À‹Z3z‘8·ÏúÞ:wmpËù&ÛÑ äŸ‚yù²‘9ÓËÙ¤ª-æÎÓ:5_‰Uá,$ЀøW‡£äw-Ä|ÀÍíj¿j‡Úê —Ë³òû¨C…^û™M›õ®šéç»,øÅNQ¬É=×y²?ZHØ3¿Á@¶/¡Ù¸ÉÛ¹ù¹‹G36¤ÑºecénÙ´‘ΫCøŠÞÿËð/Q&‡)SÙ££‚pr‘ø±pnåDgXNÒ±Z˜Ì*&½-)&Ü!zcR¬xޱ½·W’¤R)ú¨7òUøÌP%ù3dI·AˆL£Òü„¦å•åé»Ïq6&Í%QjvK› )½s"5IJ‰ª6*®¡Þ f`Ó8àE›Ó$’l2 ñ-íÂSX— ÷sRw‰f·¾‰´2@úÀÿ6>5¢žž½[ësO[kV¯vÿoX»8δR_¦•ÓÊ\giúr€ÙÛK2ì¼Ln±S{8A[µrÈ$3ÎÞ|´Át—Ðsœ”Ûª­:jÿ³j“]×ë2ÛÂh?ÏfÓƒƒÙ,»îºm{|tÄ ¿®Û®\Nëæê¨-»ÝWÙ•aVÉ0×ÝzÅûspÙÔëìjUϳj½­›Ž~çOíZ§ø¯ý¾ìfÛUÑÁ¾­÷µ[Ô›Û²¶Ew +ßÍÛnv[4mاlšºiM¯¯Ìç/š«Süfì>z³Å]”O:ÈàÇ~¶}+3¤ÏÃ!aó×Åf9•í0c¿z}öþÅwßÍÎ^~{ú—Ó³qÆ¿Ìþõôdz„鲪¯Æði3ÃOû†!䙵‹¦Úv¶çeÕÀ†¬ªM9kÊù°½oͯµýí—jË¿ÙV×4šüÕ•ë-¢Œj®ÿTÀ í§0¯zmþ²ÇiA~èîšbkþ¾+š `ª ¥‚Úì.:v^Usûýn¾mêEÙºÞ׫òƒù£ªªšzÉÛ~=máÃyýÁ4kv›}5ÜÞþŒîYçá.á#þ“½¬®Rª¾rv¦#|So»¨UÑ,®«Ûr¦ñ~·Ab0“¯âI1¥€«¸,íÞò‡¯ð³ÇõøþÁÓ‡¦>G„œ•W€¨ð@¹¬S]Ô.åp¼ üÝŽ³uñ¡­~z„äÎÐ` K¬õ²ÓÜóÓ”MQµÐùíÏñŸÏG<òöæ ¾­w à…• ÝW%ܼ0øp²XÁðrh¦ÏÌL¤Ü´»¦œÁ,]ÝÜóŒðlqÑM5ß1ݽ„½ó>à§›Ûª©7HÇÙ»òï;BXÂâú¿…áÿ4}Ytô¼ºrüP770—³²{^×Ý×õn³dp-›>| ·ªØôô¯§ß½y;ûêÕÙûñÁÈÞD½3‡Ùû]³ÉêMööôí_<ýÁ\Ds#§pÕá°ÌŸù`Y^»U7g‹¢+¯`ON<˜SÐèß ðˆœdç4Õa[¬K¤ Ãq6Ô¯þý¶»Ö‹l© ¿‘³»jƒ-g‹Ë«!¯z¸.ª 6Á)?À16ùC Ý.`h˜lVµ³ß~1¯º|t|À8Óá’™¬LÅjø—ÞFÙÉIöÏÒÍL2ß>gÛçÒy^w×0Ì–SãÕé®§ôw G^‹ðãç#êºk­(t¾.Ú¢ëš\ZÕ¶07u¯.=ÇîÐz̨ἩâùlûLÍ?Á_rýÁ® .Cwzþ¸NÏ¥“ÌÆxbÀÀ¶ÂàžòÌq‹g]=+ÚEUåí(Z §iWµq«®¹?ö¨ƒŒ.ÞšGÞ÷ö}³+íçå‡E¹RÇ]é%?NuúºXµåA ÿø!âýÞ(Äñᛡ† ·¹Æ;´ÅGå®ê®3iLØœMÞ<£yÿ4`Ñ >ø g§@LÞ<›P|ƒ&ožâcSÌa€syüîÓ ’°öºYÚk¨À{´W W{w]ÁNÒÁæÙ _R8-9e8{l¬_Pf·K‰[ð?‡ˆãªé;‹l°•°-0^ÑùÀP´À£ji7Ï”™„9À 0ïîºlÊlº…¥ewÀ†ùJ@ÜbQŽ‘ŸÛm¹¨.+ȰtÓ7{íCÚÔ“e¹%^çu¼6øªìÝ,ªxcVõÝÅq^Í·ØyK+ßîÂê3ü·¿ÍÖ;X'lÌâÚ³ª š´›bÛ^×] ´­Dƒ¡2ÂZT)£ßfÄjSç ¨Õâ¦Þ…˜+ôÊÑæ-°Õ–Œe(*4k&ÔˆnÀítÑθkšÀ-&8x³2×ßYàïézÙ˜—8o‹g~R/„««We±I>0C~-pG<òÏŒ©Gñ#¡áø«¢tj+ڸϤà *“6!"óôôõ‹?w:ûþìôÝììÕûS÷î_—«ílÝ^áslUzL©ëļ Ã'íp=ax…£_ß)¼t€Žy>ÄOíÉš¡FŽU vÕtä~ÂmÊ+8~p¡Ìòßý»~lwÿ?˜YhJxEN=ñ…ZÇ`m€‚³P'#Ã{ººTìÖ!‘ÚÉ„öÛ âlMïÍÞò ~:©P.RØv˜­ÅžB38 qèA\ÕÔ¶Äñ¦ý${ê ë™Õ7ð9ýE‡=³‡Íßà†úäìP 5=åô'‚ŒV ”[5ƒ73ù- ±|ƒR_³–ɾrÉ6À½¥;›7ÌÌV誩aƒ¤%cÄ ¯‘ùˆ.âÌP‘ Kl¥Ç¦žás0šÍˆp&»7uÝ™¶ÌA*@MI’tªß¾)™CÜîšrUÍ¥ ¢1ði¶®—;˜³§Gè ¡dSo&$Çîð^9íÊ ó‹i(×%ìsÓSyyôò³Ï2ù.ÝѺ-;¼9%°%¯¿ÇEñ,Ó0öã© |Ñ{Ç·w·a ©FÏ^håèäŸ_œîï‚m½.iuBåCczÓß7R¼€´ñÝVtí¼{Àza^èòÜV…Ð2Ô˜ùP}µaj\àžf¢î¯òŒ˜‡T'\R™½˜Q.g }þ (6û÷ÿˆAl­`["™a¹×-ùMØPà´,ïA;ÎÊÛrƒhr\«v7'™¹\’éE=®@fÆ0jºm@¤ãk9Ͳ÷×U+êÄ–3yFàªV«•†ÅS[ †v ß„·,€b²Ny×0×Dšžv4Ìz­…="£YO‡©_,á³U½à‚ ƒ00'NËla XM7¼\ÏË%²Á‹7[6÷³f—&@çukQAÓ8óßÁk ø™Ñ˜g=º ãDOÔ r@ªE—ûGG•ŠfY®JÀÁ9¼Î7p«rmþTŒØbÓÙ†°6NVòA²ªÅ ÓÃk g¨M—…ù®jñ»ïÔ Ìo(Ðäëb›Ë±ðzXÍÌy¤Ö­Ê¢ñWµàU}5E¦=|…M‘£~‚Ò?5óh+£CJå¨OÕκ¦,•–±jáöç’¤¤JÁâýñšr]ß³Õ¬ VuiÁ"}ÅÞ» v » »@%÷rŽfeòÎû+#ÙLgg®˜êÐZ › G–¯âkï[D‚.¹Šæø l MÛí [ž?½pm‰iÁÓ.3ËÁ6)£;cQÆ6ª1iµª [o¢C2þ "·ž¾}øe®¤:×ÍH5}=åûtçËÝjµw\Ó êî6úº?z[Í€9o:¯íùÓãÏ/ú;lêev¸È>Ó?»Ã‰š86ç °÷[ì¯OñX~Ðö‘í€3جîÅÝ!û|úü34[dżº\W>õšO ì>Ù6`Jcõü>TgñÞ½z$7¦ñ|hØ£á…yWBÆépä42ColÒLÉc3 íÔv†óðê”¶øb‘+°4ù(ùµ|ŒÄ_æC5n¡“üð¯@(ú¨°ÃpUêÉ;Ì^]€’ƒi=ݹõîàÔ­Vkl`à4§AS½ºšµMYÕM#ªX`F_Hv,åªÍ8ˆ`ú|n?Ø£ˆ[Êw¥Ý š¤œù}¦E Ë)±ZvzÛèóÀÿãé˜9ÃkÚþøÌuÅ ) a×Ð{g·é ÉDˆ8ie'䡃¿"b&™3[4»eÀ”!ã´ÛˆF,Í: Õš§"ŒÓ¦Ø دꦼ#C<î’Õ¸Ó£¥ÑOæð×ÏÚißöÝ•ˆÓÓˆCºÜÏ”¤¾G:Z¯‡V¤ÑÅK‚Æ 8|ãµÎ5øÅnçZ¹­¦Ìi±geµÞ®ÊApÁ¯‹e}7“‹¯éüØá›+»ë:Zž”+tÊ2 l†'(N*Þû°N lºüéØAKd­ í½ÊF{n¯¨½¡u'ÝÅèbA?^D³ åzù‹P3ÆX¢Œñ•ð1c,6gÚ²“pÇ<Íú×gøÜcû‚™†rHË#túLÑàhá>W•> ºâ+ºi÷¾ùŠÍÁ'FÆ}HoêÁ8O06¸Õ×O«¾äLχ VH$ΤáE¼ŠdÉ žžˆþá é£^‚Ûþ)6øÇöVnHÚ€ë}iv›=f ²Ñ}²ÇHç£.Êœ-kêá˪»Ï5 ‡|¿@Œ:Ð+Ç«G‘ÝoÏK;=î ;¢«Ên¤âˆ¡ºG?@©ÛÌ`µŽIÉRàï½uªe­\šI^3xaø7·âiöƒ”~%Q©¦Ø\•9ö“ÉzX!µœséªìð£s3›ã‹L:ð ßu:ë9”åbqz5¦óôã|fì–™«C›)ŽÒÈ=ÀŽÈÒôxˆ¢VJ¼Öúå}*ú>0µaKÔ› "A´×[^Ú5%ÓàêþQ蟺7ênÛr·¬gWGö©˜:½cgýBšNLS~øQϬT–p 9` >WÀ†;FNÍ«ûlST·å—ˆÛE†Âÿ¢ªw-àsÓÝg édt`°»îêÂPÜÎR«öïëݰR¾B TŠÃÂÊm¶¬kø_š±ŠHÀ¶Zòs áw-Ü ŸjÍa…SüJOmü˜¶{ñ0«+¹|žêc€þô¤,ã=ÿ¤EHGU^G¶-Z¯èƒâãýkÙ ?OŠûHŸ '†Ž3“E±%±‚¦‹\)ùÆSH­…ÝXŸœÒä( nw”KŽ·CJ"²ÌžàD´9ø0{…öŒ¬°n(hzûãûoß¼~ûâý·c¤ˆSIðNÒÄ<ãBþä¦ÞÚ "I‘¢7N©å‰\,¨º¾žÐåùúèsÛŸðb”Æ®wb*@|"Û L“t¤ÖçÛÄ·ò_oêJˆ{ëúìUVf5‚Þ@è`¤/žºl¾È “ÕÎT!!.šéíÛ£ÞMÖÆ‘k´O“2>:9Pé7ɺ[ô¦6[xÛÌ×€uwÃÑt±:™'Ú>O$þüÍ™i¿zC¿ô)šèÃSHÛþ“Ðìe¡}÷ѶJÍñ`ñsöIh,™9ö†lAÖ·$¶|äÏVÍ4ÒÉ1®˜[Ÿ”,íÆ(âÆaææ»qâ†>¨–S€}ßCG:+KVQâ“Ý—ì: J@AÞ¶Üz¢´¡!¢šNY™8–5gu=ä­Aê æFö"$À@ùH°½£78¼ ð¶.v Ñ©O¼ìÚΈ~äÞÊœ’ïÖº>™pRÙÊQb›{†"‹"JÐdÌF Ÿt“ŽŒ—‡•°–X¦uuçSŸÍÔõc†É0…÷ uÓškXjùáfˆl,×ûLÇ«ËGà»ä¶÷-<è“ú×\Ö—uqÏC««6D-§}Y®« ’í¢«Is9@¹o`&>¥¹ ¬eíæ¯:UÊ©9XкX\WH7ÍT"ù8A O­1»l€»½Çæƒaõ8j‹v[ÑßÒY®,¼Û¢!/õ©ÃxÌŒ£cÊðÄÛY§îhòvx2y)u²¢ó®Ô¯Ì„cщo1t`[`·°À Å5 ý-©hü˳¯IøH17ÂhϺ¬?Érv>]P&|tþìbÛŽcv)x§"$Öfv’ Ú Ñ‚ÆSñ¨Ñž"ÙÙ]i' ¦ø*Òx²ZÀ¹ÇÛéz[5Õ‚$è[–ތܠbD9N`‹úÆc\ÿ”B—µ…ÁJm‘G›iâü¬_âüî9±DF@øä|-ð’2^¯¤0@xnNõéa;£4Qß u“>ùAzïQ÷¡bü¦Whp ~‰Î©jœ!Æ•OÒÍÓø(]24ÄûHŠbÓÊ×UâÈ(¯8å•@]ñ ü±Oö° "\OJa—,çå›ËéK7Ë' ÏïKÛløæ_ñÏ´ þ .ðõÓ• fcÇ£X»ì•Ó.SQJ¼A¨+4ñxD]Ì)óQÆ9)v,Ѓå7HZåZ¬ºP b™¾ßáL‡éî0ÑÜŒ=&‹[}؉{z¶ŽÔO€¤0¥}ŠÞC´[fjjĹÞÖÀºáÉSŠ9zÒjʰYÖw½°¼3qc5ol¬Ýw›® ÿHh†ñãüÜÁ†œœ¢ô6Y࿨'Âsòt÷Ã_Ìíîww#ÙÕïOÏÞgo_œ~u ´_Ûƒ"ê¨÷ ßÊb˜ÔwiäH¥hÁŸ¤YV™^gÿ}ûØ{€Ì¦AöÈ›1LÛ0d Ò™8¿E:¯¯_¼úN΋øì×oÞ'O+~÷ü7ø ǃóûŠ.2¡}c#åé9íC’i%mÌ€EÅׯª›r…~*’|åó ³Ùö~òD9›éî-\Ë›jë… èÌýWmvñ›‘ð¦NSÜ‚±^gúÎÓN¡¯±Ù­þ}Šú÷xS |¹EçÁ@Â=‡¤èöűtທ*<.Æ6¹#+3vJ èyW¬nR}L?œHýöxÑŠáÎøÏz(ocT °‚p<’Ä¡Iö•& ËuÚ;÷ñîL¯6·Å žQ“}*{Ò“°Èú'|v­£ÊÕß¿û®MðSJÁã¼°²\xCTðpÒ •¦Ä¨*b8(„¡ÛG¯Hlypoð^Žb1ã%²¢Žm<êô¦¼—Çoþ“ÆEÂ ÑæKÙüe\$˜a-kÊê››‰Œ“x½[é{ØÄ(§m{B‰NÕ¶Þ²ìf²¢N×7Kü=—ëÕQvÀä…’òå_2PoÌ R7Æ×¶Ø nyúS7ØÕ(.Xþ1}C£Y/)wxn`@LÇm‘Ėˆ·J±ô@qº“8ŸŽrNŽTOáºÂ¸7³L\§×1å[ŽÜ]‹ÔÞX²ý5…6÷¢cCÓXM¸iwev³©ïØ´^HšÁ)e‡¯è>ó]çV—4îfÝÓÄ îË•I´wQìsâ&%ljzýBµ¹¤ˆ!fÓ„uºyiˆðÁØñ+q+N€¼/•K‡?Î|ðÖ5ØV`À(.Õ±û%{Žj)Fn!ñÏÓbÔ»éË´9àñ¤xŸ|i¦yÎ/øÕ•Ê.ü"¾WŒÝž?½ˆž‚ë{±–)جž((õØX²„LÝ:ƒÁà ó¤|H1õéü¥«{cm7m¦ïh]_24Ž• ü»ŒÉšsM•÷¤¼#­ÐXxœË'NEB á‚ÊçtáÜ;‚n‡ª˜áï :ã‹Àz¿£²ú…OcéÁI–ö8G¥:Œeúç0„v°OcuUü®Fã¼ÝãìS¼³ê „]büÐI4éŒ|L ƒƒF‘B G¤ çž6U»)ûĤF×­â±Cúè¾RÍTZ77=8Q¡²ÔM÷$ú+©óÄ6óÞzCó˜^­RóÙ\»÷wÚ}è8?çïx¦l~{#<#¸‘ò‘‹UôÍ­G´%½ôœ{yQ™?‰!Wò™9ŒQíð£>ýþˆ[$+:¥1 -ø8ùxáæ„dæßþíßlæ:œ†ñ„²¢Ï:Ò6ø Öd/¿TNF©µÐ: %–U5 ¹Nx‡7²Ý–Smk—“CŠJˆ¬Ð+ZîÊ!üzUûÒÍ»ü»àõP œ‡;àfíí³™;|´§ƒÒø¤1 š{\ÎØ~ŠO둬)%/o{0.Ét¤ZÁÜã3@©ñ w%Pòó‹ÑT¶8^й|KáF˜W ºžµˆÖ6Un]­ö«™Å}Þ O.aÉ~–ÇB£ØI$m> otJö!þJÚˆº.îçåŒøO@‰øÄ0BÉŸv[ŠÒT-ÛÈÍâC‚^QèÅÓ†škVåýF„0fþ '\¥½$O:Å nà®úûŒÁˆn²icƒ·©-w_§+y~ôæF|…é/¯ˆm¸G"R#Xå†7ʯò>?­ §:CU4šhêK[o£H*ß¶1>dÆpÝ·Y0a 4h~Ïâiy“‰qÍÀÛÑA~Ûëúððþ›ŸC‘r8b–™š2²“_yÅJÀÒZ÷ð©ÉèF8^š ÷M垺…{ŒÜ¨ÅÆ>3uÕësnˆ%]Ê‚5 ‹f:/[ ÙÄåâ÷y0€Û•¸°«þ§Ø<¡¥”¯Ýt}+¿ù=½QäºåÄ:H¨}Áø›rS6Ú°*¯ŠÅ½Éj(Cœ¯ˆ«Î gþû¼P®ÃPOðwöç²KÐ3õ< <ýŒ×‰¢·ç¸ÙP®ÇeŸ%QQŸÀ õ$ä>Šeˆr³}£ì «ŸZ½¸øÌ¼ƒPe³Ô$0‘¥‰3üÌ2W-àõº®—ö ûæNòž® :ç ?Ün‹´ËÌô¶Þ;¢CùlJNé°ÛPælª.Ò’£:¶µ7Ëm¹¼áN#žït_ErV–Öo|^uóÝâ¦ìÈi|{¿-´çxÕ¶»òèÙç_Hª¤èÀ`>4FÒ”Ã~’ÃåÜmi/P Z–OÎþúî ÛßèFĈój¨1Êì¨PÒËÏÞÁáÌ2<‡ÿ©ð³)îfóû®lIbñ**z¹E3&Û}º,¹Ú®»œü³.¢æã3$Ë ¡G²»,O˜ïÎd¼>ÉGI§¯v‰¤–ć[,ÍB„ Ãñ´XûEŸéöþþ—Ý¡3Cô6ú"zÊL­Š’á®êyè §ût蘌‘aX §€”*É'²_ ÚaÉ-¥`æ½á¥ž-àSØ<)òFÙSráG¬â/螎l¢ž~û_8ÿgxXÁA¡Ýëú³5e˜MÑÝQf©é¡Òþƒ¾Á„‰¾3ÕØ›Ï(©²8ß—7U»²ðMÅYΫÒO\2ò í³üÄáǹB'ÚàQa2U]Û6ûÕ~¼OzègxúÍ7“W¯¿~3Üëú¬¦¦J}ç¿T[¯™ÚßJµ¼ˆQÖêé)jy-ö©Eš±NÌ/iž"Øï±,ÑQüH¯ó˜=Œ\ Mi/œûöa=0nhåQ!§j4¬©¾í6RƒïÕÇÉS¬šö•¾édzn8ïm©ŽîÓá=9Ñ”pÅ õ®{GM'³Œô8óF!ðg…þ`¿ÚÁ;ùGd¥Ù”wt@³ªÁÝÙ&J~õnzùPíM‹+Ó«— ë›)¬ÿ/´útf¿Ël í:x´R;9 Óåñì=ª6üaé¦ÿn¥&¤ØM®ãMµˆab§Ì8÷Ì­o­É“ŒÂèÌÏÿ·‡ó|ßÉx×úö‹¨h¾¦ìùOZ‘êG=lŠëÐOq"Ø‘Ù@M3",>+tŽçåG½˜ýW½‚æ$FT*¨ø¤˜QßpìÄšf,ƒ<¿Jב¼;šCŠÑ¢'È{ž?”J³½_Ö?“ògè•E!Mc²ÌàÃo[-.Ñd&‚íì®Úà@3ø´…€Ø'éõ8&KRo^ž—ÊcóE*·Þ ô]O[>ðG×*yir-wëõ½ï RÏÑ¢ 3ÀG“m€Ì8+1V‡O½f§üU§3¬¯æ\&N`o8a•a±Pò¢ÒdÁÅ'‘tS’ ÞÉ­¤h>A½ùC—1ó¤Ó—õú²KŒ ߈ºè§ö67Þøž8ÏUŸ£³®ÝØ;™Ä͇žÎ -ƒ'n.˜i>rêhò#§þ“˜I‡–cÍhÛ^Ûêö±À ×ÛzEì €ùIúÌxÈa‰Ùß)*[n«%•!Œä š³ÈHš|'‡Æ‘„zL x‡ÎJk3«#³°Ô fm™Îæ·à¯ƒôÔÄd’0Ëšˆ#Ëqölúô§MØ6ÇÙ- ЈìDÐ*tOGŸÝ +Ùõ ®B_šû0óyÒb¤8&‚y’å7ÎF1£¤ÃÑ´«º–ÌnGéb½ M½8dƒ¬Õi°p ¸Ó 9°[‚ÍаÜmu&ɤáÀ›``Pw4‚¢ [XýmŠ,ÎÌš2f& Išb²}pÁ)_©9'¼„&”/ßKuüز2ï%.KòGZIÎÌX[™¼)Z– ŸÁÛɰ:'¸½cÉÕÜ4?÷ÑËȃiÌCÚuš#UÐM6s×–¾rùЙ¹d>¬ßìÐP$Þ`°MËþ¬ŽÄðw¥©…ë0õ=Ú°NaÆýR(Jó…©Æƒ)]½­0ž+£ŠÊJ·>ÍyÛ,Ø› ÐI"÷Û,Œ’>¢õ øàݘy'I@«ÙxèÕ'©4hjG€Ÿáïç”([ÇÙ­i÷¤LQêõduIx+YDþ”àôôÃ][Ò‹oZàrå+ù—C*îë¼ÄÊÄýâMã|ò =£Ý¤L`3.!ŸÛ&é‰à=nKghk€-”Þ@`àÿ8ȳ^ ™L ?lrzP6ê¬B#]4’"ñ?{ùîÕÛ÷gG=dÿ?mÞîr˜i/Cßcó£ÜeôÇFá(¥„ù’ã¹;è^¼{ýêõ7ÇÛnBÙ*îœ –kÎMT…Iv¿Ã±ô¿ nQìÕÂBM !#%XshÛCòﺄE¬¹mfXb`†yrþzw#NÝõ6Ü0}=›­ogH±ºìÏúçrQ`~I{ªC2ŠV•m˜p"쉔˜—pN¥É²â$Î0ÆW¯5•O10Tjn`Ÿ …¨U&6a°S/çGµÀ† %sÚ!§Ôä²Y¨AŠ£^>R[ÖVëjU4Èâ±ß—c’®ËS>X‘¢žáùF©sŠQì3…e[aša›ðÊ×èÙLÍàƒ'9qp¨ÊGOµ¶S(°>ÒÉÉ“ÜÔ—°´•0ÿE÷kþ± IZ ﺺº.ÐL¿[-‰\¯kÊÇÕÖœ$¶ëϨlе©ª¡RÜ h]zá@4c8¯»º¹™fY^N¯¦õ8/MÈ£B®a¶»Æj÷tÌÄdšË¥äì5Óšßs~Wtn›Ž¼Š”^\› "4>®dtb\½ÊåÀ\¾-WÛËÝÊß±5¼åx‹$xÄers1—‹Êžëô?mžä8Úx¤z@[F-üFA€ Zñ°'™¹ ˜ãÅžüQVWG†Bj%ß“øÝVhL§×ˆFuøé../:Tœ)±jm¼¶½€*ÛÀl…´ /ï$zh)ÏÚ›¯ÞgžÁžäöô#Õ2gï5Dß\5cçD®ktQehòWÙ{} ÇNiWØÜ`¥ªtç¯PíŒÔfÎÉ“²àv­çW164߯±c¼Ã]•Vd@Nvxg®jÉÕN¤À÷‚kާu¦?ÏÙ¹zÔ:×í¢ÊÜ:÷ð¤ýÐxU°™ÖÀTߦoÖøˆ¡nèÁÔÌ‘ç…òâëqøéO}ëupzN¼×›eUPÅÇvEB ’’a3ÏL¹ÇŸƒ5S:‚f!9ÖI’„õùÐêþ§²“SËûÿdý @FS7d†ô­î¬IYvB™Æs%0ß„5Ðþ˜=÷‰Å-ÞÍÛaöiæÕ8Ë&Ù3Ÿ¥B¸ªÌñp‚[}øày þŽøû0žiÒ»!ꩾtÊÔÁ;¾çJÙyèJ6Iµ ÔÕP|[ÑÜ»l‚”êùÁøûYé ¥Û uÌõ žx“rHÒ—ë¹ÄCáVKvjª¦‘kHc;õŽ«49{#õ÷WB âÒaS˜¾*s›š£¼Ðü[•mxæ qÁ:ß‹O™2ý pX—õ |¢î¯.×H·“©$TÈz6­ORA©fgVß^K¸&qŒ ^µ²#XXqØC¼7Ñ•ñýT³àRp{v,9UqG2P¤ò¡[hÞjílÏ«êå&2?¡GmÊ{Ðê x*øH…ü'4ÊŽc7Ýn†MÂD õ–K2‘’WBò½ÕÉ9>þ¬CøÐq[^'æíBZxpó€«Ô™D°Î†Š$MeµOmÑyúˆG‚“Îæ%¼ ð¾ì6ömý$ “±­T̳†|QÒ Öü)êÛŸ• ð˜×Ë‘ª«‰ |ÁHNàBû£R¬qÁQ×á]ÊjaÌ þ9‘#HS®È¬œ~¯½!°5ùöÖŒ{fo¥Tsäàkꮹ/¼\Ër¾»Êß›/¯¬ªFÐÀT€d°àŠ&ÆÆp9ˆ’^x=Ñs%\‰ò…ŽB+ÒÎô}þø9ˆò§N¢D¯ŒË>‡ ¼+è¹—0µ«µr´°Æ«£”ñú¶r6íû’½tþçmÝ7®²wˆT\cŸ¢:Éàp¨|K™³|“z` OžÔvû‘–ÓýTOÏ”J/PY~B?ÚOàQDÇÌùåèÿ;={?ûË›¯N/FÙÿÊžÖ¿ùÍoFÙ?Qððo~s’a|9–€e§ýÐ+`4Uëð¹§ûvº¬mñ*ì‰ö‹„‚ÄÕ!6[ƒWmƒH`—cºDè 7¦N±_~"üטõÌ÷dÂ?4a¼¶âv´vm1†´oeWú¹jöK³¬÷ó:ôàÃ83RÈÉÓ1ù¢®+ƒ•‰­m ]94S¶r£Òû¥ÊV’8}]È-qláPä;¥ŸyL×§”¹ÄݺÿçµcúV²§(§-Æ©ŠÁ¢ôZÀ´B¨ûû[“¥£ÁÑÆDCXõD&Ò†äc±ËІKü”NmI®$;Ϊi9ëÒ£j†þ b>=®=¥ ÷©á‘ÛÞcžåÉ5MUUÓ,Ë_ulÕ&O2‚³}[¹ƒ¯ˆ“E¤ðo¦ á æöƒ°›†Mx“·#êW4vÚH”G©å‰êþš2]bϵìÁ5|]..€JÁ6øØ.šj8Ù{þñª«‡ ؼz=ÑóîTá?^“µÇÞ×S¼iŸæûLV"[‘Õ§t!ƒjÛ?ÉbÄC5ÔS¹³¤¢L0/XÔ_løå4£Dì^õðÒ䈡±‘Ý¡|áH‰#ÍKXœ<@Žb«åËjI‘ïÈAº¢]­â®ââÕ@æ¬úY¿À0?ÑÀaÔ@zNöâÚï/d=#ü¥†yhŠ£ø9ÙÄ–w-M¹µ¿bŒó—Ó“—†‚#næS妊®Å2ðM>¤¼¶H `Æœ“/…œÈÛ?Oh(-lùͤl 8£tÞaMW-`6¯ë.§ä…Èí CÏÜéN®$ÕÛÒlù—Ù–(A:t`jÃWÝ” ¬Ð†'8! f>9ŒëIÌ0 `6›¥_°&µYû­EQ0S H„7w!ÞP3#ôÓä÷IòúÓX8:ça.Ôî$i‚‰õµ4еֳkà\õ ŸHI ÃØmÐ#ïOû*2¢“ÓÞä×8"5GÖñÈîfoú#ˆ|ð¿ÊÀg¼N¹x;¾” [hXÖeÏà‰Ó„ÃäÂfœB* @Oñ?»¥DX@B®#Ö¥‡OÐØâÓ§#D`?ùÑ=Xæ|$Aš~c °P¶À±8ñ?£õ9úu2üo¨ú?ZUsyÎÿ`€yÛkàŽ„ê“Ò¦e Í«6Ûð¯2á¯N¿~ñýwïeÂÑ|óúæÕ7~<ö™ƒyƒñb4¡úS¬ ]¡‚y÷ÑFFÒÈd¤;BË^>ÔF2Û'~]™á…ß3|š…ÓWk=²•MQÀ6Ò‚ÿjxT…¶º ñù÷exa‹qÅ mÑj q-RZ?ÿ ãà"Ü[k€càiû›ìW\þaÌÙ£ú @дÝ`ÐÑ£ÔínÞvÁÑ™¹“âGàoT¬8Ú+5zhå}™§$7…>ëCëÓ5Û*Üt¯{brz‚:Òæ<~ðÚà%°¶Ys~‡†;,Èq E2à’žü“2Üdç³KÚÚÙ¥Ô>í凓ËéûÞYBMd©m¹á>Í.YW«BôÎÉß”þæïD†y·G,måvÖ@±®&~7ÞP\ž€IÔás’ 2 PŽ}óaÝ>/×P8hªvQ'‹›ÝM–|5ª†PNÅ23ñŒŠbÔd–[B¬T —­üÐáhç©á>êì€OXáä>¶¿O˜è÷MÞ¨óãÏ/>R°)èŸÞã•ÞcžÝ(t‰JÃMMNàܪÜ®%ލе˜ëðØ—EsW¥b»Y%ÞáAï|vÏk³OÑó)J*FÍ‚uMÊ2{±Ý®âä0‡™ô§ÙK«“"«Î¶l&H Æ½ËðÁo v#N€9z]v8ÛlAfÀyiýúëñ²öejW2t75MF…å éÕ·oþrÚ²Ã`§þHÉðÚîE:ïÈîGàøP6çcHªìÐÇtùõ—pèstB”Ÿ‰µ7QÕÄæ· AÁ7˜‡C}ØKZúK¯|„çjùÓÂXÖå8“IpH¦—ðgzúúÅŸ¿;}vúnvöêý©ò±N˜ÚvF½äûœ ’6FGdâëåcy¡ùçåæÕ«wË‹ÒÖU —úh™Œ4­ìM'šálP¯–“¶»_•ƒÌÒ£OiËr£ÑÙ[³1Q},k(q ú`Å?ët¥$Õrs.}ü¨â ’ÏäSm6ù,kG½:Ñdïi?åãq¨|Öaމ¢í2»(±l:Dù0ûAª,È2—bÛZíöI:¨á°2)öóÓÎ,Ä£Cj.¯®6h rc3þÜ•4fS¯úçˆ@ïÐÒâ­#­@óèŸÝñ Š=þP5.s耤@×eo‚‘`J|K¬ÆoSo&ËÝGƒßD`pzuË{úŽFä€ß2 Úô¤T@ÀoµraÀ£ zGht•H#ZîÞ'‰úZ_¢ðvéºWØ|¨~ò’a·=ð'‰œú‡/BëKH -±{(G–%}&K‹U»FÌ#˜å“Î.Ì‚\=#Æ;¢³¨[I}ßbiìfú®¸Ó­Û‚ ÈdÑ o½ïÔÀžIÈ@CU*$wËtvºY¾+_a¢¢KHJÓ=n’DÀÒJ¨Ä˹÷ùï/²‰@:ÿÍÅÈýñÛ =–ëú‡ìÙsrªÜÔ™Ù)ÚC´?ôÎÁ|v rEy“;p èŠü zí|åÎÈðêÍØ;7O‘ä»f·è”ËAq5FGWØy`(×+zµ¸‘¸«äƒ?TUœ³èßaJÞNsaò§ž=ÿü‹ßüöw/Æ™ýýÏé$çTÁ޶Ê%Uë¼0øx;`pfxºjœnúùÌã¿ÛleÇ ã¤Mðéì DÁlÎ !ÓIn49²åôXxÌv«Ù'üJ¾|é$̓ˆéóáOOajÏ0H+SÉRîVQ”"Y=X&@Â]¿ªÀÊR­¥ÎØü6‚ôüøc%AF ¶8²+–øÍP}ÅZ¸U—ÛÜ`iΠâ sÞ)’]¤ÿòšÏŒ%†ÁÊamIžá:a—)e5¡°«ž4üÞòŽ.ôQï¥Õy‰Žð˜ð~Sb¸W9ù#FvÛ©3(±–M‚+(;¹Ó.S+mìDòáÛïß~÷êÏGl3ã'ß½xŸlï,}þ|Æçõùsi¡ûJËø›ÜF¥‹0ªØ#¿éW/Þ¿ y Šv §Q´üVÛ¯)õ°Þ¦ø 0•eç!óq2Á 7Mq­ÉTŒ& ±—=9X$I;ç>AÁÿs.CéTž_*À¦äK2/ÜôÙEPhbBž= €U¡¹0Hœš(3àñó‹‘>„0=¾ù‰ËuûKúä${nnÆ#ùì}<³ê>Ù´Û›«b MwX¬*1.ØŒØ#ÈÙSJ³ýÂt9í1Üg `˜_E8lLZL6”i6ÚVNé9]J^¹%cq¢.þå§Ÿp‰}™½„Æm}3›$Ù›n+PÉæhJ;‚ÿQÎA³åc„<‰“­/$p¿xÖRMzò&/Ò8»—R?ð›ÖîúJæiKÅ@ýÏô²ð…Þšo…¨nñ]Ð…É03 GöÇ´B`¨*²SÀ¨™©kZ¬veðÚEÁ6%d¶ç'füØHÊ×ëÄ¡b²GSSP‹]¹ã»v¾,®lÚú­ÒHùÍöîqÌz3ÃN:×XO¥>„"*©ÖI@›aT+'Óß×»¦¼ÚaNÔòÃcoqi¯0"ɃàgYœû†€qE;õF ræd#Þ,ÊÜ… ïÊS*uºÎ,ÂkËX|Ì)Býñäóé³é„4øûóé3ÊÁŠÿLFšjÝ LÀx°'§eu[Fe]ìL oŽåÃ)Áj6Œr–ŠŸã¸µ¹Ñœÿ\9[n:¥ e`†£~g¯~xG~á^\l'Z™†½g3› pA©ð¬nˆt396ËË[R_Á@Fù,Ë’5-v£‘]dª–þÎH›®¤ Õ×Õdª©„)JWµ’g‘ýœ‚ÏË¢¿•t è‡ÅòL »/Æê^¥ÌåÂÇŠç\4ŠÀQÞ)"5§aºfþôm,#é$0gÕ§J5GÕ¬ƒòø¸ >”ÎŒ„ rõ’$ab¸;‹k¥5OœÀ¡4ÕP¼ \©fDªOÒù¯9ÚÌm¨ßÒEE‚,Ë(‚Yo‹LЬE;Å0¶K‘lzTYÈu"P—õŠv¥Én«çP)¦Ù·ÌÜÓ‚á¨Ì¢d“ÖÅ=6röh¾¤¬¬M$n†z„$ƒÞ³p0”tÒ°O?J€ÊFN9YgÓž)z¿Éà^˜ïÍ›²öPùÕăµ› (R-)1y&ÉÚ)æEE|,-¸¦¤“XÈî2&PbL“Y•—x”@D—˜¨¬¼§€ÌË¢ZáV!Pox÷ìÑ4;Å£Z`ðdÒûa(2ïd‹Á£K; ökÀ3 ‹dád0ÅC6ÙÁeÛR\#Ô1TR«ð¼ÿ¾+[sõM áð/WÖ«3›04Ò“-I%³Ä±½·kØêSqî5‚'è™Zðæœá ı3µ¨J{^ï(Ü1ß NêŠDÀ ÅvÙcÐ)—* ä×%žþ4Û%Z#ïê¦uÛD°[”2ÐQõŸô3Tm¤blG„ÂHl]ÀWH¯ä²=jél*]­œ&~?b°ˆAéÒaËšù f°))—°I‡Ï›™C{]H<úXfÙ(}ÛÞ` ÉßÎ^+¬²h®l…yÙ]ê^JíÖR)ª£ðÞH4ÊG-ÃS…GæZ¨ZÍÕ7Ìm[Ss)ÓLÏ:gÐÛPêbÒÃéé”k_5¼ KuH<³ð |ü|]µcœ d„@EÛîÖÆCÎܳ^ééSÚ@ý¸m&—Üj\'†I˜©ø™ìëÞæ°;+zœù14.€[Ù5Ýué•ü(sÐ}äR*²éVK’÷0Y»Îïà¦öBÒÐ$‡„K§«Á6›ñ$g3ŠEÃ}"ØòjÙ©qÁ nk‘AÇé#ÒOÍkô9È›ËzÑ’ìæ  ¥¦»ãž_ú³cO½uÝ"À¾:]S£ÅÛÒ¨¶6)K%þ°µ-_s¸Mæ¦óžXÝÌÒ¨#Oy®XDœÁ) ȃŽã>!id%ܤèDÚ™¼M)ÎeF%3ƒ!E¤õT‡”‘íÔöwË0F29ûó¶ã\a,â.±m¹ 'õÐè‚p“¤HÊŒK Þ{€ãR=÷·oUª÷œéwWn]Ч¶þiïo20Øk¬¹+pø` %‘”ô£ªÔSª:* ´$’K%* bœ}*8ÜÉGâœqÏ"§±ºm«ùŠù œ<ŸDúUy‹`·‰aÒK’¼Ì’|Œ3–뺮ËY \E‰8°3mfŠ™jª€ØÁ‰‰?‚<ˆsQ¯°SL|frwbZÆ”+©ñŒÉ#-:…Xþ”R‚ñ+ï`³?s#/0G%Wc=PrJ³ÔJÝ!æàI]æ*d¨°KÃ. b’Ñm‹p¹…>°WíHOÏ Y\I¼è«ÍbµÃý¥Ó|B_ḉqr°œ\-3¤[i·õf)¤Åc×Êõ¼¤I Â&¶ËÓŠø¼ÀÁÖO‡ÖfÎZ|ÈɈÝ:àx´‰"~ݶže)ßlµŸI= ºÙž»i«~–=» GK¶A°`¨tÇõYßÏA¿38,ÊÕ…{Pw,ŒysBþW>"O_%™e!å݃»}¨!%!Ó¸‘Ä -Ø>7¾¡™ÉòXS !ç¿/HÎ*‹iVä’çÅ%2饓H»ï9±¼¥Y+žŒU°q/òhfzï  B æ(i[çyÁø¢ÿ3UÔ'òZk³œ8orž(?Sêd­< ¦,Àë£C«—Vf‹*Ùhòþãk¬ÊȱÃ\ÇJ¥C’$)cd@ q]Á}·7÷¥Ùü´¼žþyšmï±HeÆIßRj"|´zè{þ§mGËåÓßýî7¿->ÿ¢øâÙåo÷Åâ)Œt9_üsQ>[~±Xü¾,žå܃åÎ#;¯#ž­Ã÷éöþp±šüþ÷v.ÀªÎøÎŸðùžo%O!ú%Ls â~é÷Þ$ 4ò°à޽ dÌ`\o›[ÛǪODÔWôcŸ4ËÎýz†¦üaÔA4V((yoHÆSqûuÌ”ÀÚ{½ t®t?yr2‚yÝ?~09EßÞ÷hÆ­œBÄHd 3èŒeë앇QRQHlÑá#?vb¥ó¥N±Ã°@+Âê²KV)¢©“ì[IV0ï…/½8«ê¤¥¢1f»[IEÁ¢5R „ZY2ÏUò¸ò»%2¼uîqâíª “CÑ zu,Uè QIZ2ì,wÄ à~‹÷áaaÍ–%88ÔF©,ºƒ—w…Mè¼Å©H¦WdCŒ TÐzd]Ì]2›!éšÍ(g j{0 ,OÊaSYK!Ûêr€lüô+d¼§íZð‘*#•‚+/R÷äöó3A¬Æ+R—R*aÊH€Œ Œž>Ì¿í‚J!Xf`QZ»›Ñ±ûr¢µv¡®ƒv¬H]Å)k„½dEµ±ðØõ†/£UùÚ‹éƒ1ƒ³N[Jh Ñ`UÝ ÇÅ­É2Ù"ö’b'çâ¸Ç!<Òäìøb“kúåeµ¨h¦Ö&J›û;¾°bÞÖj€â‡gg"‡j Ô‹q pÁÈ}U0V± ×8/7 º1‰×ß&éB"ÔÁAáóÈ÷ÓPviOÖ0°œÛé#žüùÕOþ˜gçÑ÷Æ<ÚU;ã´T9‡D·Ù“áÿh":¯ZfùsÁ.Éa±ˆaMy©ÛûÞ ucš´¡”–ŸÝ¦ À³qöþ~Ëj±#™ òµÌò5ç$5 l¯sWYÕ‰Ü_a5Eî°<är´»æ,ÇNÛë,·6ú";ü„âkFF<òÖËN'õ”¼©¤qf‚ÅO†hûØLžax}·>ÍZW¦|¸ÜrTçs‹ÞœÉö¼zÓ³9AYSm˜ÁždÃÃO†²9›nö÷] ¸‰1…è4f7ç쨷-XGNЂn>97F[ðˆÀh³Ç@Cü¨A»S±óän.Â(¥íx¾X/b~ /"\”Ò“¹¤ïôÇÍÑ $O¶qRõÂïVf9|[ƒP%.1í5Ë£yÑ•Ý"rn4#EÕX0ÓYò»»a| 6$ó·‘÷e[Ü£gȼÊyªÒwpß‚  V‹Wfa˜ }' |ÕÖúdèIå¯PS FI-$ß pŒ\D ù žíPlÉ›ö,¦n±mºñ§®±aˆéL0­—ÇŠî8gèH³!gúŠ8O f5¼¿à=·×ÙÚFúp8zvñ<+ôоU±¯‡ÙgМ_¤šW+¬c_±žš|:? j%o‹Öér&ÛT±…[©`zþÄ3ŽìîRÚ¨°Ã¶©ôQ“Y[SÌ>‡ëÀE*2è Œ{pI¢þ1QX‰ ¢ãçh†G²L…@-%Ö[)pú=oÜK¦g@@þW%ìöõ÷³Ux…å¸Ož»LiÈYD¦Æt‘ï%m¬Ò^/)ŠëŒÒI>¢hÐê×ךö›>6?»-§«+!šÄЮhgì–ÛztmLd%×Ë2ÑÌjùÊÒòÂRS|iDŸ O 0VïÑ2“:ÕP]øì¦²> ¬ºEd’öŸGÊX¹h+`Ššž®ÝLê Sfe9‹¡°‚Éâ=måbÕú1ö÷—\¿£3"¡Z}ÆûaÝÍUéŒb…ì,«(ÛtýS³ÿ«ö18B@ÜbϺ0ˆFx‰¦”ƒräGÖŒŒ~‘öÈ¥;Ì9›½ýñ¯§¯ÿ:ûîÅ÷¯_~{ún†?Íû¶^¡/ÌIüÚwÆðJ ©Üˆ·'uEV‡4”T=[R˜Œw‰6/Eý›Éwü'ÀãÌß=µôýþ¾«**„æŸyê/údoŠ+èÇw_¡œ Ù|qW9?<~E ak§ ,d€RoB&õÀÑéÑý Rë;GØ!2Ž..3!Äàß>éaÔ ÅiúÉv[n:±Ôp÷¦ HÉ$ˆ/ž£…cU~à§¼_0©74¸†96Î>ýWïRt™p‡@¢Š_dZ1a:G½9PÒ“+ÎS`T¦-æT9w’‡¥_OI‹AzmÑ.ª*—F© aSøøéU¥Ÿ|0èÿ½ªEH¶Â £ÍÌ”|O#€Éq‡Ü“WDÚ%è¢ÅIm†•>Kn}’éQMÁȳ(–:…KSú‚ctÜֹ⯧WM½ÛæÏˆïqgüá0¢¾ÜÝ„i«ØNûˆÑØ6² Ñ¡AG.në¢ôú˜LúŠž³‘ÞŒ°Ç=‚âÁ”ˆóþÌvç}F1šo¶óF8Õ/YcIöE¶bjúìrGªIî6=ðILÀ0EȲ3"Øi®Fý.«ŒY ®)AÜ»ƒ½Ï PIŠgú$õU(:mµ'éü­¸-‚(æP7ï¸ÙÌ4Ÿ®€eŸžQÞ0|Ïß6èVÜÝc v þR>©áwÕf÷ÁaãcO_¬êæ†Ó²I$Ói>ÃhY QØøGê®ËyÁæ¹’­@ÉáßQr@K¡P1‚ƒ›~„Û&¥ŠŽŽÃ°Gš9Ž“8ȵ Õ±/ ¬ Ul·+Žý¸³«n ,ÈM/›7õMéëQ¢!©Ãû”–öËw¯_½þæ8û~þuV,‹mço rÛ¼’q*.Ÿ¢µs yCFãÍ{%t$ØßÐxŠI´Gî@JbÑŠ,’dü|öìÙsœG ™dµbT/þª‘Wø|x´k¬¾rìÉC{‰Ý^i^e¹Ú\R…ÒZ49e‚ÏéfQl[2ó ïTPöa¤7ö+6knë “G™r'TQpÓ¢ÿž¹°W» ñ§ dU•m_ÉÃìôÅÙ)b29}ýþÝÎóÒ1§ÉjÆOrz{è7RÁ¸û™ÉÅÕÎ0VÓtq»mÓQ¸§_\ÏAÜ´B«‹g´pïÍÈnƒ£œ ‰õA~8Ž(^ù¡êâk‚Îíâ2·ºÌ,o” ðO”É®p†°f|þÞs²‡w¥R!ÌcásÁü+:1Õ ;áäT’JV^­¤B”ÀT)wXK Ö×àOBMcã Ií„[:%¶Àl\¹¼}·ñLLŠ[bAô—#QŒî>³hÁ¹Ì|„.H@Dú - D‚‰¯zàBTçnÚûOnšý³sÕfQ„œê½ÛmM)ó"˜t+b’iä|²ÎÙ´+RÛ£‚ÁRŒÀIa;Bn»¦‰™”W™`À†©ì€yP…­»ß–3ä]‡2uÌ 3¨‘-$ðÔ˜b³¢¡×ÌÕu+Ég&@Éi‰bB$&€ýU§H2—â|mqÉ&ôžüš WdGTÅO²ü¶‰¬Â1Ó@!e¤õe V;˜BI½ä†c B:IçOoLE‚>)3¹ê4ª¾e'—‚ñÓŽÑBz SSl g iÊi[¢Å2o†ç?ýtt1””þfª>ßJ ,]jË|ðÖ÷´v4,+ £G²+I(¼³U]ßг—Uè'€Ní'ß»ÍâºlxTßeSÀR‹Õ â´RŒø›ìííØzÀ)žo%C ²YŒ&†ý..Áuvúþû·ïß¼ùîÌ^†ân€‡=l¶lŹ}ñ_Ij_»ãS™´"Ã:Җĸƒb΂ŽGø£ô:(`UÀ$ˆÂ9 îÕéÀŽ’2ÎmÒù“¿þÛû¡µ»›|ð_†é[LÒJušVb#Ò—Vb'}¤Ä<¤ë2Ëê­ýž¬îlZ*ÖLò Ü«&ºEˆº Y?yfÀ&¢»æ¿à? ùo-ÿ½£ÿÂ8à ËdWó¨”ÇÞΊ%úb%'l$0ÓeŒÞMÉõ,)1ÔgÙN N›¿ZºQùÁF´ÐÔ«5:`Êî^–-9CÒÓË4ÓTÄU‹7»¡ÍƒS'M f Á¬mÊçÃ4å,oÊ+ š+ŒW­A¤#7D_•Yµ£4k ‘ ˜ºT&C‡¥.êvå¾ô¿Cÿ- [ˆÅ›“L`àÆæÓp³zÎ|¨q[ƒ_ËvQlÑhI-Fhúê›×oÞ¾|q¦2{¡¿½ÅoÚîæb÷:Q§Âó!—=õ’b^ÄA<~ìrÐC#îc™ÂjÔ’€S9Ì" f„‚S9Ÿ£â–7N»•RXªõ†4×­-|ÿû™”VfŸíà§Ñ A"×rU¸f‰yAú„ë}èjúΰQ&M‚gßEóîüï¼Sä.Î- µX=4TïHÝu_/ÿ‹‰iîQÓå~RVë Üp?\Q.ÓÌìTîmYPv8Rm’02nÁèµ•à‚œæ·_Ì«¨ Ë¡±v¢G[]"£Ç¢–âŒ:ɱz „k\—¦£ (r.ÚØœ{M–³†¯SøCNöС‰¸“cÀ™©Û4š’§AE)å6«û°;F$’ýÊ[†ʳcFÀN«†`ÎÊÒ~(³Ãg_|ÎU&)-h¿ž™ò’ê<§f> p—1kÎí1›.¬!TByÅ—&¾œ˜…'ê_DºÚ=,Á´RŒFNÂIßöò s0nºu´$ç Ü„ÏÌø°Ÿq˱¬(˜è™é‰VQ[S%/àé “ÁÓs¸1³µÛ~IœÀâ°l | ·Æšx×Îý „%ŠZ4kEQ}ˆê/[†f0Å"ÉèfŒnì“ÝÊGƒúí’Or àó瀋9'Ë‘ñýQ59‡c ɸvîCbž½Œ'Aò¢p,c‡Ü·¸c:O?¬WC»io|Yèí0O2*eŸÚ— ©ÉÒ:Üu—“Ž\W^[³îš²—ØŠ ÎÈ ¶eËÅ£ªñï—ÞÕÝŠw€Š ÆÀ¬LA R¤›ø-ØNÉC¸<\‹ì˜PÐ8ψ/òóé–G¢*÷×X9N Bp°ýóéç3%‰5¨n6e(ŒÓìêÅùR²ÄÈ+È3™·¹²-cMþC`H›JŸ~Ô¹‘zÊæ;U‘SåòÝ”Uh¦Œëz?h?û­KajÔª`6új·Z ©÷‹ 0_w•5$glž:JV¹†EMf޳ݻÆE'W—6ùïÙW¯ÞåÊ'Ün.#±1@d‹Âû2CGË¡µ‰Çíb†nÏB‚“a@ãÌM2u8Þ4°×úãq€úôa€øØsQøÙn]´7†,wkÉ3Ο>­Ÿ>—pû4ñH)ü-çuÝ+lMÉdó™Qpå%¦œaŽæ~Š5í(7ÎÎd°%¿ŠV²jŠ€mÏô®ØíS…§®¶“-p:cÃÆ ]r¨îö;''A‚à}nR”Ð7#!ì€þf×èüRL¼Ÿ~zs7RÁ:-›šuªÁíh¦•®À%ž$ÁéÏàÌß–«­heÛ\¯ýäàûz3ãŠ'™qêÀöؾ®QX\mÅå“È•·óCšzÜÅÅ5ƒK™÷ô,¦{ÛPÜØ„Ò§'‹Îpï4hO×5Çžœ''…¥â³IÇÅN;8Ð8Õ™âö4 CæñºáyÒ©`æ¸ôA3Ð¥™ùC.=iæ']ú°™?ìÒGÌü—¾ÇÌßãÒ÷šù{]ú¨™?êÒ÷™ùû\ºbæ+.}ÌÌséãfþ¸KßoæïwéÌüLšÖ Ó~ÐÌ?¨ýÜaZ'M{ÊÌOéý˜i2í‡ÌüC¦ý°™XsÇMë´iO›ùi½ßiZ3¦}ÆÌŸÑû ÓzÄ´5óêý.Þ?fæÓûÝ|ÿq3ÿ¸i?aæŸÐÜ=¦õ¤i?eæŸ2í§ÍüÓ¦ýŒ™Æ´?fæ?fÚÏšùgMû93ÿœiŸ5ógõ½¦uδŸ7óÏ›ö fþÓþ¸™ÿ¸iŸ7óçMûE3ÿ¢i¿dæ_2í fþ‚i_4óMûe3ÿ²i¿bæ_1íWÍü«¦}ÉÌ_2íO˜ùO˜ö'Íü'Mû53ÿšŸûsfþœ‰š•×M$¿ßÄçÌÊes;‚H&\æY¦WfU&óˆY4óWLtù‚€ôUÝËÄ&~Î$ÿ>ŒŽò¶j¢û˜˜5=&ª¸Ìc6SêŒ4‹òùãȹmÌ»óošè~>~ËD0ñ¶‰N01g¢™xÇD'™xmŠ/°Š)_ż‰Nññ§Lôï™èa&®™è4Ÿ6qÍDÓæ ²ß7Ñ 3ë&:ÃÄ‚‰1ñ^³Ò0×Mò³¥xÁÌG¦3b¢GY 2Ñc&zœ¯Ç&z‚™‹&z’‰%=ÅIJÙÔ%ô4–S»iæWL0×9lÊñus}Ô$ÇËÝgXxÅtóNô1Þ4Mô,-=gâ6»xÖw±câŽYéâf¾g¢s¸E‰ç}‰U½àr?îs7qÊÜ}nf¢—Lœ1÷‚Ï]3ÑE¯1÷eŸ{WÖÍü:f~ÃD¯°©›&z•‰Lü-&–A¿d¾šù›&úóo™è“L|†£ÿ‡ï[M|̬|ÖD¯ó’ó9€ãìÔe`Í{cF/ÖÓÍÊ¥NšÕ[­Ñé¿ÑÑó•¬ÛmU»I%ê6;K•úZÖm׳fCî×;­n=:odI½‘YXk¶¢Jw±5Ól-k¶Òé…zG•«›Ùr·3Ú«7®×—ât¦RyõÅY½Ù’ÇQ·±ÖŽ;™ÔÚ휮¤q\É–ãJ½Ñè¶{õÎ&>‹&ÚÎdÙ袼yº"µÜh¦ÍŒåß/”©,wÛq¥'_{¿V›­Õ*ËYÖKŸ=s¦ÇÆ,wÓ,ŽfºÉÒ™4ÎÖzèez&–jMû™å¬Ýmþ¾ü›’Q2YY.K­î‚Þá.Îj½V=“áiO….·Ñí܈yRÏ–³QŒòÚBšÕnÔ“t ud»årÁÑùdéb’t“l_1÷Jƒ¡vhÖbÖUÛ>ÒfLÈåÒåÙ7Ï¿öZmö¥W/¾~q6Û!yš®}ò⻳Z°$—Vw)–¿Q3©¡Bí߸\›‰4¼Õìĵ$¾¬ùCry©Ûn×;‘fŒÈ%YëÔ8ŽZë°ŒÀ„½‘aYl.é0ðElÝòR·—é=ú¹Ö”ÔêIc¹y#ÎGúªÂÎ¥Noh.ö­ªëž~MYôÕâ%í“ü• ]ìN ¹çÍ,Nä·²'íúFÚü fmÖ4KÜøh­ÓltH‘Nâ¤Þ”¶b¸®¾û˜ýûøúÆÝlÆ­ˆ#•²™zKjÎÇ ‰ÓîZÒˆkö»Ð¼Nº–Ä5ù¸‘u“Mfb°Ð‰¤¹°(Èöp*:Q_nÊï^ìÜh&Ý–ï«ñêšTÆû1 $¾ÈlùuYyQ]ÖkXZò÷…¹nr]š7g"]—»ÙËݵNÄî¼'©ä½$³Új6ì×.¾}ñµ+Wk.;Éq‹âÅúZ+ãT4êY¼„>â&­·c¬a¾V\v«Ùò…¾®îE)E3µõfekÅ%.Év½ÙñãoȈ'RõFœz°ñ>Šj2cVl·I&^b:/g««M´N¡‰ð™%k ×þV°2…*óKú2@¨ï Ao¦]otÓéG™yô‘égžª=õÄÃ"žièúéÇ7=™f*/,43T›¢&h„–Ð-¹Žü€ïÈJhn­wrØ»[!ÖwÞßÐt?fn†æVÉÜ,™ä-W¾Œn²À¬ÍpÏmí¨®lîò4pOÌM©h@ ¾\=ƒ1âÂý`\L×à çSFKWár=­gYÂ8X>,èn²6§]U½GõÏcºn»ÙrµšÖRYb¼†ìû5y%O?¶-ÓÇæuîä´= ƒ½ÁQùßp¹_N!ÆBÆv–Øì²6ˆˆ —t{à ø¯–ukõ´Ñl¾U0ײ׺à´ý˜ç›ÆO -›B³,ƒâê”âJ löȸ9ÏP«çVW=lìÆùf²¦‹ý-E«º¡ôËõVª˜¾zqÛVÖWöªe¿KÁx0,¿¾ÿSŒë쬋)H¿â§‰ ÜAW¶¹íUTUû&«ØÞoh²´7œ§×py—K¸|Âus»õITu—¹0ößAù}Ï_´°òàïCôPØø¸ ¶=úŒ‰¾ÕDBÞ UûyÝ6ÑLôm&úv}ÑDšèK&ú#&ú}ÙDßi¢¯˜è»LôU}ÍDßm–öƒ×Ê`á…V¬Ø4Øa1„WX 1+2†?MN@Ò;Ìù1™•qðÑ-™Å>¶¹¸éÔQÚ ÕSó;M<é€p Òw[Îa~¸$öZ®‚—˜Øo9ˆ.2qÐr (_0éø‚Ãä eÊÜcâ{ÍÊQðÒœ•ûÈÐT\æk…Ìc.óõB¦ðý—Y0ýW˜Žÿ*'Lôš¨ÊÄIÍ21eâS&z“ÜÇCL¿ÅôÃ&z›Ncò¢9fÊX¿Ã̽ËÄÍ3ñ6ú‹=jbaßs,Ìã&Vó{Lôir@O˜¨ÆWž4ÑûLÈäÕ™xÚD LHïÉ ºš*õTZ$¥°y ·…|lNßPb“/¶Ó¸Ö¯Ké^/­,×oÃØ­$JúN’\yÒñ½¥¤.t<Þ}+}T®Â,5âŠÍ¯L¥1Ø8•^]½DVW.t¼«%=•ŽåMbý+‹Òwé´äÂ¥j Ò:m$Í^ƈGûÊëÃÔ•Io4ZkQá¥E£ ]éŠ×,OXëöT¾çdÄz/íhd¹Ì=[‹Û#Ю µ¢¢ZÛšïw_1¥‘`Wp0±ÿ‘>X¸/þ &B¦øSƒ#Á„ü¥ô®TDËÜÉÐä7sÁJê(ùn!£»MÜä¼zÉ'PSŠ_l-RþÚs+Ø*úK§]NÉæ$L¼¬ñ;©yTT}—çŒl4S@“ŠAq™y„³ì¨™m™ pg—âN¼ÑKžÿkÆÊÈM) n$,€x¡ô½]ïÖsX«˜Åª_1Vˆ¸ øñ:¹b½¬ÞÉj.o{à ²íqú%×î*ʦ ÈMA"­2Ø@ áN6+])CäªÓØ}ÁØ'{»E€I.—vùxØÊxµDŠH¶_@ AhœH§0æÕQ7º jTn¯«9 Jêš© ˆêW$í,‰ñ¯u/e7þúŽ Ýj,¥„q»+¨`{ÄITªú›¨Pa¸Ëá‰`¿ÊËFJÐ9軜pOÚ"ãžv/–œ¯¼*/ËFqˆopc0àr•Ì$ÖÚ%:˜¬÷B,^í&i!™••!4OÙûaÞùûÞË=íø§ÑÓ±h‡»›¼I»‰ÉƒÑ¸d…°ŽàŸ²ü)Á6‚ÌS²_K £]°‡¸]Bâ)%Ìdq¬Œ›dŒÐD‚leÌ#Î"5áî÷š³‹]ì0R»}jOíµ& j¨p»¬¹û¡×‡MòiÞ0JÎÙº§›AvÈRtöÑ$mNzhŸ¤áÔ¿?l’_dâHžPÚé{ú¿£&§TD}¯ÉŽrÎîÃ=Tt/\!¥w}Ä$?.›#³݃ù¿pí(Ùýxå¨3VNà}yöéЬo šUssPŠ.š[C®èƒææñn+ÌNš•)l Gš´z>”&éã›es}È$_ ³SÈ‰Žšƒ’ûùÀH!4å˜YyÈøÒXºò`Îöóa“þà^Uá‰f.»†6SŽ{§W'QGÃ5 mÔ;0*²\6²êQT`¼¹äAÍŽ¢¥·ë­5Us+2!q¼âðHw-ë­eéJ*Éü_;ÄZý¸œ3Vûªcù†±öKèk LÕ?c¶K[h—®õqÅ¿Žoü)|I(ë=Áx¸7Ø–„ÎÆÿ¡`g°W®üN’Þކ£Áh8 •&„;žÆƒÑ~÷_Þeÿ–‚'Âq©s¯üJ¥{å ¸îú°¼9‚— Ž…“r·'8D^åÈ—ðÖ);.ÿ÷J»JÁ˜<Ç•´É.@…Òþcé>`paµÆVÏ"¿äiÞ2ò@¬¼ ît¿c¹ò]ÕÊN‡¬¤4£ž„u ´ºB£¼E‰ëÊùzµGŸ¥-K ~{´bÿ½ÜÜ >£°ò+ÍÅÊñéi,œã•õz p4ã߸Ì=å-H…©¯É±¶ÝU<æå²ëuSÙ)-îHYD+SX¾ºæ=J"Ø…[J.1ÅSD%áê¸|‹_é¨Ù#½$îµê •P¥Âp6_È*nÇ&||º¤+™kÛ&]¨þy©êMjLyŸp‡£„© »ÉÀ³æÞªâC¹l|Ž"šk›VDñ-…3Ê_[òsÈ(Ëx Ñh{Kë²äS¼Už&òn‡xî¦RC¶ÂlØÖb%!¿‡ŒüÌåÂáê¯+édʹÿ”ŸrêÛáèêÏâ‘þi‡qR݆r&]mu$Kw<îQxåF½µ=h°`w¥¿‹åi¥ÆeÆ‚£Â¯ïÉ-\¼Äì°_µêÜ!ëkIÍ-d™ÍNqS=óKò¥´ò~W)©™|ßy¿BM.³=]Ù*°…Ç/-ˆg ¾ŠñW‹˜ÿÝ8Û˜¯l®þlP3ù)ùrrÿ¢2‰h¾™!ÚZ>üŽ uÂ3ºó¯GûÞ0ŽØüÃ…ÿAªZ ,qgÂ1Y¬‰Áâ2ݸ‘¸©OY“%vtê#Ë­}ðËfã„EÜ®RÇ …k*#ßû¤™Ó…™ü_Ì6‡ËbÿÓ 4­kyã  d†–k¿píDXÉe3)«ù>Mž]ýª7o”èB$|³Ñ 8ÁÌ^] —8dô j€ò®jÜE}QÁp}Ĩè–ÖÝ´XOš”~„ Jj¨§`©^ýci_¥Ö,‡XS¡~3Û$QCUµ‹ X£ê¯¸U£&æÂ`Æ’zg)öŒ"›Sý?‚Ó¶–)[ˆƪ²€¨Cèˆd“ɪÜE—QQ Û?L"K¸†£îFw­“Å ?¶=È ÝLÖ:ë€×ˆÒö Ev‡¬Š`B¶™É`W8H‚eg¸3ôB}èРÍ]V$,-:×™¤ížÛb2òî,ÁWÍtP"*ÜvFÍé_ÅI㓎ðv½4^‹ºÓB;öh“@¬' iêÈiˆœÌxsYÈ :‚¬êV†”æ­ÍJ§Þ¼?2¥^½{£Ù]K+½z’mV„b®pš|]øTVO ÔÊfwíd"ø·%ôF´‰E0ÂâwóvPôB‡ëœiLÀ´3Ê9‘Õ)!¨/ôš‘Ê©eººm¥J$)=¨r%áf¥Ûì9"¿˜Ó&RÁöé t2jn2¾8KÈÀLIÛ»Û Gw±ÞFüO¥ªïó;‘¶iÈ„é>0–2ZQCðÀ"&Ø•;Ãó[¡C±ðøRêi,™uXצ(:yôY‹v!)…‚.»:G€GÕÜ|óY Ìä+|4jó)²ßAžòa¡º.ûŠÌuŽ™² 1áâÕ8öoa©`œ¢UYXlßïúöý.(b/ÏyÙiNYY¹ì¼à ²}DýììíÐ=¬>@:hoÑ ýÍzMÂÊAfbïÈid“Ô æ[ƒT †ÖÞ ²#Öê¡ó¨mbòãA>D܈ÆåÊùwŒ‰½YgiŸOFäí8ˆ¦5P¹Îô1")­ƒ¦õ{$ï4–½Ú—Ñ”«¸Q–b›b€i,X ­Ö‰Ý¯¾ûæ«W._=ÿæ«Õ#$CT¥†È­b¥c —¿ŒK«‹_eÐh[EÙȪÿÊXõeõ‡Üªîöì¦ÓhA÷Œ~^™U³s¤/]ÉÝ®P ê–“É’$~ªÒÛ{4O ‘—> ×Rý‚q´÷£~So"Tñ“îåzq’â$ÙÙ°Ñ⌧A1“2BÐo¨Bê¥ÜÜ0 ÜwØu€H«ÿï¶a‚_”ª~˜à)Ô,,ýþÒD¸;œ()>–?Ø-¿;%wÆêH8 Ž åvUäélP`xeÔOfe2Uhõ ¥@š;·¤Ñ–û2˜ŠÐ† Yé6kI"$Ìú2,ý²„ŽƒBÉÔ£ènÕËV”o-E{Uÿ½góâ߉´¿w »YQäy£Y¯Lû}ŠëfzZEÓ•ö팞(ªX€“…˜P;îÿÎæ¸dú—La\¹_çíñbhO'“m›°2S©\mÅ ì43Z²ÉÀUêKõf§¯yån7¥¹psq1F=Õÿ)£?Óø¾Þû •„;•oïé:q5N–ë½£™ÐTè·¼+´ùUâBž À»†Ï°-¨+êæí/¼$TT^e‡dÅ.7;qÞ”õfJ+Ò?`F|}…ÞìâDø¦0}±¢zù¸µDähçØ¹çî…¾¾õ¤‰=`&G¸ó "ñ#Ã’ØINïÒxÉ|ç§Ï¸RÏúàý?Ñ}׃“B:­Æ9a=ÙµNOjCž®Ñ.Ô•í9 ã„2-7)†\l£öYó˜® ÀÀæïGë"FŽÀ@¨SµTé{}PUôÈ‘„|euý‰Fä i2·F¥Q£´pØ3–hÜ,•aÃB yÿ¸&?Ø9™ps"6;']‘~%µÐ»|¤ýËÿ,øˆ¹´Dp2Ú¡+ñŽZ˜¤§B|ø,gì‡;ÿÙ)HˆÓËåb»×Lš ²º7”<^_Ž‰Ù ¶òuá]Óµ R‹Jg(K«A¯bGô¯¸Ò({"%WG‚ {¦{½ú¯ñý§AõµY¬›>WY¬œ«€¢:!ÄÉõ“§$K‰ë©“W>©·$t§NVÃX­©bËõ™x#NGý=n â!ÕrÖ×;äñ¦/ꟆõÖMUåŸNËåÍ‹³oV®žŸ½xáYi9°h\O¸W¹.åãr™rG¾òòùK¯ÙW¸…_¾òæ]^P.€8‰Z±ïÃå_݉¢”ħ™Z3¡ÂH ¨ªÇßA‘ßÅåßâòï\9XÕã©v¢CÕNBî„-Mè?é¾&4f¬†Óž:›áhUGç3 Þ¤úóÆ9Nîðè/@‘/¸æv¯«DkDÓ–bß2pÆ­B”©–‹²W±c€ˆz+ã§¶þ¶Tõ¯FßDÍáÕy£ž¢ß#ÿA׃ª/ ¿Cž R–uˆ¢ú=áX¸+œ ÷Hn) ‡…îç;{„‘÷¼ù«—]Öo—cIkÏûãËíÆ,sB›sáÚ Vx°¢ûbHËœäU³zÊ)áhçxS • …¨C9eœýÔ€7‡,Yi ëœR‘Âg€.p^Y ÞÇØ¾º²ÖWŽ„ånmè#U¬Xw¬á<}沊&Õ·mˆ…m(©]óY ¿‰rý¶çÞžÀ•¥0Ô•YO°þg§^P¬•-´f¹ÚöiÖ²‚ÃUä®=2ñ ˜p28ì- ø$ôá ü µã ædÙl4˜éÌX ¹¥lÇÓØŽ/\;AÛ3cUlyd‚»­¢ýÕgÌÜêq…]yÉ¢q¬ÊÓ†úq͸¡\¯·®«@ûjÈ%ϹÑ[ýÓ&¸ƒh­úÝf»dÎÀ^0CPc‚§BO ©6ü!ê>Z5W%÷Ñð•¤%%T¨U0e{©s£ÞjF÷K$Ï+'’gIÏ+ÿ¾–ƹñXŸ·ª¯¥êg—Û U¦dÅĽ¬n˜œaÁIʳ‚J7ÂèƒÆ2òŸmÛb…‘¾µ-}>´C0s(¥|½Œ~Îa:®6Ú„[T›(çøfeЂ`2‹=@GÛrä î6ìpý9‘x¸nJ-r¡&ǬªÊR½4>|ã*8n÷ Z  Ä Õ^ …ƒ`®sÚa!ÖËü¡BÙ!õ=)S.´8§[ÁÆ1­þ€í‚,ßø–ÐFùÚå¨ÓP®ÈJ)—Jj8 ïÆk¿¬ÃŠ–õ2Œ)ë…æyBlfÆjRèè ± ×΂¢Ž¸.¬ªõ&7AØ/†Üuv_h¦‚Ü$!j·‘Ÿ¹È[€Ÿš³ô®ˆ3°° ™AkÓ)òˆ°þKg4šäË¥*ge‹µÛßÃHøéÛ®áÚXOõC°2Û>“Â_“ªþ¸'ºK£2è£p8+B,¥/x¤CÝôÌŽ½ÝÞO\4‰•õ²ÍZ(¯lVX¬hpK-C¶–³2+êx3êEÙ|Ù—Ñ¢ÍÏ[Õ1› €€nõD.À[ êî±ä׌¢¤°às$±#Ð+#+¬Ú°Û2åÎÕݾ1,ÜH |;´Úïòmúœ)"í=t¡í^Ò$ûxÝÏê鑬Ò^*U„/lNa“—¨¥_9„Ü¥ @YMòMH\/™rv˜²Öÿ>‚¤Éîɯ@?2÷²Ìoø2R`åhÁ P‘â„IÿoÎÇ}&y8Üø˜z‰Í•*[¦`ˆ]ýmG†¹“GýmüÌå=*»Ðê>ݵ5^Ʀšž# *ƒéÌ yÔÃÒ*FÔPz*¥WIß­,Ã^†Jj1=¾nÙ©Š£HÖzŒ„{‚¨I!QdEJ·p!ª?”¯U„›­~±Kg[ãYß~"îåzêeê¹ð×%šŠb ¼©; ñdqj¤ŸÉ.%éžpXZÚÔÆ"Ì’zZExk½œv[Ò^µ=ä)0"¹,©>l|·†;T¾{PêRüê·‡h‡‡ì†!Eòt7­~jÛh.ly?:¯vAS» ‘+R÷Èêjo¸;(Ëî²K®‡d¶ìHS¤±àžûÍ„¼µ‡–ú÷ž-ö!óÎo’ªèà “òÍ%zÉCG—Ed$û²²²Sn¥–+ŸF¼¨´¾¨n;îFÿ‚Ÿìû­ŸÒל«=²]RSÂfº n¦Æ=+ô†Ì²Ëo™¿Ü †LDó\íŠGùÄ–Ö[ÕØ›jª”ÌbРO¢_ñÍ[ؾXR"­äÃv;­GÇÆùì|ÖU9ÒGû&Œù£…%Sö¯dí¤‹ÊEZ+öß,4»„G Õ²këÇÓ~|õ7‰žÇÝUæH%-‚›eg«J^à#[]ÒN@¼„ØV]ú³]{µ¡$,§è©µÅ€¨ép‘ŠCFŠP$ à½NÁJc«ÿŽyÂb’7+ˆl+3•û6ZIXî5©BÖQš‘¯Òh²]RnS |½]ß\ˆkhíßt'tÃÞ#°¹' Éb‡;Í$äø‚våÒz/0<ç—uú1È\½Š» ˜Ýëì£I~Y¾³zŸñ W¹h)Ç♥Œ˜²÷D…§°s¾uŒ.ƒbª¼Vr.ßV„º²mèò°Tÿ[¡³;ÔxOа+ÙKéÉe¬fB·p,ÔÐ NBË'%¯Ûˆ º´¬d+r*cT‡OºeN‘©#§¯핸'0[¨WZñR½±i« \ÄʪosôI?¿Œa{ѱ?Í´¦ê@;¾UxÇr0 ‡{h ª".—çÒê*ÄÀÖçæžÀ9è©ò!“ Ve'ñ u%â²ÑfØùÝ–¹<$-ùm/qæhB¥±àpp§k = ¬S@rŒSk¬s…µ¸¦…‡'Ì,e§R4ïÔõ%Óg‹…ÀjPÕ+îZ¯ÃÜÞ¥×)Y#l¸g†&\¾ŽÅµNƒ’1ÌCJË.-›TÖ"D>Â~ ÄÙZŒªòI˜Éä£)àXSxR™’ 9Åûê£$¯e‹ÓÏèjû;¸TŒb†»å“kã»ÿ½¾^[ØÌâmâçí\)£5 5Ò~¡HhQšqi¢žËý—e-ÕiX/RLEíbŒëöD³•Ð[¹rÉ[_ ÜÊÖÕª®6-•­(eĤÿ”æö™V°ÃÞ'?Æv¸Ý5°;ä Y$á¿Q;c3x±O€µ€ÈvÙWXCÖb!w€‚ªÕfv*¹R[MhN–œßMéZe#ú©|ÆáyãDJ[„æïÀ!tùÞ»l¯±ßT)v9ØÑÖÖÚõôzõû݆š+ñUW?P‚^^­u—ÛÝHññ PIµX‰¥<‹« ùU•j®kCÁËwÞÚ¶}èn`xqÉ`p:< ÆéŒ:j5åÜI÷ýj@Þ…§|äúî)BLèäx!XÕÙ¾rJR]ÍÅ…rTƒn5xù ¿Ã(24ÿŠ•XZ%Ã0¡ºsÒ½çèÂä']Ž# ¥î—' “ß²r$<ׯ™;s Ãí’}×V8a¬D1,˜Fír¦Qßd»ûK2¼ÎmGˆ À§Ÿ 2Ú×oia®;ƒ„@©Ua°Ë&ù2_þè°ŒF̤ \­å/Ù~Åfå U„Xýñ’QýÈ!ÒàìÊ,i@}AØ©‰XMyz›jÈüüwÆÒaÔƒ@‹G5H½ÂnÝ‘êUó>ÀÙ눙‡}£XÈÒÆJñÒS}Ëäq·ížý÷q!¦“Fúz¨‚£¦&ÄÀ!Üÿ’ì)©*ÁÊõ…4?ÐDÖ\¦ÂY’ÖdÃ`Û­ø€ëM#׬”ô|ްb€yözA‹¢±á j›¼…Ò®^ñBÙ«Nº«d¶µ˜tÛ´=)_=ð q|¼öÓ¶á8˜cnKûƒC¥ýBi¥ML)€uŒþ/­]=•íñxÿ­ƒp¼Žipî4J{töcZÖПÃZñÑMg/s;[ h¼øÊ+Ó—.¿|E¦¬EÃô›>TOz?åöyauÕ&Påïâ¤ú ±H=´%"$î¤þV·Ížé)©ù5O*Ð~iBf‰úåaSÐ/ ïàÄ‹­ú–[¥KUæš¾FÄêU E•0ÐòH®[NƒÐÖ2ê0éºznC?7K6f+l‚ è<æÊîtoÿºÁfª¹¡)¨£ÔStshõ–·‡u@õ”:P;+Ö?êD ¯’Al+˜s~Yû„mVg‰ß;à¤ïE–¼ úж+þ \—T†›ésw|©³ x{åpáKV±5hÇn1¤NjÐÜ25öÖ© iGbíŽÞî-A0·„ptÙ2$Èþ<ÜŠC;éÞb?륞ӗI´00aLª-€a^gÚž…Ôƒ:ƒxñ¢Fª–[¾bŠT݈Õ¥°bj:‚ŽO½ AEHh¯ª×qÉ)'@7ÑŠP|Uz©ÈÌ>Ãí) þ'žÎ‚`¬ ‡òêë¸\¼BX@”ÿ¤Ô¶¯ËïÉ· c>›R6¥ÒäÅÇTWÇ¢*¦DûE*° Q[sx›M„ÛovT9}ÄU҉׵a e zq¤f‘—· *ʼ dñ*‘ujÔFOHúÄ"’³ƒ¦{'"Ü+WÄaÔˆFŽC’:HÃH¸mކãŠjvZtCTcB'*°¤ä¬9fô¾@v=1ÃǺžWÊ}±Dò’& ‰TøPÎáV ‚¸›eipˆLEYè©Ò–dØ„ŒÏ—'5|7TÈ‚E·ò#p©Vv†œ‹Æ¶C}ãêoPÍ·µ‚ ûFz‹lË0lÁ­iùUBc¬oã-vj¥W/\»@ÃôQsK>9 Óqzóö¥È„QûbÂmr¼íp¶TÁê~æP~¿7/öi7›1fQšPvÙAveýþ}æÖxá)7ޏ‰“–WüÑ€£0I™ŽœÚíAˆD$î‘úÃÀb–+ šÚÏ ,XÁÆg©WÔ´.÷ûš‚°»žV@DRQÁ­Rí’knuGÎm¡;…‹ïÛáysõ“z£FåÀCî´¯i{‚׳•Gg¥¤GY)çåÈàí'R˜m’Õ®ñ:]ÝXa«†zR4ö˜'Iø&¨þ\‚;‘œ'rõý1GuèAEBƒÞhBe´á›)/(nóœ£F&Ån”Vð6kf-kêM~’­êÛ¸`H4Â\¼fcççÝ F˜Úé±–§6)Àm,.©x ÈL>¥ý2ìÚ^wÖœz|^ç 1‡McÐßPfyûd—Ëò•o-9ó«ÆÙURv´¼?ØMõ~åWK{ˆÐî‘RÈ_xm–‚Ç…š½§D4†‘r¥6( ±/…X:_*ñ¾T6_4æ‹ùbh¾X2_,›Åà¶o§KwF$÷¡qÁm–hÈ·ñ}æC,º¯¹ø‘N²lùÞ·™Y¶ÈA¹AA†“ÀSÊôêýmÞ{PïÎf\º‚þ>$£÷å(ìé ÅbÀŽþ5íjpa/ß6ò3§¬î‡%_fÜ+Žˆí¿“ß)[Â<Øø°Ö…kŸ®Ë(¸d4)”×–×%W°.(6AwöÙ.à7`Íý¨(xP°ä¼Ÿ×z›çí2X% ì%Æ[ý±`õ!üÌ ’%8ÓÃÛ’'‚vôD{’ž“  5 AZZª¬Ó`o-ɱ8¿hlÓ×'dƒè+4ƒ[t"xÏYh« ÂÒ¬{i,dŒ’á“?g?T*܉¹äê¤@rê5¸@•þ**YJǹº×…’‰è5•¾Xó.‘q2<ˆ@é!„g¬KÐf¤‰¨Õ¢»N®åê“/̾T½tõÍÙ3¹#$sç«—/]~åYk/lÕùP݃÷Vy)B²ç?y*ôñ>„É }µv7Zk©Ã #Æ™Åç:5à=õX#iTß@E]N·ñ¯{– ²FµŠZª%úNG&vè‹ÀüzØ€;Ù‘;‚ì–,%úͺ½Z æ ßtešnÄáûs%Ýe,1¸D#W¤êü¯Ã *æg±úÝØ01ƒ}óæöéê‘Èl€˜sènMïÎËIJ¯‹é–Á™¢•ê¸ìñ“Ëéã¼b«ßÜ9عB¸!B8×åûÁÝ?¯/ÆÙf ‘Tõ¬†N½µùAÌMùS^»Ú/ÓëßL1·ÕÿÂ[`d8—¡s„eø^Ç–¸£Rõà‡MîÑÛÁ†'—ñz€áV—¤B7øæn¬‚&ÌŸ*ùðctf ìßÀåi?­(ŽÐo\€aœîÞpœÛ+¶Ùc]b¼jæÅ¸Q‡ó„u[/X@#Ò_‘izºï ¬Ó•…Xˆ¿Ø¹`äîíê,¨+ÔžiúÝa1MœTCû»fÞµŒ:T—®þí¾²“¶61n6Ò“ê­Á`¡Ñ:éÏÜ:YiÐŽ¯Ùn¶ê vUSäð›ª#~mŠèk•n"Ä…ø€ºÅi1lg·„<èkÍŒûøñS !O¥ÇOU*÷»Ã»ò´uýÇÔtî܉)ûš«–C)íodÿ)>ÿºã„ºIe¹¹´çñRDòÈC=v餖vÕi?ûèð.Ìo!¢pEÞÀÙÍ6Oe*ÌI“ ö4S©LÅ3K30ÑÔcˆ¬›¼–“^1T(à F#ÀPÀ¾H=Šl ׬…Mõ·‡VqæTÞ,àºKnú¨KAŽ×¼#^J8 ÁïY£Å1¤ÊÎ}>„û¼³•‘=ÛËJmbÙa-»úÕ!¨ˆ[dÝd—¿EÕŠìì·Hi@;W¦‡‡1¬!Ðê«q«·¸ÖꟖ¶ìXz»¬VuÖ\*¨Î|hÚbX@€ D>ø 3lyвueÐYZƒ›‚ÏÌnäá’,QB°ñøò מ¦OÔ E°Cð½:έ{Ðyßjˆ“ÑÂa[«ßgæV?~ÿþ‰uEÊrìƒÎpUíÔ/r§·nsá[wñ^¡ðr™ A…äô4¦q° n’KKš›µ{Ój(ÚLè.y¹k§ì®Ñ¦0;Õg+ l©`Áö §DOF¦‚;i~ð] ãÄGúÿ‡ ŒOñ§îþ9Ð’©‡aõ:¸.˜çôÃ¦ÚøaѺ@uÎíJU€ÿíp·Í4»*ˆÅ~¶lÕSfä@÷ ó“„,GiQã]=øg‚¢»É0ÌÀ¸Ÿqžv\´‚÷[Î8½dÒ‹ÎË{¨=`r»ÏЇ3…Q¹óÖ0=^¿jÓÞÏŽ{ÇWÍêø™³_Úä®Ümðê/¸…εku—³;õþkö g±Q¨g˜(e—5TPY³ûþ.G×!t‚­CC‡YW›2ý8~ܺa¬¸p¶ªIÆn­ù{œÀ¾Ë’{‹±µöQu=èâ%”é§Ÿ:7†g«d9¨ ‰÷RnšU¤Ô :‹ŠVXµ5€¬F…‚TS5¦Î;„‚ Brá4æ;Þ¦¡Ýù(²_°åŽúÕìy§[ùT<¤@z=³ ãEç_¹Zȃs¯Ìi»çqûWŒ•n2êkõ\`%­ÜS5P¹àÑ»Ú|Р£ß2VÎ…¶2‰[ùª\5'©’Äù0Œ4³ö¯ga.uú·Ö‰ v{£=Ý+í~Z¼–4g2 ÇÉÒ!ZÆN%KÅUŒxFÅó/±æJ\sŽC„@û-Z¢ä3y"U/¯Q7ÒQ¼°¶Tpù£’m£1¤¹f³lÜÁž{µcƒ&?Ü3r‡j4´ R¯],”¢¦Ÿ ý#ñ¡â)ÃJ¿ÝlœU%飴+SYýG¨ˆšlò¢ «ŸØMgÙ¬^Î}pèfÕ ˆJ¼ÏãÜÔ<쌥E6„ô´Æ›$W\CX¾înÕ0ìZ(m ÇSÛy‹Ü>¤ýXr‹¾Ÿ-F pªlfN5rÆ+ÀôqÚÕÀK{íÖŠ§X©| ûA ßj#˜˜SKðM×áÓ½ÅÏ—}ˆ›ûôr‰4!)hþË ç-CMÍû–û#tRÓ‚³oÖ^¿rábž*…xS´¤ú,M`—{5ò ž¯_tªo&äß’ú>ƒÞñj@öÃÑ9ŽæîcÞöéGüO[±l”ÞRçšVÉ´ËØ¥ƒb§×WiÙ²[ðÍÀžn1;vÖì‚p”SËw-§9w)Š3#Ó÷‘œY!ÂG °iU€먂$gtšAhàe=“‡Pä4*5 â’ò Ö Z d¸IP†€•u}hV| ðÜi9tàª0Â×=¦ s½©öúámCz¨ùk˜úCœzLx9Ü–Â}á}Œ•µ?Ø]J×Ëfd¡ÝbJ\G‹)ßí®)yŸÁ=*³²P÷zÝ ÍÑ»P› bÜéæœ‹P… Æà Ö—›åÊUÊó0Ò '*DZÝ·±ãCá[ØÕ .yH…_,ãJ:›k•!kÎHIv’²ßç©ZýŽ;Ú….9s«þ\ÒlÁ9Lª]ôÒ=nùÝSÒž¿‚•»fSB´ÊC!‡{hû57"Y¢í˜ù*O؃H¹˦Àí~—ÇG©_‡96rQåd"ôí€÷Þ¯Já²;wÒ;|%Oº÷ãÊXò¤£~Y”6ñöø#·²qÀθ#€Ó 눛ý~+Pœ œT>3£f‰Ÿ!å×Mg\¨í)œwºòH÷éG9ÕüK }ý>.a?Ðð@JpûU98gh’ïÏu>ó&5Ìg[¯xŸAåŠT¯®FT•ñ4¡­L‹ÜQ÷MúÛû­¼Çø0Æ  î=XÏPÞ@0k›öNèB‚®ž¡ºDñ…«îvXˆk*ÌÛOЭĹKø7²Aj9@¯’‰ÜmØGJìoÄOù™+#ýqc…âfæ”J3èä™ÝöÀcz;FRy"óO\‡Ýöž¶JvíÂÅ—Ï¿õÚ›µÙ—^½øúE•á÷‡ª«þµÀ}×/†‚cëß÷ËâY”ûÆÊâùÆö€ûÏ€TðšÞ=ác &ì [§ç±Nмõ²FQ;Xp4ç.§[£vUô‰–ÄØ#ZS÷zõucý˜#çØ¸:6P뀡oQÐY4u¤çùqR…B¦ª‚‚&ËY‰F‹ç­\ë-%uᨯ|xÅfC‡ZOHì^ݼz‰T¥5tž/§´®BìH°tç(e¥–bko¤E.Uõ­<䆾tqëK·»ø’žêΨòÓö9C¤Ï ]˜poy=ÿX!Dnu™ð¡_"ÃÚ+âZš™jižÖ³ϡȚ^KZçªo GݵI«ÙåÀ{Ú³3羆h×EÝ=«× %d‘Œás•ë81DXã`![%OZ°*¹sUîN[°GѾYBî4BWßCÆá;ºTŒCXŒVw}šzÕsÕkÆjþ{ìm‡0éžkˆz2ómPÞZ$™Œg4vê=ÙÁ³ˆëÓˆQ¿!#aN‹ è«ø’ÁžæÝ°Xä2UP¤j Šªü”,€ rì'ýÏ×Ñeš•êÒàW óš=lÆ«ZÙz˜Ñ}”êYõ?`ÿ>ù·Ü5èSõo6Hß–ÁÑmž Ú²Xá)eÔÉ wÞŸlÃã×£Å{rg´³‘ˆéŸÆŒh«–ŒD[Wœ-“ÒØÃŽð¶àú£­­¥/x]?ÔX\j O‡-´%Uýr`{èZDM¥·eï‡~¨7`…f€œ‹à™rx×`wx@°Ð̉äA<”öKjW0T¤Ìp‰øhÔüþ¡äD‡L4i¢Ã&:b¢{Ì’ˆABYCVJú l,Š˜òûw-o°RrÛvÙ*X±Ø XÐ hðŸ ~ÔL 9Ÿß™IX%34.²Jã©§yÌ7*¨d»)”JWW‚»¿¯~LŒ g|˜$à¡!«O8ð ¥Í“ßt™øÆ¤\u/ÉŠ'¬®Ú<"lÕ„túdžz¶±`ãè’ÙzÃÑ;OfRÝßlþ.í'…ð$iúÝ&:à>.aÑ,€LÀ“ø™“ÊÏÜ\t0?·#xgɨvã(U&Ãîèä½6@Ë¢Fú‘ÀÆ1Ùç-²÷»Ô,c'q{%†ëY<ý<¼3Huªë¤*aWó‡ºuVSQ£<½U½øÚ¥Ϩ"jº«¯9½MÁƒ?VÓÕùøcZÜ>ì‘^ÚƒL)¸¾pþÍóÔxÝÉ '¡ÿ]_¸)%}°~á¤7M'=ã²¶Xw‚š¡sT'í]_" 4”÷IÓÚ`Zc¿WýÀr&'Ò3'pÖjþùâ8hö׌B±â°lÉþú¤å¾Î(ùʪ{åZ…¸@¨0´(|¾Ù{¹i£ª`¤ €U[nb[: ’zû«Žz#¦[C¸wbꂚÝÏáÂØÝ¹,©¼ ‡SÄðT¡4D“±ž!¯ôUìÝ=”§‚ Gõõ¤ø@%i@fL=Î}a(fLÍæö W,zeL«²FU f÷ò,âãò÷þ`HþÒÅë¯pY„¾þñp‡0c£ˆËŒF:ë¢XÔ?ÖBë<`Ê™žÂþ4NaÏ\Dλ¸¯ª‘:tL—iwñVõµÓ¹ñ† ßeÙŽƒ¡HüÙʉDµÜ'ÜtòÀêß@`[u•Ûv0gõ´Ôÿ³ÆJ…Oç8â4ö:6(ÅôǤ ø<š¸dæÉóɘ|!0óä¿ èÄ‚Ín‘ ŠÄd@HŒšªe± i8_8j˜ Å0($ñÕ¿¾áœ|øV8$ªEWÀ'ó••rgNäÓX^¥iVÛm,…ЧÃÖLX8µ! –h.UwYÒ§¸¥0¼!w•ÖJHCüU_ÍvÛÐ_Ü,ºVÿŒé»¬'Üq)÷‹1ª8s{«—&:|'é±jÆþ‚IVu~Ý!…8[·ž)t{6•PmÏQW«õ„>©œ«ÈuÊ èNžHG‹%;ñú9÷ðSùkÏ^{®Å­ÊG<êvÇF¢âÓ'kp”ˆˆ“ìäéGN=—¿Ö{¶wíœ|Ã5É—“võFËäá©Ñê_± ÊñB,$5Èí^¶éÃJœÝ‚àæðó[w¹I%—U¾Ôîâ$¨Ô-1yZîòD?bȶÏLòç¤ÿÆÛÁt.Dèû½aipˆò±^ƙڛ‡¾÷ÆÉ‰q>hjž}}ÈtŸ*ä0ZSÏå¨ÿ›êuÄɧí‹öÄu ä˜PkCù ‘¹a“d»õ­¼1x?„Y BÚõÞeuÞyÄOÇ}”,À4Ö#Åq¯ú)e<lÍ[έ"E¨k@ÑöL¾ºÐíÉ¥=Ážp Á‘Æòcûüð_’ËÆcý3 \·É#pƒZ²„Õj‰A 4rþ£ÊƒÔ´Ø¬ Fw·¡ìÚçƒ;FñãD?~÷þAËñé¹ãzêGëWLAÓ›¹ÐäÇ›çêA¹z&´ÆèY \ ~º™CÆòI$zo0sˆQKÖø¢Ò®es}À$ÅØó\Õò“@Q5舧^TuYÈKsÌúæim¹Ýð@n%¬Î ØCLÈÛ×h9ªùI¿eÿ#·eäë­,{Õßr{»JØÖ6™t­`áȘcØÞ;Œ.O-A=Í<Å ‘ùÊßÚ¶ b}hÐ8÷µ£²ƒÈqw8º÷P°;ÔOÓˆù×Ñœ¿‹Ëox*ˆ Š—”ŸR߄ڟïkû7½à1yÀªƒàx9ŽŒÜ7rïÈΑ!϶yH=­š9H•%šÀí¬º {¯•ä+Ã’B&]• C›ÄKkéoôp Ö-y¸@-6“4ãá«5¸­åF]j`å․ާ—CÁâ—q´©ÎY­µxB’¥ÖÆßž;PÛÖ¡ÕSîú:óì 1™=A¹äý»=ÿù!¶ÔÅmÐ3L‡n…?ãoá`[7ų6 ¡¡§ä ­‡íјÔ&1äõ¤Füº©\\ÌOPV—éêo«1Pq¨q­4"×ñó^U× ÉmA³µKsÕKo^Tuý žÁ €ø˜ ”ÇΡßõd‰ãç&ÎôÏ †NÙžÁ†[_s¾Ú/z9ÅQ®ÖýqP¥jï,I·ò—º·{,tF)«Ö›|óªÚðrs£RïlV–ZÝiÕf…[XZ»÷û†dÕbá.XWinwQR²÷·6 ¶õöm‹Szø«Ãy~½?5£_ph­ÿ$ïéI;AÔYX‰™UVÓlz!ªÙö.‹¬Nká1Ï^…†º›4—`ß×¶™Êy‘t ö»üJê"ÇJ嬮ъë ]:ØäöZõ†Š¾ú·*м#d”ûŒ¶6O³6F$¥kïn#¥5ÀçÊ~Ćl«wü¨á%VµØmqT’ÊfC#‡Ôg*¯*£Á·"ß);Híú¦º}j¤^5˜ampBV?eÚf¢Ž-w¿NÇÕýÒ†î•qRïZV'v–ýI13…3cüœÂWÔÚcë[)˜«dÉ €ŸTÖʼnõƒ, ÒŒb| ClšAlKÀcì«KbÎDÃŽŽÆ»€Äi6¦/b*ãGˆ"oÒ]u±Þla¨h¾Zï3F3•‹˜úæ"æ3s÷ñà*@Ó‘LáZùU²èŠPd;~q91É.³íg/¶ZåÂ4³Ö<¤´Ý«kqê–¾s\Oº2\ιµ2­µu`ä!Œ®_ØüèÕu2-ÎJîÔkáÄ[ÏTf±12¾¥T9æÝ5©TÖÆi]AzÒ€ z¾×+'ᡯvÌäÇõÔדYÇP3­w“4&ÖB9×òmM$š{”‰ Ç Œƒ6j¾;[ñ•]lßP×UÖjå"ö¯)­¬iˆ.Cfks¤˜ñ`Ýé˜0ÈwmH—ë6D³m+?zR´Ó²êéuĉ°±²Õ‰®…3¢Ü’m"v~•æ8¾õte=ÖuÓÜ`eÿQE ³*›Ì²Åj]è×ÝjkWàD¡ñd•=c&TÀRþ0 3Ïr²Ë¾™è0D…IÒ–m¨~øÄùµ§Ñ’FwTOi8î£W[Ðù™-¼ƒ]ºù0ÓÏC~ʈ}Ã#Åa–’ð(Јçp)ÇÔ¨‰7~£z³óѺÍßAhio†ˆ ËÝuº%ܨˆ¡ÖJ /ÎÅŒÀœ¥è»84 Uk©EYÜŠù®GôðÁJѨálŽßî Üí |=ï§nh…EŒr´<ðAÂx¸ytþ¨†`|k´." öx—ÃØí´€–º©kF\¹Þ‘ñ!$åH•htK{^{eL¤ÀÿÜYµÜˆ•øÈ[«¨,=…,r±Öá7Ѝ Mj‘tƒÄ§QAf+Á ÐPºmåµÙ`cÚ®ein »-Ðæë£¸êæ‹½¦8gi!þº_+ög­ª¡µÑ›<@Ì](¼ìJÚEs7”ZÃÌei)žG§ ÌÄG§tІ6žp­n:ãŸV´úDnŸ´ê[åk—="õÁ`| ü>í…KôjÍÉü’ÙxW 0Þ {iàÌDÜqBZ.™´19õpŃÇ2çr½¨º™IŠÃÝÁìÁꤑŸ¹›þäõ^ÐÏñ€ng‚Ädy@5â#Õ¨¹F>’ä,œoë¥Ã‹2i/fôÔã×¥£ôbPŒ8æøt»è2Ųõ;*Æáu™ûôT±y~wÓc’Ø‘¤ðCŒµ¿0ÍÇè!Ïb -âBnú%$mÐ… ¢6íu;‘Ep}ë$n/Ä<Ç@ žB?9ª££•~Ì1¥*‚¢0ªåuO^¥E^­œIŒÚ Á ¥º¨Ö@¾ êÙØNo{8Xˆ–kn G[ÜyîcÍæZŽ…6iœ>·•`_D9‚?\Û6Þ¶°¯2× ×.R²ÇÜ“·Ê6uNà¶û1wèsÑ×: ¯5¨µèÙÕ]F~ærþ÷?wg”¼ElzH×]ª`‹ôÀýQ°cÏÒ¹;ðÜpŠ$Ç7<¯°eº#p¨ó„ [çXߺr=Éæ©s>R©U}¹”‰?ÔWà÷mÖzê´õïëy SãY} …zÝ4m.´6-­ì #1Øê•´Ã8k€ÀL¡!—‹|FNhÙÏØm »ùB¼•[ö”†T1£¤Uqä8ɧó®õMf bÖŽ‡­P˜0€‚°viëé±Í=žd²ý ¯“Ñ/¿kRp²×zßš¯~ÜÙRÙjª/…v[æ‘‹m“wP¼ðn{=Õ°‡¡Þ±æÿÜ õX5FGƒ!u§Bf·—c9ÅJnNBŒx)t:ßõíÙ™Ÿ•šÿg4:¤èíÎøJ0:±F©7¼Ù¸ ´ñè[}ÕÐMbW¸ÛÖn*í¢}¥>â•íêkö˜ûi&K>)eOÚÉ¢— 4økùèT_®TMwý.¤Waú>¹mÓwNjþ;^¥Œ”JoÖ’¨·ÙÛ¬Õ¾Y3Zr3z¦oF³ §ÀhóZr^8†§æ©õ«N9#þ| \5uî(º˜ª¯y˜ßf88E’AIì?púÿ¥ÝahöÝ mç„_Ù¶ ?+5ÿ‹Â„cÂysV50Ïûó6æOËes_Žp"=Ûc®sÈ”ÕÔmQ-!g¬%äì;Y™v+–2†ýâ¥TÏ’Ò¯Tܱ¶VÜ¡–²/è qÃNö£¡þ3»)ÜØ†:G¿¹Ù‹y§J7µÑÏðÄÁï6Û5ýtôHkêZùûž+ K2¹{ƒÐ›ôøD€ŠÍGs RëþßuÀ^ºóKC!´Êæwtt©+¶£ûIŒ®¼=ûÎÍнQ+­¹Ë&Ònbƒ×Í2ª€]Sµ‰œ™t¹2åEkõÊýÇ*PiÒãv­s£Àª¼3ýhS-Xq½ÿ˜Æ¼£¿IW­Kh^ü»Hý[ã@{§ÓÒYߎv}©ÙØžùÐùH—G†Üæ)sq(˜Äläö¼¡› Ò~*4¦›Õl~\.o¬ñ5^F¦âbTê Dß°T§;ˆV¹ÈJ »V0¤5ÚÚ‚¥gh4 ‹íÇ툮oܤŸÜ6 Å0 Ym}A †½Cn ï$&$´=HsÝB©:Csp©K~ÜÛŒ¼ZîP' '”Ò/QOÄü„Ã$Õ÷œYÕö âw¤úCCÞçhPF°ô`"<*tp©²w̸^´ÕÊ© 6Å·í¸hn±ªc}ȃQ®[õdÁ~Y©!üÍü¨¢ Ð\çAâ5œ­ Hí5çdëÖ…î€o;O"‚‡ÕÒ2Ð*Ñ(¢³qÞ»\ÐlEšq„ÓÈuÿÈíã>:s,<ˆ±u(¢"­€ØØŒK³=s©œòúé½´¤ßs—1ŒŠc˜‘¢Âò ¹«êÊJÄ`Ϊ©åmc ½ß©žãÌ5Gœ­2EVÞ[Ú÷2nÔ[ÂO‚«î%mý,¸Q.¬Þ¸Î³dÕwG–=í€fØ/ìy€©†¦Þè'åÌsú®…w~¯'±|¡ÞɸËVßr+—›*â<#hÄK„šü¬ ݰn«Qh1¯ÂT+ÝÔeð v<7æwï)?jÃe}$ÔÔ[CÜk­ø¨;¨Õ®¾ûöÅËo×^;ÿÖå—^½X­Õ¶±c™üˆÅ­‘‹[¡ÓKØPfÛ³¦°äá‹WXMo wªÆþ»ÈF®è€¨ãˆ•½ µ¢Y™Ò/§Mni¥ ̳^´öS³JÉØ"*õ\ê+`“d­®"HY[â+PäÏa(jÖð´ åÖ®çѶb+Âr–ý¡‚ ÊÒsš€ €J¼ÉLe¬ “cÆêííLáJÌÛž€$ñŒ"tBx'Í »éün÷“ÝVdÕu Š­ßž6÷¤æx -Üg vŸ_M6xh¾ÓENU30‹cn}0ô£D…Ê+cÇú&ØS™;+`Ö|ed8èèGŽm‚ÙV¼1CJµ€Š¨”cd^<¦nNÑ‚è×hs $¾ùyÆÝžÑ]•/5ýâ¼›Þë¦À{ùÖÝ®d-!só¼A…æÖèR`¨àއܩ5J âCÓz9:&X55ÒšESÇåS°™>ü÷ÙàØµm®%ùr2äE1G€K§\\:onä ®ÞRTf¶†IÎÛоʕõ.€è0Ú®u÷'!aC:¿jî<ù˜"y°ƒÓWÐðUAÓ è,‡G¥ sKÓ<>~õ†ø1‡’hõËÔRÒ]ëÑ勉DeP«XT©§£àÃÕ ÔÐÜ6´pCjÞð31°Ohóc¹àÀkׇÁTä© ,Ã|°€Ë¸,11AHŠDñwÓ#·¯˜íêŲ|ãóÍ!`IGŠ‹O‰¥  H,.%Oæs7ñëDo¼x}Û&Cà×|[¾ÅOêµÅÖž ˜Q 3'#$5gC(‚lâŽÂmŠxŸè‰‹®úñ“Î1ã·Ñ(tþù!ëU0XƱ…#áÄÐÄÀÄÄDybddpbt¤DÎÉ ” ôDŸÍ>ùÄWþ@ê ƒ^ æË Ï `¿ê×]>d?íݲííëg¤ú¯8 H*ßÉãT¶ôÁ²%ËÚhgPúNBâQS wU^Õ}Ĩ÷ýíÀÆ.×ãoó\áÿ¯¸kûã*ã3³özg½¾Ôní¸MÛMÒÔvˆæ¢)¥Iƒ‚ÆNЄaí];›Ø»îÎnW1ˆFjÓ–¶¢‘*(•´/‰«¸•WT(´HˆŠ„/ˆ'ž¸œßï;çÌìÚUyÈEÞìÌÎíœ9çû¾ó]~¿ )CmFßðùÂÅ]›Õhð2ÇÊ•ÆeÑ´w‰Dg]D¡Î± C]”¢‘k„‘™Co©T?QCvU}­Ý& Ö×íôH x—‘“À¨B%Ú—¤_õšMÜÚ±˜p’õ[,¦´ê®wÅeØÃë®®·6V2A#*I2W­](Ô˜¼%Ëÿш¹é ´@Òj§tÁ&‰Æzå\i¾€ŒYº¶+ʤVÖ“úÉ—ØÅ(öŸ;L>r0²b¸_ ÅÂj½ù"X§ÊÓHy±ŠäJæ¶ cr9ÊOŸM¸Íc~›¨T"ÅÍÁ={æKѤ,õIpSŽ¢FiïÞ½‚½ReLœïÈõÿžFTºÿeÁKýÅi££:¬P¢€‹É•©E®Xü‚ÄíS%_ï2i'ýî ç+±ÕÕ1èÝî¶ —u³æim.蜗ÌÐO»}™`ÖMˆ—#^~âl@£&Ÿ«,½J µ €ÃÄBi©›^NøCìΔÙÙ£wÂâj?I©/áNéçi³y 7­Se€›³9ÈM¹`ÖÜâV=bÞL¡©ÊBa5jx™ó…‹eøXdBŽ¥ÂLÞX­BÚ Æ !W%ªªI`ÖK2áñµßü~71Owä§Íœž8:=3{èØ±‰©éÙàô„`ÚÌïÃZf¼¶{ç-6~ƒì)ËBËõ†ùí)ñµE×vmËÕ KêLal‰ÌQÈU• ŒÍŠ  Ê ³êüƒæGÃyša8z°‰¹LDL¹>Ö´—‹«–KÙÆåãÖåMóÆÇÆ›® [ ~NÂ0ŒW5â¶e)QÊ©m…bª˜eÍU‚ a‹xº…Òs)…š¸¾S5bŠa4À? ê ,èĦ†‘<#æ=ª­¡a5}D\©·ˆšÒ¶µñ—>êšh,¡‰µNSŽGeG¿ʩís÷$žþ¥5ÌSýî”u¡ß›¸«¦ß£ÿïF?+ñ¤ñ1Ìêç¼)éÒ¨ ië2ïÐEwæô&^€4›.| ýB‹mú2`Ê8tŒ®–©Ø¤‹Ö¥°ì´]Æt}p ›çÛf@<­®ü¶uH§IëT–é„°f¸òÅ]—.`•pݡ˽¯:ºOëR÷2@)çò3‰‡Ï~Iw­ ÃR®hæg)?–¹pøì ÓÄ[ã¬ÐˆÊ‚QÏਡuÂøHú€@ٵ˃€O;|¶•W²Àk½áÌ=þY8lˆ¢ë ã—’&‰@¶ ­¦Œ2ðƒ˜ø®ê½å’AQk®»±WЂÕ8ô˜ž§„«ÝNä„ëXתòTºŒÕ)â?Õçiˆ²Äa‘>L  40@P<„YÚ£§‹H´•Â*mÎuµLdaTX,Qd¿cË5.‘–i&ͱx߀EB뤾¶Z ƒ5ì#§ µ´*ƒ‘Çàõ¶Ù"QÄx%ó{:G€Ö7ënWŸý2r7˜ÀJJ1f5VÊ¨Ž«iŒ.riÓõÉqr¨gjDX„©]›½à<ù"^tÖcgÎì9ËG8ÑœW-õ(°6%QSÛ›¼†x‚û¬·Ž(Äú“ýŽ9 pL¦þ« ·§Ë¿¢nøWt¹©nNoâgßµ™ÐUœñ7fl>€AËhŠPŒ¿fÙ<åi…•pdc”“x­Pqí«'ƤU÷xÕ¿IÉÉÖ£˜{Ä”K³uÌàprH͔臢’šš"‡i ç~BztŠ>Þ¿O°»âejÜam^xâÿLD¢:Z˜ÚbP´…ä“?»5S!Vw×(As¦mâã%uùÛÇNÑ„²Pqöu2)Q`°¬[ÕB$Õ˜± •qàéhV<›HµömsãGc‘êÚ¸½Zê"ÿEzäËæ¶š›˜í³  \R3íS¬ÓÄTnu¾ý ÆãíT,ðrIC¸¤¶¢Çé9lÂè $ßLðUÛj¼#Þ½‹GXÂßïÒÎ'zá²}^ÚK¹]êÏO¹}·ôù}iøåR.gÕF¿ÚcýV•½WÜ´±ù47½D¨>Ó›DéXÉbåêí›ÉU—ÜLŽvl"G?‰€Ø›i“M -û¤1E†+ŠâWr<‹éwž&¢Æëó4ÁˆVÇÿϲ³ UD/ƒì™ñz¦R¨7j…e.–f¦fOž˜=~üØŒ€Ë\$Š€ú:SÖ t¬Ð¨,œ+ÕôÒª…Î7޵A]‰ —«Õ ªñ¶–õÙíηfL†Q§ðШ¥š?“5éß´/Dr‹äxªãG¤üGgr#}oˆV9Àãã*ì¡Cux«0$%t0Ŭö’sÎR—§ÏX0E±äYV$€z£C?W€—‡†|@Év8¬5 h`2ÎbôJ¯š X+r62~ë»Éî]ȃ —¤!ä|Þs ÇÂZ!x!±uI ƒÍ>2uj–_0*¶Sl5¤¬ˆ©¦yÀºX.¡6ØÖÊ,T—*,n*D ¿a4iÓ ^¬cfq¶â‚ùR•/êÔ àB]fÍXLŒ3&(þ¸i²Óû¬AMgZÊE°j ÅóÈ,[ÅÙø^šWC·Ôƒ—q@õ/·MCØoÃP ÔQv¼ïöºw(m3àÞãiYòM‡ãufû:áÅà×W6טæ|ö½ªbg=¡ÀëŽw‰QΙ×Qd­'„‘”½qTowIÆ`ˆ »¨  ¿’@QL Jù+Ì+Qç꼨g“ò*¦‚oÁ¥Q >)Eo`ÔŸ>¢é€ÖÕf~¬VZ*ÔŠjPEÁ‚¢¯Õ•^ŽÆ+Œ }kÔâ¸à,žcˆ˜W%ËðžœÛƒ¯yè «IÆ'ò~´PX-Ñ^>zdúx0õð¡™)áëiÌ „glŸÆùD0•$ÈrÝ„ìíÕ®¨=¸Ç랺h´§°:ÏMÔdÉq\-5®Ž¨à†zÉŒN5sÒÈó.µÞr·{®ÌÐØ0úB³ýÓbÜÐê¹Ñ^÷8l–n£þ¥¬™ž¾žà›Ú2­qDƒÓqDªôu‡Qï8¦úâÎI;¯3ëp‰œ;•;˜kÐI^ø´žVjJ-¥Œ›ÇIÈÿ å—ÈŸòÞùŠ>“mXI}ÊNÊ8¥²ÎpÝ5<ÝÎbJí¯“Ü z‹^«œ3,4%uCf¤®Àà±zÔ´%?Αä´}?U¢ç¬@ë•›T-ÝM¢þR¬j$Q°Üª Z2Øc@U+Òœöè-5P*åEe M‹ù‡±E¿W°åJh.ßD¾ú¾ÍîМ/p~ï©z¦K/Pð~{ÙhsÅZ¬0(VèmjŸîxCü.š99ØõÒDr‡öñú݌秳®tKK”ê¥öÎ@Ì´CýÞè–ª‹*»â.obµ)y=˜XÖNÕ¢¡b_§›ªÎUgídâ×Nóë@bgZïT–Z±Ë&~¾cFú1€À”6,æ çÇbu2ÞlVË!«5¹?‚f†Q‘2+•Yp=ª†ú(@‚F•®mf×aÑq¬¸˜<¿V7)r:D%ô ícn…Ši’N¶ µ9ÉÉ1qÿýeÿ¾ÉàUÇD4ž4v¿z£êÁKb?‘òs"È;MEcªÔIv´/VÚ3J¾«îYʘÄÉL–A ß½ÍØdÄüÚÑЖrJõGm‡†„“œ„N†vÍìK¤ÇÝ–hWÞÌüÉË+ËìÊF}qâ#ê‡éÞ“c/É4Újºêb¡ Übì˜Ì°ŸµHiK·}OÝìRƦËÁ)ÙíÑ“ƒwlkí0Dà†05ªžSÙ’ˆbìÒ‹r a+$å¬ :É:Tµg®2ÁÚF5©P¥Rcée#z(qA±ÊåŸ Ôü4Ĉ…§·Ø kDÖ´k!eK*ý8W¹=yŸ_á>jƒ¯F]TsÐÞ¬ýøÜz‘L*û'ÈKá&ÐêçÔ¾Äõv¹ñsó˜¦çVÇžRsú"½¦ ·¥ñÕÄEz7mÀr@Y‰‰—n‰ç «…“>%猬>Çɶ¬^ÈóNŠT Ÿ‘JÌ^û>bì ö‡È¢{í7MòóÌ ÔË#¥åUÔ5­D#C(-™®¥›è¢‰²åËcàÆ8˜ñÎq3âÈ×Ù/nqÜkföˆ’|Ê,nˆOZ|è| ™…s!Ñé$ÑSÙ°p3,¯&j cî¾p)nèMŸco«;¼a]éî†å‹x=ÔÉÕŠ<0ÏH¨‚¶<ÕoÔ=~jž föÓJNdHñÅãdu—®®¾¶°qÌ‘tNâ·< — œÄql‰(j•7¡_~kƒaÜ|ÇÓà¶ôÂÍ숎Y/š½ýÞÖ®œúÌ‚¼Býãh6lͦ‚P,sq©«ù¬‡x C\§ÑÒ¦Ò1n†Î>®ó(ǰúç~ÎvBò¦Ö ÁñÁ´=¾£ñ(ÿ˜ŽCžMrŒ…ÕZب-ç'''“InÕZÓ©˜±7ÒØ&hï ™½×A+õQ×ã¸C¦è0m¼ÈØ·MI>hãU[Í7J˜“3‡ŽLµEH/•ôTú}<ï|W–A½zÐÂÖj­Ôó¤Šáþw=üù >Þ5æIT¸X*&†æ¼›;41%Þ²nteˆ¤S}^_gŽLá¾7ö$nÊh-~ÞÆ7>…) †þ¦VjûŠ/‡‘0.¢I¥>ÒÒ|¢Iý0ç´o{€~Ñn£ 6žÖT Ix™è Ãù4>FñúCq>Ãn þî¯2ߣ W°d¯Y¾’ ÂêËåy©ZaØ£ž:0'™ž—:‘z¨ùêåïœ%ÜIÆìµý{5.mßþMÎ×í ˆÉ5Üü›B8¯¾¥åaSür€ º—QwòkuâáqÙ§xBÄDâçš\˜†ãHøFøÃ<>¶ác;> š„nf§‘“)X0BÈç ´ì6S`± ŒHSáOcüÄÔ‰î3uý¬s QŽŠOyF9Kê¨Èzü / v3™É,H¶ Ö…Å@>cà6G¼Aª“…¡S/WB eD#õ8M¯%>®!\Ÿ3¡†£Ì-Ì  ôvâ&ÌZ@ÛÛ\g,.ýõ\uɨeÒ ¼}‰ì¸u褴®k`:¿ö´Ê{誆Œzï5Ñl”öãf :ÌÍIw}¯/zC}¤=¥ÈÆâb%÷þÿôýúß{À+¦s©¡õ[‡ßágoÎuù)?3ôGþýÐßãû»ý{}¨êçüŒø·æòêèþ>Ï÷üÁ\ÖÏú~/€“z¼žuD÷ЧpÕ¡»†º(ï««ú~¦ï?ígsCÿPKƒ,ÒF R2ÔAsetuptools/command/egg_info.py¥;ksÛ¸vßõ+p™zHåJ\çÞ¹íŽ;šév“ìxÚ›dâÍnwœ”¢HHfM‘\€²­»»ÿ½çIÙN«¶Dçýƒ в=4m]—:Îêý>­òXîvIQmëÙì{%ÓVŠTä…nU±9´E]…Zà”%N%³¶VG+EVW­¬ZÁl¶UõžÂ*€¾-JYÂ/Qì›Zµâ-üþOüj‘ØÃEø×.àwRµI“¶7ƒyvJYïfækC*U+=~n²#u7GIûMõlÖªãÅLÀ‡6í –è»Êî _;“™lZqIÏßàÞ¼¸Iµ6DéAØåß3é‡ÃKtîPŽ~LMÊØ9›TKdYµ[ˆ¿üu!®èÇåûçmqŸ–·‰’wY«J^ÑÜîà®*“Ú‘9™Ò=€0ì‘ÿ ¡Ó­Lªt/fX§Ax´‚Fíq,d™'eQIXø¦r¨‹ª]ˆ¢•*‘ø ið ·u‚|CÈóŽIýaU‘Õ¹dV dyf¥I³Ût$šÍ²X%¬D†7sfc.u¦ŠA¬D=_C@%ÀAáj Â5=ÄOâdÜ*\ˆPŸ W/T­´¨Á Ø…ÔAgâˆ(—ÛôP¶@ÁFÔ[ÑÞHÁ$­’rÌ&mº[‚H/A d"¤Â~†¾Ës¡ÃDa'ŠË×°ƒ°«Ã~#ÕvDC˜9Aá¡Ût߈HÆ»XüåüüoçûË·óç€ÛŠ2'ªmàU#³b{ò¡)‹¬hÌA0)lô´ªû£wî×ð°%H'Nm(ýeØú5âÈpŠ*+¹t?Zÿ…åf.ÓÊ”#–}¡e•Ü¥mq'q¬ùmt‹‰¥‹IaêÎ`–Ð÷?fF-¶p˜¢-Ò²ø‡´HFZ–[£8¤÷ð“Ü ê/`ó®®äxÐRõÔ8ªÈÉAÒ‹©AÀ8!999Š6¼ãäJœg›F#UßÊ*qv›–z°Á¬×vëŽd:½ë ![œ¼ëiwÒnËYk̘̋6[±-v³né]Z$nžYy¼µH¯ÆCø’eu> K˜Sc¬œ–†:šûÓæ³ñ7ç‘%ÅÂcÞSo[T_%nS¢‰±k²ãlyh>Ÿfœs€ÇDÖNÛÉÜ>æ=+ÈæÎ|Ï;FC€ÎÊ. ±ŸB;`€;Ø*“‘¿Å¢÷l±yÿd»à4M4–àL¯Vg:ÅÖÝS‚ˆóž`)~0ÆC ap&"m‹‘çó›™Èë''𲕀ñ0.Œ_ÛïIˆhá.+¿"÷ü¼ ¹ªUçQôœôÃ…8ÓK$ØÙÌ“g­û ´÷í_¡É”øG„x UOºYd|¦ljDàD¿ý1G•ˆBp-5›ƒ‚^Xéƒ" ¤9¡Nhˆ±ŒNüæÓb.þ,Â.² OüO«¡‹éؽ`æ ñÿ@ìy@þܹ»[¸ Á“ù¶cbŸìFf·ÉÀô»šþB\IVÊNB¶@[ ½6²’[ˆL Ë) ÆžkGB˜/Äÿ%÷âOÙfq÷ Ÿàï÷²MÁ>§ñÀH9bçb}¹÷£`¤M#s‘ªúÙâ]ÂyéT|ø–—ïÞ¾_`˜½/v7tHœãÀÊHR+˜½…€ûFÑê ¿Oo!à鵤Ց „‚ì-ÈY2w Aè†(ØcPŠ:&@“Oj¦°}žPòäðæƒ.UuKúDil“Ç·ò(V+_ â²¾—*šûÒ“‡æß¥ìpêW;€‘ä>Ö(¼¸WB%µJrYJø†ªg"Œ{ {g,0M(ž™\QøâÒùŸ’Xã¬52bmW®ÑZ0x¤¦Ü7í±'&³†h\-iÒ¸ø RÕBÒ‡C” 1YZ¯mBv¾^ÇÓÐ’2ïÖk<ùzm@@fiYbjg­×.Aº`köp¡Êª–˺éÀªRBÆèÐD>; ]Ù¿¿)²Ö„òjE)ÁÑÔ­ PÁS›Z57iCND@Ô5±…0Úk=ÑóáŒVäe4¬:»YOEš…¬"Tý©ø)ë]Œäû^:Æë(D»l!†H’øCŒI0ë¨ùè‰HÊWSŒlÆø±îM‰ÍPߞвg+2ÏœŠ\…:Ts‘n[piUAÎHÚ^ÙÖ¸ÉÀL Û] ªØƒp¢èE‘¦Æ8gn$BA¼[ÙSÁXZDeZ’Yäð\Š € °êlÌϹ~øå¯ƒˆ%dEÿ œÀRMÚíòÛÀ[ǬG¨c”ðlÑÙ7²rr…ð~úÌ6BùòÌ#YYk9ŒÛË !‚¼fÃ÷ÕL›¦%íÊÄ NðqBÔXKw;%œƒ¤d+ \Ø(7ês»âE—<‚7?¢óG3 ‚·¯Ù­W¢†|„B¿>¶p`øÒõï\¾i©dšw0°¾%DZK'UC;c3 Õ}ÑÞDýøÀJ±þ{Éhä{™a«»§6ðf2ÝߢéŒNÅŸ˜ÄÕ$¶ôÝp>!g_ ËI9ª˜rPŽ›°ø+ ›ØdaQ·ûªûæk ƒÜh‘®Ë;MÍ0:³X§#qĪ›4÷BçÀÌ+ȶ Ò¬¸|U·-e¡X Ö¢aÇ Â¶9ŠºÌ3’]ÚTåÉL€÷ø†gàêªr>á=]k3YÒ¶¨òÄT›#_G‹^ Ãq ÔS|:A\ ¦Mp«9CM¸³R‡ ïN0àÁÈ…áx‘sæJÈ>;#÷µºEÎêæ8ò¦ÒáRé€9‰2—¡»Úb/g§hƒ1(Ï¿DÁòì—³ýYŒ”ÚKþ ľ-2H™nê¼ãÔ˜.¢a×ü éü ‡»²Þ@¤6ÌÌ–Áy02--(_ÝU—¨²eæQŸ~_z$üJX/c™_ód› k—Wï?}üþÍ)d›ÅVBÖ€rë:$;ÐeêOiÕ¡ï~ë:X˜ð©qÝÍw­Æ8¸óж·Jfº‹+œÐµö:M§ëJA0$9ßÿ¿*Á@«EÀŒÇlû O‡ÊÁ2/Å¿|‹h®Âñø»tIü’"Y®b²™{“b–cJ!E«©Òõ¯ãlBIÑ}Ne•4^! ÂLð½‚{ÌqsNÜɲn‚øs5…]ø¡”HLÅRgCJük@r Ö¨zSÊ=@ ñ €%žy\}Ê *=”)O”òO/–›Ñ`©²QJ g®êû™m*Ú>wÔu¼ kAÿð KMI$Ãj¦†ª8 ?+ˆ ù·Åƒñ¤Tu‚üI 8ˆŸa¿ú^ûf `íþ]_,_}ék0€ ¸ûˆ4 ªhþ™r¯¨Í:6'¢Iý9åCÛŸ“È0 ¸xµ™?lxâìlW:pÁÌ6i¡&li÷ý£^@|ÛïÂâN CØ µ?ò¿Ë,…ÌLè«Æ÷`’58ÝE´yÍ¡D;qðx«Ê£_· }Ök‘¶lB¥QÚÒUØu‰ýA·NHÞö¢ËƒÉò0†Ó)žs¬×ðO¯ŸéQ°glχ”í%hİ‹ž׉©.èä~T·dÝ»³ +«T™f²©$ÈKÞ¶hn?}bª¿¡5m¨“ÁÃÏÈ`‹M1Þˆ"=ã@†ñTÞ»Xєܠþþݻ˷o®~Œ‹Êq ÏlЃJÌ%ÔýWþhÑ—?î#ó7¦¢_âx¯žßÆå›Svö©ÄÚ‰;/;* ÄÃÃ|ÊõpAÏΈæ”ï´l] sL|@\v\™¤&‰Ûbð£dLò0|Mó¼#yôX0ÈI‘áôÆX,Iì„á6Ä; ©“Ò§¥†ìêä ’ûòåü€—k`“QC|H4Ç'tRRACLŸv_o6­{fÌœ´lÀ6}ŽŠ´zxx®ÍÚJ(ÇfÀâУGh«¥^>Õ× ’ͱ@zÂ>át‰Ò6ñJ#ïê{h¡oêC™{®`ÑõD†NÏ:óköà¼ØÎ)bÝv PGnamàíõÍŒ-þzGèÿйyö(dÁKÔÌÂ×F®êù÷r¹‡¦“e(jÕ‡¦QØÙZ>KBÃôZ´¹93ìû!…B ¿j9ðEž*Ózáf„aÁPÓX<@Å ¾]mÚ*Z:žqBœ8¾WûgÌíŒZ¯ ™̹7<Ý;/XÛá™'"qÚÊ„Ófæãí¡',™,Ç\tÀŠ$ÛçnMÊzŠ<1Ýò¾¼9¼s ‰»Dà¬Ü)â™›xèÒ!È…(îeVIÉmñ`V:åÚÞ y»°,à&Óö/:RÄÍ[›v3_¨L^QB£à”Â^{åÿ¬Ì`U á éÞ êaÓþ€°ªÁ”†˜™ –-ØB]—þ{©„C¯Te7ÜXí@÷%2„ö™˜š½TUž‰ŒÅ' Çw±­7ÌAJJˆ,ÜÁ¾®nåÑtÀq0³ý ¹o’ž$‰›cÏu@®‘ 3hîÓ¡_Ô³0hÀáj•kø_R•˜Ùgƒ °ãq.*0‡)´RcîœÔ®eµÈ%k˜Ž1ÖÄ{w$ÝèºÄÔÏJZ÷HŒþ°7æOŠ"¨©‹Þu8Q¿z1¹{¬¸Û® ÝÑ º×(.ˆ¦tï>2ç¨ÅÚ=¶gA(™Ó•ÄS2¹ºŽžú¸6òªj>±9#@’q2S9Ûž4 eéU ìVŽÂ#¨aÑ\0}ÌbÑÇ\!¾x‡êdëm{(K¾šxoÈ<<Û…i[g¼h»˜›F>%¿ˆÁÑ]ÜÂJÆRgicc­çWaôß¿‡Ô;k௠çÑÇï¯~ÿþ§«ß?Çú®š›±é‹ÈãO¡Á—íäÃê¦JƒV|ß¶ï§ôE·î PiÉ,Ð ò¤Œ*‘ØR$€"´ B¥3>诉6£Þš–%+?^ëÀw /S{0’š.³mlw§ÿ"TŸ«À³Å”E2d­{T/²Üv Öi7Rb£Å:Ê»S°µ#g ûuÔm§‰\Àò[éÁý&˜ã-š-[i ¹¹6äøðþêò¿–º=–½qïãMÓqwÎâ°ß°¾yAJÀÛ íS7 FÍqΡõÅíõ7<;ŽO]M¶wåX ½£–§5/ÝÈpîˆi~–¹i¢XüÜ›öXq„I v‡4-ç; Hý <ð,\µõ^m€É°/×¢“ +gxuÄС3fÏD£šìZ9@upð‰‹‡†–¬N§ë¥+L¢±² 99Ü?ІJŠá‚ÊR*Óã»7¡º–poqí#sVÛ“m™î¼ãòkLØB¸ŸpÍ]'5ú`‰Âý¨ô>ë²Ôt;'øù»ï.ßýp!B³)ö×B{Y‘®øxñŽ8ÿùO`@|(ŸÌ­ ÓÑ·7®õ7àãTªío{£ ʦÉàÞã–%BÂóïm·`D÷ p¿ZËJ/s?W»"ÆÍ68]I2T®2Ýoò”–]°ÕtXØ>m¢nÑ‚3(Æ€¹É›™A×àx8?Î6s™r(…<ƶľOgœò]øJeÎÙ…O}^4`Cñà)]Ʀé”4à ¥ç Û2üÉŽPõª!¯£‰|šb-ÂÄèåË;°À^•NŸÂßçš~~á…H¥É‹¦ '^ƒÃІÞèàòfÏ'’įâÖWrdä¼õS§¢ÙËÿÛÙÚº)±J.à©s ¶/íÄhä ×ѽ¸öôü6ÖMY´Qƒ}|5¿>ÿâ £èܢ،ÎN7†Ü'µ^(Ò*L 8Ï’Dq’OÔ_ÓïfYÅóÌçF³-]0"gˆ`yž È“óTÍ÷Iþèôñ}g˜>¸ò@„,€ŽºÄâG½–æº,p ¼Î¹uî\2 {âÑ“¹kOŠf·Ûà)sNŸ.xK¬xR)Ê {ÃlfO异„E×þ djÌàý´aCÉ(®ä›ÔT;âicº˜©×½X£Hk™1»×±Œ Êö Üè^2ÝÒéѵ«=¤Ç #'ŠîßRŽùþþNÕà>GøŒï;@F ‚vï—ÇüÊÚhSï ¯Ï4Øõ3M—*øª!ó!!C³3߆}\¬Bb·`v‡ã—\Ã|ՆޣûRøJ ½%p/)¥—<ÄR½xñ²§-fP}L‹ÆŠ¯„šK÷×Na–M‰¦^Áå±ÁWhÁ»— »ÛÃý(¾íüÉIÑQÖ(*¤¶ƒ˜—º„” Ó×Hæõº‹øåREŸó?Ï?ë—ÿpÀ2ºHG‹N6'â͈YÀ^9œì¯-; Îgÿ PKò lH«HlµÅ¥Nsetuptools/command/egg_info.pyc½\]l×u¾³»\rW¤HQõkkdKáR)ÙIW±;–í*qhgh[6me9ÜRKÎάff%1‘P J#m“¢@ƒ¦mЗ6©[4@_Ò)ú›mѧ P èC‹6@‹¢-Ú§¾´ç;çÞ;³”úガeîÌܹsï¹ç|çw¶ú¯ÍÇ¿óÙ×:Jÿ7BŸ¡¿Ù?8JJ­ÐÑQAEEŽêUÔJU98¯ª¨¦z#jeDÎk*ª«Þ¨Z•󩕺Òm§Ôn¨•†i7ÕJÓ´÷©•}j{†Oë*W½ µ2¡œ+ñU ÷«­¦J¿ªljõ:ªhRõ¦ÔÊ”¼sLEToZ­LËyCEUoF­Ì¨Þ!µrHõfÕʬÜkrßÃjå°œïSÑÕ;ªVŽªÞ1µrLõŽ«•ãªwB­œP½Ôʪ÷ ZyPõNª•“ªçª×®ô”Ú|H­<Ä3çV+Óí N©uºº_}N©»J½¹rZ“*¬òÕ){µ¢‚*œæ«ÓöêÄÉÊûT0Ã9âFK³Ü˜WÁanœUÁn<¢‚£Ü8§‚cÜXPá¢ Ž«ÏÑ6œWÁ ¾xApãQ¬a¹õ 6ý5Â|ÐÏ“$Ê;I¯çÇÁb¸±ÑîÆëI³ù\úyèúnÐÍò´»6È»I<—¹è²€.t# ;y’n»ô¤ÛIâ<Œó¬ûô_‹XJåctx¡…/ÑreœÔñF˜æí¾Ÿ_“«U:DÉÆ’œ50³q›^eri”ÏÉ åx7ÃÄZx6oÒaÍÏBL4Þàñ^yóýüþe¾tùåâý7ýh«†7:yµÐ%Ÿ¦CßO³._ЪzXˆLÄ_Û±ß ó Û‰fŸ-x0¾o.ì£ ÛÝ0 ÚQ7¦É`ZÏÇyºýJÒóüvó0m‡¸ÖîãbÆåI{è„÷4èû-ëÁ$ÍÆXñÅÅbßÁ]Ú]‡…˜øë¤ \œRñéÃ*8­6êf’"Þ ’ìšêVÐ&®}W§Ôã$Ýšë†G Ž©°ÁLè° î3L8n˜pÂ0á~æ@jLB(„ ïÒ³ N«àAnTÞrë ñãÏqYCH²€]*ÍÂì%:< ~ô»1Ñï>tÃÌmáº?ˆò‹nžôÝdÝͯ…n– ÒNèæiÎgSØ c¸q¦Ë›Œw¥Ù9:>n6XÓ»ïšîåK4¢k.ǃÞ5ÇôX-‘Dz z \r³ÜïõÝV¸¸±è>váÂ/|ð±'æï3NS³6èF¬|-[£÷ÃNw}Û oõ£n§›»Ô Ïûô†{‡™¤'âäÞ•yÙY:^"ºçüä±¾·4í®f£2]Ö¥ì!;@7îDƒ ,/Ð>ØAgü­@¶ "ßVªí˜FÅ4ª¦Q3€0uÓâ Ñ0}šh,·ðŠ¥.„¦ÅÒVÃy‡V°XÀ÷é#Íæ&XÌ;h¤’¨ÚfÚçš;ÚÀ*KC½Ím¦Pê?"˜¹×Òd+ŒÛFùî ê«1®Æ€­·xž8do~×ù5ˆÄbÏï$Ù­…G/,>zaáÖ·ÿÀyî|ãç5ŽŸ7oYìo3¼‘ ä]?ê~:l'}ÈUö(Þ€[ÊiìøÓÁ0Ÿ†Ù›+k(ÕsÔŠrò Œƒ\dšÇQ~³ µvWUï*çNUÝ®¨Û´Et‘ãã)4Ó>èæm’Úõî“Û;‰yc‚ž‹ÔV ³ÊÞ_wÑ%Z›÷>CÍ ÛɹÁDFÃ;mÔ’[é]ÇVøÑ ÌvŸúXKܰZ‚o<‰‹û™øS•º#¦«,˜Ìˆ!üéJÎ̼é¨Í “ÕÑ‹5\qÀiÝœYØEÿ;ŽÚþ8ø—¶´Òæ>µ9ŽÍ m¤½I»ØÛ¸Ší¥Ý"M—ïÇnÉFÊ ë5KÑÿd¥½_Õˆ£a¥}VIÂæµ9 v¸Ï3Ÿ¥±ÉŽÃµƒÇ­1•V½¢CêNMÝ®©þßc«7gÁLùaµyÓÃBªX–ì…÷çÇ ‹±ùx½Ž+^ݪªô íjó} ÇãfÔãÕòêV]¥9ÏèAÐÏÑo5d?©ÚûLÛUwˆÔ#¼†JÿÆ¡öæ)=‡ôüV…¯Ë#ªýðÐ^àÊi P4`Ûå©X¡È°ýg²§ž:“1¶¢‰öcÔ¾“vƒ!ýè‚‹Ý$µŸm“Þ»uÑ=“-œÉrŸÀIe«ªXõzûŒaT–…d#̽ãè7ÃÃè¼_dj# S{'pƒ°ÑCXÞÇаýf`í×u2Ñ[½¦yòuHáóiš¤Œ¶˜Û,¢!®gù Œ¹ñ2£?ÁëôŽ<û)l“Îg‹V“ج3Hqk ãlrG^-$V¿ÆÃä׸± {íž¼v¶Ú;á#-âòûl,ÂÀ¥®A‹àl…ÛŒúQr“ `<`•ͤ<@楥i«nk¿Ò¶§½©ÉlOY{ ¨„¥öƒÝdz)FÏxH—ü(Æ‚áìˆ3éLV&+UçPešŽ§*¤QªÎ±ê¤3Îg³Î´sŠzMŒL×ÇÓtuÚéŒhЫà#= JO°œ(V Ö!ä—Æ/©œáp“• IUz ÷À€.oQÆé¢ö¦˜ü4¥.ËZ4ùA;®±#‘}›äâJJFº»Š}\…å´jtÅ*Ä,£nw×ݰ×Ï·›MWÿwyÝ<ÓÍÜ8‰øþ9²*ébÌéÉhâU `MŒ-ešŽX1å.×üÜ;kM€:ð¤w_gì’´]šÔM¼’ªu¸ƒd_LTj•Nm§ ùŠ- RECrBø‘>™Úd±‚Q5ª¸¦²«­ÛlÂŽ`N¢v›µ²ƒ“Q£JI£/3‘²_Sÿ­taw±wä’ÿ–ây×_'Ùõã8Ä榼¸UКa@ȈíöÝ(Ùp{Ä¡ü½¯ ¯]Ñs-Ä( YÆv$ê ÂTJì4¥‰‹'ˆw¨éa,d¯/<Á{sMx©`ìŒ7j¹(î$AÈ:ÖÔ¦5q§¤OÓ1{Ç­N”d%^ò<ÀGÞ2ƒ¾Þ}×À[¢a~B[´.™&¸&p'«†Svp ¬y°CEeóâ_ÜvîÅTè…K‚šïy³3+l² KB!LË»‚Û8(­¼‰(·ÞÀâ¾qéêÇ´O²9IÈÃÀ9{6ð%™n¸Â.ÎfCm6õÈrñ®à×õyueÇ}‹Uúú>€Èÿ›Üa\Ÿó‚Œ-s0X°ä¦$dc7ŠLXÅÏ»äîEݵl1¿•·öîìmÁ–ß–7½×C2%¢[Ò㨈§C‘º%ѱƒMT««¼gpxp%Ûñdm de%Da S„}žŽ¬€¯ÄÑî«&‰õ70ä sÈ™zùx®z„pfªÂÜR+KÍÅ-,4ÂI# J}ˆ®Æ†Ò%#?ʸ±Kèp{}¯/™îdGncûi3£s‡#Àd¼åfdGkª%X—af é i³7¶pæÍ3½3˜æHp‚mbHd9ÄA ?t{j"÷j'E,‚ESHÞðz{"§ðÛ¾…ñfyê„V@¬qjÍàßʬcƒÊv“}È9?±5ªÒƒŒè¤‡r\Âz1®‰z¢êªªL<ŽÉck/ˆ¡ÊmDÉt¼V¢ƒôÁåñeøOì &~ ¼ý”afÕ´ Í®®Æw 8ŸtjcÕ2A>¦ŒòÛ¬hž X벸é.GÆÄˆj× ÑÑ’ØäXI3"Rúb‡)â£Ë/¿æ=÷ü2 Ã¥)v×Ã,g‹„u`éîR ˜³Ø_Ô˜gÛ=+LhÆJ×½-sƒG&‡"ìòFY3Dôz»Oø æO1^“ ×±atˆ A2ñ¿¤Œ!šÖà`XÑž‹Ü®a´.0{+s«®5lúE0Þ&oa AÀaÝ<¬±¦Á*DZG–í† Ö0L U¼E:ë¤ʾN‡æR’‡Ý7 ˆÝÎ MÉä»oòìš7kna,™<Ñùp“=°›Ý(b3éf’n¹$ÅC™³¤å݇˜¼DHòn„QÒh±Ù|% ᥼sÖlÅQ?-®]?MÖ¢°·Øäˆ¸x°lõ”ºW½°9ñŠa5¼[˜,Öd[ï>Өߍ7Æ“ý“ô/¼Ieµ<ð•SÇÐòC©c‡Ó²ìñ£Q*¢Á†’d‡=íÌÜw¡BH\È¿ö;²-37‰£m µÀsû‘Ÿ¯'i¤.Éó…OîÂÎ:Æc²I@Þ‘ÒâlÔ¹Ëâw*ÚþÓñ¿™|­ØSÆ&ɰæ É8±I¼Š瞘«8Ï¡^ŽÖ@í²‘ì÷1á’†d?{ »¿ËŸ§aþÖH³bG|œ,ëŒ[•誒{™“DÔVÏKÏ‘­ÍÏ)ØÊiEܤe’à݆r€wg÷W÷æ1^…WgsÀvU€†\vY†–,I§ÐÍþ’6Xã…Äe„ÕÈ .òö‰ŽdVÄæ ÃÁ£†ŸÀ‚0é“›d„e€}S®Â&X˜  ĵi´=Yå÷¬®º~.y“P«”È„}ÜÞ€\ 96tíiØ÷»)uN2=Ã"þ¤7îƒ8¼ƒÃ]³¼¯¼Y»ï¶­Û2­¶;5Æügbô¼S¬ÄQ«h«XK%;è:É÷¸ ‰#?˹»ò!”Ž–c‡ú‘-GâG‰öã¡ísÚhƒEÆAÆìgJWÄÿ „yùJ|VÕH9 ?ùGœŸ, Ià-Ž=§P^Vø÷€þ¹3Ù\#xç“™ä.,¸ÙV·ß§íÏæL/²Ö1)UÚpÚTî û¢Ü× %€°Ì î"$(ÕMl°3mgí Ä"â,ÆÖ)Q(’pbÉôÙ@Ò«é äDÿk2þóÜSi¬…·3Î]‘;¥ß—£ÊIæ\ pü[bI6‡»9®&ÐØåÀ©¡'²½ÜDØþ:6„6î"»l‚ìíC|œ¸oºDÛ2…nä5Z+²©¦%Œ£e燑ñ~ÒàZ*†ä8ÉÃ~)´¿'Vh_Ãîc;&ÛÓý8Z~`˜ÚØ­5ÞÖÔpÆÃÙ°çuéê!Õ­j‚|ª¢®ƒ!C4™½SÕlOjG.‘Ú^·yÿ"t–¨’ñ'9E“Á‡„´óœ5qeÎdù†‚kv ¸˜»¶­Ÿ2æJùÀcªÈ âÂX­Äª–š÷+V@p7¼vÈLdײ¾jºó÷²ÝçàŸYp™¨¶î˳¨†+»_Äʼnxꌟq«˜o3Ž äô6?ÕY|Oë ÙË‹Úlê‘æ’šb‡eSbâoì‰Ðâ%¾‡c«eŽýv!¢j81¥këv^Òhul§Ä¼EªÓ·´Ã‚(¯Î>„‚»M®¶³¦wtª©„ÈšÖڣݯSœø’1'9wÁ²°9E]§AJà«êô†‘³l²õÓp½{«ÅµLLó_´ÜÉ&Ò× cŠƒÁ!å/Ü î4[X×fdÛmM}©zÊÛ¢(À¸òÀh$o3æ —j¹Náq‡Ý6­d÷ÙëÿHádQ$¦¨Ó(>éLu¯F&²7èðC˜ˆJûfÙ§]•Û²DÀuŽVü8§(/iHéø3ŠŽ¤@"0É’ìJ Èøc/$(um RüY\òcþ{J”wMÀs±pj_%xÛñ”Ÿ†¦ÜhBõ9q»YQ’3ȳn hj¢Ö>ôl†1QÉ^o…Ûºï |/±I»²èv›Øc¾\ ÒSÄ«$Ì‹*Ñx™¦E#Ó Å%iÑ¿‡eûι"~r¡YDô¼× ´cŒƒ©à­àð–2ÎYÃRflêïM_l­ûÚdu²2ít0…±òžàKÁ¢€¯R.àû­B¸­† ™ºªÐ?í:‡i•¶`øê¾…øô _j˜PoÂg·k¦› ñF¾ÏTNðw]äÑÝ©kÓ6šP½ýêÎ(Mh¯ v»>ärHÎÝ”íJE “÷ÓÝ>gpJ_A 0MaŒ¶€:;«,6@>^€º“<øºŠgô·„Ðbi !ä/Xƒ ë½#y¿¯t9… ‚ÙåÛíõÈßEônmÒΚù0P%Q€¯dG¥Éeÿ qxìÝg¢? a>SÈR#4KªÕ™Ê i©JÇ”ÄØèÕû,K©¸‡Jg§Ã˜ÑñʳÞÒå¥/ºs’ä:¹9©›Ï¥˜wÈPs/,>~ªI!K»®¶3ßêfçÉ"NýÌœ›šo²|72îLÞË¢„Vv®l”]¤[â}ÏÈíîGUà8!¤ÞÖ«n'°ÓÂ<ü’cŠPÙP¸!Ö-ÿ°P™±?nÔ„ñÅW³‰@ïÈ‹:E t(ôˆ¢bF‹ÛRSc¶‡Q®0eô:ñ”®ãåOF~o-ðŸþ9À¾Avƒ3&ñûE©>X-¡hŒ <ô{Í1ßWp–aŠvú Yq‡d¿‡ìòQ&¾_Hª )\Ó YjRË;#RiuÌÂÐ~Ô‡¶B,åý¦«Ý ©fù eŒÝar2wŸlG,Ù†&ÃóþÕîD6&vÐÚ)¡2JEG+ú‹âKWOè³,`È# â(bɳŒ‹&q"ñ²€‹TIJŠø.ÿŒÇaK^¼R‚ï‹ìwðçÆ\þ”'ý…eulSf™Ø-æëiÒÛ ·3¡< ®øçÊßQré’àRÖº¹T=ƒÃ@ó‘û08^µ%ßnmìÁÉÅGC´H^£Ìò›xÕ+U籪U÷¼+ó9²¹¿jC©"öòö ¤„½/©ÿ/ ‹$\sûîß.eÞjjÇ·Õªl»s8ê(ÐØí¤2†jù£ßO€ñPÃÀxLíÃt»øhXj Ø~¶Äa„î*qRñÉÙ˜a‚1ï-γÜ!ß!¿¯*m•ÒrÙLäß`ôÜmúzGÃüŽ FixˆMD«ä¬£tĦ‚îð¯5rF¼l®T#rm¢xüus‘èûÈ=]¼õc¬õª:#ɺoK½]ÁnÄ u3軺Dô !QŽ Aö|ºŽ¼K=À¢ÎÛVã |E?«?[w®¿¦®Õ¢¼³T&D_ÓŠ4Ÿ,öXÜñ!oÉ®6Ïdͦ|MuÊ¿üâÊ/¿ˆSbÃå…ñP˜çÕ-*x_Qy–yŒOò‰3~f#M}á’?Ã!Å?¨"‘~†–ÁûhSïšÒ:€y( ;@-ïw÷Ll ÞpYp™£nH9ˆÖp©Æ %Í‘élïÜ9z’XUÅ-½n%ñÙ¶â1šOIdµø¬;4ˆ%Yåæ»ÅrÐthÅ×\D_ó'˵DžÝºÇ+<ØH „*`ÛéŒåµ× ¶­¨ Ä!n¹æÌ¢ÇJ ‘øng<Û{÷»Eãs&ŸSøx;Ôù9•¿F•@ÉÙ¦Ä>´é E†b£7K…à«·ø­Êkø¬[>3¢'0¹5_8ßóÎdŽ, ‘Û$cÙGBÁKŒa«Ä¿ÜÛ !¬!Üè™Ùë¹ããiZ¥h¸ ùd¡áPrïü`oÉl°d6Y2,é©FyK!¿^Úó‡Ç³¢ì¥ÐJÙ á G)±†”_I:g‡d”<£0€Æ ¾ð\é# z4˜j'õ599èré/ÕBÝÄĪ+ÊÖëMFïÄö°ç²Ï.”ȺÅy8ŸŒæt?ˆ®=*‚v@ý5Ëf÷Çî ]@‚|‹õ.€?5•ȱ2oQ(lÅ#Ù‰­¨„í V)DP˜d¡òqPúa¦±bk9£g´ˆ¢I‚;©4Á-²&“T‹:l9}Э¤ÚÆÐÏ{®¬!Ká ì^µÖ;ǹéÅÒ3Ï/’$+Å3Ù×K[Mu)Ž'·¡hÇŽº€wÞÈšÿÓrãÚ P‰4¶Cƒª?üFQV`S²'n>[¾Ñíç<5 …¬ÇLÊr<Ä‹¬Ä%s½9¦4oµæÒ–û}²\Gا–œù¥ø¢h2m㦎- (Ù¥÷¤IghÏHì·yeø™jT¨¡Mô³Á áO¸²"¯9†J1úÈ'sʪÑHàßßZÌõÆ5ð‚[´0¦ †%ŽdzT Ô~°ÂïΧAìÇ2€¥'£>Þ­†9… Þïj v_¶49LA“ÐT ½Žä…xšÿè » ¥Ë¥°æòn„rS]g<ÞLD&;pŠ ºÝj&‹¨k^5—µØíí%É<“s…ÔÒ”xP2¶Xq`á\N¶Í1(…O}DSO!5íž‘yŒË cæH=žO5Kh%{d¢¢\1Þ³ŠèH—v‰ô¬Ï…Ëô>,ˆ*Ä<òj³ÃÒ°øeäër)`wéP³JÜNç}ÁOô)½$»œm£$~ÆO›ý"3à+^c„0jÝi7X£>h%?ºýø´¾wÖP2meÍ # ‡êõíõ{RÔM\ºÊ3Ù3=mc/ˆ¬'gEÓ7ª¤¾¤ì¸Åò͵³¯ 2ðîûûy4è’!ñÝõÕ´CáÍQÓ礧Z¡dX‡ZWëûuZft«ÂP ê$Î2ºÍdͰñ2:Òd>7!Þœ$Ýì4å ––­ÌÉ_ŽbÞãù`<8ªiCË™*ax˹Ê òÖS ™VžAæ®NIÒÄAÈk×ÂÝäL À±¨è¹Y<-V@ý÷fœSpí§›`:[ê,S.M«yæÑ㻉_bœ–46ôYDãAÝJœ©ÆûBÌàX……É ÎMçŠ;õí4&Èš=p ^P)ôÝ»º» ÚÈÃátôóF`:·M_”Ýù”$ i.ÂUwÉɵ39†áMYð§ÔäL&i)ý$ñ%ÅËÀú½¥¦pHâQå ÉàtCú²£Õöï91Ë0ÑšÖÞÏÚþtù¦kžE8Öxç;ë7ùŸý)'ïz8êê¨oû(5µs®mòzõ2×yP¦ƒÒôgöݵÝÀ€/ Ž¥ènoo¡¯’ðCz…YÆ µ"ù»¢iè~NèÔ]þD~,1í6¼´ö¹rGIDSýG£×ŒYà™»×÷®_ˆqN‘ÿ=¼rhþSx1–ÑPKò lHK]æ-wsetuptools/command/install.pycµXQoÇÞ;R”H‘’,ÇqÕ´è¦h*U)HÝ4‚ºM\¤„àì Ñözº[RGï˜Ý¥eòKÔ×þ‡¾µý }ékNÑÐ~3{w¤ ‹6³{{³3ßÌ~3§ÆzûÿøòÓX”Ÿ&¾?Ç×ü—ÿ=‘ 1õÄÐ}‘ùbè‹Rnˆa£’›bجä51\«ä–˜¬‹É†¶«™Žv„jóä¦H¥<òDÒâJˆÏ‡b,Ê“®øðwßÞP=‘¬‰=…¹-q¾.ôŸiê÷¾ø&·Å]ü„]ÚæÑA N¤ÿÅçÀƒdoáòajìܦ™y Çi]è»N«rc£,«qXÃ÷„Ã_pQ‚܇íð[5Ĥ)&pnG$·ÄØwái9»NxÁž]'K“ù3^n”2nÃ;¸S¯<Â"iÓ-¢ÃìßdîvYØj[$=F`ó-ž¿%‚G»déOqùÔ(©"³K¤-d-ž)9‹âóh¬ŽäÅq¢f*OT§Ê˜×ðl‘%ý(Oúó|åXfŠo<Ö ™–t͡ߞ¥æMó&m™æãLõŸ(mÒ"ï«§Vé[-úNCb~‚Ux&‘§ iƪie‚<§Y‚'Im¬Ud•Üe‘Ý—j<6vg”phTÄÅêûK2€ÒÕ DšfN\”›lò\-GFe£Š*_Ì\x÷ãÓÙ0˜Fqažöß¾7xû^ÿé»÷ÃûïcËc£ì|f‹"3Çq1…KÉqiÑ`¶°Ðò~MO“èƒ7H-é¶Û+f›X§3k¾‘ÕAƒÌc©Yú ­ (Ÿ¿SYY[äWýÐY4ñÄÄ—œbtÚ!…|¤Iàó\Ùܪ°-t:é]v=µi”¥Ta1³H ËNŠ\Ù2ÇBX®æ˜]¦RX¦R¸L¥°L¥Ć")I9%¼¯í}¡Ï^€~& ¡ß"$Bù1 `ýX¸»ÝRj±d™!ðì—žøâ±È…Ôv9ao>/ær:7Vš™ŠÓÑBöûZÅ…Nd¡I.p/ÎTîŽ@{îX™ò& JsQ¡s4J󝯄TqÖ›´Ž|w;âfS± -o‘º­î.¾¯yÀþ®àä›@ÜeÁúûÂúí¤YâQ™¡-—„õX-ÛϨô*oWð¡šp ‘|H:…³ÈžmºE…£YÚ¡BÀ+’T›ć"vÔm0>»þNóe ùõȸl´\‚¯xÊüúùE^Þa´Â[9ä@Ðyh”6zžó‘cØ­’p¤‹iè<+ *2ØZŠv<×Zåv¤£©²õ¤(9¾A,oCË{¤Ž¼þ®·ãßñoûŒ&e|£BóoM”ßó ¡C‰ôÌÖv>±žeÈ®¸ƒ9÷…þUúçáDÛ5ñÈîàEK³÷ |êäo¡¸ÁÙ— ºÿ¬IÂN‡Ú4 W¾x¶&.רcÀNÅ_Å%š‹MêΩ­¡h˜ÇŽ,?,8`Æ%:Q¸I àk‰0üH^DFº8IŠ“dÔ0RAeŽPݱ¶ÖV9òãQõp÷ÐQÙIPHÝ]-/R4§Ô¨ZË>¶KUû‘?+4#r?©Z°IûGØ?‘‡©5‡Ï©«Uц«êL¥ïš‰Q¾ìÜ]]³%NU’RQîp8MÇgöl¾fçˆÕÊøù¾•gÑt*JåKlj8®4àѹ¤ÖƒÜ´gÁƒ† §#ñ£©Ÿ/í2ržGO¢4£JXëxeôùr‘5¨×›w(ak=Ü–­<ÎG%<¬hä4ZÈn˜¾>ÖEþɸåæ>†)ú µF+3Ϭ9BP‘ýÏÞ{H'•;3•“æÓ)1PÊ4@†9Ö†a°]Qúõð2¬"ur@3ŽaIÁE¤sÔ1W”hÀ³3t‚£BOí°Ía:ejЬ‹¨Š¹ÚE·™RÆÊs4 L2†wŨud2…ã¬8¶L`¸Í[æyL ]OÓ.ÍudEë¦fìji‰Ë 6—5÷ê¹pZ$óL½r£Îé#R÷mRºÙõZ^ÏÛÅuÇkz·!o{wü®«dÖFÅjÿªkªƒk<@X—^9 "…%\&LO®g¹òްßy`% ÐÞÐ3€Uyu'Ô&ºª‚ÙŒÇ ®±#½®˜ô„þ;Óݱ™›Ýob–vÙæ]vªZ„%aÏ•ó—sŠìê+"ÒH rÿ©+ò”<ê|™CëNF)‰ k¤iâì#¸'@vT)ÆÎÅŠbªÐ*7s­ÂªµJx2ÊÀ<ÏÍ\97ÊÎ ö&èø}$Žr(íæõ¯«»§×| b"ÅgsËÃeÊØ×É1´sp!šU¸8Z®#_ƒ“ý·«³wЬŠnpX•ôxšðªWžÀw¡åuû»~ÃûßñÚ=¿ç}Ëoû¯ûm¯ã/}=yéÛ¨{î½’žüÿ卵-Á¡ÕaæsÇ= ¹á äˆÁƒË.©ë6ÒUÛí8oÛ+SQ^÷ã´2W5Grr$)Ú'r,Ìc~GáΙÛC#?eˆ cW ™'ëe_eÉ)fy‰KËk!f ÷~{.Õ®ß^ko¶;íÍí7ÜùÚ©ŽË²((ú£‹á— fï€âÐtð]Z½wmuÕŠT‡Ð-çØ÷ϪbR“c3?­ Þ§uDŠÁƒ›ÈýIÀ%Å^•É;x»qÿP)Ÿ{ÿPKƒ,ÒFœ¸"²¡&setuptools/command/install_egg_info.py•WMoã6½ûW^’º²í¥@ l/=´(Ú¢—t!0m³‘H‚¤’¸¿¾o(Q¢dïõÁ°©™7o¾©£Õ=k¥óƒ—c²7ÚzÖéS‰S[Óén:Ôn·;’¸~0^ëEþ“î{®ÚíãŠÛæ,_D€‰²ƒ2¼y®§GÜ<Ÿj+œl#`g×tÜ^9Ï»®§S-ÕQç“¡â~ÇðÙï÷?Œ+VAê@RÄ\4^Û ;jËüY02ÉO » Ù ×Xi¼ÔŠ=°ÿ‹2b NØZ ÇpHŸ<›xñ•,kñµ_𼎞áç¾(ƒæçÈ숇ÒKÞÉDÄÏ莓×ô¡¿UŒ€aÿ­Äq”ê¿©zP—J´³dd_wò)+g¯|P!Ó¿E1CY7} ®Áú Ö#ͶnÆÌæû˜ëý¢÷ÄP¼Ð\ÕIõ# ×ʧˆç+¦rúÍRbkBY¼ë <ë³X^°÷,›Ë!Û„.0¡‹ÄÖRž[x )í*Ãý¹ú[K•o“WÎku=x3øP\ \R(vP7‹ó9 Y¤–-èò83’ ò¾@´LiŸˆtR=¯dîWÁŽ“¢²¢×hwo…HÅ1K쥩‡p8ýIê¢K‰7$Õ}ÅZx"ÞD3x‘CkPD¯d+‹î7b#Õ‰í‘É/9š²ZÛZ—›Pn°¢ž9¿ ºâwÍ¼ÑæBa"ù ‰ã£±pçöìnòd´ZÞf^ÜTDcJ¸¼XÊ„:mª¥m¹X k«Vå¶èEª[¥wŒX‡‘¸ŒK$œôâ0MJ7«œ{–}/Pl¶AE¸m^ßahu^XltþÐhå­îæY,…ûH)ƒ¥3÷,TƤc¼{å·ã,ûœ0Ür/ZFåUÂã·m'°^ô‘™Ž{Œ÷¾b˜ÒÎ`œ(spF4ò(›€T­¤hEÀ?ƒÙ¡á^ÔšƒŸþüýCv5BQv ^!eÖ»WéÏ9© `LÅ:!AêZ;I[˜ùW6å±âÆ ŠôJÛ½jÅÓpʯ«¯dsvv7 â|7Ÿ¯7ù‹¶Œ‰/Ò wU¯›SÎÄEQSýiWÇÂʯš ÷7(ÏG(.1ÿ·t$;Ó¡bßüífŽZìý˰ñ|ªŒ?o¶Á&âQi¡‡ L¼jŒAG¸oÈbÓÌï¹É£ÿª¦kzV’«Å.õÿËìÝÔ˜JP„® &ˆ¡¨Ì I«d]$˜Ây»U‹u*_¦áv¾8{õÖˆcÇ5™cõj뀱ƒÀäïMÇ—¡¹Ÿn‡î¶þbˆ´FÔsµ\/.ÌÑÒÿ¶¨Žu§޹nj&ÝH>—ì›»Y,l‘bI‘€Mkh…mʬ®érVו¹àf“j÷P¦: -ÐýÊó=Ñêu;`îе =À‡Îç ñ|*ìä\õsø¿ã“ r7ïiP<~u_ÕXH QJpÁ“h×uVB0…ÈÍÈR±ÞL&Ö­‰’cÊ÷c%ÆÛïÜ«±{…Ý_¥¯îa^®’˜õÁ ØqïmžDâNr+”/,rr—cŽt-E£/²Þ¶’îx¼ ¥›»‚½žQ»œúñfNÓ[*„ƒæýDî‡ð*Ñ Öí<6-•7*‹ž.¹qÝÓ1áRÔ8fžlt+Ý;ÑÂt{¶ì× Àû®ú~Ö&¥’ i\ŽÑ, ïG ãðɳ*½%‡0Æ!bUÞ(øMsÖ”,Äm¼WO|V€M§Ä¨³nÉÄØû+kc2·w…ìc6¶Ã¢[àÒ2vÙxkþKe»4Ö×ã{3íñböÛtA¿cWÓø¡ýLïH1¹Ë² ÷¸¨…OV•lHÛt³i“÷„j†™ÙŒýtuó›"ºäh%ðŠ ‡â¸ÞРT¡dIg¨âJ,ìmÞ6AÆü¿PKò lH"ŸŸW‹q'setuptools/command/install_egg_info.pycíXÝrGîžýÓJZK–m p æE»FZY”±¡BBÊU U¸*ã9ª©ÑLïjVóçé^[¢¤ P ¸ËƒP<ÃCðp¾Ó3»²Lq"®°¼==ýsúô9ßùúô4þÑ[|ø·?ü&Õ¿ý>¤Ÿ>¢"¢ÿR$B¤RìK‘:bß­ŽHb¿Á#"iŠ´%ö[¶¯)’¶H;b¿3» öDÔª%FRDmñ•Büv¿‹îgý-ÿ“þõª(‘äc³âÒŸš8yÚ—èÂÈ'yšYdnP1ÍŠ <öƒ2<Š_)³ i™6A’øj<öãl”Ï6ئßclð5J`_¤$í %mè–Óf›Ø)I{"µQiWjÓ®¢WhG \¡Mt¹²(¢ÛbIDwÄþ²P=Ýä’À"Zã1+Â{Ö_‡C*>±jºAæIÕ¨êÒ–UhòòÔå¥kŽ”‹íc¥—ç;Û¡Qï˜ ÒÖNÕ$“»Õª† ûËö¬cÏ„ðyëÏØŽO­å›¨æ™2K—lH¢­­Ñ«U2êÃ\è_Qq8“h÷0е¦A˜ë“½ûýû;'?}è?|°KÛÕÊL “ç‰Þ ­ûv¯ºhXœš5^66qÄ¿S~^˜8Ï4Z5ô’÷|´êýü^ðf&ŒUrÖAïÈ$ÓŸKa1±X¥¡RLZ\¶ÅEõ Æìƹí¶Ì‚0]1Y“%–½,ÎFW[z€ ^oXVOß°Zz@+£¸Þ£îÒËÌÓls}ÅÔWßû+r‡Moüi©Qœ©¨¶ ÷Œ©‡ZÙh‘_ØÀÓÅñØ/•Χe¨´~>"7•ñá³½öe³ µŽÇË+UjŒÀ»Á0+Ã@å\3ŠÀqe’Ç™Ý+Ë JÒ‡#5Ÿšbjtóê*öÃ4âe­°ìõ! dP›¦¶sñÔ•¹"Ûò.=—©œÅK»Æ×ß/ã‹ð$)è& (´6ÑT~&ªÆÖ¼q­í PÔ1|& Ô'eö^=£{IÌ×\_䮥ª}Ä8¶õ‹†™¨äè¿rè¤7P÷-ryÑ@ÈF}¥–æˆuÁÛ*/çèµ®†Û¢òÔ/§ƒÕSiþ*ÎÆ®^eê-Nñ²©A3›Úúí&&b6MªÑçÝÂäÛèA¨Æš ì­×ˆugÇžœMÄ*Ê7¥RÞÝNNÈÿš5R'*œÅÍÓŒç‚øÙ»*ÓÓRù3d`…¤(Kƒ›+Z±àÜ4ªÒLj Ëëƒ_ÃZÅ…èÛŒ¸žü‘|GÞ‘ïönò\g†9Yc®3Ã\Íά*xþ¡ôRE)Uøî\¡_T› ë S)þ(˜n…ø30JfU@ކ©OC§š !€‰~AÅÉðúÑÁ@œ;ÕæAºRèmŽGlPëq[”¦Ü—ñÜ.€P¬B“ Ýb¾Z–¾5p8Ô¯²]…Ÿ|þl—ÏÏÝlææ·§°,³ˆN":£_Çæˆi”½Ã ŠBQˆû‘:œŽ™º ùicOÔ㸸âÕoÛ¡»LšªòǨâÍžü\«„BKÐ\ T8NÙ¬’·;CÛLÍoYCï‡$î>äÂ"ÂYY kžñ_gAqÁ0#Ïêu†ÂÛŒü¥3l—*Hµpê[TI2 ‘(X™viº5wJ¼Ÿ[â\åW Ù3K°¼Z¥60êëÛâœ8¿¶­†<§1Ÿ~ÁhçlJ+;™¦“xX˜#οª´ÏâÔׯžóà±ÇT¥ý:ó»D§lþ"‰:1ì)Fžwc®Él7ÊeiP˜+4óY ÊL²Še12‰+æ„Zöë’dcf°Ûƒ²h:¯>Š>µ¹‘´`”ó¨ë˽M÷ ÈýÓÑ2ñg“NíEBñª\sºÎ¢l:k’Oø8-òÒ¸úTo»æ´Pôȵþz ÷}ª‘¿ ‘»ôiÌV•ÈEöÑŸäaè[šlAGËÖÁ¶{o³O” ŠÕ%)ö¨ê¿!´ØÞò}$³¾Oªo úøƒfe¹qi:mÚ Ó<š&JÉ”ÜÓÄôi¥ãñ ¬þšG|Fõº‡¤=‚4l¥ŸºtOxq0`‰éЧ³0Ī—’*ÐÌ÷·¶i þ>TXE27-ª©ÅÐrW¿è¬,ë¨L`LÙ¿¤ë R#( /ƒ’ ³Ù§‹WAßtÀìÞ©ž·~DÅÑ88v'N•P¡Ñ†gƒ#Vr¶Äí_6‡açm„Wù…8kTüˆ†f|»DHs¦OM̰N‘¹QÅÃqÈå{åbfÊ‚·„»DqƒŠ¿*PLZ$%mÖÄÈÍÍ7»ý”¬{wjî·°á -¯&šŸ4Þ>)e†DžkCÓ¬1­^ª`mؤ×I?ÁA¹È£Dc™2’®üÅÓêüŽÕ¬=˜XZÞ=ù\Øûy°¸+Æt¥8xÌ.´×¬Ú£'÷ÐRÌ=ŠôØ©\.ÏØsHA_>Ï_¾#ž“ÿ,Flž@ç>ÒO3-3WS$«ÈW¹ùÈÅݶbFwžÏyÀXsÓ%]téÂÙàlÆœ]ד‚(²ÎdgÑ}Á^}°úüãý ÅÇâs0o`šùÇéÊïÒ=¥+×åš=­ßúà1„ÿç&óÿ3ãÍŒœ}czì¯Ög¸ÏWßg>ð};•^;üå!ÕAF‘ÒaóÍ•ñ<Õª¬o²_Ñpzï¢ØB\ŠOJÁëýRT—¬0 ´¦Sû(8ücs_ ŒA!ÐQC©¶l;íFKÝ•+Ý[téÁ%`íV»¹²ÔgvìVq‹/š³¾+rd“ïÙò¸Úx£mX} ä/‡6¯E±6×»aöìÏ­/?` @Ûu¹ì CYnü PKƒ,ÒF$€x»!setuptools/command/install_lib.py•WßoÛ6~÷_A¸$·ª°¾H:`íú´¶Xн…@K'› E $WýëwGQe)é& ¶Eò¾;~÷3¢iµqLÛ~á×®6ºaÂqZKËÂNktÕ•.cÖqÓðv”¨„uÒæ¥n®ª\(<"e!Å‘qË´§Ý®”Ü"Ö¼•Òz|öðvÇðÙï÷ïµJãUŲ*VK~²ÌiVã«â nÍ”V¯¿ô_·(»ó ÔÌt*µ ë€K½æÇNÈ*=L‹ºs^˜Ý ûÁ¤è„¨çC¢VÇ>i3.=/—ÞÛÑæ /ËJn]€ù#0®zß(+Ð`díèoT—ì"Üy7˜Ú;(^:šp˜¯xWÀ÷Rv„h¯oKlŒ¿ÿ×Å8Z'%”ŽÎçwâT‹•ßµr\(0ÄnËÝÙ[x„ Çk«È!Ú0+ÔIBñ†ôt7£º¾À8à'<¸äú¦eäý–—xž\.XhN‹wÒªlËÄ®ç¨ îþþðgñé6ž_޵¥Ò,˜ïYØJ²)„~ g“v5» ð”¥‡Ò ¼[piÈ›t D’^*‹T"¯zùŒn5ˆÌŠŸpýGñäù`9£ìÁX¬fiïi‚È“;s7žÍ& ÂÎî«;)¯„·]Ûrã<§Ü¶R¸4É“{Åî—†»¦KÛÜ£þ£ÅÃS¨„ÉØKHú 7œ(À2PÍ´-MÜѵŸ`èöö–I,ciT®B%©µÎÜàß$òïýb#cãkø™|ÛTx9c"³ÑªeéÈjڻοH±×f¬D”j ×/ç†x”kžè(ˆ–9òLøÎˆÅ››ò2%zìØa¯P²§¼š‹êÿ«Cè5­ë™Æh2aa;|^°¯Ÿß~K%W UP‚µÜôT‘ì[ÏëR˜²Ã-DwLä#³Ü%Ö‡i©­‹°ÄP.k¶QÝ+B»"ø­C;årƉ‚¹4 ýÁ¥…wqƒ ¦à#•ú¡È^6_ã,âýþÛ\yÆ,›jìH›v§I8™ÌÑh¡A¡"ÿ©wvëZõó[н2@&óŸHÅÍùTøaïáXgjŸ sZ6ž­¥^YêjΘ’—çÈž °Ð²¸›±L6XóÑáˆIdÈΤ(„®(ò¶OvÏl–É3›: tæ–;gRœ­°€ß?%‡­ ™e4dÜ,‹&êAíÄ@QP-šÔ&X~=Øq¯,ôh¯X²e}´7O.uÛÎ,›÷Ш„ªý4Æ—lYÑ X0P Ûpó&›œ@/VlßH¡ìͯ“˜ªòæÇŠØÁü¨¡úz³„õKD÷ ûzΉ30´+Ç…ó›Ù}=èæ3_›Eè/؇`È*äYI/‡0g~r§ F$l×3ŽßÀ!¤kýLŸsƒÍïMƒû8àwŠ©Ãâ4¨M¿žÆüñ¸Ô§?š¡ãZFÁÑÖ©5eÆ*l Kz:\¤Ùl“=zPI~áF¥û»ѶXËÍ„¦Ô_0÷WäöÙ kzÈ’Õnð•/ì»Å.Ù€ÒéžüF& Ê×·ø¹ÇFLW3©#KRR°Ô0ò“ó¶¬Ý+‚z\Ÿ•_;$½N%äv5iŽš–ÿ$ ñ°êüa™ŠÇuŒ®¤þsjDî}.+îk_ÊkòÿhŠ é4ÇÄz6ÎîþPKò lH¨%¯Ââö"setuptools/command/install_lib.pycµX[oÇ>³¼Ë²­:‘½l´¢j›rz1\À𯮂 ‰:¨Zw±ÚR+-w×;C[ ¨—8¨m }ëéÏêhÏwöB2-Ps8œ=sÎw¾s7þu}íÁ?¿þC@å_ƒ?¿áyÁCÈÿÅD‡õ\Ñ¡’¹C±CÓ6hÚ¤Ã&©rG‹NÚtÒ¡Ã.… Ò]ÌÇüN“¾!zCôÇÃöú->!ú7ÿôžÚYž†³ÀÊÜX?Ÿú™½†} ÿŠc/ŽŽjUñþo±/áAS©Ø¡é|+ÆJbÒ„"˜´H·+EØÖ£%ë]YoWë= ;ò¯+c¾a×(\“Í×h8êC'ók§ÉŽuý0tƒtšE±ÝqìOŒkSwÌ?ª›ŽÝ$Mî=;·Çi"ë&Pü¶S~>‡¸<̉N%…™ÂìBÑ\,;íQþsÙÑÀ kªñ˨Yý&P*G³(Ã7‹Gi¢í:Ÿ[í•êÐã±ÑñØvy’άhØÈ2˜'•н£02v0õƒÔœÝûôþàÓû÷Î>ðürOO&{FÛYfÓ46{,ê'áÞ’çÙ¹¿òYÒƒTFjM­«uGàÀÃfùmžòð–„:ŠþJô®‚æ1[ΠXÁ«Vß8táËgc°Ø¢¹ƒÅ7 Œ4ÿàaÍ-ÿ†¬iž¸>»-Žu`£41ƒQô•WV>OëG‰ÎáÂÌ·ÇâØ#]ËÑgA< áõ4wM”Lbí½Ò¹á·=}fuž°ñçCáOxW‰†_H¯¥ÔÖãó ({§ ËajazáóÇ/®ÁP6î¹z¹E/Ë Àh¯óàòÌNùTÓ‡T ÷m›¿ãe§ñË[ÃÎå;ÛÀË&:ÑgY¾¿Ùðn[5TjØÐt¢­7zþä÷ÞÁè™Bûa±]ÁR°ùØ¡Øù=ì*ñ‡=²Glc„êË0Ø5ä Þï™L%½kÛ/‘ã0 VÕÚ›šîíuµÑÜTÁ2Õ%úï’xøD’(û™5¥ (æËoÚ[Ƚ•n‹¼´Yæ‹qħ¢y%¦öc˜÷ÿ´[JyËAL⮿ÒÓ+ñ0Bö>DÂÕÔ]WMç¦ê9ÒŸ©2½I}I3ÏUˆ¢Å½Øse i[1®ÐæÇèÃFVr'8nĸíBÖk¡°o£² M¸Û–ä–Œ'x©³Íé*¸\ûœÁÐÄ,×ìÕZý¿8‚Æ(HÃEuüà¸dv.6€Ùó¢$²ž‡:·¾ú;øöB*½\lýÉ-^ç}îyR&ëÝ’DH9I‹Z Ǿñ­Í%‚£i6܆ã?ÂpÃNUÐÄïG¾ÑWâ÷›T^PÕ¨ÓrZªÅžo:?R=áühÜ[*sæïˆöåм)c‹ÖÍmb.|­¨îwßK«g>£šs©Œhç4b"áîÑ¢i›.:|ëPèîãM»ôž[bN ï4Žo½uhÜ˸}¼èÒ¼SÊ™w!J½sÊ[È\C è`Ô,'P¦¸Lóóâ lˆÓIP5íxóØõ¬(ݬõi›r—ÞUe›CŠ©Ø‡†rûZg§m©[ÎPKƒ,ÒFý<';·%setuptools/command/install_scripts.pyUMoÔ0½çW ©ÐzKˆ¸UBê­BâBâÐB–7™ìš&vd;]–_Ï8qâ8m){Êz<ï½ùtctµ´np²µ »^­>fás±••î:¡êR*ëDÛr[Ù; ‚6rqÐ6ËÚ?¹A«Sá‚|GpFQ«¾ wú‚NÔ‰PÙÁ ¯¥ÁÊisɲ¬j…%ß”‘yº­ŒýÇ è—çù¥M'Z˜L³{};\u<¹T†³}&Ü´ä056ä&­üƒ\÷^¯eÛ&ùßs:Ê—Ü/ÿ¯Tšc·ðI´#§Ô–$$΢z§õª(ì…z_”YJBh<\fùs•ÈfºW¯ŠR†8¢€#]Ä\yåÐHc8íÅÂÐOàzplÑ.xH§èÉ=JÊŸO$ŽùJ½® Öj·”—ÚÇ™ ôZ*7דl¤¦¤ÐÁc¿Iü eÔ¨˜2”¼êj¢ èx#ÕXÈúŸYôÙ#¯ug³„hö*øAXLÛž=±®<Ó¾x L‰.½þˆÆú¹Z¢Èƒ}=¸Ýam=—wñ7V¼Ft@¾Â9Ã&ÄvÞ:8qhqWÀW­pÅzþ”|ù™æ† ¹îN;®YÏ•“™zŽìG¢Ç(ºžt4Õ·”œòûÎýx²n«Ÿ¶UlÞ_܉†‚óäÖšá^ªZŸí³D4´ÛGwÂÙ‹zÒÿCõ(V5îSåÓGy@ëX lÊf°… rÛ“âqS†ë¥ß¿S ,†Qm@˜£Ëׯ1_ŒÂó”ÂòŠ Û×Ñ14 »ö¾û¸Ç£¿^„‘ M[iå(l[@§k¼Í]^Àµ<ÒÞÆzEFûxÌ'-mˆm6ÎòœÄyÒ—WÃïð%Pÿ½¶9­N$…” Æ2>tÂ>Äå@/bé§‘åŸ'7ê;xkç'†Ä¼µù&È1MóÒ$}±ŽÒ…¾­µ-{Zå/ÚZl{?Û¼ó¶,ýûES4!î£`/Ÿ’pX²ú•vaý›‹¥Ílã…a}©ñ!0Ÿsx7Ötsqj6×}k­Zm‘¥§cAäúææÞqí³¿PKò lH;M!3B &setuptools/command/install_scripts.pycµV[oÜTžã½Å›„„„¦¥ÕHTÚ‡v“JP!*¨BTÈE¬„,¯}²±ëËâs–$hóBúÈoáW~V@™oloÒ¾'Éž=·™3ßÌ73é¼Þ>ùï¯_"j~:üùš?fÆCÌŠ2¢\ÑD‘ÂÚ¡Ì¡´Ci—&=jvú4é˼CÙ€ò5š¬QîÒÄ¥|H“!KvI÷ s¬(îÑ+¢K¢_']HŽúüVò†FŠg6dåìÅ»ÁÃ³ÄØ*™.lR²ñShO~Ô6ŒCÚmÞÐ…YT:ˆ“JG¶¬ÎítƆY˜¨JæÖ¬@:üù B’€Ÿ8@˦M:0 “.±í¯Àú‡£¤¾„E¥W”Uf^­ÜkÞzèͳ…ñÂâÜÓ³YÇ¥wZ…ó¹®¼Ö €TßBáÇÀI”*JZ²oØ×ìž]Xv(~y!¯Û.e•Ì|LìŽÀLlfÉŸ:(çp‘±¸ù]˜-³¢ ô¼ö-„ŒÎŽGðƒ æ9ÓE’ÅûÓ˜ý<Îè4gŒ<:ûâIðä³}ƲÏÊs[–™ÙÊ<‹xÿçç>b¹µx‰Ô¶¸ØéµpPÂ+–µ /Цâx Ç¢Kiª§dû”(]k=S¸Ää„s\Rõ³x ‹õFÃ…æ,™ª›dßk&·èґɶŒïÓe—.Ä×íˆl~]vyÖ{Ù¡‹^{¡'úr)Ï“䀖 ä]°™ª^S<)ÞÜÃfÁ¯Qz¼Çžßi–釴¬ÕºtöHŽîÒ’Mr)ýØàg¿íÒÅPŒ¸GË!ýÍ®ýý@ 9Ö@É‹iË;»Ù¶âøLG N3]_@̃SæÇÒ"NAb‚jQðÆÌ@`~nOÊbÌr#!ê}¡PË…qÃ…±ÍyÐÂøNs ùúÖ!á‚ëâëéÆd¬©©Þ©Åc¹°ÇI¦…½ÅÃLÛà8)$ âVµ/œo2 ö‘tþðúvæZlÂâ]™ÖVZ[Iμ( íÚzt(ÆU‰Õ•Ý壤ˆËSóÖ>ĦšºsåŒÀÌuDYhê`WeÌÃ*ÌÅ€«™±./Bœè0fMxòJ›@Ž`­;ptbûòDy,Ï›²75²×ƽyJNNW'ï6þýö¥JÜÝêƒM7V1=Tk3–бãlª µë¸ÊuºÎ–ê¨;¼·¥v>®êóÁ»÷••øF0@ðý=4ýKu…qšæÅ™˜;H[”ÕTªú²®8=d¯º^bRÉZÎ9ä4/]TÎi)Ký6¥˜¤ÈÔgœM<ã’Á©{â®d°Ô‘u¥ø0BÎvÜì!ÕïðMÅÅ+ÉáHxÿtB¸‰xWÉêïž-={¢ÛNâ­Ú]Ý=A)øÑI^Æ’ÞÑ¢ªtaƒEš—æ.ï<¯#ÀÙí=0m÷b½Œxó4y£ÐkÐT}„Å?À«|j;ˆ”—õk– *–FÎçÜže’–IáïA ÌBä|̸:G‘ñ;«–ÆGb»Ð¯F‘•F†+®¯¯ÊB³k’W…eÁúY­E{2ãæ¬ã+ÓåyË4Ö¶¾ÉÞ¸7×?em`´|röœ=¦ì6h­†jWmò(ÿøŒ@äc0E†å@–qtVIQ}e÷MÁ.ƒ3Îq»î});Ršð—êÌÔ”øäúÖª!¼£Ößn+y]Ó?‡$(:9 *mÊEqAGPê"ݹi”âù¯j_?U-Úm®2νÎÿPKƒ,ÒFÍÿ­Ÿsetuptools/command/register.pyUK Ã0 D÷>Å@I6é¾Ð#ô ÆØŠkêO‘ìôúuJˆVbæi…ô.\á‚ÔVC”Ù–”Lv3“ï1Œ pðJ)þƸ©6ÝúhíŠÕwœÜy×Õr´€[…â²ßmsÁüÒ˜PŸ¦âC0}o²Çjbp°™rE6‰®+±„’òRŽ”-tîézdÈ{½!Ãt@çrGõPKò lH€½è@\Ïsetuptools/command/register.pycµ’½NÃ0ÇÏvhQ¡ #[–&­„*„ìR1Åjc7J•ÄUíHEb¢¼ÅÀ“ðÅ'û>þ÷Ë9âk<š¾?gÐ=×.£Qø2(¶ ¶RŠƒ´ß0P>Ž/)§¼e`MñÏÂâv¯óÂ:½ÿg¸Iü Hh[ ¨ ¦',CJÍXWÃq=QÝ5š7Äñ\GÌy0T@/QbRzK ó\õÆx2wFLM-3SU«Z9rš}‘'ÄæDõ}ÈêrRÈKàë¦(U¼VøYQµÊŒ=LfÓh6nçr~c¿Øj×ìœ1¥»Fq?ˆh÷šòôh|ÌÂ5$Z)ëU¥¥t#¨ŒjJ<&DÖ2}@™ ½AOö÷Œ¤ôŒvÎÛù]Ò/I+Ju…Q_èá:§WðÜÿCèÇu×èž.ÌÒ_ˆPKƒ,ÒF•¼Åòösetuptools/command/rotate.py•UM“›0 ½ó+4Ìì`·Ä?`grêöØí­—L&C@wÁ¦¶é6ûë+›ðá í´H@ÒÓ“ô,j£;¨¤uƒ“­þ²ëµqPjõ;õ…»$uä7¹´ºyghŒ6³ÃÓôþkï¤VŸ½1¹Ù´MÆ`‹nèÖ î'Ýu…ªÞ›E©;b3y ‹Ö©š$Iʶ°Œv…Cv‹ç Е¦é¶èt[¡ d<ž‘%c¼*´¥‘&ì!­þ‘à bOYᾨe‹6 0ƒEsÒÆÎ!¼ô˺•—}–CÖÑ-¥Jòr‚ ˜Áƒ4Xñ”ç«@Ÿ~WIb+KX:m®ðzAƒà.“„Â` âI€ †îL…ézLí«‰ã‰”˜0Žc“Î4,ÔºÀãÔ¾¤’N­|ÃÉYlëÛüåÅXìžµÂØâ)œ¨¶M£§3攵TM(ëuNiCøbö—)¤ÅM¥²È/HéË@ã¶=–²¾A6Ðiš+½ævûÂ+~›é<åôŒ¡hdâMö™Ê6MÆcO~WKhÄÿ–3_Ƥ»L{†sæc¯g •cóóƒ¿Jì|+ÚCÖg·ÛèΓ<#ÊçÀMÕ/­TÖªD¶Œ5_m¾AzÒÛánëÇzá!zÆ9Ô4 j±ZÅ Û·Ò±,ÏxsŒEJËê4(R¦TXÍ¢ÌÎ^ÙtîÆ³ì%ŽòôŸóEÑfP›§†ÞŸÊq¯±”tr’ªÖ«î„]Ù´ú<­Gÿ?Y̾¤Q‹qaqÃ&—ýr § ªM2!ûÑýæAŒŠÚ‡üL[á›+¾k9–5Ÿñ| æ|3ü0ÇRÞÎIÊ[óêq:~ÙŒ®Çûha©~¶+ Ò¼-UDFúŽ ßN–>TÁ“Y¾,Æ›æÐ¢bƒ/Ä7y‡ßÃ|:ßñ#îÌ…2¦ïd¹Ð ß­™CÍï\éL(ínÃ2שäÏ_ÔÌAµR½P“ßPKò lH@û5`• setuptools/command/rotate.pycµ–ÍrE€{v¥µ$ÿ)ì$„d¤¼†HN(Š‚pÄë‚€ ØZiGòÈû#ïÌ&v*¾Ä¼“w¯À#Ý=ZÛ¢ ª‚mç§g¦¾é–ûûjçÞ‹ç_`þãâçüèÇØ$ø' È ;:¹0píØ…´YM;n@êÁÀã½MH— kÁ eׯÓE6Ò4Ò2“ŠÀ&¼‡•J“!mêgñ¨ÐG½»wúwïôŽ>ºÝ{GN&;ZšjfŠ"Õ;# ÏŽ…¤?;6—‰Ñ\§ê©Œ fNoÐù müÕv6k[6kÊ´ ¼†™:ð\@nWÝzõ>¯:ç«Çd’•ÁIë¡Gù[Ð@wt <!mrëM¾EÀí¥øN(_°vfÚ¢7‡¢¸'Lž ˜vèAâìþÌ×@­Ü2½ë„òþ®þ Û/*DRÏäH} ‘_”~V F;°§å,.ÑÉöœÈ3FÙŸôý­þS5Û¢][}ŒÀÖ¶~û¯§žcÆè×Té«(ØëQ×ÏH~(ý8÷UnäóÅá6Ã!—  Œ¾ˆÎ  ´R¢鱄$®Ô™æ$òMœV’S •V¹6q>’!³J7êYªLgC|3óci¢*OäXå2© b­ÂU’&¥g¯šÛ.‚.Pû&~…©]®Xq×ùÿ†X]qÙùÐa޽‹¯‹3Ž™]‘0r© R‰£ßxÝA®~…gŽì´A\!p›ÏؤiA^™z0]b‘àÂ)â2¥.žpNµòɼb;v˜OE¢(g¡Ô[æVŽé*ÑjÖh6áÉ.‹Ðeëpw=°—|ß;pÒä«ìF¯BÌI¸ ú%ëpi®€8| ø÷èp ñ; *³Ë¹£©|\\(b„Ã$-†Õw8QÜJ˜á@oŸ§Ì[Z/×%ÂŽÊ4†&Ë*æ ¯Õpru¼˜hY ¢•Ç™4DS¡ùv*Ü™*çP‹fF¡(gJ䘫e)±ÜjžéNæØš+sû H,)#T‹ h•§*?¼š_Ö‘¥æ¯œñçWËNsk^5à®õT¼ÎL#ÅNWlŠâ]Ñç*μ†d·EàÖùÚVÏЫwýSñ´»*hHfþûjO8«¢!Åá?QþŠÄá‹8ÎQÄé'в"©R.ñ0)FاX'R(ñ!¾J˲~ÿfþ”q^Ï…kBJ a¯Ð+UH µ5!î ÏñóNÛõœv³}™3°Y›û™¿Úõ©µ¹´}qÞrÚ]•”•µÍÛôƒ=t®OH10—æú¨#Fžs7k÷˜Ía»oõ1é­Éή ßµëþ PKƒ,ÒFÖ4F’setuptools/command/saveopts.pye’Mn„0 …÷œÂ¥‹‰r¤9E—U…2!¡–òƒâ0UUõîu2a4Y!ûñùå9:x ¤âºDï õÒ[+ÜÔsÉ/Ð.>DPÆQz§qî€ëèÝx¤ªª’F‰«â:5‡f;TÀ§®ëwîB!¿tª0¢bU•å“"0·á u­ËbPMÇß²ç^ê|¿T€›Ánƒi«kH]ìä2Rdxªöé;àeMà]Àðˆn&ýþU{Yó(i'@—[Xc±5Ü•é ÎâóN[<§áA‘›æQ«x…É»SÌY‚_ùVßn»ñË#:áN ÙÁU˜v75«X ÊØ°‡¶Ç¨,5íóx6Ɉd².·´ úYyÌ%=ÎV¬&ó;N©ý࡟›¹›=<œ¼„>-Ç «ºÕ•=„Ÿ‘WÕVÿPKò lHþÅìvVrsetuptools/command/saveopts.pycµRÉŽÓ@-·³0CËiHF\|É&¡ ‡B0ÒÜrH„FDŒ,ÇÝ ¼dÜåQFJ.„á?ø,>ª*àÀrWW/Uïõ«ò<8}ÿò>úói¼¡ád4ý¤™323žV`,<Ð>|Ø|˜ù 0 ›dÒ*òð>£-FI‘/ìRÖÅm‘GóؼÇ@ñ¡=÷›Gã-<ãh``âAÀD…qƒÎ0™†LÖ½ 3¥$ARdYœënjs`\€E ›wZƒ®Z¯SkôßwˆLµî%‹eP”AŸL8KlœÚ4Z4Þqžod¶+€–¬‚ ÂÖƒ•çWv>l}füYA9„ëÈ6c¹¡øhOŽÏÚ_ÂG»†Ø&ìZ°mò+9ò¶´T°jp áì)¸g×@ÿ%¥½Ä¦‘kì´aïSH‘g<áJ¸™ZŸ€õ Yzä]m–v^±øðϵ¨VGö–ëu¤m‚(uF“9<æìµYÄUŠ. ”•eËãÌ Ë¦ËÛ¨¬ò}lHDº‡Ñm`m¾tȤ“LËL2»2‘ù&NCFã¸Iæ•MuÎizYœnÓzÃAwój^öÍrÙ—ÚbQ¤®_¿­×t½õ­$&rGœò‰4à‘×RT‡lèu¼çJÚZXF¿)ŠäÙQ”ºJyÙ–¥.ò¹ÉµqIiE°Éã;Âÿœº”Vää¾lß–‡¼'Iëà^Ü£-Š•*M¸§%Ãÿ!'zzÍXޱžú¿PKƒ,ÒFß‘®I. §setuptools/command/sdist.py¥ÛrÛ¸õ]_Ê“!ÕÊllït;™õCºq:}ØlÆ—‡×ÃHPBEŒ­Ýé¿÷œÞ@R‰»«IdŠ8÷ûAaômK½aòPiãèyQàÛ\ZW;YÚö¨ÔÛEóØ%™>¸Ê‹¯·LÙiÛ>Ù£]x²V¸ºrZ{ÜŠ»–üç_®&ÿ̦¾KÅ °rÍëj¿M°º6™€··7ï?ütsÇ®Yä£uû”ë¿Ü‹‹‹4¯K4¾dΔ€XýÅÞ³g^îÛƒ8—Fñƒ¸Ž¢Õ»ƒÏr¹ü(UÎxY²B–²ZåÂ0@VjÅ2­œÑ%À|¡ “*”9‘N˜Tè1­´TÎÆÑÀH9-$R¶-ç–`ž¨’Ró<^µBàðs”¢Ì z±Xd%·–‘Ãbô–÷]¯ÓÝ£ÇÈ¡nBæ–qut;©¶ÌÖ^älsœÕ•Õ”Ò•ƒ3 6}ìä‰#üÀ½_|ÒJ¬{Q—Í)çÍC±fä¦FJ,¦x;·¢â†£è«Õrµß Qƒªúz Éãè4"ꌌ]£/ pËŒàu]²¿ йÉvò‹ gÇvÄIžƒùQ­(ØÂ[‘9mŽÌiVÕŽD˜S¯a´Ñ«Ë‰Ç&LßÂSËúÉ[‰-ÈûE ÁÁØ¿ý׿Æ6µŠ­(‹ADàÏÞ§MòÆ‘ØnS© ­: !Óì1‚Þ ‡1ÈKù«È¿ŠGàh ô  {:Ý›y¸„W•‚Ú&˜âÉ â³åV½ûùáöÇ›;ÊÜÕˆe¶æ*Ï"^-ºÃ3v[+ˆÙ k¤¶A‡íÝi ЭŽ6¥ÒÄx-…€çX¼HáxÎgZ•G& ¦4‹è(jE Æ}Ùýáš]&ëÕð½H‡Ñ:„À÷©¯× LÈ3vÉ£„4y|ZÎÀ÷#š\ðÀ¡¸dÎkÈ9*R˜oðáV˜ƒ ¶˜£Ê߆"b®ú4J)´R,+%žtdzý8¯ÎØýNZ¶5:?2`Y©-˜Ó½ÅôJÆ?½ÿô¯7w÷‰T+”«&^2A¥“é,«eym°2$Œš*3T(ÈÐJ°\3a õy'à‘Û#d‘u—à 0PrQ  $òG{òИB‹õ]# $òéKi¢¦küç6XXŽ6Jî8ôœÛ$n“*ñâðoa ½’"-uÆKûµì¢§„ ¹\³«ä"ùn ¦Êáñ2¹ÁÐ¥àû£÷ÓÎJÑЂ_–m˜³/"_£½)©õ0µÌÉŒ h§sô鳈Œ€FˆÜÑÜ”R˜–˜Å[§Ä5õ 1¸ûì;ì²d+ö‹Aøï×ì²W_­ÙÛ–9 8ý¾›`\~ Ø\x ÿ JEíÝ„h0—2}BñèÐ:(²€w©´)ÄgºJÐàt)§Ló7Š•È$L\È–dïdé×Á ²ë¬Ø¬hÃ0ø[çHëoþüuˆ`ä%Ÿvì#,ª¢W»¨0R`¸ q!Ìæa “M»t¤È„•£¢u V^²d9Æ«&«q#Y< ù§ëiæžùœÿçͧ›Û÷÷7ð’·ÀŸš}úùž‰\º«(0å"(l´ôµ޽±\.oáÜ/Ê Ls#‚Í“®”£ÀFM~€«0Êèíç¨(¨ÄÑšhÓå£nFYŒòfú@„>҃뫮y …ížK½M(—¨D¡ø8ì/×, »ƒ}U`¨’@Øh\ î‡<Ôð…ð0î?žÿ=awB°³«·WI€ýù—«i·˜^§·=ü“䂜‡hfG¢ûö $Â} 較:ALê÷¦7†ÒŒè2â‚s%;?gv/« ¬ÛÊ0?¡¡êRÕbd#¹UÚˆ6Û-ÅѦäPB‘”  ‡zb,Tñd-jθqþ8:ƒØÔ^t<›j9+×ìÊêÖ:¶ËáÿPKò lH6÷<ŽØ setuptools/command/sdist.pycµYOodz¤D‘"-Z²¤ÈvêSCL*É1’º‰›¤q"¹—VqWve«Q«Ý!µâr—Ú:T ]ì ôœK‘K{jŒ\zé-‡æ3ä ôØо÷fwI9>­*‘£ùûfæÍ{¿÷›QéŸÚÍ¿>¾ïCöSÂï{øUÂ$À€ ° ¨lA$ gÁŽeÊ%ˆJpP†ƒ Ø™„¬¦;•lÂ6ªx«EÒÔ5Lî„q`{Qd·ÃH*{2µSù(TaÛ~ë4‰Ô"u—zÐ× –Ö¨¯Û©¯ÚdYºI¿ÛqS©’AêK¥Ï“Æ´L]‰2ŽÜ~Ƹù2«Ê ̨ YA˜Æ^Oj ó²ÏpX¯E»çDý“½A×÷ÔàZÏó5\½ñÚÚ×V‡oÞto¾q]v:×G+¼î'½ž×èé:ÊøØ‹º¸ÀG¾N£& ¦“kA, =Aeê\˜*Õ¼Oµ§…¡… 23´Ëà2 ´74±`ÛXX‚N vÊb ¶)`{æLä ­]„.ªés.e5åRW@Bp™Zb ,AÍ/žjþ ‚ïÍhÞ²éï@¢LCŒ œåIêÌqMügÎA0Ï™8Óg«u…6õ&[=/Õ6ïÚÖûž¶éH•íÅGz?Œ;¶ôûIªe`ï}×&¦PB;I{žV福£‚mc6‰Ný¦->”U%û^ê‘Ô[_QUÚ•²¿Š‡Þ×dî]u#«Ãe=#D§RÚ^š ÈlÛh^¶ŸJOórgp”—úûá#ÉæÜRF: XE3{‡¥ꎱ:éë$=²ub÷šgzÞª3(ËcûWl{ƒHßâN»ìdÄdµ^'ûÞd®)ŽÇü}Ô8(Vºœbþ Dp‚¸s0É­Á'V1xŠÜY _âîU*¬ïαWó4Ǧ硇ž]" jpÂæyŒÀ9 uèV ý=wo°¬Ø,ñô šdÍœ”aø6WžÇ©nÀ ›yPcÄFlÆeâ§Ìb¿¡ îkxß~¶q[-²MM)ú¦ÆíDM“Ñ}xßù`c‹Žñ”=Ïß—~Wײ³r‹‚‡Z[³„48ÄnæÚzž XRçØ‹ÂOdP´°e¢²/F[¯ß—XO“"<æÌÂ’C`ÀÁë@ˆð¤f6ìå¢ ªÑÑ8óÉÆó®‹êºýY&ÊóO{, çu¥;ne<çò´Ny!§#»6ªiUò¤dÔæ-ÊÐõ{fëø×eD­Ž¯Õ™ÍÇÎÐzÎfKæ–IžMREC̈º¸*j¥9q¾\·fEêYó¢Éõ§Â;Ð/09º…7ã*dYÛñMBh&h·•È›èÃá͸ùŽ€¥Ìe#b xÀÆhÆH(!ü´ª¹>’4ì°±±¢éðݼïG)cÆCŸÍ˜Kï¹±Ä=eòí”ΆçF‰ïEÊØu”(É¡Îù>u¤Ýºl‡zïŒ5ÍîÔêÝ}ÏïÞ¦ êÐJâ‚(‰y±(BZBHûiq!5‡´¸‡ÒÌeûkƒ|(‹ùÆWX뻦C@Uá9 BºÒ/(O($MÞ ,Zß]á~d¥· è°™¤òÙePv÷ð6àg‘E} MÀEøCAØg‘Áæk8\“÷Õw$as6œ;-duÛÎh0|Ÿpm}÷Bâ ŠD'4f€øE"Ú}›ÏР"Kûð³)†5}ʰ1wЇN š" }c1V=C‡ÛfqëðQNªpRãtz4Ñùx{\‚“:è98¸À ©Áq–ùk ?¼¨¶Ø>|šÃ<Î1ÏëúG¾®*¯«1¶®ÆØºFÃxØU+VãaçÆ†{î°Eö06ÍÃfƆ͜ÆJº9²CµB‰F ÷Ò€ƒ¹'HP(îß²Õ~2ˆ{ßÃ@ŸÄømÛŠ,zÅV—¿3nùšZ VìèHO¯Sò*zSö¬5¿Ýaf_tÑ©ªE|½V”ü(Üc´0Eå§a_«Ö qZCâ·œ«yà2= ,“¤R1-Ó—Œ8y$Æ kÎBŽM{iì,å¥" áÆú8¤.ƒþCMŽ|vßÃÛÆ •n/ F F±Œމ" aìGƒ@âÅïzŒJ£jYpÈ1±‡÷6“M€óåò‹:ßE¥¤^bÝtV—+¦Y `uì|#a;æ½yQv5ê$Ú °&}ŠØR1!÷³¾Ìº~DRßÈu®RcjÊ3P;éZ\€JΛ4à-JnåØ{¶7 /ÜŒ!ª$øgKë(Nâo£Þ$F¿)kRTÅ¢UsÖ<¦ q ëK3Øoa¢..c¿×,*-¥ ͤµ‚pn`2|—Ðy}÷2¡²«Còœ/Fg¸Pš/•è'[,Îðá3gxÀJUK´¶-¢\•¡€Oš|Åš¤èƒ\„.*æÊE|ñž>y³Çn)÷Ãi÷î«àß—Kütcsù}ocnÆÅ^±ƒÄÞüðž-ƒPט`>ã ¡bò=ŧ‡mÔãÙ$Œ†“'xSávbrxRÒy½ð¤ØO‚q6ÉèÙg´n‡)Þ›¨ÿ£ù“›¯Õ •‹hàvd,ù ÿš†ìÑ—‘Û—DÓš&oËOj2?©¿'ENÁ7_ò ¢\0ŽE¬òsÃ*3[,CúŽæ2Žoœ‡Nîð”Q+ݤ)_ €ÙyÄóVû<ˆù†lÎ4»*T‰’•¬P±ž~ Ø·ðOòÌŒ=® d º@“u gÜâ{—ú#ž?äª1vÑ¢0ÃÏ%Ët3[Ë[—_±Q«ö@I;Ô¶Njvöƒ£"zW0ÝóKëò ˦,A¬yšÓ‰k0z®(dß׊Zu13&z"9½ZbFŽK["¼ïÎꛊ˵”1Ÿ+ì@¢Õy{Ø}uÕVݰßGA Ý/o¶øŠ^<ˆ^8UÑ#šcå†Ë"¤¦ èý8¤ü:×l¤i’rd0ÏošÈBÍÄŸT«C½?¢Cì#ãçyrŒ.“^×åƒu3ÖˆEóL$>æ9ü!Ÿ`…N’º†ù)®ˆeÇÓôö•Ϋ$—A‰Oëy7^g ²çœñ@VcŒ—Ý#ìøVÉ”îQB29ò8û”ôaœ ž]l#Óâ×tÚòÁ±C²¦ "Nµ¶jÉüH¥Pxï£dñl“ϼ)wQÝ´ŽÒ»+Š¢_XOú3#8¥¡FÚJ=;Þ¢L6äT·Gümé˜Ø’ ƒ¿R`\à@.ƒìÉp…eÜHÛG BëÈrP¿¼"@v;+›XsÄK€T¢QÞ ]VT§xf¢Ñç6­Ì0´Ùß-o7ˆ—)¹@Ç“1º¹,ÏSt|ë–Å+@¼å˶‡èÁJTœÐµ’‰ ˜ÄYŒ*ÄñSlÙ—æ!dâ'hýûn-»[@*"k\-Ք咑?i=0•‡£Ï‘Ÿ )éosÁ2ŠoœŽ*JÚ'ˆ:¹Ònë¼ò’0±™³ÁŒîys‚”)Å-C³û™Ö’ÉöÌ5Y3Š©«2ô-áMQ%# s0yåž —`]òí¨¸a~¹'Î$r>~ƒÌ;È#JT>³+Éñ¦° ½ÃÞI¦¬òιŸ˜‘ £DR%«YÏÔŽ`MÏ#Æt£ð®g$pª!6ÒI oq¦Í hAX‚»€J{‹—)¼{kˆ®9Ns6ÊNMÌ‚M4),ø y3ÖÔý* ¬Z[(mYÉŽÃ)‰>2Zâ“à àZBØ0ë4ƒ"#!¿}Äì#½úÏÉ83ž2WP!zxÊI࿽òÒë±ÉPkFéÆÇu=èáEèbQE8–dÒÆ,¬`%ß!~à/·€LèOèP÷;×,¦u¯;ÂÑ'ê¢fsÉ7}ìƒxEkþ-*XêÊ« ø˜iPÓ0ÁzX?Ã*ˆÏŒ»öÜ :ož]ß*7÷þI:gæ³³Ìh LüþÑö‰i:ƒô\y  ÊŠ8ç9œ;¸EçgÏ 7° ÀM ;݇ôj¯*È”üH~u+¾ôq8/©Ñ¯Ø‰Ë޼‚¾¶©oêj!Íuœ ¬£Œ¤Ëy´t l±Ò_‰W³ÆZõ w´)LÛš7Áö¦z÷Ú’T2Y®†a`á³ÇÌ7žÞšØSÊÙ}Kj +›!¢*C¡nú’ —ƒzUE¿W–íøm éðb«Ž5[âM÷@æ#Y›†6úäÅ©BÝÔ#I†ÀRe¥ ¬Ñž¼õψÌ÷ù©råÏŸŽ¾%–«ê”ùÔì0•¬âK媵±Ÿ ¹qiÔÈõÚ*ç³_ž;«+–¾ig‰ú©/v¹Ïìèpo·þ ÜÞÀ³Ù¶s£– ša¡òùn.ƒÑ¿íV£Eé¨,t;S1ýû`ÝIù:+A¾°wä«§'øÑÕ´€JºÅ]‘ÇéÝÄýoÚ·Í|eÓœyÿÁüPKò lH(]+#– Ásetuptools/command/setopt.pycµX[sGîÞû®Wöú‚ƒ )¡µ£•l‚Jbc9.ŠŠ€Q×jv§w5ÒìÌfzÖ’( Û/}ú;_oñßKÍ>ûE_d?%ú¼Oý*|ú“"b$Å®í‚ bT»EÓ.а$Fe±[6íÆw "«WÄn…ëeVŨ&vk$G]Uáׄ_Ã’Ø­ ¿!ü âMÓê‚ð›\oBFÕÄ@ I¼â¹ï.AM-qïż÷"¦Ûi_¢eÿ¡Ÿ¶¤ZÚ¤¢GOU’vÇ^ºoz‹T„ñÐ4®Q±èt’¡þé8 âèa’Äɶ®Rñ ¼ÈO/kƒ`Ø¡â¶òƒ´k:¹³…nÏÓ*­À‘*¥®´ÌSö½°«…ÌÓ ð'*NÙÓ‡‘´àâSö,Ú÷D*Ä[)Š´$Êâ¹Ä–ŸgÒe–þ- ‘{+ÜìÂÏãÜx&­~U¤ìùS)®“ úÛIùÈ Y{&q;m¸NÿŽŠG*uÒ}å`Ë‘7RN<à¶o¶æðÎÖœa÷ð?Nœ±J:­Ǹ¦Ñpègï0ˆü=g4Ñ©Ó#;ÛZfíå5gÙè/³eh/³š[ÃRêÆ™“ñz0d×q½„HµkáA¸êìõq¬ƒã^_Oáú*¿ÙXÑã“9-ýýùÓmßtÒ“±ÊW»ÊË\]sVͼ«¼ÌU̳ºÝn Vp¬±æél\9ˆƒˆƒÈx/­Ï.7ÅÖº<_·Ëò,kêxL1ó.–Í}¿ô‰âèlc.V€O9¢ý8mC’ KÜ›¡¿ÑÃlë#¯ëãÎÛëwnwްÙÝ|{C ‡ìÒ4ŽC½Ñ7a¾aBv}|âÂ>Ü«qID¹)K²)ëòF¡)_—_“EÙÇÄXYÍFóß$‡2p‚qãŒp‚CQKm"LžÅA ×ö¬$N9–i`È¡(ß’˜Â4¼õä ùIAœ•ÅYEœV—‡5‘¼€§jˆþSV}NsÀNmùôÇl·‘µõg"[ByAã‚Õˆ„8þ;æ°3ÿY`æª8«‰ÓšyÓn¥ÂvªlªdL5³.Þ µ—ìä=™-·ú…ËíÉOÿe—X³¦k,[6²§½P'ñÇ´ÉÇ™åzîقЕé%”ºþpMœÕÙ-qZçéÓn~þíxzÏ?¦S{HHæxÙ…$pŒ/½“ÆNõɯœ= Ž4ˆ†z/»ÒyÛ 4iûAz^r‚«·¥q[öö¶éÒïí9OȇêDùNï„mMãµ\…uǹ¿ æŒ”i,ÊWŠÁHEi('S]c{GûXüÜšBº Ú±k† ºÙý}/Ò2hÆ¢OÛ%«^jí­³½ûV[Ë×ôòjXÞB>zÀþ™—ÐÕÖoP‡«<V<ŸÄ#gE³ÄLCĺæW+úÉœÄ}ŸMDêh^†ÖE×gm¬èõ+¿9;¤FãôÄ(Z+VîÉídÛ7`:§hð8 ²QFÛ£íöelù²Åm™u:dÂFæ\v 0ÚW½É0Eîv½£Yÿ0Â%ä R52ð ßs%ˆqz‘…FñSÕÍ–Í©xßÓsmÏ÷óöÒTÅdlÆhSÕ §8Â÷Qlaö#ÚŸ2@´³é6¢ Ò''Ýdñ3©Éfw¿‘J>!›çØfÏ ÎÆaÞµw`³Ö*´Æ[ò•We«p %·*éK4z‰@¾!¯Ðn^§žŠ¼"s’{?‚½w‘§¸!Q<¾&ˆ±²!DŸÊø` hDTX"xž+t [Óï!|{:M¼>%ZâMN?ô4EhœXHÐæVué~vU4““;ƒ‡ú6¬{O‰d˜cEÄ+4cç(ðg( €±v!㳦&Ì >ÏT’$³í,P c±>,wÝ;°ÔÉ©Æ"Î’!§í«7 Ó»9ݹɬÑ2GγßÌÏ ç»ÒV ¶RDe‡!g»tqüéÔQ³ŒkÏÚî-ž´q«UxÞ±˜^áKKHá…Á¯íåÓO`BPäÕeN’‹v»Ÿaé,–öw@wwü•è,e@Ÿ™C–Å1\ÉÖÌpaa¸ïÖE2È„L§• ”ýlF»8£MwöTfÄû°$’¿à}R!3ælô?a“Ý’9lkÛE¸f³6¨7¨øôRU?Pʌ¦şÆSmh»o[üðÆ„N>ó4÷{(nå‡Í¹p#³EwݳѨÏûp[l<š;Ú¬¶BG{?€œ ý¿BS”ÍB›÷¥‹ì~ÝÿË=6.³û]tþwÙX= Ý®Ú<Òí±ÿ7F±?áÇ@•›~ܧzÓ^S› œ=:â¶ÏžÜwížwA´}(²§@EVˆ„¥ùÔKÍb½œg‡ŠÍ-fÉIá²ð¯ÿªð¯áñ¯˜ÿ¿F‰5æøôx ßðã~—.Ø%®Ïmq¥ŽÔñÌò²ƒ£ÌÖÛ ƒhî\=Á|FôŒõ¢l´%? ?/Š)’¹ÄRãCeÃw9ô9޳.˜Ÿ·I KOY„Q‰9¨3£Ád‰þw8ã1ͯRCo³çuF àMCTX0Ñ_Í;œö$";7Yœu_NóîÇ Á|‡“gˆ¤P)ÛJe6y`?|ö&¼YªS'¸Sh!]^ƒ»esÎyÇ!–ñ Ö )Kœ/²Œ1·óÁâÎòœ!é%§ßšÉô°{<Ôä‘ ÅÍ×(f´ÇͪhR r…©» ¨°­WѼӱ¡r‹Š[ÔÎ"ó[/Kæñ€`ìt̰¯Ø{í~`€ÝÎÈî>Bñj]޹?ëòo~ߘº<ûß5.?e¯ügœn’2ÜÍß P®ÜDWÙü«ð“vêIô—]€ œ&µ=²»ç(LÔ8ôúÊ8fíU:Ó)‘ú?Â`ýP¤°{3Ë\³PáÞYÆû2¤0z3pá2f¾„Fn2\öö †Q˜Â†ûí/C ~Ó¸ á.Nн÷"uúJ÷“€­š(ü!Š÷s4à ü‰xE§j¢Iðë•2N¡R,2]¨ÈF¡U¨WëU~@ðóoš«Qò7f.¨¦yc¶æ$¾@Óæú@7ͼ›-Å-Úðêv½0ìv™^ñí/ÔÊD#û£úŠöÎÄà=Cîq~@ÖmIü6‰.µŠWŠÍ«ÍÎõÕÿPKƒ,ÒFzB·qGsetuptools/command/test.py­X_oÛ6÷§à’PYk–·†u-0 ÛЬÀP†BK´ÍF5’Jê}úÝQ”LJrœlóƒa“w?Þo+EE ®t«y©R&¥ŠðªR“ŸûõßÍEý7[ähk®5Sº§ü ¿? Z0¹°+=Eÿ_Ô¢ãmv™dJ´2gÃQQ¿’•phÁeB†ö –TBj!+Zò¿YÖP½OäôçIÈ^ï2ÅtB²šVL54GÆüî˜z–™EFsÍ)jmb53ýÕrÉò¾ÖòðIðZÇNpNÛh!ÊA¡w¢ªh]Œ·Ó\T }OõéËõ„¢9\_ùT½-³Šòz±Xä%UŠü‘Óº%;»GGÄ7F»‚mI ¸¡>À!¿Š¢-Y¤X¹MHeþXRüAp BÈšP¢Z®[BË’àÉŠäT·rQk„×DïÙñGV[°Å€õËÖlvË„+€´–OŒHÓhnŽˆsž€ÚSÀªÉý=øˆ£wh™¬û{²më—0¹Ê9`!ìt|¤eˈfÍ ¤®%Ž,Fй[ûK)mVŽÕÓ³¶Žâ[T…j-£n3!ÁX¥ÀqÎäÜŽ+óDg 3“;YŽÀ·B’-GgÕdœŠýa™I¤,˜1»=RO=q½Bå06^0Ðß­ð|Áœe¸5…Àj7ÖÙ+2:˜¼!aÂ7ÂÝÝ,¯×V*6 â*ÊT/#&ò½+挪¯•uà´¨øÁLãu;eõÂã˼ßàôhk%«#ã3®üÓmfHSÞa™±ôåTjËgèîÞ® ¹ …¨CMrÉ(”JjØ‚’ÑUŒ4Q—øê³q(iˆÙÊiÍÉh0[e[›jhó’n5“²Ë¦„êN6-/ Ì^[ÿT.¹¹¹À=ÁKX;ÆV1™ ÃhRÐ6 ‘wÙ™vBTðܲÙÉŒ†!æjXη´î¨ƒ8Ãbƒ¢Bç> ЕÖVV㈥»È– 3ç¸x¸àÆ2àE4˜Ý"‚‚†=Óz1\ò¼»`­ö&¾œø7±q<Œóxqf{ÈŠû¥)™§÷­¨vpËëYùÜË·‚ø1ëѯ©)á¼Öf»&É7-Jâl{ìó9~Ðæ ŠÀI¿ÑGùH¹b³½[4‘$ø"ZRу×$«²Ôö $‡†æK“ÐûÀÃpÊËQ(*w&oFj®§nzdr#ÆòR^C:êè-„òriÂxÞã6¬f=9|;¦Íí8qgb󹣄B¸ÿçÌÀï±°Š¿ æ³yqæ°!{Î*ØQ ‰†÷wÖHñ•å:ƒºwÓ8؆[-§,ê´¸†#¡£57þsGCù1äpî â_Rš¯Þ¶‚OÌDsü“™À,°ãØ;šjó}­Z M$ÈTPMÑ~m³Ôb ÿØÔˆ’9¥Ð:) Í‘ACôç¬ÞÆ3Ìm=ÃãnšC–WEŸø`«¬/mÅÀôÌÁˆ¹[o¿ÿ&Š,pÚÑ”|Mñîö ž4 KèKµg»ôD[ÚãÏ <VGIÎÙaàÉsÖÜ èëíLÏu,äOˆ1UÍ’E7F…wÌ\b½H©y‡㿨}õµzóÄX¯Ià0ŠcxAÞ§øóîfím÷µŽÂþƒzÖ"É#KZ8§¨¸:íC,ö5wžõiߢG>ɉÇ{TÒjSP3ê¸1ß©¥bÑèûÊÂKµZ]ª\W,lïâ,À„®¡`‰tD3¦/O˜¬ –ìÍ>!Ì[2*Gêºûmƒå,rüó"ë EBjÜðõ—×ë€ó4(“YC©™lñè·LçûÌÆèn§¦mÈù3¦—ï¤ýR=ñ«å9ƒ?×_ú‡u ÂÓï«à5­ŒïAyÀkøD—=€H‚hT¼iÀ}$†o—* ð£çbŒS8Þ?ä™þóˆŒMÀxn`~¶?0µÉ>Ýà²#ŠQˆ]O­Üç?m’£›Œ9N>Ûi ±ýÔ/KI²¥™é=«:~ð_OnŠBJn;ÇäiÏl7-b…†:’atذœ9xð_u;¾C†§’,wË«uªš’ë(LÃÖãèéŸ-õÜ€sêô‚•NÙ¾›ŽN'ú©Y‹‚o«¼ƒÚ-|fË”Z3D1Ü¡ÿPKò lHVWW` ¢setuptools/command/test.pycµXÍsG=³Ú/IÖêÃ’C2Œ7Ä’l’ Â!…TA‘v6•vzW³šõt¯#¹ä1¸QÅ@‡råÈ-þ Î\8@Á{¯»w×2©JQŠ“mu¿î~ý¦û÷~ïuûÿXn¿ñ—O~ÙûÏÇßÛøSÃ"Áÿd¹€žAm2rz¾iûÔîy`ë5èÕ¸^ƒlò:ôê7 ×€¼ ½&ä-èµ oC¯ ù"ô!_‚ÞäËÐ[6 »ù ôVL»YòUè­šv²5Èס·Ží&H’üà)À½ HÚ WXº8•^&óºKøYéð_W`Mo`q7Uz¢ÓLý|¬Ó²x§ªÊÊô¶±ø…Tú½2Ndµßm’°ƒE%U9©ú2Êpn’Vze^(OPªô%”e•ÇYúXFãXéE}\VÇi1Œ”ÔzÛQçRã>éÇC\p åq’Dq_§b²ŠW’…¬tƒ—z8I+ɾSèêôý2-´1šúï”y‰Б¾ÿÁk¦±ŒÅ¤HµÆU¢<ÆYdæA?. 4Ê|è 4ãdžU,$ðpGñ¼ÃVØ÷°X°¿;4vÅC€'œy0Â%Œ°p&à©OGh6nWwí8”ŒjtV4¢`»iǃþ'½Àƒêt’(¼ûÑ<ÁA>Œ„7œWý‘šˆ cŸëft¶HÚ€`ëI ŠÐMÛEâ&lÑ ƒgGóHœu£œñ*d vÜ+"güMˆ?Z³)hà¢àÄâöâÐ@O5pwB©'UÄš¤Zå ˆ³, QA?V˲Ðx62 Ò"ÐG2¦däe2Éd»Ø?p§©B•B7‚ ÒêTen–˜V¤8Õ»_ ê(F]Eðà‚0%øÅYĺ<“¢O¢h+êL5ŽL8ÕEŠ*óâl"]²Œ5Ì–dO:¿€&‹Ø[¢Háww|ª¹'EðF¶5Áo7ý7ú²¢­Ý›ëK©/¥Ùû¼íºNKDzHBvr<Ú!ònõ.îÏÏøÃÙyðãc­«#$x[›ÈOÑ&j õqªB²M¯žW¶#Ùí2Y°òAßÉb¥ºä'ºF2™ Ø.³çš;x ¨w¢¨ÅSÍ€.}ê-,'i–ì&H »yÜ/ÕÉέ›»·nîœ|ÿè×÷äp¸‡3ë²ÌÔ^ß0­€Òi©Ic£.¶½±‰¿mqU\ñ6ņ狯{kbÙëÒ—„—!F‘±'ŠXÉ̬ ³8Š6_Ñæ×ïõMyiÁñR4ÏK„Å¥d’5HÖaès4â Ð[€d‰+èãË\Aָĕ&$+\ilCÒá !(8!ËQˆP»3R%4W“" µ´¬Ð£vÆÒxÀŸ¯¾I<ý%Æ-Ù¯Û1Ûz›q«oѦãôëÌÔ  ëä´j,ûé Ej°ž¼èæó3]©[6tYޱ6wåîp7¸®JD²™¾;§þ•™-8cQV©5§ÌˆIÛDɾ°!ÂsÔß59R`$\ÅsßU8?0ÑcæûeaâÙÌ í>ÍÚ:kg§fmc« _¸hkiÂù‘¥ˆøLWÛuýsNIcNI›FòÓöì3BçpÆØü œy|já|Š‘Ë†ž²rñ:ˆŠR‡¥>b6WĈ;;duX*^'Ñ·™KÝáíÚÃãõÞ|6¯ ]²&¼F»Mׄ{BG•â’x¸!-ÆôËfÇÕPqh° 3m§…B² Ü7”šÃ/ò!±Ã‘¡x‡?"Ý­€ì½"Ö¼uÄ¢/–ü¯%6QrKøãT­ s©ÚoÑLŒ±åJÒ¦ÀÃÈ…iò·êO,gÜY4 ! À …i`:†{AY“›57{QôÌì…éìÃç¼ö†Iwà‹Ç7Ÿo­áÁOè ¯/>©smFK”a>iÀãû¶o´Lë’Õè2—8½CÁ„~Ô¡¡£»½[PâºFù\çrlòº‚Gß#Ž«[Õ]»æe£È46áÌX:[â>û árŸ³ äÖ軺|Œ˜ϾÁ˜ãÈÁ¾`‘᳞A9mbþÈÀ5ó䉿\hÊMô; ³oO¹é錅Ók/ÒHjÖ=.̴γ8?Lâ·NH'+&׺¦nß¾¦ºt Ù])ü†ß!S»ïƪ¥¸\É9^¶ú9*`@˜¶/猜ã$®'¬9/7›•¥‡œµ©S“ƒñ•¶ÝFZöKÌPvȞשX€i~h²Ï&„Íù¢Ä‘­¢RˆB·åég2®˜L&ã„v»éhÃ䀔i“y”jDòÃñiÔÏ–d(©‘)÷šÒÉmÃ~ÄÅžágݸ*G²¯#¼©âöñÊ¿¢5^çyÕ«×ÖÅ2’Њ‘¢:þ2×V¼¶XÁTók¢ý/ˆEþvL0%ÂòY}6ì/z×\Ý› íÅѶñ6öÓçùóƒjP}J„7r±“8ÃaªO\ôèfÈNþðS'ó§2{1ä¸hu³;sNÃùSÀ쬎ÓñCQð²»~×ÔËA7©N)­zE]6°-žc"£¿câŽÆ‹Wdß” R÷"ëóCŒVË6v)7ŽCÃjT¦Eøª [¸>¥OÆë‹¢DÌÉpß9ù«ézShÒ‰ Ê.H¾Yìפn“1³„a¬ƒå6†±5¬ox«ô -‡Š† aÕçÿ#„¡p¼¶)Dðé#ÛoÓ) º×i”}®´#xº$4÷þ?ZXÄRð=œzrÓ¼ûÑ5÷Ѷ#«Çn¢ÚÃÇ€ÿßC/Ä$Ã̈sæ¹§‡ŸS²¤/ñ›ŸðhÕ¦thøVb ¹Æå:›_Ÿ“lp¼ò=Á£ãÜo‚}á é^jB…Ë«M4m†&m¾ü<φ”ÝQ©q–ê&¤³ߦbÍiFO\7 q!,)iîPåÀ<Š%ÌK[–vӓLJ&XLŸKÞã#‰—À$íc´HÊ7)c•æÅ¼ÈÈäF@Ï7T¤zŸùXVrªfv4o<’žƒ1½Ξföùê}rÛì6çÉ-‡…q\)i_!ùˆ˜øÀÑ C<äb "}í–íæ3!;ø/~ßLúkðó–pàèpÈ[òÞô©Öñ7_ú/PKƒ,ÒF",³™ ~!setuptools/command/upload_docs.py¥YëoÛ8ÿî¿‚pHÚµÕWÚ²ð‡î5Ùf·ÝIz‡½40h‰¶¹‘EI5u÷¿ß õHÚÅ ˆ¡Ç<~óàÌ9 óæ$9/7ǤÖëùßðÍd:ÖU!h¾ÌE¦&“³]U°+µ"”¼åJךŠDQDT½ÊÄnGËœÄö5²QÍEI´˜\ì/Î"Eª½ÞŠr+”fy*ä&IQåd²–bGVT±WG„ï*!5QR™/W¯ŽX P™¥Êް›Þ—”I)dCÐà>¯Î ~ìs8R‡ßqÚ§‰{Êß)‘Ý1퟾òjÍ æ5ÛužÕ¾åÛ¢6g®bº®´V{Eµ×ºÕº*øjFjYTT*w%GÌ×LÂßNÍÈÅ/¬ ên³”L‰Zf¬1 —¹_V‚C'“‰sË‚Dª†Û ÕŒ©ŒV,"|ò+ƒ¯ZòLGÀq@®·d*R Mþ¬•†<¬*hfÒ‚¬…$«½f¤@…´PÀ²ª5¹òrÓfÃJüBªZVÄÛ`ÊIÎÖdƒ!æ$â"2‰%Ç@⊗˜C:ç÷/ .”%€™±—2©É$¤{²‚*E‚ìu ëdæàÉM– —>Ž'31É<1µ7 ÃŽ½i Å¸I(®…Ü/¢‰d4k>’)„–ˆ5iiÈ øƒÖ…>&‡êvJÊôíÉé›ï¯——'çWg×ç—$³@‹ÚŠû9D¿ ôü.J(Š Å!Z{²®‹‚x:ÈÑ/;›…ò3“QG¦Õ<Ϲ\x‰(H²Ì X Ïuk~WÊŒ–7œ½çê5ÙRµTÕ–—_bÅŠuXˆ=¾I}¤¸ÄD$- ^˜~¬"¼æ{ V·Â8¬j^äNm”tÅÙr-kf‘By[zâ¸+b˜‘ܶÆñ’kN þ•yÃûF:÷å:EÇ4CòèØ4‡¥¶f]"D (2ˆaÈÁºfa×1´fÞº€û¿AjÃF¼Hô–ZÃo©yffáÖ;’åøælÀv™ãhlÒïG°(‚_ó¶‚6yòópÛy6,ÝTèJ žÒœIUçAXÑ þLÏÈ@\“À?›‘ÀyáÃÙ‡Rѽ)Ƹ¾ñ%LçפÜ–m U¶óÎõË»«ßN}ûþ—·W¯_½8ýõ·÷§ï.O^¿|uô~^½xþò( uµ „­âèS9ŸG À]ÅþC0A”yHÞáFŽy”9RÝÜv*ÖÛÏÈgZÔ¶O6ÛÎ-ì+͵©€êï6‘æÐéÌÆ’äåíæÈ÷“© ¨Sœ)@GGÎLÒe¢v° âU[EX;¦Z+L'”Ñ9±ý›E |›R(óÃŽæì£íÝm‡•™÷h¸%ô¾rš…a3_ŒÌ’­ƒ~ýÔŸÆ FÂÍÓÛQN‹cሞ ‰ÆØuå0§\|J+¨zyæÈ㔫ØX“|‹jú©üTN¿Aö2p®E“•5}þìøg/Ì}9¶m"€tŒ3šÎÂìz%%%»/xÉH\Ô°÷%h¦ºËÁËÒ8…±3´Ò­&Ð%nâ‡7A×îÝÓ«zµãZãä=8f€ü°Å´=(è•øö*Ä&=ûýô< ë–ÝÊàÚ¹dÿ†LÖÁ·2˜”ËHã!ž5|õœÀ"ʹ‡eÆXŽ( [X¦Fì¦vJ¾ÙjrÏáiÖ0^k˜üºªT¶e; CÓ…ÈÌ¹Ö ê§¤xŒ¤jÍZÒ=h\O ý)ØÀmWÐj´)Vj3’áí€îutvµæV„oQ¯¥ˆ‚Ü‘\úîúúj\ÉLƒŽ­AáÞm(P}[âÕ£"û Üî%Þ››]Ä´†ýa…'5‡Û™½ RÂMQÛ]3"L3 )N†ŸªZ»ÇSìzSÑ!6‚%ITgK:•úIÐ üÚZØ=¦Õ¸…¡‹É8òG³Žžq¨}F(¿½V˜ËbÜ“˜š<Îün…ä_ÍÚ^ÌýX*–CùM™ŠaÊAÝ/«üy²=¶ÆCÓ±€¦f nÚp½Ÿ\^ž_vUÙó«6à¸A0êaHôçqgŽ’)´M]+LÙçOŸ>¦;º2Ç…íAb|¨’cwF{A3 C²åƒÅ ¯¶`5î(zp^<}Ö…kƒºãY‰ù½wï{‡! ®á=®êÉ´+öøÉ“þ?*žª'hcoÜ~ÌUîôXÕYÆ”‚}gJþ3ŠvÞòZÿª‡FO‡Z׿ŒüÿO/¿üá:/}táT’—F̈ü@^¿tª`»*÷.™üPKò lHM^dÛ `"setuptools/command/upload_docs.pycµYKsÇî]€ |$%ZZ‰¦ 9i[å’c—eS´d©(ÕR-Ä*Ô»ÜwIË—T¥ò#R®J¹æ”äžsò+R9¥rÈ-NwÏ.ÉÎ!U! zÞ3Ýß|Ý3Êü«\Üþãן5!ùËà÷CüŠÿ`bÔ1ÕÀÖÁÓÀס®ƒFù xð³PϪ|¼1ðsPÏ©üxãà硞Wùx¨ ‘‹P/¦òÔ'R¹õR*—¡^NåI¨O²<ÞøÓPŸê3àÏB}ü9¨Ï?õy5_¼ð+P¯€æÌCüW° dÀÆ™ÁÆ Kðõ%°Ëàä¡…}&á€çOêË4é~uŠôaҼвvØÅâ=?òß ¤0,cDz+]Oë#Ö Ñ=l†¾o¶QUVt©›%Ý00dX|töèÞº0¢3yG¡Ž½ÆíkE÷;ü«j8³œ¥5HÇŠíÆáö–4CÛQud+/l«Ì<&ƒÕ<Œh’;qƪ67ØÅ^uŒ Æ19’2òÜC™§ÊØ‹¬X8\Ñ \šEPv¥ã×<Ý£'×Õ€3IUwŸ5¢ÐE…HÖX§m[ÒqDÓŠžZÈØmJA3we«önSGIOàö15X¥Az˜jð\‡ø2ÉzmKö1¿Ï“ïU³ÔºHKn@êi:f.ݧR‘I¢J3IבO¸A»J€çDÜÁä°ëzöæ¡JÜð­f(Nko¿µñö[µÓw·Û[›N»½‰ êF2 =±™ØwsÄîhKšæp…Ƥ€6¥MkrâE N)ä#jû- O›ÆgNOÎ3',TZÝi°g ¡3F¥ãP' #hñ”!¼ Æ:´5>gE./ÔIP€>^eÊ àñ`™ûU†­ú³«A`´Ø‰BáÊ0>{Ÿ÷‹Ë >FØ2†•Æ/l§eu=yËXOE™Æ? ŸÕbGDa ññ‹+"Ï:3Z]Ï3ÒC:§ÒhÅ¡o'þÒ‰ÅP{5ÛßsÜ5vš<.NU6µ—Aõ60¢:ÌdÇyˆkpzdª^ÕÎÓqè3Âön¶_¥î{bV­O§ÄØB–R 4Dtä§C(¦öucIe{aà˜t€8÷8î: †”Ž×’”s¢W‚AZΑ%’%nŒ‚±¢™Ä¬«T_£°£‘ÆžkH£¬»F!«´£ ×̤å®t-Ï=w!30+Ô`!Õ´â¶#I7Üß\J7ý#ïܼˆ#Ýî·¬4Þjfß¾¼UÅ4 FC&Kž ÞeyŒð‚í(ÈF«cN~•Öê\«²K§"ôtèLÐñEˆ©ÆÁ27.‘«N©êH.“Ï$a*‰ö÷«´‰=¶—KUÄ¢í²vÅ2Y$Á¶‘º™ÁÁXÕÉ™¦1i¹Á‹F¢”¥.PÊ’™Òvv#Ñ2™gGÂÚÒ$Â`£ó¢eE–ÿ ¬ØÉ°UOÿD¼36,Úyú;ø"}ü—…>Vd’ºc¡6%üAge§ãù¿ÖÙè´Cõ;O¡ŸãqÇ¡“çr¼„q’ÑI&»ŒÐKÚM0$ó#Ýòi·ó=ì_ íäNÞ…ƒ:ê:Á¯}>dCfúgbÓ 4Z®ç£…f³ 7ø>ðÖ×Ä:Cƒ‰s7¢,×Ýh—d¶Lpa ™WSf|fyÇ&éß$>2_‡4ÌA_D<Š$".Nħâ…',5½P8ÕbŠ#†M=À.¥Ák¡©â0”ê0¹±àþ¼/.â$gâ®±ã¡/üR•ÚØì•7)­;<5µÝ…Ä1ƒ6«e0–¸Šža©¬-`nA[Ñ™âÆFûkLN¯$ιótŽé+1õ¤ xz :@xV´‡àE†£’ ٯÔÖc—Ù#pêäóK܉nÈfi†P„~QÔcbL€DVÝc^^¸;…é„s0`n œ,ÇÝ`@?d A‡8òmʳ7&•Çîa—([¢é,ÛÂÐ%ŸŒMÖdˆ Ae¾GCŽ„e­–âˆ<>‹±/cÇQ¾n¨¦oó€¼éGL„7©ÉõWÄXŒvTÇ•˜ô9mF/! –e”™²È÷åR˜YOðl-±,É:ŸrEhx4«›I¢ÎíëÑ]m£2aà 0ÎDwµ|–ÐO‘nL‹ ‹Ä<9‚Ž’Ëÿ†²IºÃ©BŠ·˜”‘É0~%¶âÈ«iØ< ‹DW®˜Pù"´q púà} ’YöŸðn²ý2Eº½Tú“„®^™î*¨±¢¡ŒÑ1¶ ný3Uí<ýô§(ˆéMñ´sÔµÞ$ÅÉXˆAòrå&ŽEò,cë ÄËã˜íM@gž™”g¨z’ò/aÿB‘Aßx•RŒî/S³Y*&÷°:Òw.í{²JÿNþÉ0Å—¦4¥Ì¥áG¯jÓ™Ù±Rî¿PKƒ,ÒF\OºEi~¤zeasy_install.pyPKò lH‰¤ræê>¤easy_install.pycPKƒ,ÒF®šø|ú(¤(_markerlib/__init__.pyPKò lHo‘wæøX¤V_markerlib/__init__.pycPKƒ,ÒF.ܤÆ‹¤ƒ_markerlib/markers.pyPKò lHfpK‰ˆî¤| _markerlib/markers.pycPKò lH—Ô`ݤ8EGG-INFO/dependency_links.txtPKò lHOÒ¨\|é ¤EGG-INFO/entry_points.txtPKò lHt²Âu1¤µEGG-INFO/PKG-INFOPKò lH8BG¤ý(EGG-INFO/requires.txtPKò lH“îÈ_ÐÁ¤r)EGG-INFO/SOURCES.txtPKò lHìîc¥11¤t-EGG-INFO/top_level.txtPKç“nF¬…¢¤Ù-EGG-INFO/zip-safePKƒ,ÒF¹a~p® ¤ .pkg_resources/__init__.pyPKò lHËÅ%⸙AФÁžpkg_resources/__init__.pycPKƒ,ÒF!¤±8pkg_resources/_vendor/__init__.pyPKò lH¹¬D}œ"¤ò8pkg_resources/_vendor/__init__.pycPKƒ,ÒF›~ÐF1,¤¯9pkg_resources/_vendor/packaging/__about__.pyPKò lHö©.¤öó-¤?<pkg_resources/_vendor/packaging/__about__.pycPKƒ,ÒFXÕç¶üŠ+¤€>pkg_resources/_vendor/packaging/__init__.pyPKò lH15C Ži,¤Å@pkg_resources/_vendor/packaging/__init__.pycPKƒ,ÒFgG½›°å*¤Bpkg_resources/_vendor/packaging/_compat.pyPKò lHBZºoYô+¤•Epkg_resources/_vendor/packaging/_compat.pycPKƒ,ÒF®’9µU.¤7Hpkg_resources/_vendor/packaging/_structures.pyPKò lH¤¯Ë/¤ØJpkg_resources/_vendor/packaging/_structures.pycPKƒ,ÒFT_Ý$l-¤6Npkg_resources/_vendor/packaging/specifiers.pyPKò lH8€pj_.¤^gpkg_resources/_vendor/packaging/specifiers.pycPKƒ,ÒFð„ß=l.*¤pkg_resources/_vendor/packaging/version.pyPKò lHøÛd9+¤™pkg_resources/_vendor/packaging/version.pycPKƒ,ÒF(¸,©¤½Ÿsetuptools/__init__.pyPKò lHMb™š O¤§setuptools/__init__.pycPKƒ,ÒF¶|?W·Ñ¤ì²setuptools/archive_util.pyPKò lHq¯ÓpÁ -¤Ûºsetuptools/archive_util.pycPKƒ,ÒF.}ÝîŠ.¤ÕÅsetuptools/compat.pyPKò lH4nüÈ1ó ¤‘Èsetuptools/compat.pycPKƒ,ÒF•èâ¤õÍsetuptools/depends.pyPKò lH˜µ¹“Î ;¤×setuptools/depends.pycPKƒ,ÒFÍ[]mg&ø‰¤äsetuptools/dist.pyPKò lH-%º¢20‡¤© setuptools/dist.pycPKƒ,ÒFñ¿÷ËŸq¤|=setuptools/extension.pyPKò lH òŒaj< ¤P@setuptools/extension.pycPKƒ,ÒF°ënž~ΤðDsetuptools/lib2to3_ex.pyPKò lH¶ðZOË× ¤¤Gsetuptools/lib2to3_ex.pycPKƒ,ÒFaà²ìE‹¤¦Lsetuptools/msvc9_support.pyPKò lHÍÔ©fC¤$Psetuptools/msvc9_support.pycPKƒ,ÒFº+‚á -h—¤ÄTsetuptools/package_index.pyPKò lH †Dv#<'˜¤‚setuptools/package_index.pycPKƒ,ÒFKóâT¯¤c¾setuptools/py26compat.pyPKò lHÆ#WÆï¤ª¿setuptools/py26compat.pycPKƒ,ÒF´ úÏ´2¤ÐÁsetuptools/py27compat.pyPKò lHÙÛe‚ð¤ºÂsetuptools/py27compat.pycPKƒ,ÒFÿ®5d®e¤sÄsetuptools/py31compat.pyPKò lHï¬i6[k ¤WÇsetuptools/py31compat.pycPKƒ,ÒF0«ÔÈËe6¤éËsetuptools/sandbox.pyPKò lHªQ§Ñ`¯H¤çÛsetuptools/sandbox.pycPKƒ,ÒF‘é À˜É¤{ösetuptools/script (dev).tmplPKƒ,ÒF¨3´¾jФM÷setuptools/script.tmplPKƒ,ÒF¢¶}U ¤ë÷setuptools/site-patch.pyPKò lHx×VìûѤžûsetuptools/site-patch.pycPKƒ,ÒFÆÔ–íï l¤Ðÿsetuptools/ssl_support.pyPKò lHP°ãžw 0¤ö setuptools/ssl_support.pycPKƒ,ÒF}¼ª.‰Õ¤¥setuptools/unicode_utils.pyPKò lHµ>7 Å­¤gsetuptools/unicode_utils.pycPKƒ,ÒF/ðPŸ%¤fsetuptools/utils.pyPKò lHš{P»@%¤6setuptools/utils.pycPKwoØFÓ;\¤¨setuptools/version.pyPKò lH¿7¿‹±¤ôsetuptools/version.pycPKƒ,ÒFùËî tʤ³ setuptools/windows_support.pyPKò lH×Ëÿô•¤b"setuptools/windows_support.pycPKƒ,ÒF­ˆ©–*¤3%setuptools/command/__init__.pyPKò lHiE¢±êK¤u&setuptools/command/__init__.pycPKƒ,ÒF=ƒ/M ¤œ(setuptools/command/alias.pyPKò lHÁSOuô ¤,setuptools/command/alias.pycPKƒ,ÒFfÔ@ÚG C¤³1setuptools/command/bdist_egg.pyPKò lHBxƬÚD ¤7Fsetuptools/command/bdist_egg.pycPKƒ,ÒFëÒt>ä¤!dsetuptools/command/bdist_rpm.pyPKò lH6b¾† ¤œfsetuptools/command/bdist_rpm.pycPKƒ,ÒF Œu}#¤ijsetuptools/command/bdist_wininst.pyPKò lHí~gÕ4Å$¤¾ksetuptools/command/bdist_wininst.pycPKƒ,ÒFôü´€“ ¼.¤4nsetuptools/command/build_ext.pyPKò lH™L ´+ ¤{setuptools/command/build_ext.pycPKƒ,ÒF »G ë¤Lsetuptools/command/build_py.pyPKò lHØÃe› y!¤––setuptools/command/build_py.pycPKƒ,ÒFÜq¡êÒÒ¤n¤setuptools/command/develop.pyPKò lH‘f2 ë¤{¬setuptools/command/develop.pycPKƒ,ÒFŠ’¾)\RQ"¤é¶setuptools/command/easy_install.pyPKò lH UzµvÛ5#¤Rsetuptools/command/easy_install.pycPKƒ,ÒF R2ÔA¤HŠsetuptools/command/egg_info.pyPKò lH«HlµÅ¥N¤žžsetuptools/command/egg_info.pycPKƒ,ÒF…’³ž›M¤ ¼setuptools/command/install.pyPKò lHK]æ-w¤vÃsetuptools/command/install.pycPKƒ,ÒFœ¸"²¡&¤ßËsetuptools/command/install_egg_info.pyPKò lH"ŸŸW‹q'¤ÕÑsetuptools/command/install_egg_info.pycPKƒ,ÒF$€x»!¤¥Úsetuptools/command/install_lib.pyPKò lH¨%¯Ââö"¤÷ßsetuptools/command/install_lib.pycPKƒ,ÒFý<';·%¤èsetuptools/command/install_scripts.pyPKò lH;M!3B &¤—ësetuptools/command/install_scripts.pycPKƒ,ÒFÍÿ­Ÿ¤ñsetuptools/command/register.pyPKò lH€½è@\Ϥøñsetuptools/command/register.pycPKƒ,ÒF•¼Åòö¤‘ósetuptools/command/rotate.pyPKò lH@û5`• ¤½ösetuptools/command/rotate.pycPKƒ,ÒFÖ4F’¤Xüsetuptools/command/saveopts.pyPKò lHþÅìvVr¤Úýsetuptools/command/saveopts.pycPKƒ,ÒFß‘®I. §¤msetuptools/command/sdist.pyPKò lH6÷<ŽØ ¤Ô setuptools/command/sdist.pycPKƒ,ÒFÙ£*ÝØ¤æsetuptools/command/setopt.pyPKò lH(]+#– Á¤ýsetuptools/command/setopt.pycPKƒ,ÒFzB·qG¤Î%setuptools/command/test.pyPKò lHVWW` ¢¤w-setuptools/command/test.pycPKƒ,ÒF",³™ ~!¤º8setuptools/command/upload_docs.pyPKò lHM^dÛ `"¤üAsetuptools/command/upload_docs.pycPKool Opex-1.1.14/tests/test_archiver.py0000644000076500000240000000170612623452313017566 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import os from zipfile import ZipFile from twitter.common.contextutil import temporary_dir from pex.archiver import Archiver def test_package_fetch_without_location(): with temporary_dir() as td: dateutil_base = 'python-dateutil-1.5' dateutil = '%s.zip' % dateutil_base with contextlib.closing(ZipFile(os.path.join(td, dateutil), 'w')) as zf: zf.writestr(os.path.join(dateutil_base, 'file1.txt'), 'junk1') zf.writestr(os.path.join(dateutil_base, 'file2.txt'), 'junk2') dest = Archiver.unpack(zf.filename) assert set(os.listdir(dest)) == set(['file1.txt', 'file2.txt']) with temporary_dir() as td2: dest = Archiver.unpack(zf.filename, location=td2) assert set(os.listdir(os.path.join(td2, 'python-dateutil-1.5'))) == set( ['file1.txt', 'file2.txt']) pex-1.1.14/tests/test_bdist_pex.py0000644000076500000240000000435712743540264017757 0ustar kwilsonstaff00000000000000# Copyright 2016 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import subprocess import sys from textwrap import dedent from twitter.common.contextutil import pushd from pex.testing import temporary_content def assert_entry_points(entry_points): setup_py = dedent(""" from setuptools import setup setup( name='my_app', version='0.0.0', zip_safe=True, packages=[''], entry_points=%(entry_points)r, ) """ % dict(entry_points=entry_points)) my_app = dedent(""" def do_something(): print("hello world!") """) with temporary_content({'setup.py': setup_py, 'my_app.py': my_app}) as project_dir: with pushd(project_dir): subprocess.check_call([sys.executable, 'setup.py', 'bdist_pex']) process = subprocess.Popen([os.path.join(project_dir, 'dist', 'my_app-0.0.0.pex')], stdout=subprocess.PIPE) stdout, _ = process.communicate() assert '{pex_root}' not in os.listdir(project_dir) assert 0 == process.returncode assert stdout == b'hello world!\n' def assert_pex_args_shebang(shebang): setup_py = dedent(""" from setuptools import setup setup( name='my_app', version='0.0.0', zip_safe=True, packages=[''], ) """) with temporary_content({'setup.py': setup_py}) as project_dir: with pushd(project_dir): assert subprocess.check_call( [sys.executable, 'setup.py', 'bdist_pex', '--pex-args=--python-shebang="%(shebang)s"' % dict(shebang=shebang)]) == 0 with open(os.path.join(project_dir, 'dist', 'my_app-0.0.0.pex'), 'rb') as fp: assert fp.readline().decode().rstrip() == shebang def test_entry_points_dict(): assert_entry_points({'console_scripts': ['my_app = my_app:do_something']}) def test_entry_points_ini_string(): assert_entry_points(dedent(""" [console_scripts] my_app=my_app:do_something """)) def test_pex_args_shebang_with_spaces(): assert_pex_args_shebang('#!/usr/bin/env python') def test_pex_args_shebang_without_spaces(): assert_pex_args_shebang('#!/usr/bin/python') pex-1.1.14/tests/test_common.py0000644000076500000240000000177112722124676017265 0ustar kwilsonstaff00000000000000# Copyright 2016 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import errno import os from contextlib import contextmanager import pytest from pex.common import rename_if_empty try: from unittest import mock except ImportError: import mock @contextmanager def maybe_raises(exception=None): @contextmanager def noop(): yield with (noop() if exception is None else pytest.raises(exception)): yield def rename_if_empty_test(errno, expect_raises=None): with mock.patch('os.rename', spec_set=True, autospec=True) as mock_rename: mock_rename.side_effect = OSError(errno, os.strerror(errno)) with maybe_raises(expect_raises): rename_if_empty('from.dir', 'to.dir') def test_rename_if_empty_eexist(): rename_if_empty_test(errno.EEXIST) def test_rename_if_empty_enotempty(): rename_if_empty_test(errno.ENOTEMPTY) def test_rename_if_empty_eperm(): rename_if_empty_test(errno.EPERM, expect_raises=OSError) pex-1.1.14/tests/test_compatibility.py0000644000076500000240000000106212623452313020627 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pytest from pex.compatibility import to_bytes def test_to_bytes(): assert isinstance(to_bytes(''), bytes) assert isinstance(to_bytes('abc'), bytes) assert isinstance(to_bytes(b'abc'), bytes) assert isinstance(to_bytes(u'abc'), bytes) assert isinstance(to_bytes(b'abc'.decode('latin-1'), encoding='utf-8'), bytes) for bad_values in (123, None): with pytest.raises(ValueError): to_bytes(bad_values) pex-1.1.14/tests/test_compiler.py0000644000076500000240000000443012623452313017572 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import os import marshal import pytest from twitter.common.contextutil import temporary_dir from pex import compatibility from pex.common import safe_open from pex.compatibility import to_bytes from pex.compiler import Compiler from pex.interpreter import PythonInterpreter def write_source(path, valid=True): with safe_open(path, 'wb') as fp: fp.write(to_bytes('basename = %r\n' % os.path.basename(path))) if not valid: fp.write(to_bytes('invalid!\n')) @contextlib.contextmanager def compilation(valid_paths=None, invalid_paths=None, compile_paths=None): with temporary_dir() as root: for path in valid_paths: write_source(os.path.join(root, path)) for path in invalid_paths: write_source(os.path.join(root, path), valid=False) compiler = Compiler(PythonInterpreter.get()) yield root, compiler.compile(root, compile_paths) def test_compile_success(): with compilation(valid_paths=['a.py', 'c/c.py'], invalid_paths=['b.py', 'd/d.py'], compile_paths=['a.py', 'c/c.py']) as (root, compiled_relpaths): assert 2 == len(compiled_relpaths) results = {} for compiled in compiled_relpaths: compiled_abspath = os.path.join(root, compiled) with open(compiled_abspath, 'rb') as fp: fp.read(4) # Skip the magic header. fp.read(4) # Skip the timestamp. if compatibility.PY3: fp.read(4) # Skip the size. code = marshal.load(fp) local_symbols = {} exec(code, {}, local_symbols) results[compiled] = local_symbols assert {'basename': 'a.py'} == results.pop('a.pyc') assert {'basename': 'c.py'} == results.pop('c/c.pyc') assert 0 == len(results) def test_compile_failure(): with pytest.raises(Compiler.Error) as e: with compilation(valid_paths=['a.py', 'c/c.py'], invalid_paths=['b.py', 'd/d.py'], compile_paths=['a.py', 'b.py', 'c/c.py', 'd/d.py']): raise AssertionError('Should not reach here.') message = str(e.value) assert 'a.py' not in message assert 'b.py' in message assert 'c/c.py' not in message assert 'd/d.py' in message pex-1.1.14/tests/test_crawler.py0000644000076500000240000001230412643564600017423 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from twitter.common.contextutil import temporary_dir from pex.crawler import Crawler, PageParser from pex.http import Context from pex.link import Link try: from unittest import mock except ImportError: import mock def lpp(page): links = PageParser.links(page) rels = PageParser.rel_links(page) return list(links), list(rels) def test_page_parser_empty(): links, rels = lpp("") assert links == [] assert rels == [] def test_page_parser_basic(): for target in ('href', 'href =', 'href =""'): assert lpp(target.lower()) == ([], []) assert lpp(target.upper()) == ([], []) for target in ('a href=', 'a href=""'): assert lpp(target.lower()) == ([''], []) assert lpp(target.upper()) == ([''], []) assert lpp('a href=11') == (['11'], []) assert lpp('a href=12') == (['12'], []) for href in ('pooping', '{};a[32[32{#@'): for start, end in (('', ''), ('"', '"'), ("'", "'")): target = '%s%s%s' % (start, href, end) assert lpp('' % target) == ([href], []) assert lpp("" % target) == ([href], []) assert lpp('anything anything' % target) == ([href], []) assert lpp(" " % target) == ([href, 'stuff'], []) assert lpp(" " % target) == (['stuff', href], []) def test_page_parser_escaped_html(): url = 'url?param1=val¶m2=val2' link = 'a href="%s"' % url.replace('&', '&') assert lpp(link) == ([url], []) def test_page_parser_rels(): VALID_RELS = tuple(PageParser.REL_TYPES) for rel in VALID_RELS + ('', ' ', 'blah'): for start, end in (('', ''), ('"', '"'), ("'", "'")): target = 'rel=%s%s%s' % (start, rel, end) links, rels = lpp(" " % target) assert links == ['things', 'stuff'] if rel in VALID_RELS: assert rels == ['things'] else: assert rels == [] links, rels = lpp(" " % target) assert links == ['stuff', 'things'] if rel in VALID_RELS: assert rels == ['stuff'] else: assert rels == [] def test_page_parser_skips_data_rels(): for ext in PageParser.REL_SKIP_EXTENSIONS: things = 'things%s' % ext assert lpp("" % things) == ([things], []) for ext in ('.html', '.xml', '', '.txt', '.tar.gz.txt'): things = 'things%s' % ext assert lpp("" % things) == ([things], [things]) def test_crawler_local(): FL = ('a.txt', 'b.txt', 'c.txt') with temporary_dir() as td: for fn in FL: with open(os.path.join(td, fn), 'w'): pass for dn in (1, 2): os.mkdir(os.path.join(td, 'dir%d' % dn)) for fn in FL: with open(os.path.join(td, 'dir%d' % dn, fn), 'w'): pass # basic file / dir rel splitting links, rels = Crawler.crawl_local(Link.wrap(td)) assert set(links) == set(Link.wrap(os.path.join(td, fn)) for fn in FL) assert set(rels) == set(Link.wrap(os.path.join(td, 'dir%d' % n)) for n in (1, 2)) # recursive crawling, single vs multi-threaded for caching in (False, True): for threads in (1, 2, 3): links = Crawler(threads=threads).crawl([td], follow_links=True) expect_links = (set(Link.wrap(os.path.join(td, fn)) for fn in FL) | set(Link.wrap(os.path.join(td, 'dir1', fn)) for fn in FL) | set(Link.wrap(os.path.join(td, 'dir2', fn)) for fn in FL)) assert set(links) == expect_links def test_crawler_unknown_scheme(): # skips unknown url schemes Crawler().crawl('ftp://ftp.cdrom.com') == (set(), set()) MOCK_INDEX_TMPL = '''

Index of /home/third_party/python

%s
[DIR]   -  
''' MOCK_INDEX_A = MOCK_INDEX_TMPL % ''' [   ]
3to2-1.0.tar.gz 16-Apr-2015 23:18 45K GZIP compressed docume> ''' MOCK_INDEX_B = MOCK_INDEX_TMPL % ''' [   ] APScheduler-2.1.0.tar.gz 16-Apr-2015 23:18 41K GZIP compressed docume> ''' def test_crawler_remote(): Crawler.reset_cache() mock_context = mock.create_autospec(Context, spec_set=True) mock_context.content.side_effect = [MOCK_INDEX_A, MOCK_INDEX_B, Exception('shouldnt get here')] expected_output = set([Link('http://url1.test.com/3to2-1.0.tar.gz'), Link('http://url2.test.com/APScheduler-2.1.0.tar.gz')]) c = Crawler(mock_context) test_links = [Link('http://url1.test.com'), Link('http://url2.test.com')] assert c.crawl(test_links) == expected_output # Test memoization of Crawler.crawl(). assert c.crawl(test_links) == expected_output # TODO(wickman): test page decoding via mock pex-1.1.14/tests/test_environment.py0000644000076500000240000000732012670614434020333 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from contextlib import contextmanager from twitter.common.contextutil import temporary_dir from pex.compatibility import nested from pex.environment import PEXEnvironment from pex.pex_builder import PEXBuilder from pex.pex_info import PexInfo from pex.testing import make_bdist, temporary_filename @contextmanager def yield_pex_builder(zip_safe=True): with nested(temporary_dir(), make_bdist('p1', zipped=True, zip_safe=zip_safe)) as (td, p1): pb = PEXBuilder(path=td) pb.add_egg(p1.location) yield pb def test_force_local(): with nested(yield_pex_builder(), temporary_dir(), temporary_filename()) as ( pb, pex_root, pex_file): pb.info.pex_root = pex_root pb.build(pex_file) code_cache = PEXEnvironment.force_local(pex_file, pb.info) assert os.path.exists(pb.info.zip_unsafe_cache) assert len(os.listdir(pb.info.zip_unsafe_cache)) == 1 assert [os.path.basename(code_cache)] == os.listdir(pb.info.zip_unsafe_cache) assert set(os.listdir(code_cache)) == set([PexInfo.PATH, '__main__.py', '__main__.pyc']) # idempotence assert PEXEnvironment.force_local(pex_file, pb.info) == code_cache def normalize(path): return os.path.normpath(os.path.realpath(path)).lower() def test_write_zipped_internal_cache(): # zip_safe pex will not be written to install cache unless always_write_cache with nested(yield_pex_builder(zip_safe=True), temporary_dir(), temporary_filename()) as ( pb, pex_root, pex_file): pb.info.pex_root = pex_root pb.build(pex_file) existing, new, zip_safe = PEXEnvironment.write_zipped_internal_cache(pex_file, pb.info) assert len(zip_safe) == 1 assert normalize(zip_safe[0].location).startswith( normalize(os.path.join(pex_file, pb.info.internal_cache))), ( 'loc: %s, cache: %s' % ( normalize(zip_safe[0].location), normalize(os.path.join(pex_file, pb.info.internal_cache)))) pb.info.always_write_cache = True existing, new, zip_safe = PEXEnvironment.write_zipped_internal_cache(pex_file, pb.info) assert len(new) == 1 assert normalize(new[0].location).startswith(normalize(pb.info.install_cache)) # Check that we can read from the cache existing, new, zip_safe = PEXEnvironment.write_zipped_internal_cache(pex_file, pb.info) assert len(existing) == 1 assert normalize(existing[0].location).startswith(normalize(pb.info.install_cache)) # non-zip_safe pex will be written to install cache with nested(yield_pex_builder(zip_safe=False), temporary_dir(), temporary_filename()) as ( pb, pex_root, pex_file): pb.info.pex_root = pex_root pb.build(pex_file) existing, new, zip_safe = PEXEnvironment.write_zipped_internal_cache(pex_file, pb.info) assert len(new) == 1 assert normalize(new[0].location).startswith(normalize(pb.info.install_cache)) original_location = normalize(new[0].location) # do the second time to validate idempotence of caching existing, new, zip_safe = PEXEnvironment.write_zipped_internal_cache(pex_file, pb.info) assert len(existing) == 1 assert normalize(existing[0].location) == original_location def test_load_internal_cache_unzipped(): # zip_safe pex will not be written to install cache unless always_write_cache with nested(yield_pex_builder(zip_safe=True), temporary_dir()) as (pb, pex_root): pb.info.pex_root = pex_root pb.freeze() dists = list(PEXEnvironment.load_internal_cache(pb.path(), pb.info)) assert len(dists) == 1 assert normalize(dists[0].location).startswith( normalize(os.path.join(pb.path(), pb.info.internal_cache))) pex-1.1.14/tests/test_executor.py0000644000076500000240000000676712743540264017643 0ustar kwilsonstaff00000000000000# Copyright 2016 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import pytest from twitter.common.contextutil import temporary_dir from pex.common import safe_mkdir from pex.executor import Executor TEST_EXECUTABLE = '/a/nonexistent/path/to/nowhere' TEST_CMD_LIST = [TEST_EXECUTABLE, '--version'] TEST_CMD_STR = ' '.join(TEST_CMD_LIST) TEST_CMD_PARAMETERS = [TEST_CMD_LIST, TEST_CMD_STR] TEST_STDOUT = 'testing stdout' TEST_STDERR = 'testing stder' TEST_CODE = 3 def test_executor_open_process_wait_return(): process = Executor.open_process('exit 8', shell=True) exit_code = process.wait() assert exit_code == 8 def test_executor_open_process_communicate(): process = Executor.open_process(['/bin/echo', '-n', 'hello']) stdout, stderr = process.communicate() assert stdout.decode('utf-8') == 'hello' assert stderr.decode('utf-8') == '' def test_executor_execute(): assert Executor.execute('/bin/echo -n stdout >&1', shell=True) == ('stdout', '') assert Executor.execute('/bin/echo -n stderr >&2', shell=True) == ('', 'stderr') assert Executor.execute(['/bin/echo', 'hello']) == ('hello\n', '') assert Executor.execute(['/bin/echo', '-n', 'hello']) == ('hello', '') assert Executor.execute('/bin/echo -n $HELLO', env={'HELLO': 'hey'}, shell=True) == ('hey', '') def test_executor_execute_zero(): Executor.execute('exit 0', shell=True) def test_executor_execute_stdio(): with temporary_dir() as tmp: with open(os.path.join(tmp, 'stdout'), 'w+b') as fake_stdout: with open(os.path.join(tmp, 'stderr'), 'w+b') as fake_stderr: Executor.execute('/bin/echo -n TEST | tee /dev/stderr', shell=True, stdout=fake_stdout, stderr=fake_stderr) fake_stdout.seek(0) fake_stderr.seek(0) assert fake_stdout.read().decode('utf-8') == 'TEST' assert fake_stderr.read().decode('utf-8') == 'TEST' @pytest.mark.parametrize('testable', [Executor.open_process, Executor.execute]) def test_executor_execute_not_found(testable): with pytest.raises(Executor.ExecutableNotFound) as exc: testable(TEST_CMD_LIST) assert exc.value.executable == TEST_EXECUTABLE assert exc.value.cmd == TEST_CMD_LIST @pytest.mark.parametrize('exit_code', [1, 127, -1]) def test_executor_execute_nonzero(exit_code): with pytest.raises(Executor.NonZeroExit) as exc: Executor.execute('exit %s' % exit_code, shell=True) if exit_code > 0: assert exc.value.exit_code == exit_code @pytest.mark.parametrize('cmd', TEST_CMD_PARAMETERS) def test_executor_exceptions_executablenotfound(cmd): exc_cause = OSError('test') exc = Executor.ExecutableNotFound(cmd=cmd, exc=exc_cause) assert exc.executable == TEST_EXECUTABLE assert exc.cmd == cmd assert exc.exc == exc_cause @pytest.mark.parametrize('cmd', TEST_CMD_PARAMETERS) def test_executor_exceptions_nonzeroexit(cmd): exc = Executor.NonZeroExit(cmd=cmd, exit_code=TEST_CODE, stdout=TEST_STDOUT, stderr=TEST_STDERR) assert exc.executable == TEST_EXECUTABLE assert exc.cmd == cmd assert exc.exit_code == TEST_CODE assert exc.stdout == TEST_STDOUT assert exc.stderr == TEST_STDERR def test_executor_execute_dir(): with temporary_dir() as temp_dir: test_dir = os.path.realpath(os.path.join(temp_dir, 'tmp')) safe_mkdir(test_dir) assert os.path.isdir(test_dir) with pytest.raises(Executor.ExecutionError) as e: Executor.execute(test_dir) assert test_dir in str(e) pex-1.1.14/tests/test_fetcher.py0000644000076500000240000000136312623452313017402 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from pex.fetcher import PyPIFetcher def test_pypifetcher(): fetcher = PyPIFetcher('https://pypi.python.org/simple') assert fetcher._pypi_base == 'https://pypi.python.org/simple/' assert fetcher.urls('setuptools') == ['https://pypi.python.org/simple/setuptools/'] fetcher = PyPIFetcher() assert fetcher._pypi_base == 'https://pypi.python.org/simple/' assert fetcher.urls('setuptools') == ['https://pypi.python.org/simple/setuptools/'] fetcher = PyPIFetcher('file:///srv/simple') assert fetcher._pypi_base == 'file:///srv/simple/' assert fetcher.urls('setuptools') == ['file:///srv/simple/setuptools/'] pex-1.1.14/tests/test_finders.py0000644000076500000240000000712612671105031017412 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pkg_resources from pex.finders import _add_finder as add_finder from pex.finders import _remove_finder as remove_finder from pex.finders import ChainedFinder try: import mock except ImportError: from unittest import mock def test_chained_finder(): def finder1(importer, path_item, only=False): for foo in ('foo', 'bar'): yield foo def finder2(importer, path_item, only=False): yield 'baz' cf = ChainedFinder([finder1]) assert list(cf(None, None)) == ['foo', 'bar'] cf = ChainedFinder([finder1, finder2]) assert list(cf(None, None)) == ['foo', 'bar', 'baz'] GET_FINDER = 'pex.finders._get_finder' REGISTER_FINDER = 'pex.finders.pkg_resources.register_finder' def test_add_new_finder(): with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = None add_finder('foo', 'bar') mock_register_finder.assert_called_with('foo', 'bar') def test_append_finder(): with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = 'bar' add_finder('foo', 'baz') mock_register_finder.assert_called_with('foo', ChainedFinder(['bar', 'baz'])) with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = ChainedFinder(['bar']) add_finder('foo', 'baz') mock_register_finder.assert_called_with('foo', ChainedFinder(['bar', 'baz'])) def test_remove_finder(): # wasn't registered with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = None remove_finder('foo', 'baz') assert not mock_register_finder.called # was registered but we're asking for the wrong one with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = ChainedFinder(['bar']) remove_finder('foo', 'baz') assert not mock_register_finder.called # was registered but we're asking for the wrong one with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: cf = ChainedFinder(['bar', 'baz', 'bak']) mock_get_finder.return_value = cf remove_finder('foo', 'baz') assert cf.finders == ['bar', 'bak'] assert not mock_register_finder.called # was registered but we're asking for the wrong one with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: cf = ChainedFinder(['bar', 'baz']) mock_get_finder.return_value = cf remove_finder('foo', 'baz') mock_register_finder.assert_called_with('foo', 'bar') # was registered but we're asking for the wrong one with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = 'bar' remove_finder('foo', 'bar') mock_register_finder.assert_called_with('foo', pkg_resources.find_nothing) # was registered but we're asking for the wrong one with mock.patch(GET_FINDER) as mock_get_finder: with mock.patch(REGISTER_FINDER) as mock_register_finder: mock_get_finder.return_value = ChainedFinder(['bar']) remove_finder('foo', 'bar') mock_register_finder.assert_called_with('foo', pkg_resources.find_nothing) pex-1.1.14/tests/test_http.py0000644000076500000240000001472612670614434016756 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import hashlib from contextlib import contextmanager from io import BytesIO import pytest from pex.compatibility import PY2 from pex.http import Context, RequestsContext, StreamFilelike, UrllibContext from pex.link import Link from pex.util import named_temporary_file from pex.variables import Variables try: from unittest import mock except ImportError: import mock try: from responses import RequestsMock except ImportError: RequestsMock = None try: import requests except ImportError: requests = None BLOB = b'random blob of data' NO_REQUESTS = 'RequestsMock is None or requests is None' try: from httplib import HTTPMessage except ImportError: from http.client import HTTPMessage def make_md5(blob): md5 = hashlib.md5() md5.update(blob) return md5.hexdigest() @contextmanager def patch_requests(): requests_mock = RequestsMock() requests_mock.start() yield requests_mock requests_mock.stop() @contextmanager def make_url(blob, md5_fragment=None): url = 'http://pypi.python.org/foo.tar.gz' if md5_fragment: url += '#md5=%s' % md5_fragment with patch_requests() as responses: responses.add( responses.GET, url, status=200, body=blob, content_type='application/x-compressed') yield url @pytest.mark.skipif(NO_REQUESTS) def test_stream_filelike_with_correct_md5(): with make_url(BLOB, make_md5(BLOB)) as url: request = requests.get(url) filelike = StreamFilelike(request, Link.wrap(url)) assert filelike.read() == BLOB @pytest.mark.skipif(NO_REQUESTS) def test_stream_filelike_with_incorrect_md5(): with make_url(BLOB, 'f' * 32) as url: request = requests.get(url) filelike = StreamFilelike(request, Link.wrap(url)) with pytest.raises(Context.Error): filelike.read() @pytest.mark.skipif(NO_REQUESTS) def test_stream_filelike_without_md5(): with make_url(BLOB) as url: request = requests.get(url) filelike = StreamFilelike(request, Link.wrap(url)) assert filelike.read() == BLOB @pytest.mark.skipif(NO_REQUESTS) def test_requests_context(): context = RequestsContext(verify=False) with make_url(BLOB, make_md5(BLOB)) as url: assert context.read(Link.wrap(url)) == BLOB with make_url(BLOB, make_md5(BLOB)) as url: filename = context.fetch(Link.wrap(url)) with open(filename, 'rb') as fp: assert fp.read() == BLOB # test local reading with named_temporary_file() as tf: tf.write(b'goop') tf.flush() assert context.read(Link.wrap(tf.name)) == b'goop' class MockHttpLibResponse(BytesIO): def __init__(self, data): BytesIO.__init__(self, data) self.status = 200 self.version = 'HTTP/1.1' self.reason = 'OK' if PY2: self.msg = HTTPMessage(BytesIO('Content-Type: application/x-compressed\r\n')) else: self.msg = HTTPMessage() self.msg.add_header('Content-Type', 'application/x-compressed') def getheaders(self): return list(self.msg.items()) def isclosed(self): return self.closed @pytest.mark.skipif(NO_REQUESTS) def test_requests_context_invalid_retries(): env = Variables(environ={'PEX_HTTP_RETRIES': '-1'}) with pytest.raises(ValueError): RequestsContext(verify=False, env=env) @pytest.mark.skipif(NO_REQUESTS) def test_requests_context_retries_from_environment(): retry_count = '42' env = Variables({'PEX_HTTP_RETRIES': retry_count}) assert RequestsContext(verify=False, env=env)._max_retries == int(retry_count) def timeout_side_effect(timeout_error=None, num_timeouts=1): timeout_error = timeout_error or requests.packages.urllib3.exceptions.ConnectTimeoutError url = 'http://pypi.python.org/foo.tar.gz' num_requests = [0] # hack, because python closures? def timeout(*args, **kwargs): if num_requests[0] < num_timeouts: num_requests[0] += 1 raise timeout_error(None, url, 'Time Out') else: return MockHttpLibResponse(BLOB) return url, timeout @pytest.mark.skipif(NO_REQUESTS) def test_requests_context_retries_connect_timeout(): with mock.patch.object( requests.packages.urllib3.connectionpool.HTTPConnectionPool, '_make_request') as mock_make_request: url, mock_make_request.side_effect = timeout_side_effect() context = RequestsContext(verify=False) data = context.read(Link.wrap(url)) assert data == BLOB @pytest.mark.skipif(NO_REQUESTS) def test_requests_context_retries_connect_timeout_retries_exhausted(): with mock.patch.object( requests.packages.urllib3.connectionpool.HTTPConnectionPool, '_make_request') as mock_make_request: url, mock_make_request.side_effect = timeout_side_effect(num_timeouts=3) env = Variables(environ={'PEX_HTTP_RETRIES': '2'}) context = RequestsContext(verify=False, env=env) with pytest.raises(Context.Error): context.read(Link.wrap(url)) @pytest.mark.skipif(NO_REQUESTS) def test_requests_context_retries_read_timeout(): with mock.patch.object( requests.packages.urllib3.connectionpool.HTTPConnectionPool, '_make_request') as mock_make_request: url, mock_make_request.side_effect = timeout_side_effect( timeout_error=requests.packages.urllib3.exceptions.ReadTimeoutError) context = RequestsContext(verify=False) data = context.read(Link.wrap(url)) assert data == BLOB @pytest.mark.skipif(NO_REQUESTS) def test_requests_context_retries_read_timeout_retries_exhausted(): with mock.patch.object( requests.packages.urllib3.connectionpool.HTTPConnectionPool, '_make_request') as mock_make_request: url, mock_make_request.side_effect = timeout_side_effect( timeout_error=requests.packages.urllib3.exceptions.ReadTimeoutError, num_timeouts=3) env = Variables(environ={'PEX_HTTP_RETRIES': '2'}) context = RequestsContext(verify=False, env=env) with pytest.raises(Context.Error): context.read(Link.wrap(url)) def test_urllib_context_utf8_encoding(): BYTES = b'this is a decoded utf8 string' with named_temporary_file() as tf: tf.write(BYTES) tf.flush() local_link = Link.wrap(tf.name) # Trick UrllibContext into thinking this is a remote link class MockUrllibContext(UrllibContext): def open(self, link): return super(MockUrllibContext, self).open(local_link) context = MockUrllibContext() assert context.content(Link.wrap('http://www.google.com')) == BYTES.decode( UrllibContext.DEFAULT_ENCODING) pex-1.1.14/tests/test_inherits_path_option.py0000644000076500000240000000305112743540264022215 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from contextlib import contextmanager from twitter.common.contextutil import environment_as, temporary_dir from pex.pex_builder import PEXBuilder from pex.testing import run_simple_pex @contextmanager def write_and_run_simple_pex(inheriting=False): """Write a pex file that contains an executable entry point :param inheriting: whether this pex should inherit site-packages paths :type inheriting: bool """ with temporary_dir() as td: pex_path = os.path.join(td, 'show_path.pex') with open(os.path.join(td, 'exe.py'), 'w') as fp: fp.write('') # No contents, we just want the startup messages pb = PEXBuilder(path=td, preamble=None) pb.info.inherit_path = inheriting pb.set_executable(os.path.join(td, 'exe.py')) pb.freeze() pb.build(pex_path) with environment_as(PEX_VERBOSE='1'): yield run_simple_pex(pex_path)[0] def test_inherits_path_option(): with write_and_run_simple_pex(inheriting=True) as so: assert 'Scrubbing from user site' not in str(so), 'User packages should not be scrubbed.' assert 'Scrubbing from site-packages' not in str(so), 'Site packages should not be scrubbed.' def test_does_not_inherit_path_option(): with write_and_run_simple_pex(inheriting=False) as so: assert 'Scrubbing from user site' in str(so), 'User packages should be scrubbed.' assert 'Scrubbing from site-packages' in str(so), 'Site packages should be scrubbed.' pex-1.1.14/tests/test_integration.py0000644000076500000240000001205212741504142020301 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import sys from textwrap import dedent import pytest from twitter.common.contextutil import environment_as, temporary_dir from pex.compatibility import WINDOWS from pex.installer import EggInstaller from pex.testing import run_pex_command, run_simple_pex, run_simple_pex_test, temporary_content from pex.util import DistributionHelper, named_temporary_file def test_pex_execute(): body = "print('Hello')" _, rc = run_simple_pex_test(body, coverage=True) assert rc == 0 def test_pex_raise(): body = "raise Exception('This will improve coverage.')" run_simple_pex_test(body, coverage=True) def test_pex_root(): with temporary_dir() as tmp_home: with environment_as(HOME=tmp_home): with temporary_dir() as td: with temporary_dir() as output_dir: env = os.environ.copy() env['PEX_INTERPRETER'] = '1' output_path = os.path.join(output_dir, 'pex.pex') args = ['pex', '-o', output_path, '--not-zip-safe', '--pex-root={0}'.format(td)] results = run_pex_command(args=args, env=env) results.assert_success() assert ['pex.pex'] == os.listdir(output_dir), 'Expected built pex file.' assert [] == os.listdir(tmp_home), 'Expected empty temp home dir.' assert 'build' in os.listdir(td), 'Expected build directory in tmp pex root.' def test_cache_disable(): with temporary_dir() as tmp_home: with environment_as(HOME=tmp_home): with temporary_dir() as td: with temporary_dir() as output_dir: env = os.environ.copy() env['PEX_INTERPRETER'] = '1' output_path = os.path.join(output_dir, 'pex.pex') args = [ 'pex', '-o', output_path, '--not-zip-safe', '--disable-cache', '--pex-root={0}'.format(td), ] results = run_pex_command(args=args, env=env) results.assert_success() assert ['pex.pex'] == os.listdir(output_dir), 'Expected built pex file.' assert [] == os.listdir(tmp_home), 'Expected empty temp home dir.' def test_pex_interpreter(): with named_temporary_file() as fp: fp.write(b"print('Hello world')") fp.flush() env = os.environ.copy() env['PEX_INTERPRETER'] = '1' so, rc = run_simple_pex_test("", args=(fp.name,), coverage=True, env=env) assert so == b'Hello world\n' assert rc == 0 def test_pex_repl_cli(): """Tests the REPL in the context of the pex cli itself.""" stdin_payload = b'import sys; sys.exit(3)' with temporary_dir() as output_dir: # Create a temporary pex containing just `requests` with no entrypoint. pex_path = os.path.join(output_dir, 'pex.pex') results = run_pex_command(['--disable-cache', 'wheel', 'requests', './', '-e', 'pex.bin.pex:main', '-o', pex_path]) results.assert_success() # Test that the REPL is functional. stdout, rc = run_simple_pex(pex_path, stdin=stdin_payload) assert rc == 3 assert b'>>>' in stdout def test_pex_repl_built(): """Tests the REPL in the context of a built pex.""" stdin_payload = b'import requests; import sys; sys.exit(3)' with temporary_dir() as output_dir: # Create a temporary pex containing just `requests` with no entrypoint. pex_path = os.path.join(output_dir, 'requests.pex') results = run_pex_command(['--disable-cache', 'requests', '-o', pex_path]) results.assert_success() # Test that the REPL is functional. stdout, rc = run_simple_pex(pex_path, stdin=stdin_payload) assert rc == 3 assert b'>>>' in stdout @pytest.mark.skipif(WINDOWS, reason='No symlinks on windows') def test_pex_python_symlink(): with temporary_dir() as td: with environment_as(HOME=td): symlink_path = os.path.join(td, 'python-symlink') os.symlink(sys.executable, symlink_path) pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pexrc.write("PEX_PYTHON=%s" % symlink_path) body = "print('Hello')" _, rc = run_simple_pex_test(body, coverage=True) assert rc == 0 def test_entry_point_exit_code(): setup_py = dedent(""" from setuptools import setup setup( name='my_app', version='0.0.0', zip_safe=True, packages=[''], entry_points={'console_scripts': ['my_app = my_app:do_something']}, ) """) error_msg = 'setuptools expects this to exit non-zero' my_app = dedent(""" def do_something(): return '%s' """ % error_msg) with temporary_content({'setup.py': setup_py, 'my_app.py': my_app}) as project_dir: installer = EggInstaller(project_dir) dist = DistributionHelper.distribution_from_path(installer.bdist()) so, rc = run_simple_pex_test('', env={'PEX_SCRIPT': 'my_app'}, dists=[dist]) assert so.decode('utf-8').strip() == error_msg assert rc == 1 pex-1.1.14/tests/test_interpreter.py0000644000076500000240000000114012623452313020316 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import pytest from pex import interpreter try: from mock import patch except ImportError: from unittest.mock import patch class TestPythonInterpreter(object): @pytest.mark.skipif('sys.version_info >= (3,0)') def test_all_does_not_raise_with_empty_path_envvar(self): """ additionally, tests that the module does not raise at import """ with patch.dict(os.environ, clear=True): reload(interpreter) interpreter.PythonInterpreter.all() pex-1.1.14/tests/test_iterator.py0000644000076500000240000000250312623452313017610 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from pkg_resources import Requirement from pex.crawler import Crawler from pex.fetcher import PyPIFetcher from pex.iterator import Iterator from pex.package import SourcePackage try: from unittest import mock except ImportError: import mock def test_empty_iteration(): crawler_mock = mock.create_autospec(Crawler, spec_set=True) crawler_mock.crawl.return_value = [] iterator = Iterator(crawler=crawler_mock) assert list(iterator.iter(Requirement.parse('foo'))) == [] assert len(crawler_mock.crawl.mock_calls) == 1 _, args, kwargs = crawler_mock.crawl.mock_calls[0] assert list(args[0]) == list(PyPIFetcher().urls(Requirement.parse('foo'))) assert kwargs == {'follow_links': False} def test_iteration_with_return(): pex_url = 'https://pypi.python.org/packages/source/p/pex/pex-0.8.6.tar.gz' crawler_mock = mock.create_autospec(Crawler, spec_set=True) crawler_mock.crawl.return_value = [pex_url] iterator = Iterator(crawler=crawler_mock, follow_links=True) assert list(iterator.iter(Requirement.parse('pex'))) == [SourcePackage(pex_url)] assert len(crawler_mock.crawl.mock_calls) == 1 _, _, kwargs = crawler_mock.crawl.mock_calls[0] assert kwargs == {'follow_links': True} pex-1.1.14/tests/test_link.py0000644000076500000240000000360612670614434016727 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import pytest from pex.link import Link def test_link_wrapping(): link = Link.wrap('https://www.google.com') assert link.url == 'https://www.google.com' link = Link.wrap(Link.wrap('https://www.google.com')) assert link.url == 'https://www.google.com' with pytest.raises(ValueError): Link.wrap(1234) with pytest.raises(ValueError): Link.wrap_iterable(1234) links = Link.wrap_iterable('https://www.google.com') assert len(links) == 1 assert links[0].url == 'https://www.google.com' links = Link.wrap_iterable(['https://www.google.com', Link('http://www.google.com')]) assert set(links) == set([ Link('http://www.google.com'), Link('https://www.google.com'), ]) def test_link_join(): link = Link('https://www.google.com/bar/') assert link.join('/foo').url == 'https://www.google.com/foo' assert link.join('#foo').url == 'https://www.google.com/bar/#foo' assert link.join('foo').url == 'https://www.google.com/bar/foo' def test_link_schemes(): link = Link('http://www.google.com') assert link.scheme == 'http' assert link.remote link = Link('https://www.google.com') assert link.scheme == 'https' assert link.remote link = Link('/foo/bar') assert link.scheme == 'file' assert link.local assert link.local_path == os.path.realpath('/foo/bar') def test_link_escaping(): link = Link('/foo/bar#baz.pex') assert link.scheme == 'file' assert link.local assert link.local_path == os.path.realpath('/foo/bar#baz.pex') link = Link('http://www.google.com/%20/%3Afile+%2B2.tar.gz') assert link.filename == ':file++2.tar.gz' def test_link_equality(): assert Link('http://www.google.com') == Link('http://www.google.com') assert Link('http://www.google.com') != Link('http://www.twitter.com') pex-1.1.14/tests/test_package.py0000644000076500000240000000465512720650765017375 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pytest from pkg_resources import Requirement, parse_version from pex.package import EggPackage, SourcePackage def test_source_packages(): for ext in ('.tar.gz', '.tar', '.tgz', '.zip', '.tar.bz2'): sl = SourcePackage('a_p_r-3.1.3' + ext) assert sl._name == 'a_p_r' assert sl.name == 'a-p-r' assert sl.raw_version == '3.1.3' assert sl.version == parse_version(sl.raw_version) for req in ('a_p_r', 'a_p_r>2', 'a_p_r>3', 'a_p_r>=3.1.3', 'a_p_r==3.1.3', 'a_p_r>3,<3.5'): assert sl.satisfies(req) assert sl.satisfies(Requirement.parse(req)) for req in ('foo', 'a_p_r==4.0.0', 'a_p_r>4.0.0', 'a_p_r>3.0.0,<3.0.3', 'a==3.1.3'): assert not sl.satisfies(req) sl = SourcePackage('python-dateutil-1.5.tar.gz') assert sl.name == 'python-dateutil' assert sl.raw_version == '1.5' def test_local_specifier(): for ext in ('.tar.gz', '.tar', '.tgz', '.zip', '.tar.bz2'): sl = SourcePackage('a_p_r-3.1.3+pexed.1' + ext) assert sl.name == 'a-p-r' assert sl.raw_version == '3.1.3+pexed.1' assert sl.version == parse_version(sl.raw_version) assert sl.satisfies('a_p_r==3.1.3+pexed.1') def test_egg_packages(): el = EggPackage('psutil-0.4.1-py2.6-macosx-10.7-intel.egg') assert el.name == 'psutil' assert el.raw_version == '0.4.1' assert el.py_version == '2.6' assert el.platform == 'macosx-10.7-intel' for req in ('psutil', 'psutil>0.4', 'psutil==0.4.1', 'psutil>0.4.0,<0.4.2'): assert el.satisfies(req) for req in ('foo', 'bar==0.4.1'): assert not el.satisfies(req) # Legacy pkg_resources normalized version numbers. el = EggPackage('pyfoo-1.0.0_bar-py2.7-linux-x86_64.egg') assert el.name == 'pyfoo' assert el.raw_version == '1.0.0-bar' assert el.py_version == '2.7' assert el.platform == 'linux-x86_64' for req in ('pyfoo', 'pyfoo==1.0.0-bar'): assert el.satisfies(req) el = EggPackage('pytz-2012b-py2.6.egg') assert el.name == 'pytz' assert el.raw_version == '2012b0' assert el.py_version == '2.6' assert el.platform is None # Eggs must have their own version and a python version. with pytest.raises(EggPackage.InvalidPackage): EggPackage('bar.egg') with pytest.raises(EggPackage.InvalidPackage): EggPackage('bar-1.egg') with pytest.raises(EggPackage.InvalidPackage): EggPackage('bar-py2.6.egg') pex-1.1.14/tests/test_pep425.py0000644000076500000240000000400212670614434017000 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pytest from pex.interpreter import PythonIdentity from pex.pep425 import PEP425, PEP425Extras def test_platform_iterator(): # non macosx assert list(PEP425Extras.platform_iterator('blah')) == ['blah'] assert list(PEP425Extras.platform_iterator('linux_x86_64')) == ['linux_x86_64'] # macosx assert set(PEP425Extras.platform_iterator('macosx_10_4_x86_64')) == set([ 'macosx_10_4_x86_64', 'macosx_10_3_x86_64', 'macosx_10_2_x86_64', 'macosx_10_1_x86_64', 'macosx_10_0_x86_64', ]) assert set(PEP425Extras.platform_iterator('macosx_10_0_universal')) == set([ 'macosx_10_0_i386', 'macosx_10_0_ppc', 'macosx_10_0_ppc64', 'macosx_10_0_x86_64', 'macosx_10_0_universal', ]) with pytest.raises(ValueError): list(PEP425Extras.platform_iterator('macosx_10')) with pytest.raises(ValueError): list(PEP425Extras.platform_iterator('macosx_10_0')) with pytest.raises(ValueError): list(PEP425Extras.platform_iterator('macosx_9_x86_64')) def test_iter_supported_tags(): identity = PythonIdentity('CPython', 2, 6, 5) platform = 'linux-x86_64' def iter_solutions(): for interp in ('cp', 'py'): for interp_suffix in ('2', '20', '21', '22', '23', '24', '25', '26'): for platform in ('linux_x86_64', 'any'): abis = ['none'] if interp == 'cp' and interp_suffix == '26' and platform == 'linux_x86_64': abis.extend([ 'cp%s' % interp_suffix, 'cp%sdmu' % interp_suffix, 'cp%sdm' % interp_suffix, 'cp%sdu' % interp_suffix, 'cp%sd' % interp_suffix, 'cp%smu' % interp_suffix, 'cp%sm' % interp_suffix, 'cp%su' % interp_suffix ]) for abi in abis: yield (interp + interp_suffix, abi, platform) assert set(PEP425.iter_supported_tags(identity, platform)) == set(iter_solutions()) pex-1.1.14/tests/test_pex.py0000644000076500000240000001471112742231260016555 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import sys import textwrap from types import ModuleType import pytest from pex.compatibility import WINDOWS, nested, to_bytes from pex.installer import EggInstaller, WheelInstaller from pex.pex import PEX from pex.testing import ( make_installer, named_temporary_file, run_simple_pex_test, temporary_dir, write_simple_pex ) from pex.util import DistributionHelper try: from unittest import mock except ImportError: import mock @pytest.mark.skipif('sys.version_info > (3,)') def test_pex_uncaught_exceptions(): body = "raise Exception('This is an exception')" so, rc = run_simple_pex_test(body) assert b'This is an exception' in so, 'Standard out was: %s' % so assert rc == 1 def test_excepthook_honored(): body = textwrap.dedent(""" import sys def excepthook(ex_type, ex, tb): print('Custom hook called with: {0}'.format(ex)) sys.exit(42) sys.excepthook = excepthook raise Exception('This is an exception') """) so, rc = run_simple_pex_test(body) assert so == b'Custom hook called with: This is an exception\n', 'Standard out was: %s' % so assert rc == 42 def _test_sys_exit(arg, expected_output, expected_rc): body = "import sys; sys.exit({arg})".format(arg=arg) so, rc = run_simple_pex_test(body) assert so == expected_output, 'Should not print SystemExit traceback.' assert rc == expected_rc def test_pex_sys_exit_does_not_print_for_numeric_value(): _test_sys_exit(2, b'', 2) def test_pex_sys_exit_prints_non_numeric_value_no_traceback(): text = 'something went wrong' sys_exit_arg = '"' + text + '"' # encode the string somehow that's compatible with 2 and 3 expected_output = to_bytes(text) + b'\n' _test_sys_exit(sys_exit_arg, expected_output, 1) def test_pex_sys_exit_doesnt_print_none(): _test_sys_exit('', to_bytes(''), 0) def test_pex_sys_exit_prints_objects(): _test_sys_exit('Exception("derp")', to_bytes('derp\n'), 1) @pytest.mark.skipif('hasattr(sys, "pypy_version_info")') def test_pex_atexit_swallowing(): body = textwrap.dedent(""" import atexit def raise_on_exit(): raise Exception('This is an exception') atexit.register(raise_on_exit) """) so, rc = run_simple_pex_test(body) assert so == b'' assert rc == 0 env_copy = os.environ.copy() env_copy.update(PEX_TEARDOWN_VERBOSE='1') so, rc = run_simple_pex_test(body, env=env_copy) assert b'This is an exception' in so assert rc == 0 def test_minimum_sys_modules(): # builtins stay builtin_module = ModuleType('my_builtin') modules = {'my_builtin': builtin_module} new_modules = PEX.minimum_sys_modules([], modules) assert new_modules == modules new_modules = PEX.minimum_sys_modules(['bad_path'], modules) assert new_modules == modules # tainted evict tainted_module = ModuleType('tainted_module') tainted_module.__path__ = ['bad_path'] modules = {'tainted_module': tainted_module} new_modules = PEX.minimum_sys_modules([], modules) assert new_modules == modules new_modules = PEX.minimum_sys_modules(['bad_path'], modules) assert new_modules == {} assert tainted_module.__path__ == [] # tainted cleaned tainted_module = ModuleType('tainted_module') tainted_module.__path__ = ['bad_path', 'good_path'] modules = {'tainted_module': tainted_module} new_modules = PEX.minimum_sys_modules([], modules) assert new_modules == modules new_modules = PEX.minimum_sys_modules(['bad_path'], modules) assert new_modules == modules assert tainted_module.__path__ == ['good_path'] def test_site_libs(): with nested(mock.patch.object(PEX, '_get_site_packages'), temporary_dir()) as ( mock_site_packages, tempdir): site_packages = os.path.join(tempdir, 'site-packages') os.mkdir(site_packages) mock_site_packages.return_value = set([site_packages]) site_libs = PEX.site_libs() assert site_packages in site_libs @pytest.mark.skipif(WINDOWS, reason='No symlinks on windows') def test_site_libs_symlink(): with nested(mock.patch.object(PEX, '_get_site_packages'), temporary_dir()) as ( mock_site_packages, tempdir): site_packages = os.path.join(tempdir, 'site-packages') os.mkdir(site_packages) site_packages_link = os.path.join(tempdir, 'site-packages-link') os.symlink(site_packages, site_packages_link) mock_site_packages.return_value = set([site_packages_link]) site_libs = PEX.site_libs() assert os.path.realpath(site_packages) in site_libs assert site_packages_link in site_libs def test_site_libs_excludes_prefix(): """Windows returns sys.prefix as part of getsitepackages(). Make sure to exclude it.""" with nested(mock.patch.object(PEX, '_get_site_packages'), temporary_dir()) as ( mock_site_packages, tempdir): site_packages = os.path.join(tempdir, 'site-packages') os.mkdir(site_packages) mock_site_packages.return_value = set([site_packages, sys.prefix]) site_libs = PEX.site_libs() assert site_packages in site_libs assert sys.prefix not in site_libs @pytest.mark.parametrize('zip_safe', (False, True)) @pytest.mark.parametrize('project_name', ('my_project', 'my-project')) @pytest.mark.parametrize('installer_impl', (EggInstaller, WheelInstaller)) def test_pex_script(installer_impl, project_name, zip_safe): kw = dict(name=project_name, installer_impl=installer_impl, zip_safe=zip_safe) with make_installer(**kw) as installer: bdist = DistributionHelper.distribution_from_path(installer.bdist()) env_copy = os.environ.copy() env_copy['PEX_SCRIPT'] = 'hello_world' so, rc = run_simple_pex_test('', env=env_copy) assert rc == 1, so.decode('utf-8') assert b'Could not find script hello_world' in so so, rc = run_simple_pex_test('', env=env_copy, dists=[bdist]) assert rc == 0, so.decode('utf-8') assert b'hello world' in so env_copy['PEX_SCRIPT'] = 'shell_script' so, rc = run_simple_pex_test('', env=env_copy, dists=[bdist]) assert rc == 1, so.decode('utf-8') assert b'Unable to parse' in so def test_pex_run(): with named_temporary_file() as fake_stdout: with temporary_dir() as temp_dir: pex = write_simple_pex( temp_dir, 'import sys; sys.stdout.write("hello"); sys.stderr.write("hello"); sys.exit(0)' ) rc = PEX(pex.path()).run(stdin=None, stdout=fake_stdout, stderr=fake_stdout) assert rc == 0 fake_stdout.seek(0) assert fake_stdout.read() == b'hellohello' pex-1.1.14/tests/test_pex_binary.py0000644000076500000240000000557612623452313020134 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from contextlib import contextmanager from optparse import OptionParser from pex.bin.pex import configure_clp, configure_clp_pex_resolution from pex.fetcher import PyPIFetcher from pex.package import SourcePackage, WheelPackage from pex.resolver_options import ResolverOptionsBuilder from pex.sorter import Sorter @contextmanager def parser_pair(): builder = ResolverOptionsBuilder() parser = OptionParser() yield builder, parser def test_clp_no_pypi_option(): with parser_pair() as (builder, parser): configure_clp_pex_resolution(parser, builder) assert len(builder._fetchers) == 1 options, _ = parser.parse_args(args=['--no-pypi']) assert len(builder._fetchers) == 0, '--no-pypi should remove fetchers.' assert options.repos == builder._fetchers def test_clp_pypi_option_duplicate(): with parser_pair() as (builder, parser): configure_clp_pex_resolution(parser, builder) assert len(builder._fetchers) == 1 options, _ = parser.parse_args(args=['--pypi']) assert len(builder._fetchers) == 1 assert options.repos == builder._fetchers # TODO(wickman) We should probably add fetchers in order. def test_clp_repo_option(): with parser_pair() as (builder, parser): configure_clp_pex_resolution(parser, builder) assert len(builder._fetchers) == 1 options, _ = parser.parse_args(args=['-f', 'http://www.example.com']) assert len(builder._fetchers) == 2 assert builder._fetchers == options.repos def test_clp_index_option(): with parser_pair() as (builder, parser): configure_clp_pex_resolution(parser, builder) assert len(builder._fetchers) == 1 options, _ = parser.parse_args(args=['-i', 'http://www.example.com']) assert len(builder._fetchers) == 2 assert builder._fetchers == options.repos assert builder._fetchers[1] == PyPIFetcher('http://www.example.com') def test_clp_build_precedence(): with parser_pair() as (builder, parser): configure_clp_pex_resolution(parser, builder) assert builder._precedence == Sorter.DEFAULT_PACKAGE_PRECEDENCE parser.parse_args(args=['--no-build']) assert SourcePackage not in builder._precedence parser.parse_args(args=['--build']) assert SourcePackage in builder._precedence options, _ = parser.parse_args(args=['--no-wheel']) assert WheelPackage not in builder._precedence assert not options.use_wheel options, _ = parser.parse_args(args=['--wheel']) assert WheelPackage in builder._precedence assert options.use_wheel # Make sure that we're doing append and not replace def test_clp_requirements_txt(): parser, builder = configure_clp() options, _ = parser.parse_args(args='-r requirements1.txt -r requirements2.txt'.split()) assert options.requirement_files == ['requirements1.txt', 'requirements2.txt'] pex-1.1.14/tests/test_pex_bootstrapper.py0000644000076500000240000000147612623452313021367 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import zipfile from contextlib import closing from twitter.common.contextutil import temporary_dir from pex.pex_bootstrapper import get_pex_info from pex.testing import write_simple_pex def test_get_pex_info(): with temporary_dir() as td: pb = write_simple_pex(td, 'print("hello world!")') pex_path = os.path.join(td, 'hello_world.pex') pb.build(pex_path) # from zip pex_info = get_pex_info(pex_path) with temporary_dir() as pex_td: with closing(zipfile.ZipFile(pex_path, 'r')) as zf: zf.extractall(pex_td) # from dir pex_info_2 = get_pex_info(pex_td) # same when encoded assert pex_info.dump() == pex_info_2.dump() pex-1.1.14/tests/test_pex_builder.py0000644000076500000240000001004112720650765020266 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import stat import zipfile from contextlib import closing import pytest from twitter.common.contextutil import temporary_dir from twitter.common.dirutil import safe_mkdir from pex.compatibility import WINDOWS, nested from pex.pex import PEX from pex.pex_builder import PEXBuilder from pex.testing import write_simple_pex as write_pex from pex.testing import make_bdist from pex.util import DistributionHelper exe_main = """ import sys from my_package.my_module import do_something do_something() with open(sys.argv[1], 'w') as fp: fp.write('success') """ def test_pex_builder(): # test w/ and w/o zipfile dists with nested(temporary_dir(), make_bdist('p1', zipped=True)) as (td, p1): write_pex(td, exe_main, dists=[p1]) success_txt = os.path.join(td, 'success.txt') PEX(td).run(args=[success_txt]) assert os.path.exists(success_txt) with open(success_txt) as fp: assert fp.read() == 'success' # test w/ and w/o zipfile dists with nested(temporary_dir(), temporary_dir(), make_bdist('p1', zipped=True)) as ( td1, td2, p1): target_egg_dir = os.path.join(td2, os.path.basename(p1.location)) safe_mkdir(target_egg_dir) with closing(zipfile.ZipFile(p1.location, 'r')) as zf: zf.extractall(target_egg_dir) p1 = DistributionHelper.distribution_from_path(target_egg_dir) write_pex(td1, exe_main, dists=[p1]) success_txt = os.path.join(td1, 'success.txt') PEX(td1).run(args=[success_txt]) assert os.path.exists(success_txt) with open(success_txt) as fp: assert fp.read() == 'success' def test_pex_builder_shebang(): def builder(shebang): pb = PEXBuilder() pb.set_shebang(shebang) return pb for pb in builder('foobar'), builder('#!foobar'): for b in pb, pb.clone(): with temporary_dir() as td: target = os.path.join(td, 'foo.pex') b.build(target) expected_preamble = b'#!foobar\n' with open(target, 'rb') as fp: assert fp.read(len(expected_preamble)) == expected_preamble def test_pex_builder_compilation(): with nested(temporary_dir(), temporary_dir(), temporary_dir()) as (td1, td2, td3): src = os.path.join(td1, 'src.py') with open(src, 'w') as fp: fp.write(exe_main) exe = os.path.join(td1, 'exe.py') with open(exe, 'w') as fp: fp.write(exe_main) def build_and_check(path, precompile): pb = PEXBuilder(path) pb.add_source(src, 'lib/src.py') pb.set_executable(exe, 'exe.py') pb.freeze(bytecode_compile=precompile) for pyc_file in ('exe.pyc', 'lib/src.pyc', '__main__.pyc'): pyc_exists = os.path.exists(os.path.join(path, pyc_file)) if precompile: assert pyc_exists else: assert not pyc_exists bootstrap_dir = os.path.join(path, PEXBuilder.BOOTSTRAP_DIR) bootstrap_pycs = [] for _, _, files in os.walk(bootstrap_dir): bootstrap_pycs.extend(f for f in files if f.endswith('.pyc')) if precompile: assert len(bootstrap_pycs) > 0 else: assert 0 == len(bootstrap_pycs) build_and_check(td2, False) build_and_check(td3, True) @pytest.mark.skipif(WINDOWS, reason='No hardlinks on windows') def test_pex_builder_copy_or_link(): with nested(temporary_dir(), temporary_dir(), temporary_dir()) as (td1, td2, td3): src = os.path.join(td1, 'exe.py') with open(src, 'w') as fp: fp.write(exe_main) def build_and_check(path, copy): pb = PEXBuilder(path, copy=copy) pb.add_source(src, 'exe.py') path_clone = os.path.join(path, '__clone') pb.clone(into=path_clone) for root in path, path_clone: s1 = os.stat(src) s2 = os.stat(os.path.join(root, 'exe.py')) is_link = (s1[stat.ST_INO], s1[stat.ST_DEV]) == (s2[stat.ST_INO], s2[stat.ST_DEV]) if copy: assert not is_link else: assert is_link build_and_check(td2, False) build_and_check(td3, True) pex-1.1.14/tests/test_pex_info.py0000644000076500000240000000433612720650765017605 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os.path import pytest from pex.bin.pex import make_relative_to_root from pex.orderedset import OrderedSet from pex.pex_info import PexInfo from pex.variables import ENV, Variables def make_pex_info(requirements): return PexInfo(info={'requirements': requirements}) def test_backwards_incompatible_pex_info(): # forwards compatibility pi = make_pex_info(['hello']) assert pi.requirements == OrderedSet(['hello']) pi = make_pex_info(['hello==0.1', 'world==0.2']) assert pi.requirements == OrderedSet(['hello==0.1', 'world==0.2']) # malformed with pytest.raises(ValueError): make_pex_info('hello') with pytest.raises(ValueError): make_pex_info([('hello', False)]) # backwards compatibility pi = make_pex_info([ ['hello==0.1', False, None], ['world==0.2', False, None], ]) assert pi.requirements == OrderedSet(['hello==0.1', 'world==0.2']) def assert_same_info(expected, actual): assert expected.dump(sort_keys=True) == actual.dump(sort_keys=True) def test_from_empty_env(): environ = Variables(environ={}) info = {} assert_same_info(PexInfo(info=info), PexInfo.from_env(env=environ)) def test_make_relative(): with ENV.patch(PEX_ROOT='/pex_root'): assert '/pex_root/interpreters' == make_relative_to_root('{pex_root}/interpreters') #Verify the user can specify arbitrary absolute paths. assert '/tmp/interpreters' == make_relative_to_root('/tmp/interpreters') def test_from_env(): pex_root = os.path.realpath('/pex_root') environ = dict(PEX_ROOT=pex_root, PEX_MODULE='entry:point', PEX_SCRIPT='script.sh', PEX_FORCE_LOCAL='true', PEX_INHERIT_PATH='true', PEX_IGNORE_ERRORS='true', PEX_ALWAYS_CACHE='true') info = dict(pex_root=pex_root, entry_point='entry:point', script='script.sh', zip_safe=False, inherit_path=True, ignore_errors=True, always_write_cache=True) assert_same_info(PexInfo(info=info), PexInfo.from_env(env=Variables(environ=environ))) pex-1.1.14/tests/test_platform.py0000644000076500000240000000446612623452313017615 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pytest from pex.platforms import Platform class TestPlatform(object): def test_pure_python(self): assert Platform.compatible(None, None) assert Platform.compatible(None, 'i386') assert Platform.compatible(None, 'universal') def test_unknown(self): with pytest.raises(Platform.UnknownPlatformError): Platform.compatible('macosx-10.0-morfgorf', 'macosx-10.1-morfgorf') with pytest.raises(Platform.UnknownPlatformError): Platform.compatible('macosx-10.0-x86_64', 'macosx-10.1-morfgorf') with pytest.raises(Platform.UnknownPlatformError): Platform.compatible('macosx-10.0-morfgorf', 'macosx-10.1-x86_64') def test_versioning(self): # Major versions incompatible assert not Platform.compatible('macosx-9.1-x86_64', 'macosx-10.0-x86_64') assert not Platform.compatible('macosx-10.0-x86_64', 'macosx-9.1-x86_64') # Platforms equal assert Platform.compatible('macosx-10.0-x86_64', 'macosx-10.0-x86_64') # Minor versions less than assert Platform.compatible('macosx-10.0-x86_64', 'macosx-10.1-x86_64') assert not Platform.compatible('macosx-10.1-x86_64', 'macosx-10.0-x86_64') assert Platform.compatible('macosx-10.9-x86_64', 'macosx-10.10-x86_64') assert not Platform.compatible('macosx-10.10-x86_64', 'macosx-10.9-x86_64') def test_platform_subsets(self): # Pure platform subset assert Platform.compatible('macosx-10.0-i386', 'macosx-10.0-intel') # Version and platform subset assert Platform.compatible('macosx-10.0-i386', 'macosx-10.1-intel') assert Platform.compatible('macosx-10.0-x86_64', 'macosx-10.1-intel') # Intersecting sets of platform but not pure subset assert Platform.compatible('macosx-10.0-fat', 'macosx-10.1-intel') # Non-intersecting sets of platform assert not Platform.compatible('macosx-10.0-ppc', 'macosx-10.1-intel') # Test our common case assert Platform.compatible('macosx-10.4-x86_64', 'macosx-10.7-intel') def test_cross_platform(self): assert not Platform.compatible('linux-x86_64', 'macosx-10.0-x86_64') # TODO(wickman): Should we do extended platform support beyond OS X? assert not Platform.compatible('linux-i386', 'linux-x86_64') pex-1.1.14/tests/test_requirements.py0000644000076500000240000000671212623452313020510 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os from textwrap import dedent import pytest from pkg_resources import Requirement from twitter.common.contextutil import temporary_dir from pex.requirements import requirements_from_file, requirements_from_lines from pex.resolvable import ResolvableRequirement from pex.resolver_options import ResolverOptionsBuilder def test_from_empty_lines(): reqs = requirements_from_lines([]) assert len(reqs) == 0 reqs = requirements_from_lines(dedent(""" # comment """).splitlines()) assert len(reqs) == 0 @pytest.mark.parametrize('flag_separator', (' ', '=')) def test_line_types(flag_separator): reqs = requirements_from_lines(dedent(""" simple_requirement specific_requirement==2 --allow-external%sspecific_requirement """ % flag_separator).splitlines()) # simple_requirement assert len(reqs) == 2 assert isinstance(reqs[0], ResolvableRequirement) assert reqs[0].requirement == Requirement.parse('simple_requirement') assert not reqs[0].options._allow_external # specific_requirement assert isinstance(reqs[1], ResolvableRequirement) assert reqs[1].requirement == Requirement.parse('specific_requirement==2') assert reqs[1].options._allow_external def test_all_external(): reqs = requirements_from_lines(dedent(""" simple_requirement specific_requirement==2 --allow-all-external """).splitlines()) assert reqs[0].options._allow_external assert reqs[1].options._allow_external def test_index_types(): reqs = requirements_from_lines(dedent(""" simple_requirement --no-index """).splitlines()) assert reqs[0].options._fetchers == [] for prefix in ('-f ', '--find-links ', '--find-links='): reqs = requirements_from_lines(dedent(""" foo --no-index %shttps://example.com/repo """ % prefix).splitlines()) assert len(reqs[0].options._fetchers) == 1 assert reqs[0].options._fetchers[0].urls('foo') == ['https://example.com/repo'] for prefix in ('-i ', '--index-url ', '--index-url=', '--extra-index-url ', '--extra-index-url='): reqs = requirements_from_lines(dedent(""" foo --no-index %shttps://example.com/repo/ """ % prefix).splitlines()) assert len(reqs[0].options._fetchers) == 1, 'Prefix is: %r' % prefix assert reqs[0].options._fetchers[0].urls('foo') == ['https://example.com/repo/foo/'] def test_nested_requirements(): with temporary_dir() as td1: with temporary_dir() as td2: with open(os.path.join(td1, 'requirements.txt'), 'w') as fp: fp.write(dedent(''' requirement1 requirement2 -r %s -r %s ''' % ( os.path.join(td2, 'requirements_nonrelative.txt'), os.path.join('relative', 'requirements_relative.txt')) )) with open(os.path.join(td2, 'requirements_nonrelative.txt'), 'w') as fp: fp.write(dedent(''' requirement3 requirement4 ''')) os.mkdir(os.path.join(td1, 'relative')) with open(os.path.join(td1, 'relative', 'requirements_relative.txt'), 'w') as fp: fp.write(dedent(''' requirement5 requirement6 ''')) def rr(req): return ResolvableRequirement.from_string(req, ResolverOptionsBuilder()) reqs = requirements_from_file(os.path.join(td1, 'requirements.txt')) assert reqs == [rr('requirement%d' % k) for k in (1, 2, 3, 4, 5, 6)] pex-1.1.14/tests/test_resolvable.py0000644000076500000240000000745612623452313020131 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pkg_resources import pytest from pex.iterator import Iterator from pex.package import Package, SourcePackage from pex.resolvable import ( Resolvable, ResolvableDirectory, ResolvablePackage, ResolvableRepository, ResolvableRequirement, resolvables_from_iterable ) from pex.resolver_options import ResolverOptionsBuilder from pex.testing import make_source_dir try: from unittest import mock except ImportError: import mock def test_resolvable_package(): builder = ResolverOptionsBuilder() source_name = 'foo-2.3.4.tar.gz' pkg = SourcePackage.from_href(source_name) resolvable = ResolvablePackage.from_string(source_name, builder) assert resolvable.packages() == [pkg] mock_iterator = mock.create_autospec(Iterator, spec_set=True) mock_iterator.iter.return_value = iter([]) # fetchers are currently unused for static packages. assert resolvable.compatible(mock_iterator) == [] assert mock_iterator.iter.mock_calls == [] assert resolvable.name == 'foo' assert resolvable.exact is True assert resolvable.extras() == [] resolvable = ResolvablePackage.from_string(source_name + '[extra1,extra2]', builder) assert resolvable.extras() == ['extra1', 'extra2'] assert Resolvable.get('foo-2.3.4.tar.gz') == ResolvablePackage.from_string( 'foo-2.3.4.tar.gz', builder) with pytest.raises(ResolvablePackage.InvalidRequirement): ResolvablePackage.from_string('foo', builder) def test_resolvable_repository(): # not yet implemented with pytest.raises(Resolvable.InvalidRequirement): ResolvableRepository.from_string('git+http://github.com/wickman/pex', ResolverOptionsBuilder()) def test_resolvable_requirement(): req = 'foo[bar]==2.3.4' resolvable = ResolvableRequirement.from_string(req, ResolverOptionsBuilder(fetchers=[])) assert resolvable.requirement == pkg_resources.Requirement.parse('foo[bar]==2.3.4') assert resolvable.name == 'foo' assert resolvable.exact is True assert resolvable.extras() == ['bar'] assert resolvable.options._fetchers == [] assert resolvable.packages() == [] source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') mock_iterator = mock.create_autospec(Iterator, spec_set=True) mock_iterator.iter.return_value = iter([source_pkg]) assert resolvable.compatible(mock_iterator) == [source_pkg] assert mock_iterator.iter.mock_calls == [ mock.call(pkg_resources.Requirement.parse('foo[bar]==2.3.4'))] # test non-exact resolvable = ResolvableRequirement.from_string('foo', ResolverOptionsBuilder()) assert resolvable.exact is False # test Resolvable.get, which should delegate to a ResolvableRequirement in this case assert Resolvable.get('foo') == ResolvableRequirement.from_string( 'foo', ResolverOptionsBuilder()) def test_resolvable_directory(): builder = ResolverOptionsBuilder() with make_source_dir(name='my_project') as td: rdir = ResolvableDirectory.from_string(td, builder) assert rdir.name == pkg_resources.safe_name('my_project') assert rdir.extras() == [] rdir = ResolvableDirectory.from_string(td + '[extra1,extra2]', builder) assert rdir.name == pkg_resources.safe_name('my_project') assert rdir.extras() == ['extra1', 'extra2'] def test_resolvables_from_iterable(): builder = ResolverOptionsBuilder() reqs = [ 'foo', # string Package.from_href('foo-2.3.4.tar.gz'), # Package pkg_resources.Requirement.parse('foo==2.3.4'), ] resolved_reqs = list(resolvables_from_iterable(reqs, builder)) assert resolved_reqs == [ ResolvableRequirement.from_string('foo', builder), ResolvablePackage.from_string('foo-2.3.4.tar.gz', builder), ResolvableRequirement.from_string('foo==2.3.4', builder), ] pex-1.1.14/tests/test_resolver.py0000644000076500000240000000606312623452313017625 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import os import pytest from twitter.common.contextutil import temporary_dir from pex.common import safe_copy from pex.fetcher import Fetcher from pex.package import EggPackage, SourcePackage from pex.resolvable import ResolvableRequirement from pex.resolver import Unsatisfiable, _ResolvableSet, resolve from pex.resolver_options import ResolverOptionsBuilder from pex.testing import make_sdist def test_empty_resolve(): empty_resolve = resolve([]) assert empty_resolve == [] with temporary_dir() as td: empty_resolve = resolve([], cache=td) assert empty_resolve == [] def test_simple_local_resolve(): project_sdist = make_sdist(name='project') with temporary_dir() as td: safe_copy(project_sdist, os.path.join(td, os.path.basename(project_sdist))) fetchers = [Fetcher([td])] dists = resolve(['project'], fetchers=fetchers) assert len(dists) == 1 def test_diamond_local_resolve_cached(): # This exercises the issue described here: https://github.com/pantsbuild/pex/issues/120 project1_sdist = make_sdist(name='project1', install_reqs=['project2<1.0.0']) project2_sdist = make_sdist(name='project2') with temporary_dir() as dd: for sdist in (project1_sdist, project2_sdist): safe_copy(sdist, os.path.join(dd, os.path.basename(sdist))) fetchers = [Fetcher([dd])] with temporary_dir() as cd: dists = resolve(['project1', 'project2'], fetchers=fetchers, cache=cd, cache_ttl=1000) assert len(dists) == 2 def test_resolvable_set(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() rq = ResolvableRequirement.from_string('foo[ext]', builder) source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') binary_pkg = EggPackage.from_href('Foo-2.3.4-py3.4.egg') rs.merge(rq, [source_pkg, binary_pkg]) assert rs.get(source_pkg.name) == set([source_pkg, binary_pkg]) assert rs.get(binary_pkg.name) == set([source_pkg, binary_pkg]) assert rs.packages() == [(rq, set([source_pkg, binary_pkg]), None)] # test methods assert rs.extras('foo') == set(['ext']) assert rs.extras('Foo') == set(['ext']) # test filtering rs.merge(rq, [source_pkg]) assert rs.get('foo') == set([source_pkg]) assert rs.get('Foo') == set([source_pkg]) with pytest.raises(Unsatisfiable): rs.merge(rq, [binary_pkg]) def test_resolvable_set_built(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() rq = ResolvableRequirement.from_string('foo', builder) source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') binary_pkg = EggPackage.from_href('foo-2.3.4-py3.4.egg') rs.merge(rq, [source_pkg]) assert rs.get('foo') == set([source_pkg]) assert rs.packages() == [(rq, set([source_pkg]), None)] with pytest.raises(Unsatisfiable): rs.merge(rq, [binary_pkg]) updated_rs = rs.replace_built({source_pkg: binary_pkg}) updated_rs.merge(rq, [binary_pkg]) assert updated_rs.get('foo') == set([binary_pkg]) assert updated_rs.packages() == [(rq, set([binary_pkg]), None)] pex-1.1.14/tests/test_sorter.py0000644000076500000240000000345312623452313017302 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from pkg_resources import get_build_platform from pex.interpreter import PythonInterpreter from pex.package import EggPackage, SourcePackage, WheelPackage from pex.sorter import Sorter def test_package_precedence(): source = SourcePackage('psutil-0.6.1.tar.gz') egg = EggPackage('psutil-0.6.1-py2.6.egg') whl = WheelPackage('psutil-0.6.1-cp26-none-macosx_10_4_x86_64.whl') # default precedence assert Sorter.package_precedence(whl) > Sorter.package_precedence(egg) assert Sorter.package_precedence(egg) > Sorter.package_precedence(source) assert Sorter.package_precedence(whl) > Sorter.package_precedence(source) # overridden precedence PRECEDENCE = (EggPackage, WheelPackage) assert Sorter.package_precedence(source, PRECEDENCE) == ( source.version, -1, True) # unknown rank assert Sorter.package_precedence(whl, PRECEDENCE) > Sorter.package_precedence( source, PRECEDENCE) assert Sorter.package_precedence(egg, PRECEDENCE) > Sorter.package_precedence( whl, PRECEDENCE) def test_sorter_sort(): pi = PythonInterpreter.get() tgz = SourcePackage('psutil-0.6.1.tar.gz') egg = EggPackage('psutil-0.6.1-py%s-%s.egg' % (pi.python, get_build_platform())) whl = WheelPackage('psutil-0.6.1-cp%s-none-%s.whl' % ( pi.python.replace('.', ''), get_build_platform().replace('-', '_').replace('.', '_').lower())) assert Sorter().sort([tgz, egg, whl]) == [whl, egg, tgz] assert Sorter().sort([egg, tgz, whl]) == [whl, egg, tgz] # test unknown type sorter = Sorter(precedence=(EggPackage, WheelPackage)) assert sorter.sort([egg, tgz, whl], filter=False) == [egg, whl, tgz] assert sorter.sort([egg, tgz, whl], filter=True) == [egg, whl] pex-1.1.14/tests/test_translator.py0000644000076500000240000000256112623452313020154 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). from pex.translator import ChainedTranslator, Translator, TranslatorBase try: import mock except ImportError: from unittest import mock def test_info_is_passed_to_chained_translators(): translator = mock.MagicMock(spec=TranslatorBase) t = ChainedTranslator(translator) t.translate("fake_package", "fake_into") translator.translate.assert_called_with("fake_package", into="fake_into") def test_chained_translator_short_circuit_translate(): initial_empty_translator = mock.MagicMock(spec=TranslatorBase) initial_empty_translator.translate.return_value = None translator_with_value = mock.MagicMock(spec=TranslatorBase) translator_with_value.translate.return_value = "fake_success" translator_after_value = mock.MagicMock(spec=TranslatorBase) t = ChainedTranslator(initial_empty_translator, translator_with_value, translator_after_value) result = t.translate("fake_package", "fake_into") assert result == "fake_success" assert initial_empty_translator.translate.called assert translator_with_value.translate.called assert not translator_after_value.translate.called def test_chained_translator_repr(): assert str(Translator.default()) == ( 'ChainedTranslator(WheelTranslator, EggTranslator, SourceTranslator)') pex-1.1.14/tests/test_util.py0000644000076500000240000001306512671105375016747 0ustar kwilsonstaff00000000000000# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import contextlib import functools import os import zipfile from hashlib import sha1 from textwrap import dedent from twitter.common.contextutil import temporary_dir from pex.common import safe_mkdir from pex.compatibility import nested from pex.installer import EggInstaller, WheelInstaller from pex.pex_builder import PEXBuilder from pex.testing import make_bdist, run_simple_pex, temporary_content, write_zipfile from pex.util import CacheHelper, DistributionHelper, named_temporary_file try: from unittest import mock except ImportError: import mock def test_hash(): empty_hash = sha1().hexdigest() with named_temporary_file() as fp: fp.flush() assert empty_hash == CacheHelper.hash(fp.name) with named_temporary_file() as fp: string = b'asdf' * 1024 * sha1().block_size + b'extra padding' fp.write(string) fp.flush() assert sha1(string).hexdigest() == CacheHelper.hash(fp.name) with named_temporary_file() as fp: empty_hash = sha1() fp.write(b'asdf') fp.flush() hash_output = CacheHelper.hash(fp.name, digest=empty_hash) assert hash_output == empty_hash.hexdigest() CONTENT = { '__main__.py': 200, '.deps/morfgorf': 10000, 'twitter/__init__.py': 0, 'twitter/common/python/foo.py': 4000, 'twitter/common/python/bar.py': 8000, 'twitter/common/python/bar.pyc': 6000, } def test_hash_consistency(): for reverse in (False, True): with temporary_content(CONTENT) as td: dir_hash = CacheHelper.dir_hash(td) with named_temporary_file() as tf: write_zipfile(td, tf.name, reverse=reverse) with contextlib.closing(zipfile.ZipFile(tf.name, 'r')) as zf: zip_hash = CacheHelper.zip_hash(zf) assert zip_hash == dir_hash assert zip_hash != sha1().hexdigest() # make sure it's not an empty hash def test_zipsafe(): make_egg = functools.partial(make_bdist, installer_impl=EggInstaller) make_whl = functools.partial(make_bdist, installer_impl=WheelInstaller) for zipped in (False, True): for zip_safe in (False, True): # Eggs can be zip safe with make_egg(zipped=zipped, zip_safe=zip_safe) as dist: assert DistributionHelper.zipsafe(dist) is zip_safe # Wheels cannot be zip safe with make_whl(zipped=zipped, zip_safe=zip_safe) as dist: assert not DistributionHelper.zipsafe(dist) for zipped in (False, True): for zip_safe in (False, True): with make_egg(zipped=zipped, zip_safe=zip_safe) as dist: assert DistributionHelper.zipsafe(dist) is zip_safe try: import __builtin__ as python_builtins except ImportError: import builtins as python_builtins @mock.patch('pex.util.safe_mkdtemp', autospec=True, spec_set=True) @mock.patch('pex.util.safe_mkdir', autospec=True, spec_set=True) @mock.patch('pex.util.resource_listdir', autospec=True, spec_set=True) @mock.patch('pex.util.resource_isdir', autospec=True, spec_set=True) @mock.patch('pex.util.resource_string', autospec=True, spec_set=True) def test_access_zipped_assets( mock_resource_string, mock_resource_isdir, mock_resource_listdir, mock_safe_mkdir, mock_safe_mkdtemp): mock_open = mock.mock_open() mock_safe_mkdtemp.side_effect = iter(['tmpJIMMEH', 'faketmpDir']) mock_resource_listdir.side_effect = iter([['./__init__.py', './directory/'], ['file.py']]) mock_resource_isdir.side_effect = iter([False, True, False]) mock_resource_string.return_value = 'testing' with mock.patch('%s.open' % python_builtins.__name__, mock_open, create=True): temp_dir = DistributionHelper.access_zipped_assets('twitter.common', 'dirutil') assert mock_resource_listdir.call_count == 2 assert mock_open.call_count == 2 file_handle = mock_open.return_value.__enter__.return_value assert file_handle.write.call_count == 2 assert mock_safe_mkdtemp.mock_calls == [mock.call()] assert temp_dir == 'tmpJIMMEH' assert mock_safe_mkdir.mock_calls == [mock.call(os.path.join('tmpJIMMEH', 'directory'))] def test_access_zipped_assets_integration(): test_executable = dedent(''' import os from _pex.util import DistributionHelper temp_dir = DistributionHelper.access_zipped_assets('my_package', 'submodule') with open(os.path.join(temp_dir, 'mod.py'), 'r') as fp: for line in fp: print(line) ''') with nested(temporary_dir(), temporary_dir()) as (td1, td2): pb = PEXBuilder(path=td1) with open(os.path.join(td1, 'exe.py'), 'w') as fp: fp.write(test_executable) pb.set_executable(fp.name) submodule = os.path.join(td1, 'my_package', 'submodule') safe_mkdir(submodule) mod_path = os.path.join(submodule, 'mod.py') with open(mod_path, 'w') as fp: fp.write('accessed') pb.add_source(fp.name, 'my_package/submodule/mod.py') pex = os.path.join(td2, 'app.pex') pb.build(pex) output, returncode = run_simple_pex(pex) try: output = output.decode('UTF-8') except ValueError: pass assert output == 'accessed\n' assert returncode == 0 def test_named_temporary_file(): name = '' with named_temporary_file() as fp: name = fp.name fp.write(b'hi') fp.flush() assert os.path.exists(name) with open(name) as new_fp: assert new_fp.read() == 'hi' assert not os.path.exists(name) def test_distributionhelper_egg_assert(): d = DistributionHelper.distribution_from_path( './tests/example_packages/setuptools-18.0.1-py2.7.egg', 'setuptools' ) assert len(d.resource_listdir('/')) > 3 pex-1.1.14/tests/test_variables.py0000644000076500000240000000677712670614434017756 0ustar kwilsonstaff00000000000000# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). import pytest from pex.util import named_temporary_file from pex.variables import Variables def test_process_pydoc(): def thing(): # no pydoc pass assert Variables.process_pydoc(thing.__doc__) == ('Unknown', 'Unknown') def other_thing(): """Type Properly formatted text. """ assert Variables.process_pydoc(other_thing.__doc__) == ( 'Type', 'Properly formatted text.') def test_iter_help(): for variable_name, variable_type, variable_text in Variables.iter_help(): assert variable_name.startswith('PEX_') assert '\n' not in variable_type assert '\n' not in variable_text def test_pex_bool_variables(): Variables(environ={})._get_bool('NOT_HERE', default=False) is False Variables(environ={})._get_bool('NOT_HERE', default=True) is True for value in ('0', 'faLsE', 'false'): for default in (True, False): Variables(environ={'HERE': value})._get_bool('HERE', default=default) is False for value in ('1', 'TrUe', 'true'): for default in (True, False): Variables(environ={'HERE': value})._get_bool('HERE', default=default) is True with pytest.raises(SystemExit): Variables(environ={'HERE': 'garbage'})._get_bool('HERE') # end to end assert Variables().PEX_ALWAYS_CACHE is False assert Variables({'PEX_ALWAYS_CACHE': '1'}).PEX_ALWAYS_CACHE is True def test_pex_string_variables(): Variables(environ={})._get_string('NOT_HERE') is None Variables(environ={})._get_string('NOT_HERE', default='lolol') == 'lolol' Variables(environ={'HERE': 'stuff'})._get_string('HERE') == 'stuff' Variables(environ={'HERE': 'stuff'})._get_string('HERE', default='lolol') == 'stuff' def test_pex_get_int(): assert Variables()._get_int('HELLO') is None assert Variables()._get_int('HELLO', default=42) == 42 assert Variables(environ={'HELLO': 23})._get_int('HELLO') == 23 assert Variables(environ={'HELLO': 23})._get_int('HELLO', default=42) == 23 with pytest.raises(SystemExit): assert Variables(environ={'HELLO': 'welp'})._get_int('HELLO') def test_pex_vars_set(): v = Variables(environ={}) v.set('HELLO', '42') assert v._get_int('HELLO') == 42 v.delete('HELLO') assert v._get_int('HELLO') is None def test_pex_get_kv(): v = Variables(environ={}) assert v._get_kv('HELLO') is None assert v._get_kv('=42') is None assert v._get_kv('TOO=MANY=COOKS') is None assert v._get_kv('THIS=WORKS') == ['THIS', 'WORKS'] def test_pex_from_rc(): with named_temporary_file(mode='w') as pexrc: pexrc.write('HELLO=42') pexrc.flush() v = Variables(rc=pexrc.name) assert v._get_int('HELLO') == 42 def test_pexrc_precedence(): with named_temporary_file(mode='w') as pexrc: pexrc.write('HELLO=FORTYTWO') pexrc.flush() v = Variables(environ={'HELLO': 42}, rc=pexrc.name) assert v._get_int('HELLO') == 42 def test_rc_ignore(): with named_temporary_file(mode='w') as pexrc: pexrc.write('HELLO=FORTYTWO') pexrc.flush() v = Variables(environ={'PEX_IGNORE_RCFILES': 'True'}, rc=pexrc.name) assert 'HELLO' not in v._environ def test_pex_vars_defaults_stripped(): v = Variables(environ={}) stripped = v.strip_defaults() # bool assert v.PEX_ALWAYS_CACHE is not None assert stripped.PEX_ALWAYS_CACHE is None # string assert v.PEX_PATH is not None assert stripped.PEX_PATH is None # int assert v.PEX_VERBOSE is not None assert stripped.PEX_VERBOSE is None pex-1.1.14/tox.ini0000644000076500000240000000736012743540264014533 0ustar kwilsonstaff00000000000000[tox] skip_missing_interpreters = True minversion = 1.8 envlist = py{py,27,35}-requests,style,isort-check [testenv] commands = py.test {posargs:} # Ensure pex's main entrypoint can be run externally. pex --cache-dir {envtmpdir}/buildcache wheel requests . -e pex.bin.pex:main --version deps = pytest==2.9.1 twitter.common.contextutil>=0.3.1,<0.4.0 twitter.common.dirutil>=0.3.1,<0.4.0 twitter.common.lang>=0.3.1,<0.4.0 twitter.common.testing>=0.3.1,<0.4.0 wheel==0.29.0 py26: mock py27: mock pypy: mock run: requests requests: requests requests: responses cachecontrol: CacheControl cachecontrol: lockfile coverage: coverage==4.0.3 whitelist_externals = open [integration] commands = # This is necessary due to https://bitbucket.org/hpk42/tox/issue/175/cant-do-substitution-base-commands bash scripts/coverage.sh [testenv:py27-coverage] commands = {[integration]commands} [testenv:py27-requests-cachecontrol-coverage] commands = {[integration]commands} [testenv:py34-coverage] commands = {[integration]commands} [testenv:py34-requests-cachecontrol-coverage] commands = {[integration]commands} [testenv:py35-coverage] commands = {[integration]commands} [testenv:py35-requests-cachecontrol-coverage] commands = {[integration]commands} [testenv:pypy-requests-cachecontrol-coverage] commands = {[integration]commands} [testenv:py27-coverage-simple] basepython = python2.7 commands = coverage erase coverage run -p -m py.test {posargs:} coverage combine coverage report coverage html open htmlcov/index.html [testenv:coverage] basepython = python2.7 deps = coverage==4.0.3 tox commands = # meta tox -e py27-coverage tox -e py27-requests-cachecontrol-coverage tox -e py34-requests-cachecontrol-coverage tox -e py34-coverage tox -e pypy-requests-cachecontrol-coverage python scripts/combine_coverage.py coverage report coverage html open htmlcov/index.html [testenv:style] basepython = python2.7 deps = twitter.checkstyle commands = twitterstyle -n ImportOrder {toxinidir}/pex {toxinidir}/tests [testenv:isort-run] basepython = python2.7 deps = isort commands = isort -ns __init__.py -rc {toxinidir}/pex {toxinidir}/tests [testenv:isort-check] basepython = python2.7 deps = isort commands = isort -ns __init__.py -rc -c {toxinidir}/pex {toxinidir}/tests [testenv:postreview] basepython = python2.7 install_command = pip install --allow-all-external --allow-unverified rbtools {opts} {packages} deps = RBTools commands = rbt {posargs:} [testenv:docs] changedir = docs deps = sphinx sphinx-rtd-theme commands = sphinx-build -b html -d {envtmpdir}/doctrees . _build/html open _build/html/index.html [testenv:py27-repl] commands = python2.7 [testenv:py27-run] commands = pex {posargs:} [testenv:py34-run] commands = pex {posargs:} [testenv:py27-package] commands = pex --cache-dir {envtmpdir}/buildcache wheel requests . -o dist/pex27 -e pex.bin.pex:main -v [testenv:py34-package] commands = pex --cache-dir {envtmpdir}/buildcache wheel requests . -o dist/pex34 -e pex.bin.pex:main -v [testenv:py35-package] commands = pex --cache-dir {envtmpdir}/buildcache wheel requests . -o dist/pex35 -e pex.bin.pex:main -v # Would love if you didn't have to enumerate environments here :-\ [testenv:py26] [testenv:py26-requests] [testenv:py26-requests-cachecontrol] [testenv:py27] [testenv:py27-requests] [testenv:py27-requests-cachecontrol] [testenv:py33] [testenv:py33-requests] [testenv:py33-requests-cachecontrol] [testenv:py34] [testenv:py34-requests] [testenv:py34-requests-cachecontrol] [testenv:py35] [testenv:py35-requests] [testenv:py35-requests-cachecontrol] [testenv:pypy] [testenv:pypy-requests] [testenv:pypy-requests-cachecontrol]