././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1619698712.2686799 multivolumefile-0.2.3/0000755000175100001640000000000000000000000015540 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/.github/0000755000175100001640000000000000000000000017100 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.github/FUNDING.yml0000644000175100001640000000124400000000000020716 0ustar00runnerdocker00000000000000# These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: miurahr issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/.github/ISSUE_TEMPLATE/0000755000175100001640000000000000000000000021263 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.github/ISSUE_TEMPLATE/bug_report.md0000644000175100001640000000127200000000000023757 0ustar00runnerdocker00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **Related issue** (if exist) **To Reproduce** Steps to reproduce the behavior: **Expected behavior** A clear and concise description of what you expected to happen. **Environment (please complete the following information):** - OS: [e.g. Windows 10, Ubuntu Linux 18.04.01] - Python [e.g. 3.8.1] - py7zr version: [e.g. v0.5b1, commit #123456 on master] **Test data(please attach in the report):** A minimum test data to reproduce your problem. **Additional context** Add any other context about the problem here. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.github/ISSUE_TEMPLATE/feature_request.md0000644000175100001640000000112300000000000025005 0ustar00runnerdocker00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/.github/workflows/0000755000175100001640000000000000000000000021135 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.github/workflows/publish-to-test-pypi.yml0000644000175100001640000000230200000000000025677 0ustar00runnerdocker00000000000000name: Publish Python ðŸ�� distributions 📦 to PyPI and TestPyPI on: push jobs: build-n-publish: name: Build and publish Python ðŸ�� distributions 📦 to PyPI and TestPyPI runs-on: ubuntu-18.04 steps: - uses: actions/checkout@master with: fetch-depth: 20 - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - name: Set up Python 3.8 uses: actions/setup-python@v1 with: python-version: 3.8 - name: Install pep517 and twine run: python -m pip install pep517 twine --user - name: Build a binary wheel and a source tarball run: python -m pep517.build --source --binary --out-dir dist/ ./ - name: twine check run: python -m twine check dist/* - name: Publish distribution 📦 to Test PyPI if: startsWith(github.event.ref, 'refs/heads/master') uses: pypa/gh-action-pypi-publish@master with: password: ${{ secrets.testpypi_password }} repository_url: https://test.pypi.org/legacy/ - name: Publish distribution 📦 to PyPI if: startsWith(github.event.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@master with: password: ${{ secrets.pypi_password }} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.github/workflows/release-note.yml0000644000175100001640000000136300000000000024246 0ustar00runnerdocker00000000000000# Trigger the workflow on milestone events on: milestone: types: [closed] name: Milestone Closure jobs: create-release-notes: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Create Release Notes uses: docker://decathlon/release-notes-generator-action:2.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OUTPUT_FOLDER: temp_release_notes USE_MILESTONE_TITLE: "true" - name: Upload Release Notes to Wiki uses: docker://decathlon/wiki-page-creator-action:latest env: ACTION_MAIL: miurahr@linux.com ACTION_NAME: miurahr GH_PAT: ${{ secrets.GH_PAT }} MD_FOLDER: temp_release_notes OWNER: miurahr REPO_NAME: py7zr ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.github/workflows/run-tox-tests.yml0000644000175100001640000000250600000000000024437 0ustar00runnerdocker00000000000000name: Run Tox tests on: push jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest] python-version: [3.8] name: Test on Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v2 - name: Setup python uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} architecture: x64 - name: Install dependencies run: | pip install -U pip pip install tox tox-gh-actions coveralls - name: Test project with tox run: | tox coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_PARALLEL: true COVERALLS_FLAG_NAME: py-${{ matrix.python-version }}-${{ matrix.os }} PYTEST_ADDOPTS: --cov-config=pyproject.toml --cov --cov-append finish: runs-on: ubuntu-latest name: finish parallel build needs: build steps: - name: Tell Coveralls that the parallel build is finished run: | curl -k \ https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN \ -d "payload[build_num]=$GITHUB_SHA&payload[status]=done" env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/.gitignore0000644000175100001640000000410300000000000017526 0ustar00runnerdocker00000000000000# Created by .ignore support plugin (hsz.mobi) ### Python template # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # IDE .idea ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/Changelog.rst0000644000175100001640000000412500000000000020163 0ustar00runnerdocker00000000000000========= ChangeLog ========= All notable changes to this project will be documented in this file. `Unreleased`_ ============= Added ----- Changed ------- Fixed ----- Deprecated ---------- Removed ------- Security -------- `v0.2.3`_ ========= Added ----- * implement readall() Chnaged ------- * lint with black `v0.2.2`_ ========= Added ----- * Add py.typed file for type hinting. `v0.2.1`_ ========= Added ----- * Add `name` property that indicate basename of volumes * Add `stat()` that return `stat_result` which has as mostly same methods as `os.stat_result` class except for platform dependent methods. `v0.2.0`_ ========= Added ----- * Type hint information bundled. Fixed ----- * Seek() returns current position. Changed ------- * Explanation of unsupported methods an modes in README `v0.1.4`_ ========= Fixed ----- * Fix append mode bug. `v0.1.3`_ ========= Fixed ----- * Fix added volume size become wrong `v0.1.2`_ ========= Fixed ----- * Fix append mode (#1) `v0.1.1`_ ========= Fixed ----- * Fin NotImplementedError when writing boudning of target files `v0.1.0`_ ========= * ***API changed*** Added ----- * Add mode 'x', 'xb' and 'xt' * Add mode 'a', 'ab' and 'at' * Support flush() Changed ------- * Change API: file argument of 'r' and 'rb' now single basename instead of list of files `v0.0.5`_ ========= * Support context manager * Support read functions. .. History links .. _Unreleased: https://github.com/miurahr/py7zr/compare/v0.2.2...HEAD .. _v0.2.2: https://github.com/miurahr/py7zr/compare/v0.2.1...v0.2.2 .. _v0.2.1: https://github.com/miurahr/py7zr/compare/v0.2.0...v0.2.1 .. _v0.2.0: https://github.com/miurahr/py7zr/compare/v0.1.4...v0.2.0 .. _v0.1.4: https://github.com/miurahr/py7zr/compare/v0.1.3...v0.1.4 .. _v0.1.3: https://github.com/miurahr/py7zr/compare/v0.1.2...v0.1.3 .. _v0.1.2: https://github.com/miurahr/py7zr/compare/v0.1.1...v0.1.2 .. _v0.1.1: https://github.com/miurahr/py7zr/compare/v0.1.0...v0.1.1 .. _v0.1.0: https://github.com/miurahr/py7zr/compare/v0.0.5...v0.1.0 .. _v0.0.5: https://github.com/miurahr/py7zr/compare/v0.0.1...v0.0.5 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/LICENSE0000644000175100001640000006364200000000000016560 0ustar00runnerdocker00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/MANIFEST.in0000644000175100001640000000022500000000000017275 0ustar00runnerdocker00000000000000include *.py include *.pyi include *.rst include LICENSE include tox.ini include py.typed recursive-include tests *.py recursive-include tests *.00? ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1619698712.2686799 multivolumefile-0.2.3/PKG-INFO0000644000175100001640000001644600000000000016650 0ustar00runnerdocker00000000000000Metadata-Version: 2.1 Name: multivolumefile Version: 0.2.3 Summary: multi volume file wrapper library Home-page: https://github.com/miurahr/multivolume Author: Hiroshi Miura Author-email: miurahr@linux.com License: LGPL-2.1+ Description: =============== multivolumefile =============== .. image:: https://coveralls.io/repos/github/miurahr/multivolume/badge.svg?branch=master :target: https://coveralls.io/github/miurahr/multivolume?branch=master .. image:: https://github.com/miurahr/multivolume/workflows/Run%20Tox%20tests/badge.svg :target: https://github.com/miurahr/multivolume/actions MultiVolumefile is a python library to provide a file-object wrapping multiple files as virtually like as a single file. It inherit io.RawIOBase class and support some of its standard methods. See API details at `python library reference`_ .. _`python library reference`: https://docs.python.org/3/library/io.html Status ====== multivolumefile module is under active development and considered as ***Alpha*** state. It is not good idea to use it on production systems, but it may work well in a limited range of usage. Please check limitations and passed test cases. Install ======= You can install it as usual public libraries, you can use pip command ``` pip install multivolumefile ``` You are also able to add it to your setup.py/cfg as dependency. Usages ------ - For reading multi-volume files, that has names `archive.7z.0001`, `archive.7z.0002` and so on, you can call multivolumefile as follows; .. code-block:: with multivolumefile.open('archive.7z', 'rb') as vol: data = vol.read(100) vol.seek(500) - For writing multi-volue files, that has names `archive.7z.0001`, `archive.7z.0002` and so on, you can call multivolumefile as follows; .. code-block:: data = b'abcdefg' with multivolumefile.open('archive.7z', 'wb') as vol: size = vol.write(data) vol.seek(0) you will see file `archive.7z.001` are written. Limitations and known issues ============================ - fileno() is not supported and when call it, you will get RuntimeError exception. - There are several non-implemented functions such as truncate() and writeline() that will raise NotimplementedError - There are several non-implemented functions such as readlines(), readline() and readall(). - Text mode is not implemented. - ***Caution***: When globbing existent volumes, it glob all files other than 4-digit extensions, it may break your data. Contribution ============ You are welcome to contribute the project, as usual on github projects, Pull-Requests are always welcome. License ======= Multivolume is licensed under GNU Lesser General Public license version 2.1 or later. ========= ChangeLog ========= All notable changes to this project will be documented in this file. `Unreleased`_ ============= Added ----- Changed ------- Fixed ----- Deprecated ---------- Removed ------- Security -------- `v0.2.3`_ ========= Added ----- * implement readall() Chnaged ------- * lint with black `v0.2.2`_ ========= Added ----- * Add py.typed file for type hinting. `v0.2.1`_ ========= Added ----- * Add `name` property that indicate basename of volumes * Add `stat()` that return `stat_result` which has as mostly same methods as `os.stat_result` class except for platform dependent methods. `v0.2.0`_ ========= Added ----- * Type hint information bundled. Fixed ----- * Seek() returns current position. Changed ------- * Explanation of unsupported methods an modes in README `v0.1.4`_ ========= Fixed ----- * Fix append mode bug. `v0.1.3`_ ========= Fixed ----- * Fix added volume size become wrong `v0.1.2`_ ========= Fixed ----- * Fix append mode (#1) `v0.1.1`_ ========= Fixed ----- * Fin NotImplementedError when writing boudning of target files `v0.1.0`_ ========= * ***API changed*** Added ----- * Add mode 'x', 'xb' and 'xt' * Add mode 'a', 'ab' and 'at' * Support flush() Changed ------- * Change API: file argument of 'r' and 'rb' now single basename instead of list of files `v0.0.5`_ ========= * Support context manager * Support read functions. .. History links .. _Unreleased: https://github.com/miurahr/py7zr/compare/v0.2.2...HEAD .. _v0.2.2: https://github.com/miurahr/py7zr/compare/v0.2.1...v0.2.2 .. _v0.2.1: https://github.com/miurahr/py7zr/compare/v0.2.0...v0.2.1 .. _v0.2.0: https://github.com/miurahr/py7zr/compare/v0.1.4...v0.2.0 .. _v0.1.4: https://github.com/miurahr/py7zr/compare/v0.1.3...v0.1.4 .. _v0.1.3: https://github.com/miurahr/py7zr/compare/v0.1.2...v0.1.3 .. _v0.1.2: https://github.com/miurahr/py7zr/compare/v0.1.1...v0.1.2 .. _v0.1.1: https://github.com/miurahr/py7zr/compare/v0.1.0...v0.1.1 .. _v0.1.0: https://github.com/miurahr/py7zr/compare/v0.0.5...v0.1.0 .. _v0.0.5: https://github.com/miurahr/py7zr/compare/v0.0.1...v0.0.5 Keywords: multivolume,file Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.6 Description-Content-Type: text/x-rst Provides-Extra: test Provides-Extra: type Provides-Extra: check ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/README.rst0000644000175100001640000000467100000000000017237 0ustar00runnerdocker00000000000000=============== multivolumefile =============== .. image:: https://coveralls.io/repos/github/miurahr/multivolume/badge.svg?branch=master :target: https://coveralls.io/github/miurahr/multivolume?branch=master .. image:: https://github.com/miurahr/multivolume/workflows/Run%20Tox%20tests/badge.svg :target: https://github.com/miurahr/multivolume/actions MultiVolumefile is a python library to provide a file-object wrapping multiple files as virtually like as a single file. It inherit io.RawIOBase class and support some of its standard methods. See API details at `python library reference`_ .. _`python library reference`: https://docs.python.org/3/library/io.html Status ====== multivolumefile module is under active development and considered as ***Alpha*** state. It is not good idea to use it on production systems, but it may work well in a limited range of usage. Please check limitations and passed test cases. Install ======= You can install it as usual public libraries, you can use pip command ``` pip install multivolumefile ``` You are also able to add it to your setup.py/cfg as dependency. Usages ------ - For reading multi-volume files, that has names `archive.7z.0001`, `archive.7z.0002` and so on, you can call multivolumefile as follows; .. code-block:: with multivolumefile.open('archive.7z', 'rb') as vol: data = vol.read(100) vol.seek(500) - For writing multi-volue files, that has names `archive.7z.0001`, `archive.7z.0002` and so on, you can call multivolumefile as follows; .. code-block:: data = b'abcdefg' with multivolumefile.open('archive.7z', 'wb') as vol: size = vol.write(data) vol.seek(0) you will see file `archive.7z.001` are written. Limitations and known issues ============================ - fileno() is not supported and when call it, you will get RuntimeError exception. - There are several non-implemented functions such as truncate() and writeline() that will raise NotimplementedError - There are several non-implemented functions such as readlines(), readline() and readall(). - Text mode is not implemented. - ***Caution***: When globbing existent volumes, it glob all files other than 4-digit extensions, it may break your data. Contribution ============ You are welcome to contribute the project, as usual on github projects, Pull-Requests are always welcome. License ======= Multivolume is licensed under GNU Lesser General Public license version 2.1 or later. ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/multivolumefile/0000755000175100001640000000000000000000000020762 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/multivolumefile/__init__.py0000644000175100001640000002455300000000000023104 0ustar00runnerdocker00000000000000#!/usr/bin/env python # # multi-volume file library # Copyright (C) 2020 Hiroshi Miura # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # import contextlib import io import os import pathlib from mmap import mmap from typing import Any, Container, List, Optional, Union from .stat import stat_result __all__ = ["stat_result", "open", "MultiVolume"] BLOCKSIZE = 16384 def open(name: Union[pathlib.Path, str], mode=None, volume=None) -> io.RawIOBase: return MultiVolume(name, mode=mode, volume=volume) class _FileInfo: def __init__(self, filename, stat, size): self.filename = filename self.stat = stat self.size = size class MultiVolume(io.RawIOBase, contextlib.AbstractContextManager): def __init__( self, basename: Union[pathlib.Path, str], mode: Optional[str] = "r", *, volume: Optional[int] = None, ext_digits: Optional[int] = 4, hex: Optional[bool] = False, ext_start: Optional[int] = 1 ): self._mode = mode self._closed = False self._files = [] # type: List[object] self._fileinfo = [] # type: List[_FileInfo] self._position = 0 self._positions = [] self._digits = ext_digits self._start = ext_start self._hex = hex self.name = str(basename) if mode in ["rb", "r", "rt"]: self._init_reader(basename) elif mode in ["wb", "w", "wt", "xb", "x", "xt", "ab", "a", "at"]: if volume is None: self._volume_size = 10 * 1024 * 1024 # set default to 10MBytes else: self._volume_size = volume self._init_writer(basename) else: raise NotImplementedError def _glob_files(self, basename): if isinstance(basename, str): basename = pathlib.Path(basename) files = basename.parent.glob(basename.name + ".*") return sorted(files) def _init_reader(self, basename): pos = 0 self._positions.append(pos) filenames = self._glob_files(basename) for name in filenames: stat = os.stat(name) size = os.stat(name).st_size self._fileinfo.append(_FileInfo(name, stat, size)) self._files.append(io.open(name, mode=self._mode)) pos += size self._positions.append(pos) def _init_writer(self, basename): if isinstance(basename, str): basename = pathlib.Path(basename) ext = ".{num:0{ext_digit}d}".format(num=self._start, ext_digit=self._digits) target = basename.with_name(basename.name + ext) if target.exists(): if self._mode in ["x", "xb", "xt"]: raise FileExistsError elif self._mode in ["w", "wb", "wt"]: file = io.open(target, mode=self._mode) self._files.append(file) file.truncate(0) stat = os.stat(target) self._fileinfo.append(_FileInfo(target, stat, self._volume_size)) self._positions = [0, self._volume_size] elif self._mode in ["a", "ab", "at"]: filenames = self._glob_files(basename) if self._mode == "ab": mode = "rb" else: mode = "r" pos = 0 size = 0 self._positions = [0] for i in range(len(filenames)): file = io.open(filenames[i], mode) self._files.append(file) stat = filenames[i].stat() size = stat.st_size self._fileinfo.append(_FileInfo(filenames[i], stat, size)) pos += size self._positions.append(pos) self._position = pos # last file if size >= self._volume_size: self._add_volume() else: self._files[-1].close() self._files[-1] = io.open( filenames[len(filenames) - 1], mode=self._mode ) else: raise NotImplementedError else: file = io.open(target, mode=self._mode) self._files.append(file) self._fileinfo.append(_FileInfo(target, os.stat(target), self._volume_size)) self._positions = [0, self._volume_size] def _current_index(self): for i in range(len(self._positions) - 1): if self._positions[i] <= self._position < self._positions[i + 1]: pos = self._files[i].tell() offset = self._position - self._positions[i] if pos != offset: self._files[i].seek(offset, io.SEEK_SET) return i return len(self._files) - 1 def read(self, size: int = -1) -> bytes: if size == -1: return self.readall() current = self._current_index() file = self._files[current] data = file.read(size) self._position += len(data) return data def readall(self) -> bytes: result = b"" data = self.read(BLOCKSIZE) while len(data) > 0: result += data data = self.read(BLOCKSIZE) return result def readinto(self, b: Union[bytearray, memoryview, Container[Any], mmap]) -> int: size = len(b) data = self.read(size) b[: len(data)] = data return len(data) def write( self, b: Union[bytes, bytearray, memoryview, Container[Any], mmap] ) -> None: current = self._current_index() file = self._files[current] pos = file.tell() if pos + len(b) > self._volume_size: file.write(b[: self._volume_size - pos]) self._position += self._volume_size - pos if current == len(self._files) - 1: self._add_volume() file = self._files[current + 1] file.seek(0) self.write(b[self._volume_size - pos :]) # recursive call else: file.write(b) self._position += len(b) def _add_volume(self): num = len(self._fileinfo) + self._start - 1 if self._hex: last = self._fileinfo[-1].filename last_ext = ".{num:0{ext_digit}x}".format(num=num, ext_digit=self._digits) assert last.suffix.endswith(last_ext) next_ext = ".{num:0{ext_digit}x}".format( num=num + 1, ext_digit=self._digits ) next = last.with_suffix(next_ext) else: last = self._fileinfo[-1].filename last_ext = ".{num:0{ext_digit}d}".format(num=num, ext_digit=self._digits) assert last.suffix.endswith(last_ext) next_ext = ".{num:0{ext_digit}d}".format( num=num + 1, ext_digit=self._digits ) next = last.with_suffix(next_ext) self._files.append(io.open(next, self._mode)) stat = os.stat(next) self._fileinfo.append(_FileInfo(next, stat, self._volume_size)) pos = self._positions[-1] if pos != self._position: self._positions[-1] = self._position self._positions.append(self._positions[-1] + self._volume_size) def close(self) -> None: if self._closed: return self._closed = True for file in self._files: file.close() @property def closed(self) -> bool: return self._closed def fileno(self) -> int: """ fileno() is incompatible with other implementations. multivolume handle multiple file object so we cannot return single fd. """ raise RuntimeError("fileno() is not supported.") def flush(self) -> None: if self._closed: return if self._mode == "wb" or self._mode == "w": for file in self._files: file.flush() def isatty(self) -> bool: return False def readable(self) -> bool: if self._closed: return False return all([f.readable() for f in self._files]) def readline(self, size: Optional[int] = -1) -> bytes: raise NotImplementedError def readlines(self, hint: int = -1) -> List[bytes]: raise NotImplementedError def seek(self, offset: int, whence: Optional[int] = io.SEEK_SET) -> int: if whence == io.SEEK_SET: target = offset elif whence == io.SEEK_CUR: target = self._position + offset else: target = self._positions[-1] + offset self._position = target i = len(self._files) - 1 while i > 0 and target < self._positions[i]: i -= 1 file = self._files[i] file.seek(target - self._positions[i], io.SEEK_SET) return self._position def seekable(self) -> bool: if self._mode in ["ab", "at", "a"]: return False else: return all([f.seekable() for f in self._files]) def tell(self) -> int: return self._position def truncate(self, size: Optional[int] = None) -> int: raise NotImplementedError def writable(self) -> bool: return self._mode in ["wb", "w", "wt", "x", "xb", "xt", "ab", "a", "at"] def writelines(self, lines): raise NotImplementedError def stat(self) -> stat_result: totalsize = 0 for fi in self._fileinfo: totalsize += fi.size return stat_result(self._fileinfo[0].stat, totalsize) def __del__(self): # FIXME pass def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/multivolumefile/__init__.pyi0000644000175100001640000000337000000000000023247 0ustar00runnerdocker00000000000000import contextlib import io import pathlib from mmap import mmap from typing import Any, Container, List, Optional, Union def open( name: Union[pathlib.Path, str], mode: Any = ..., volume: Any = ... ) -> io.RawIOBase: ... class _FileInfo: filename: Any = ... size: Any = ... def __init__(self, filename: Any, size: Any) -> None: ... class MultiVolume(io.RawIOBase, contextlib.AbstractContextManager): def __init__( self, basename: Union[pathlib.Path, str], mode: Optional[str] = ..., *, volume: Optional[int] = ..., ext_digits: Optional[int] = ..., hex: Optional[bool] = ..., ext_start: Optional[int] = ... ) -> None: ... def read(self, size: int = ...) -> bytes: ... def readall(self) -> bytes: ... def readinto( self, b: Union[bytearray, memoryview, Container[Any], mmap] ) -> int: ... def write( self, b: Union[bytes, bytearray, memoryview, Container[Any], mmap] ) -> None: ... def close(self) -> None: ... @property def closed(self) -> bool: ... def fileno(self) -> int: ... def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... def readline(self, size: Optional[int] = ...) -> bytes: ... def readlines(self, hint: int = ...) -> List[bytes]: ... def seek(self, offset: int, whence: Optional[int] = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def truncate(self, size: Optional[int] = ...) -> int: ... def writable(self) -> bool: ... def writelines(self, lines: Any) -> None: ... def __del__(self) -> None: ... def __enter__(self): ... def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: ... ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/multivolumefile/py.typed0000644000175100001640000000000000000000000022447 0ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/multivolumefile/stat.py0000644000175100001640000000202300000000000022304 0ustar00runnerdocker00000000000000class stat_result: def __init__(self, stat, size): self._stat = stat self._size = size @property def st_size(self): return self._size @property def st_mode(self): return self._stat.st_mode @property def st_ino(self): return 0 @property def st_dev(self): return self._stat.st_dev @property def st_nlink(self): return self._stat.st_nlink @property def st_uid(self): return self._stat.st_uid @property def st_gid(self): return self._stat.st_gid @property def st_atime(self): return self._stat.st_atime @property def st_ctime(self): return self._stat.st_ctime @property def st_mtime(self): return self._stat.st_mtime @property def st_atime_ns(self): return self._stat.st_atime_ns @property def st_ctime_ns(self): return self._stat.st_ctime_ns @property def st_mtime_ns(self): return self._stat.st_mtime_ns ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/multivolumefile.egg-info/0000755000175100001640000000000000000000000022454 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698711.0 multivolumefile-0.2.3/multivolumefile.egg-info/PKG-INFO0000644000175100001640000001644600000000000023564 0ustar00runnerdocker00000000000000Metadata-Version: 2.1 Name: multivolumefile Version: 0.2.3 Summary: multi volume file wrapper library Home-page: https://github.com/miurahr/multivolume Author: Hiroshi Miura Author-email: miurahr@linux.com License: LGPL-2.1+ Description: =============== multivolumefile =============== .. image:: https://coveralls.io/repos/github/miurahr/multivolume/badge.svg?branch=master :target: https://coveralls.io/github/miurahr/multivolume?branch=master .. image:: https://github.com/miurahr/multivolume/workflows/Run%20Tox%20tests/badge.svg :target: https://github.com/miurahr/multivolume/actions MultiVolumefile is a python library to provide a file-object wrapping multiple files as virtually like as a single file. It inherit io.RawIOBase class and support some of its standard methods. See API details at `python library reference`_ .. _`python library reference`: https://docs.python.org/3/library/io.html Status ====== multivolumefile module is under active development and considered as ***Alpha*** state. It is not good idea to use it on production systems, but it may work well in a limited range of usage. Please check limitations and passed test cases. Install ======= You can install it as usual public libraries, you can use pip command ``` pip install multivolumefile ``` You are also able to add it to your setup.py/cfg as dependency. Usages ------ - For reading multi-volume files, that has names `archive.7z.0001`, `archive.7z.0002` and so on, you can call multivolumefile as follows; .. code-block:: with multivolumefile.open('archive.7z', 'rb') as vol: data = vol.read(100) vol.seek(500) - For writing multi-volue files, that has names `archive.7z.0001`, `archive.7z.0002` and so on, you can call multivolumefile as follows; .. code-block:: data = b'abcdefg' with multivolumefile.open('archive.7z', 'wb') as vol: size = vol.write(data) vol.seek(0) you will see file `archive.7z.001` are written. Limitations and known issues ============================ - fileno() is not supported and when call it, you will get RuntimeError exception. - There are several non-implemented functions such as truncate() and writeline() that will raise NotimplementedError - There are several non-implemented functions such as readlines(), readline() and readall(). - Text mode is not implemented. - ***Caution***: When globbing existent volumes, it glob all files other than 4-digit extensions, it may break your data. Contribution ============ You are welcome to contribute the project, as usual on github projects, Pull-Requests are always welcome. License ======= Multivolume is licensed under GNU Lesser General Public license version 2.1 or later. ========= ChangeLog ========= All notable changes to this project will be documented in this file. `Unreleased`_ ============= Added ----- Changed ------- Fixed ----- Deprecated ---------- Removed ------- Security -------- `v0.2.3`_ ========= Added ----- * implement readall() Chnaged ------- * lint with black `v0.2.2`_ ========= Added ----- * Add py.typed file for type hinting. `v0.2.1`_ ========= Added ----- * Add `name` property that indicate basename of volumes * Add `stat()` that return `stat_result` which has as mostly same methods as `os.stat_result` class except for platform dependent methods. `v0.2.0`_ ========= Added ----- * Type hint information bundled. Fixed ----- * Seek() returns current position. Changed ------- * Explanation of unsupported methods an modes in README `v0.1.4`_ ========= Fixed ----- * Fix append mode bug. `v0.1.3`_ ========= Fixed ----- * Fix added volume size become wrong `v0.1.2`_ ========= Fixed ----- * Fix append mode (#1) `v0.1.1`_ ========= Fixed ----- * Fin NotImplementedError when writing boudning of target files `v0.1.0`_ ========= * ***API changed*** Added ----- * Add mode 'x', 'xb' and 'xt' * Add mode 'a', 'ab' and 'at' * Support flush() Changed ------- * Change API: file argument of 'r' and 'rb' now single basename instead of list of files `v0.0.5`_ ========= * Support context manager * Support read functions. .. History links .. _Unreleased: https://github.com/miurahr/py7zr/compare/v0.2.2...HEAD .. _v0.2.2: https://github.com/miurahr/py7zr/compare/v0.2.1...v0.2.2 .. _v0.2.1: https://github.com/miurahr/py7zr/compare/v0.2.0...v0.2.1 .. _v0.2.0: https://github.com/miurahr/py7zr/compare/v0.1.4...v0.2.0 .. _v0.1.4: https://github.com/miurahr/py7zr/compare/v0.1.3...v0.1.4 .. _v0.1.3: https://github.com/miurahr/py7zr/compare/v0.1.2...v0.1.3 .. _v0.1.2: https://github.com/miurahr/py7zr/compare/v0.1.1...v0.1.2 .. _v0.1.1: https://github.com/miurahr/py7zr/compare/v0.1.0...v0.1.1 .. _v0.1.0: https://github.com/miurahr/py7zr/compare/v0.0.5...v0.1.0 .. _v0.0.5: https://github.com/miurahr/py7zr/compare/v0.0.1...v0.0.5 Keywords: multivolume,file Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.6 Description-Content-Type: text/x-rst Provides-Extra: test Provides-Extra: type Provides-Extra: check ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698712.0 multivolumefile-0.2.3/multivolumefile.egg-info/SOURCES.txt0000644000175100001640000000130500000000000024337 0ustar00runnerdocker00000000000000.gitignore Changelog.rst LICENSE MANIFEST.in README.rst pyproject.toml setup.cfg setup.py tox.ini .github/FUNDING.yml .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/feature_request.md .github/workflows/publish-to-test-pypi.yml .github/workflows/release-note.yml .github/workflows/run-tox-tests.yml multivolumefile/__init__.py multivolumefile/__init__.pyi multivolumefile/py.typed multivolumefile/stat.py multivolumefile.egg-info/PKG-INFO multivolumefile.egg-info/SOURCES.txt multivolumefile.egg-info/dependency_links.txt multivolumefile.egg-info/requires.txt multivolumefile.egg-info/top_level.txt tests/test_fuzzer.py tests/test_multivolume.py tests/data/archive.7z.001 tests/data/archive.7z.002././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698711.0 multivolumefile-0.2.3/multivolumefile.egg-info/dependency_links.txt0000644000175100001640000000000100000000000026522 0ustar00runnerdocker00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698711.0 multivolumefile-0.2.3/multivolumefile.egg-info/requires.txt0000644000175100001640000000031200000000000025050 0ustar00runnerdocker00000000000000 [check] check-manifest flake8 flake8-black readme-renderer pygments isort>=5.0.3 twine [test] pytest pytest-cov pyannotate coverage[toml]>=5.2 coveralls>=2.1.1 hypothesis [type] mypy mypy_extensions ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698711.0 multivolumefile-0.2.3/multivolumefile.egg-info/top_level.txt0000644000175100001640000000002000000000000025176 0ustar00runnerdocker00000000000000multivolumefile ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/pyproject.toml0000644000175100001640000000062300000000000020455 0ustar00runnerdocker00000000000000[build-system] requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.5.0"] build-backend = "setuptools.build_meta" [tools.setuptools_scm] local_scheme = "no-local-version" [tool.coverage.run] branch = true parallel = true source = ["multivolumefile"] [tool.coverage.report] show_missing = true exclude_lines = ["if __name__ == .__main__.:", "pragma: no-cover", "@abstract", "def __repr__"] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1619698712.2686799 multivolumefile-0.2.3/setup.cfg0000644000175100001640000000251100000000000017360 0ustar00runnerdocker00000000000000[flake8] max-line-length = 125 [bdist_wheel] universal = 0 [metadata] name = multivolumefile description = multi volume file wrapper library long_description = file: README.rst, Changelog.rst long_description_content_type = text/x-rst keywords = multivolume, file license = LGPL-2.1+ author = Hiroshi Miura author_email = miurahr@linux.com url = https://github.com/miurahr/multivolume classifiers = Development Status :: 3 - Alpha Environment :: Console License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Operating System :: MacOS :: MacOS X Operating System :: Microsoft :: Windows Operating System :: POSIX Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3 :: Only Topic :: Software Development :: Libraries :: Python Modules [options] python_requires = >= 3.6 setup_requires = setuptools-scm>=3.5.0 setuptools>=42.0 packages = find: [options.package_data] multivolumefile = py.typed, *.pyi [options.extras_require] test = pytest pytest-cov pyannotate coverage[toml]>=5.2 coveralls>=2.1.1 hypothesis type = mypy mypy_extensions check = check-manifest flake8 flake8-black readme-renderer pygments isort>=5.0.3 twine [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/setup.py0000644000175100001640000000016100000000000017250 0ustar00runnerdocker00000000000000#!/usr/bin/env python from setuptools import setup setup(use_scm_version={"local_scheme": "no-local-version"}) ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/tests/0000755000175100001640000000000000000000000016702 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1619698712.26468 multivolumefile-0.2.3/tests/data/0000755000175100001640000000000000000000000017613 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/tests/data/archive.7z.0010000644000175100001640000006065000000000000022024 0ustar00runnerdocker000000000000007z¼¯'¢Ì™2-Ì$æi#~áfái]Š€%7 B¸ëñ‚\@ÜÞl dœ’Óà{•§Ý™bØ”ˆI˜’­8Ê=?ÇcHJ‡;ùò਼mÀ:[ˉìÉòfÍïÔÎ0)ºé2æˆD;Ç“P·¿.z×–44�Ý0òáP1ÏÄ©z#õVÐNïoh윢ˆ@áµü (Dce=´ ,ƒ#Ú¢ä7·ƒ‚ gghªES–[ö™Pþ;¼ð»¯0�tŽëYt�.NùÇ.Ò wY‘` øâ´J6ŠÚóŒOÓg’½ª_}7¥ÈŒ/üÂÊ£¤¨é`ª®!Åãuïëh`“ï9K²XLÿ× “Èì;>2câ7þáìø„xäÒëÃÖæ½Í 'gÐ�©Hcˆ©l‘ "+Ù8ðiíVb>ËFN·MÃððg‘ Fç(a*�H=Ø_´Ãñ{|©Â 5õƒÞC>¢}ò"ÜbZ�†ý)D£vï�±n÷ÌdµÚžM/¼–uÙÊÏ’¢o>ÎHñQ×H�¿[€@â&g¸Ìç€=¹�傜]Ë“�;¼]¡�sÓK*š)Þü%Ï?©�’ tÙy×.£÷üžà,�{_ j—ôug¡ì0_辰'{�v0åvË]G¸ÅIá²êßdrNÒž3Zâ&6Š·� ~¸‚ˆ�ÿ=ðXeîx½ªÅö/ Ve5éèPµ3Yþ‰â<ز?ÛŽí¯mðë×ÖNAf �ROìX'¼ûÓÀ¥&´�q â,†#žê§Ê}D@º{×8xìÝ'Ÿp Å6ð€úp1ÇV¦2àž¾äjîî:–E/[a€Uu† ÞÓXãÍÎíXkPÊi¼ÞÞ*¥0Œ‹ÒRß903¬³eþ›…Ã&–PþÜ,g¢(dç�._ãþ3êÇ?®ÛúѾîÑAÄ}[Eâ5ð�ùoñr¢o”#�]œ�(ž³E«¨ ãøiPPvÙÎÅE§¢éÅp" úextt;ó†Óˆ0äçÈì¦:.†j𩵭ÉááÙÖŸ(+sxûk„‚xðŠq–±éÈÐÕŸä yoúœ‘Ï�c4qN÷"�L�”Â4D+¹=�5s9 UL±# Âß»à"!UC[Öâóå]®]鎹'OÇÇO Mö­sòÅŒ}Œ{¥ô¤ ¬9ëÄf/¶æpΫS€2�¡ØtÐqó®þÎ×èGÄ4<>t~b¿7® jùþ@ƒK%Kª«#”_üÎþKÇóëF«Òk,Æ’�/H7¦±g Üïî7VæDõéç?u•ÜÇQ¾8Q®š¼#×Â~!4‰ßlx[úˆ²ç·Ñ;-iÐ� Äý{� eÊ—�°,ÊÂíù:¹öÁl|+ªËÎ8ùÖŠUÌÈàJp—/)ý.û2м8Œiçm±#¡˜Û¥iÜ9Xp­:¤ªè�ù­Z&æ’>Ÿ°ÙÚÆÍ�åK /Çfh̆Dœt�Õ_;>›ȤôöWs«£æ:PõHÏIüV©ÅÕVo%8I= ûú€'”"ÐاÝìñW௨•®3�ò�N ÏHfþ›•˵"ù‡®-&º¶"ð× Í² O~ÇÒ[ ˆåÇMfô…*^x—_ŒS0x 5ŠLB zÂ…B)5ªãÌ,$–Å߀ϋÍÚÒ#ä*™jg´_Ð)êÕvª2X“½7ßÒw¯#ù²=7¹|ªÉ3)ô—îV§&-ŸIþI÷;f±Щ+J¥°äÙ·èµþ1å2€¤ ‚ò \ó¨QQ¯4.x–¹Xª‰4n…}k`àm‰ª`ïÀ»÷|茜O·À™• Yáì.V/\Ï øé1+Úue;XEÑ7jÀ…® ½j‡æÈûÃ÷E�Ôk�—oÞú7¯ºÜ´7äÙReàGS�KH^õXbÚ;‹‚g<äµ2»¢Ñ¡³bN÷JF‚1Q•cØûL΄lò2€ôKsÆzö˜¼gÄ+°Gòˆ¨ÙÃH-æ0é¯côÆB’hþÌûý™ªçu§|WIÛ$ãÌsñê¬4Òà¡ÂLÌ+²'wGµïHŒ³Ç�K¹ÝöË‚NƒÄ<€GÍbf_Òsåˆ?œärŸ†ÀeÐŒYÃ1èÆ4„�7ÃÜ×@…Á{B¢èǃT—`aÝá_¢«”~(m›W“Øuºä ]LͪÞW­üõ,'µü•~Ìõ»¼n½¾ €~5ÄŸ%„¹+µsˆÄ?"·­äê°!˜¬q<ÛmA)Û|ÍŒ*¼4ÀH„€Å†dZ\çbŽ #Àg6jšüéÞ…XbÊC%$ œI]†á47®›‹TDMó.lNĽ„E’ˆH!6i¦°É+\‡¤µ«×h}¾;!jÆQöUfT\}�0W�lºà QúŒx²iÚ¹`�ÂîÇ›6 –qY«�Áršùo ¥…?„¤|2 ãɺ.±$ŽÚ`Â"‹Ã‡CÁÐ7`mg6"phqˆ-�LóÇО_eþº:kû¥¥+_‚èSËp¶»“w›¡ä ØÜ .÷Ö둢暾~a#3t•¨¡V"4íÍhÜ¢¶®É|Z ¹*9êä�6D¾6û€pl—+\GL5> õ'xŒöõÄÿT"YG¥ù°ÌÝi̳ËÚ©ûHßüMíÂÈ­¹Ž¿ìlƒÉ0AØJ2Ñ\ÂÉm(ÏòˆÝ“ £ ®NÊë×�…µþ�°ÛóØ•ú¨"å_Vf ôØ{lO{adå ±ºêÄÕ‘OÕ º‘ѵŽÞm+GåẺõÍ„ ¶VÉ=õ ª”;–úox‘£‡ Z�uñ…zcQe—±úJÞ¼-RþI­‘L”�¨DöAdƒø¬Ö¬rÉ1‹ün¢ÿ–êæ²MÂ*—ùmëÐqg 3)}’¾£=ÕíݬJô_I¼ÎÞÃÆ“N™ežÑÉA¥ qG4œVOl°)æ_l´tmÞ!]�_Go–»¹® ØÀùl¸àœ"*}訹T\6g1ðGþðŠ{Á«À€•fh8ÑuOò"ýÎZküª�Æ¥ÍC�›jfdNà†L:Ðà0ñ9˳‰\ùõz¬Áä°;¸›€3³¬Øû7,Ò„9î›~ƒf„óõ¼ÀB»=D›Ù–spu~Û¾$¯½ÉRIÄÏõ°CÊЩ?{6Ðëªç‚ô…„Ë õOlàÝyŽÞþŸþÿ§qc˜;{wºncF„ª³‰‚LÄ4Ú®bÉ8ßâ¢�RÛ£Úþ¢¹/¦!2@¶%:ÊÉð|oî§G�ç¤eÓ–š_H‹HYt�å—ìwœãk1B$k¹ˆ¢B+yzØïí·>“d¿á&ù3Ýù­Y9ÉØ2…Àò“Áqᲃ]‰¤‰A8b[°7•´:” 0´üz!3Åí‰4Ø#L+å$çí4óu‹áÁÑ<êM@Sõ£ª]fº%({. ÝÓ…,¾é)'lŸ„I‘ R8@>¶x´Ïãú ʉ’`IÅ•ã)n߯oÐ}<3>qm¯3OÖ>ë$ED¿ *Ô!*î†xJÉ„Œ1}tL9nÜÀµŸ¼Cë�¯.13ajž‘UqPïö¥o•U�’Ÿ±onæ ¯ow½Þ&Ûæ`T‚RóŒþD¯Ë˜ä!¶ÍíŒ ¯Õú+´f¤e¾·j»8EÜ8!’_°cϬa¼A£H ä¸ë£`÷Õô_L“•D04E<Ÿ†Tï³ßÌÎX¸Ç»‡/„Ëâü˜rƒœÕ…`bû1cüÜ ¾úÌæõuÊK�Ha™�»LSé¸m„î �ân �C¾•¤–Îß:,Ja�d!þ‡ùE[… M³+W†–¥€ŒÒ©ÝtŠ�z6"Ó[J~U�æxÌÒdÜ=Ïã3`„ÑÁØVa|Ù ² ÞH^×%Ô©E+·/;=­!¬ƒÛuÀ•C€·ƒÛn�t�Zxæ��¾L·üH“xâÎ6‹åfT¾ñù†Æ‡�¡ü«T€LŒñHªFûF?tý–ÇÏEð‹S%¦B&Ö£úŒJ;‡ºrKî'Ö¼Œ_²B䜙iêü9à0½x/*åm³Ø…x\¾áÏ‚ëO\<&ÆöEa… -¡Xã¨û)<øUY¼<:“ /Âf¥ú9QXal‹ xV(ŸQcð¿@×oªlïzxÊ£ùdñÙºö–´·±Ò¤2îó—ÿh7ž£O1öÎÝØ]Ìßéð³m%Ò˜w,÷²Î䥠&iÈhcèJ™Ý“ö½R±»óû©æØAÂFÅÀRùAÏ^xCryÜ §æÖ8ßbö°MÖ«vW¶?RŸð]SmÙ¾ËjXÓñûw^óÀ@îãQA§c}+ƒÑz‡püFÖJÕòO�ÀuÔw·Ýž«1oô,$�\Ì…Öý&äŽÊ€åoÏÀz ÷§40¯J�Wc{_š™ÒFw·†‹w¶Oy±Ï¿Ììd V|r×ÅýÝMÏÕ�.ýr“W©²|(wÎ. z€-Î¥+"ÿå÷ã0e4du/Sàt©x1t‚ÛÎøîgܬª¯Ç˧ª)¾ºo4Zh�Äù½@p³‚`×ÔŽtçuk…JÄðFÄ Æ�ïê`yv¹µÈ)Sæy•ÐÞìˆ!âªÉ‹C›g‹tîôtAqY»ñ|&?Šb/,iz¨2N4Œ!Yä¤îô¦ó…昇)SõAc�}Ã�üE‹$ ËÄQÚ5˜a”N˜±�h^Ñ’µ÷-I'· OFd;—ef7Æ×Á¥L�/™P°ˆ~BFÝ�"•»¤*€ P¥÷¿ûli‘¾úm‘o)Ovf�SHùeh¨m×çØ�J4yö4ÛOƒå Éõ v‹ÜÄVE�µ1ØÆù3995h[B-ÇåªÝ�=~Úc„ �ܱyBS©ÝÄýþÛº‡!³Æ r�n  ŠnLñ”žóB|žVœ³\ïš4�ìSý°ÅäËÆÚ©ö�êÞ*$Ï T•F~Ç@÷S`.¡éª…n-†Ìˆå¿Š+/ø“q_�?�à4ëP÷‘¤áÆêP^c†MM‡óE™Ywo&ˆd‘À­ÖÊa]ãýkz³Ü ó㈶“dy�ïòµaõHۤߵš`ÂÑ`CÓ‹8ª ¼k¨±mH=¥�;]4ýZsð�“HÂïeÔW‹\ýi·lloÈ^ÓOuQ®¢“A|Èxo¿õÔr#†��À”à]ÈÏÛ”p½nH–ºI �Cÿ<§%å.ô†êÀ¥^ÝxeÉô–³96WÆa^Súj˜ &�>-I0o> .P¡—¸ÙÃþZ ,ê’Àå•óGÌÿúù¡vѦʕ¯“wX˜@2\™"¬–6`þk¥Ð%‰‡ŠôšgN^4=fXy+âFYì.G+”Ö›_éaCª»KpV×tê|LšlÙü^ݸÝ|§ +zIØ[¹Ä �(çºÿ±B­ieS\7mQM/¾ke1šòì•äx=-´Y_ú[íþ€è ÐS¼‹’ð×sÊ-#Q Žø K0›’BKhæèá/=šk™ÝŒv€Íóšµ)e¯�õ3ÄT­þçt|‡&d÷«ÌÉ•é2+±†Ì¶|�(¤I¶3Äy}v÷O°ð:gÂ1 ßH¬é}×f@¿¸éP/B“0ª'Ñ0ªy¯Æ|ë%ö¶7½�‰î�ÍGlåÍ&;‰Šl�éøneTÇJ•ûÃxñÒºÿ×lá·•D}áw8Á1ú¬KùŽgÆpFøÔW?^çÞ}8•à-n�„ô’�²"ÂæU¸Ú3!Ac ^ç,‹=QOC)qs'Ð’ÄÅÆIN¿º 9j$í‡àÍ“˜ø(‰Ð]Gƒ•€Ð¬!SýDØ{qG´Ê¬S÷ª[Àï»Þ}iç¦Üëo~¢aã_¡âéÛø—[)d/¶«,,ø0áiêÙ?üW+ÄCÇ„jÚ–ð»Ç‘1#M�§@ÒV_-ø‘�ú WV¢^öeÕ¾«Kª? $n�ñyÝ®óB-ß5Ü€t0¹ÏMI‡ÎmòX‡@P×®hÑãþà2yG{å[þ€ˆ 1ˆólóОú¼LT­¹v�Ð%Ï[]i5+¾ st�Ä©ÎA(DR°rÈ~+ew°óGžÉá蜺¤²O�¸\P©åDéëO~Ô�;z ¤è9’A'Ë<îÓ5'ë4Ç“¶‹×êW,«ŽwlêGiEKYîÈ#~Z‘D`ºrÛAï×”G‹ã‡Ó ˜ù�iÀL²ÐOFžŽB+®P^¿dí¯(®•Ÿ¦ßIÑ„º€¼ÿõ¹þ:„�çÍGºŠh€c©/Ÿƒè碩ZÐìаæ�Ê—t´C­ã\´ÿ‹b¢.}3ðoå á¿¯¿<’Š\f_jÇÔ\°ü£Âvwj“¸*ÉZ' ß%-JËÛ'Áð�·e»ŒöK tßU|5V³$Wd��3Þ†=ð'Z…¦‰äÍÄr=ï µ'︗ß½F´Yø•ê!J÷ü§zq©=×;±�«B±•ôx?!ÌNY(ܧÂÃ&§oª’&ñ‰,Ò,Ë®Ý(•¸4å¡èø*ªVå‰1=¤Ñ¾?$ONŸZB�‹3ÒâI›CÙØ¿uS€îi ±f4:u–í`�›š!(é¾ BáËÚ•\ÆÄÿÂ!’'3{ÚK¸>J)®`›5ÏÒ“UHÕî)©ë P´0 I˜c¤ÈV- JNÒ<†“Â~$J¢ÕÕüª­„-²Ï S¢I¬â1&Ùò¥é/0lNÈ‘GT‡æ¤´\+İ*â8üKQ²ñ7‡O[í½ÀKc·¡±Œ<á¡— iOã"„{ÅÅw©Â§3CObTfKoCrŸ8*¡¾7/Z÷g&Už�§?ëËó!¶Uô1À9¼c¿l6v›‰=éâép:ÈÕÉø• JàÅÏH€Î|¹ËFÛ¦@ÅÅ0KÏÐà+ øˆjc¬”à E#=ëªO¬‘Ò@ô¹FÊþ¶8?çÆÍÆø’n¬JÇZ6 qzÕ‘.€º6d˜8UPʳ¥žy™Œ Õ#Gݶị*&�¼ØI±áëO£WC¡vÚ}¬ˆºÝk�ü^úr¿Ø`)EG2]–*„t†3õ%s(QÊk─.F…¨Ï5"ÉVíɰ¹S?¤urå/š_íqV·4Ÿ®1ÂÍÅ>¿%Jzýéá•Ú x­¨y�r+9)ÿ…)ýbÆ“b ¾¹Ç¨}f6õáÁð™c� Ö¸J›“®!¡+rãëêÎy~Íö˜8Rf€�P!HV*Éâ» p®Y²XõZÒµEs¹¹ ÙU#^ºÑK1Þ6%zòë{hí¥²E^11iz˜=ñ�Þ2ÊV-¡Í%,$²da¦Îo„`)Úìá´‚›8ö>Hû�‘íEù¶LZĈÑ{*á–Ú2ƒ›N!¶#§éÿ\ãv< .fú‰{Í[µÎ|ïÁB{?:šmÛUé�!ÐhlÅzf>“¢Y~¬Þ'Ú›i/uî_(Û‡�vn�ð³¤bM£ ²Q‚Ê£ÝÙž;foSðÃ13„‚8¡7sÛÝ�ÀðoÒ ü»¸³;޳veL©.+êq]¨Ä ˜¹ k¶cª+¹HË…ø/Ñ}|–ÿ\ën„mÕ®ª3 ˆÍ–GZü�ÜŠˆó×µ 5jÑbù'©€´-ÞÿÀš(AXìÄ#ƒPn ÛÀñsÀ u�QNe OüЧ�æEƒúçâ×€…¶˜£aDbŠÞ r¼1(Óu6³‹·Z-dÔø‘M1O&¶iÙßy ÁÈ®UûNn•$'OÒøB«ß�ToK³�`ݵ2FóÅN_. Vh{�ƒÏžã“æc’Wš¡÷ñR‘HÅøÂôU‡wßmI—ù/3�Í=Ù†Zñ}j´.»¬äN’føáeàe>Œ@ŽëŒoÉ*+*8‚¢Ý4j) D îè¤ä1E6ü¿ªe7CÎsBê€Ÿt!ºZáD–ûíŒ("1†{÷®N0"ï[°‹à¢æn k5v;ÏþW:öGA7aüº­”ûÖF˜à†É™4“åµp?ð(<áˆÍÙø”˜„ÖÈ9ét²n W1ÃB¥­F§­Ò4QlU�Q4º“0]‚ÖM(³dÒσEœ>[ˆ�Ìwu-LC%…ÓÈ´¦Z)j�¹cëk?‚/¯¹>ÍS\gë zP¸&¯H ‘ŠŒüúëYã0$nh”»ÇÐA8à ڣ ò)‰& ‘r3î˜>ê¬ÀÐwa‚–Lw¦fcbÊqb7ýˆí&¤óŽÈZ¸y€ºä²mÊmcF„ñ.åP>øqð¯ä×ñeŸ“š^­L8�Ý>ªãŠÊ> Ú N÷ ( %\ ›:`E4%#”àœŸÁ–:Ô}T²ç˜hŸ¨m œþ™%°'Pàà`!—Ôÿ5Ûë)}ò»?°§Úù¹ÚÒÏ~<ƒ isÓñ<>mGOBZ3k†xifW{½„fàI6Ú,qŽÆ¼êÕ0å—©ìÒaŠù(>øõ¸ÏdQH$M‰g¯* e¯ûjdØ_¶=rNFw™[{@:ÉÂ_¾´åÉb³¨ù¢ŠÈ¥xv¶îï9)?ÈÌ`ÂdŽeRx.×yå¬gA&68å¥ùÆ:¯%c“úo!•Â;4ݾ•Áp)ºôeÓl‹BÀ÷âÜÜÔ€Ðìãá³,ø]ÂOx`âY[°ð�]˜U3Í*¸�mªUí�ÁY2„žÞèÓïm^ Yþ־ö9; XñùyÇ0+ hô$îYmøÑˆºÏ‚m„n•æÁmЃê8k–œ„ñ³\fŠÿ•Ô’U{”§NÔœëd„Æ€ x"¡·úu·ôNO�#Àç£qN#40]3¶Z¢!sŠ“„Ÿ#�••m#Zœ’ö°9.;!#Ü�Ø[ƒô¿"èSݪ©7×ã‡P½//®¢pJÛñâé�STâPÉ`@L´6Y5ioÚ R`þ¯œ‹¨žñ°‹˜ÔÌŽŽ7R!rAÔ|tˆÝ­zŒ³)»+cN$->VaTèSÁI,>Âq…½ŸÉ;û H»éŒdÞ¤Gi/7Ò\fŠ— MÚ’äóE9iàxö³'A�Do ¿Ú…X¼°ñwt´8vÁ�zÈ4χYûm‡4ªX6‹¦÷kåÓr+jM3‰|œ">¬ Z­†}™?¬=�«µü�/§²éB QÒW(#¨)S¼÷ˆ p/CÀºÆ)¦ÉÚD‚{p2Õ68sã ádY›Ý õT”å°{]™ÑRÂ^V}:�òò¿á÷»Áxá>!>+^eóÓë�#áë"'µþg àYh‘Ý‘î‘wý°·½}í5Œý�R\„.yÈä>c©(~Ê€ÌÑ’§úØÈÏás¾ê±Üì<°ýMm Â÷qÕF{ç¼»Q¨Ö PRLø71)úGJÕŸèÔPµÎåÀîf‹!‘ÁPr4#E.÷]Í}³ï^¡„,õ˜ï„îÈ÷oÃ?œúÕËtZ}tj¿£cæjQ=¼™R ÈËGc÷wS¨Ää%ètHb~\±«®„Ò7[ÌøÆàô™r\:2œãtƒï9Ôd×v8I¦ ²¾¢VðÍ�á‘ȹ—™ï{ïÔŠc?kæ|QMìÔ…±ðÙYU-ž;§Y'¨]O^vôÄ;ê(… BG ™eôÊòÜT�óÿ]Z‡6uôðJ�£�"‚òëì&A3ýž·J)të\܃ôg€W\DjDíôc£ø`¥kS”­{Û~Î@ÄÍŠ|có½vdtãQp‚³ü˜?b_gêÞ¿Í�FÌÒÍuei—±Ú�ϳËÏ}J�Õݨô Õš‹½Á#,§ÖÚí°zåÛ³ƒ~Ī)Én„›Ã–: p©?à<÷¢ÿâ�t‡AÈ` ¨Ûó6Kz}Ψ @ÔÏ{&lˆN€ ¸V5vx�jNBö’§£Â5ì�<3œÒ=BYš˜^y²¾vunð¤Ñ9äév*Ú±ðxñ7Uû��`Ç}uóû«�ý�fVÚë4\‰•èñ ç.3ú†ëÁnüäÛX1óCÎ#¶Ñ�M‰‡Ïèl�îÛïQ'L‡jörðÛx˜&$T½6qã—ö“+*X¹${)ÜEâa!]Rþ>L8Úù9ÌÝZˆsËn Ðz¢DkÜ9dî‰XfÌ”f%®^½O•ªêFS'夯³c‹úúUyJÞÁZžÝ;½ä…B©„Ô‚gWÆÊ˜F�X¬¢Ä25ˆ3f8)Ç* W±²Ðf Ȇgµ¾þC¹¼ÚX¹£S)äŠ;Ùß©mø÷¦úÐs+ð.¢eXS¢jÒ‹(ÂmC.«Òïg·E¨k `Váø°?N�Þ&©d¤iBm9\ñÔ&Ë¥bŽ7~¸#È?ÔÄ3Îevgp·!„f[kK9uωÇ�z›Å±�ØiS}ROÙN“ƒTÆùt¯Z 28�âTôr\…‚€0ú¾j¸ M$†7UHá'˜f§–=½{ î 7ëÁÄ4ŠËUVÅ´cWØœ['Î¥d¯œLËÀ`T€ÅjÍx¤™ò1…4 -Òž¡6MHëž•g=F„*ë`zdjþ,@&“±l3%DYkæ.è œ£\éí˜ÛÁôŸ‚Aa¨4§69ûôœq¯ut#K˜yÔÈŽpþø5¶¢ÙNíYùÞ"€»èὤÒ•ˆ³ÃºGmr±éH¤&£I©žOú@,¥Ýߦƒm³ƒ�ÁÉzÁp�¢÷B„ÐDY°°dšKtIQÈÄ&–+ —3™èkx¹|Uúqoïf·¨»áOÝØHsâÚw�]ö„ãd8^óŸEƒ¿åICÑú#½µ J6„1ìxQêö4/ÇNî6é=à5²@s0:™ÌA↣â‡`!"¼Í¿TXGE=©UðÄ€*˜òIõ?4vtÄÀ|BŠáJVå9A=1’ ­¶M Pð›Î%”(þ«SQ0‚0Ê[É&täwo¢ßóÙõ²†�´:/ï©ûƒxÐçFÔâ�a{îr¸8ûCPJfsèj÷óÐhÙÙ…ø»þQê!™_€‘“çgc-¬L>×ʾØwZg'Ó…i#lMâŸ�Fém‚ßÃÖJ¤ñÀ+‰ÈäÑPò»úú:ŸþAìz÷²Ù…E¨5/!ö®'!1Ÿ;å3ÀHß=,Öx¬ÐÔô�2S�HAø¯Uâ›Hj2 š qÕ×é£Ä%0 4¿]«~ ê‚[ \dH2(C‰‰£ ÀÿµMÀ"€ÒŠŠ<<÷LŸn¦•&—ËÅ5/ÔS�z }S)·Ísè }ËbãÙ-üRt„s£�Òp…ŠSÌ•hr¾YVl(H›-yÿþ9|ôîÉrõïq>(A#ЪJqŠý¦4.åÕ¦° K;ôöóÅã È„±É–„]—÷v—38‹ò$¨a‚'y„,º§èY€Ðwrmôx`¦êÄ�£/…~8ÑAàÏ­8>ÞúNí ÙÁR‡ËY1­Ý¬j ½{á?«'¬ó^œ¥/0?‡:Šxð¶Iíª„#«~ùÿgUçš 1S«ÑzÛ¾  òá‚W%îtÆ(ywxÁæ-0êËv: mH%Í �”ôæik*œž®=|A85 ¹K¨cÍšÊÉa®À >TyINå6�½ÖR6O¶µ¥uhéjÊ,§×®ÏVo¥Ë¿±Æ¤ÝRÌÃæ†´ ¦òôÍà<˜œZR×i�Niß³‚ÇgÉ5u-ˬ.Ñ�Ñîj|? èþ ”—ôªXsò—;¾€¸áp½s@FÞ{%»d Tò�Vbh1ðÅßö4‡ü¾kQ’y–xÊ“Of!©^^Éé–-ÃLª¹�rPõôµd¤À�|µL9É ø½=§Á³ý�úÇÜÒ±x³ËUG½-°I͆³Ð’Jš)Ê…S×î`0ß"We´~í4`iÈ™·V²Ìk�$ÊIÊWzàù¥<§¢Ó8ÁUö}ÜÌóûªØ1:¼gw°^À–¤¨[N«Í1ÎÔŒlÍž˜Àc¨á) `Myß± QzLWÞëP‡,�“(¥ÿú³„Ðõ)IŸÁZ A ¶u¶ k‰¢ªŠg>Ç–ú:Jo:gaÒ+{‰P-Î;Ù›R]>¬&ý̸“8¯Ä-ÐGãrÔÍ¡�Oô¼Û©¿à6ù¬0—°"Ž�&o@š¤=ÒÅ3œ~N lб÷„G„Óª�+iÍ:Ó6kÕÏP¾:­Ã7Ò·£DzuÝl¬à ó~Ì8Ù?i¥û“–$�N†x„…U<è;*J>=(AR÷âe0Ìb+Æë¼V½­Ÿ5jmk î™2�™ákånB2'Ñ)ZË ùLÛe„Ó¿IÑ”ÁÛ+æËÑ {`i'ÐNíÎ’§ÖÌ%¦ˆ¤xVPz"2¿Å“»ýÌrÔ6/ ¤!1•]¾ÐjýŠÕÊþ/RdÂGæØáp‘´­^¿j;sž «ÕX|/ýTÀ”Nº™yÀÁñ\ÏŽA1B^©òúÙ LôÆÄ8¸—fu燣†åê"ß©ã~D¨• ‚Ùoödc¡#$¿â^�>‘¦žõŒÁ®IôZÈ‘d˜ “¯uÓ}*z*Ã1#”ÅFñÕ¬1Îä5BTpßJÃBòEßm „i{ï4üÊqI„oqpÂÁ�!Þäõø” µ7dpGƒfX7SdS…ó²HHŠ¿Ò`õ!÷µÏì>´ÓÕûvÅ'yÓÈâ]A3{Öß{¾ÆŠ¾ï UãK§Íâ3 ²pNëŠ ‰åaN-¡¬ SÉ'¥?×Eû$¦ì1«£‹„Ü£^=ΖÀ+œ€í둵¯Þ;Øsò8Æ+Ó!+!dn©“gމ£HÃ-:G®M ­aÝš½2k§ÑÊœ¦eÍ’ �!ÀÛæ¥x~`� ÅQûŽgCH�iþŠÀh~§^*ù¢iCz½Æ—"!ÜÒfÈTìFJf¿)½CÕí£¼ E¤Œl„uÑH)¦<ŸµÕ1„Çïýã¼üä'°ô»kÔÒ¹ò‹ ¹‡ ª{?𕸙UÀýdÞ’5h5È[u…^ì¼a (.‡† MþI«“rû�"Ñ(m| ‹ö�Ø…ä'^ £ÑÛ¸#aQ¦Q³ø…üûšÄpÑ5ñušˆ¡uO=ÿ ŒõÙ“Z+}ªt+tð�xù›ÚÈÝÌ>–²˜ §¨6ãoZ¯�-œ<·SŠhÊ ¹q~ì«ÜÌŒ+¤sî­]_b1‚1ÐFRJ¯l?ø¸+ºÞoy�cs¼vÄ}P¥M°_4ëÎͺÀ Î…Ó¤íj¬B÷’Þ™YÙÔÓ§ÌlúÌ[.¬mZâN‚»EG@š¹–Š-m¤Ù€ýÝpÝë*ÝÆ�Ë«&A­"º–S +ùø7íj_p¼Wäè+„~êßU±«JäãïLƒ‚)S“Æ·ïÌPôS[c5«�‡í‚¥y›TV•šcIŸ{o¡ Õt½uÄéÿyÊ0Ó˜kpa>Çø»ÏM÷- OVhp&Sˆ&i\€‘ß/ÙhàoGÌ«<…=˜þâ~÷Œe‰³,’©y;%|†9#AÃ�©£|~;‰ç­@2‡Ð÷ó Ã3¤JÆûsêjænÀª¤hyBÕK£åQp²ÂL ó5Ê�ö™Tbf<^?ú/Ÿ`qÖ¬ó$䯨Ñ4ÄÈQÅ"ÚÙB.‹2¯vÕ0›!fqÍËúE7x8`ÿoä)zZ°½¢¯?ë÷{øLüz2N»ïÆ ƒ lkŸ”môJb ]´*–í2?Dш:¸É³“¬Gý`ÿ^4ò`  ƒ²Û�õ à�¿ñ*£À¤04§Ý 8ÊT C»Ÿö„âNÉZë±�’ŽÔäî§N‚~�G&¶Ÿg™³h(`‚á_§nÅšêîoÊ6Íîfj~ç=´çöá o»^µ'åÐwÄ9B9çÀjX8XíjT¡lŽ ùãõíùX"/ßv›¦eèQ\üuëm…V>N5òå%Õôª­=ç0Óï^Ïå^èJSŒ„TØKë+K2›�nTäF¬ø;�Ä}öºÁG :E7QRoŒò[1—Çý8¶á¢ÔB=:±Õ0)çÅ UòâäG†öw`ú�æ7 ÷ôN#¤?²× ¾¼â<õì!H“Ñ£Íq~&OzЇ_Û,”`\ß__  öj+‚å¡‹9Æóçp—?âo '‹khxËÃú–Ñ`Ä;N}•„ù0çQºVpÞ¹•ûcË™ûóUC$G“…WGÇ7U¾qV}¹úƒÑ–Û{¾öë›da3aWº ì …êŽj#�d\`¦]LZ@¤œ³©Èƒhôѹ ’½%>å­à.Ôfà9¬)­t³J`Ï!gk9Ngœä<åöÃAZ¥1r](_tá!5="ÇK$ m„¼ (ÛxÏñå8ýV¹á�RÐs˜x'‡¢H£iÀÄ!ø>%�«×–6ÿÑlY5 «ŠßîDÆNé'cØëÿˆ«áI8x÷Û ¤_ýC¡A*·” ij-³âÙ‡’!u¸Õ _“fÂAѲ/9/éG˜:Ëu÷ú‰Ø .EQZG°tçŽU -Õñ$—KŠG…pæw{ìF-\ò¹ bã‹Î›qe7]ŽÊÀ—¶œÏ÷âµäe–g²,…ñ[¼æŒ(×§ÚØ*RŠ*ôé\3)Ê´«¿c9us”�´¾>*D8_ÿŸŠdïå­� t•C!ÄÁVðÈœê Ã�kŠ�¢qj#„÷|mós¯¯ ȳüe• ®¯ÏàuÝáÔI&\BžÎç <èå`¼KKoLº&…îŸ3;‹iÀ}—R5’Uh g ¦'ßÕ5¹÷Îö³f_�Õs¨À*Ù_i-{+Ö1ä=÷«ÜjÏœœÙ}…KŽO€Áã#®7¦)�Ü ‹9÷±x\©Ü mvŒ©¼0zIAÑLt|hTLîþJ„f}Vpžéïv½U÷K[,8\x¸ÓIq·{9lR~=gMÂÀ^Dé›=trñ¥6a÷ý®¦XýžíáP+ö,ÂëHTÄôy“�–}YÂ"–€Ò¨‚\5¤Ì©Ö„Y°‹ª-Œ“…:É¿ÿ}2°TŽ1¶ô})sÜÓ/ýÁÏ ß Êy˜'ᡲï" :<¿JŸE.Ô“h†/ìÆÊWÒ L SKyòŒ„åVO%ˆÉÛO:ÉŸlöamžNqªÔ}|”´�?)l•I�q˜î7®`¤Äáf8Ç4 ýa(¥PnÂv;XÃf,¬…°Æ…¬­îŸŒÏh�Ì´MË(!SMêë°NçÕË#UÚ—Ê0 ×?°™�Öö@]ÖÇÿóû8zÆ‹aCÒ°³ââù“’&u�ÍÿÌ{ žä4�¯@&`ie²é7³3^o×—H>°•©§Y9JÌnIílaÎûÞäd;|!Èô•éÑ;yÉ"ÿ߯7ŒÉ›X‹ERÁ:œl©‚`$0l‰ñÇ+Ñ‚dãË‘<ȤۂŠX!q…wÃR’siÕgWi²ý˜©÷áíãýo®RaLËÎo›lhœ˜Z•2#™PöÎØÈ‡´°Ó5Á+ØOð pxW4„òi8?K0ÏsÊuìæ‘ºR÷Ýs[SAw×Ü$”±Å\†uÑø+œ9,•ŒmêØ/^h…p†'S¥FíÃiA¡°-b¨›¾4£¨Á«°¸öÒD)MAùO8Š”\4#lòô{„n¤1Rt¨šuŠ–i3Ú4W«Ïµª—žž¿R0ô')‚l“œ÷Á{HÂYˆ &"vDbÚúÓ¨6sP]¨®' C�)žÕÃ=óîàâw¡ Ü¿¢jíb8 5x…sX,k¯A™s¢PTⵜ:^ï“50°´'‰¥fãªiœ›Nªr£¶ £„ö“[Â3,‹r[–¿…ƒJ„ó�üŽMN•QãäT4Y­F€,òe–Ä/ ñwÁ½Ï¶~%IrY×$kû²scÞô�Ýo3Ó“@ïð䌘+°‘,Bx´ÛŸ†®¥6‹;,K� Êi–ªM”¢½´Ð[l|9p¶Ö’Æ>‡M°zÁñ§ÛñÇæî²ikPZo¦—ß”«¶=2Ÿ6*Œ <Ô¦)!þêùGúv6ɵ;¶iºëTóRêúŒŠÐóP�¼·.uàÿŸ(RU�Áp 䨇´Ý% m4õZ|ÙÓý©ðwqÖ2ów û’ Ž\2·a²ƒà ³Mr ?X°DœÖc»Ø«_;@�´ù*¶É¸ù–ÎÒœ’Ý ?òª €Â Œ‡¾ÓÂÂÏ ÷Œ$[#«†±· „}=ùgqdŸ1ܿڀ×ÕZTàK‰4³níO½d#ºWM=>ïÐTf¢|´¡¤?@Ÿ€EŒŒ¶æ ¿”c@³Á~q£ˆµZYK›wÅ0L¿FŸðé¢çå‹%7îƒm;¦ó¯Ÿ2%ûã¤�£�G–öûèÊðkó>ž2Ú�¤]!ÝF¦„ÿ ±Î[h¶"+Kd# -÷|U™P5D}`›ë%à µQ2_ß[cû@'r7VwVu}%™‹œúWgMq?J�†ðþp¤ÿSNw8™\¤%fKnIêª�K›;?àª;Û@ð8ñӦ’��n÷Ö-ØÜÖšºA¼üüµ\i–,Yu¸Íè�ü†§Â(žåœ(PZ=]5 qÌÅ�æü–È¡TѾÀ§_+Ôü ؾ–¸Ž}ƒ°S9€”?ä’ІEþZo@qçξ ¬ rTѺI:ÅêGp+U,?¢(úLò†M— öU¦Tªú½ %I6Ò<�Ò¤¬¯ÃÂ� •†Õô€…éÀ¹éå¥S2¢øÓã½ ~fêoå äìükr£ìa|CÄ,�­åÔd.½½(h„º ²tc¢Çy›!7Y8/rʧ#ØnN‘"íEó5pLîÁ`]eÂN¹ J@�H&l½G)ȶð�Gƒì¹�9ÿ"Ö«z EÕ› àG¹Š†\¼ÙäFšEõjÚO ïP@P3ƒ>Hi‹Bœò¾i‰f�V8¨}K´Ðº ï qÈ‹N|N¬LÆÙü6àH.õê£RÓ¢²†ÌÊîËË8¦“c¨´l3ìÃÜÕ³L'ÉvŸE„_MÖ~,Ggxè =.&ÄÜO´™0õEi<úÒO€ÞÀ…:bì9ƒZ÷ØÙ´³É@Uá€ÛMFÜyÔ‘�p®=0,²…#&_“_uÆ·.iiãKvâ]–Ѩ§®×€YZ ¤V ãÇeÊÙ …¢x¼ÒS„¢ÿÐõÜÎcãÛźä8Ñc*ˆ4 ¹ë�ÒÆäºèQ,ŸØ”=J¯üµdž@ÚÓæ€THµ&Êî'8—‚5‹– à–“®çQ'ç_1W~WoÐ#1«…ìBs·u,¦n*ž¹žwí—rjÍFY&2jrÛ¿­6XÕ)üËÙùÛ›ÿ‘êÎrW sB‚ð ô¼JÚÚ Ù&o®‰_äG¼x´•,بþ8Ú›ZöZM¹¥Î'VVo> 3]0ÿè•ä¾1ü&…‚R›Ø°ó¢“Kf ÖÖ ÓLï¤×-j”©“�v‡‡&ÁŠÏxYi‘‹B| �ùîߎ=w\Ýä–âí;.y/wþdÆÚ®Û¿ëº]#=ÅÑ Ibj�f³j$‡ê6Ìï­ÁÔÄ婨m ¥WuÆ®žjoFw¦ÌLïÞú¼!°^ݧùª*»óËg^¬ÊJ\Fê#$PÝQP© ö/¡FD�(Wš-µz.xñ¥™p¤Lz º}žæuRéú�þáZ :»OöÓ 9»ñžã;ÎRŽWã9qf>hÙ™¥GŸAÄ3Ga“@ËïIèb$Q�æ Ö:Mö§HbÏÍq,*™Þ­.žF&;‹/Äš�óÒtöÒR'¡�7XÛ»úþí|6V§B9{F\â+„‡î/¶.½jàãØ,¬Ï WlgÕfÀ–Gp�j=â½J­.)KâÚøzeépbåƒé®¾Ã²ýhcÇŽ¨Emˆ9Z_Í’¢D™½d.½dV¸’<áìð^à„ù²fâÊ…Ç­ˆ4ñ ç‰b[ÿÎ/²+Ì.°òäšå9¡š-bÔªJ1¼pM»=$eEsS&I®Ê¨¾«b ` ´@µã�qŽèïzG�^J¦#k’µÈ  wýJojw6g>iûu,JQƒŠ¤çÓ^ftjì´_Sµz[Ç1š¦–iÚÛ,ÈÆêG¿íQ/ÄnU†�§WàÔ/Ö*¸Éënþ–¾ÜšGQ…m[a#jmJ F •¤Z¼wh×c‡ Xä‹RÁÔÅ›—ú'AW7t”3Àt~|¹#bXF', ‚ü'ïÔ{D‘>Ú½&0ùᵊUzP*1Ïö:ûÖŠù¶kÇ2=MSûÍ€e8b¼z 3óÄêCuœ 6Õ‘¥=3Ó¿SÚ€/•޶ÝT#,£�?Í¥œœ„2J³ŸQ7ûSÈãÆMÄfùY˜ò·){w;°3ÓÛ9á,=¥Õ(ÚÑØ¨ð½8L~ù-„¼�&–ˆÈá ïÛ‚*9}!y»»àã™ñŒhT²VÝOÏV‡ÔÅ�Ôî}·ßu{&ÿ^ï…[Q~ýWD:(Ýo¸Ó¿?†­±„Y‹·X„Y.VÆÚ(ù™ÁïGO¹®Úp‰}X™D¬êEd¢ýÝÊqrÊAJ& ^¦l÷Å+Lÿw^g±î6ÒŠCªðüé”ÍZâáH‰o¾w‘A¬|úPD H˜ 8¹š5\ Šª+÷d•”«ô5HˆùÅÀ9Ư¤Ÿ®SþÊê±0ù½XàâZW”-²{˜U‚«Œ%·(Íâ!iøZ\UÃݯ‚Â"Þ�‡¹ûoª/á.+ý ÒH ›Z„)ÖéR·Ï)�ØYk×ÞÎ 7-ä�$^%¶x/ÂÂTòaû9Q¿g®lSnÊwWÅeñ»eç©ú%…ü‡][ø„ÍÞ£u*¨B î�Vˆ³ik-‹¨ƒ¶&^‡¸X÷õðf–rª²…»´�ÖÕ¼6ó§ËËv´•à,$+ ÐX‚ -¤zJŽ‘Ðo¤ÂÆR‡§¢:¨:b&žØdÓìLêYú%^”DœF¿ !£u«üuއŒò8’Kaá/ÀÎT<ÁfNåâ‰J¿èÓ%^uñ¢§¶²Ò?#¿æ<2�°ý¶? ÇâŠGlËÅÎö[¨@¼™ FG´×M7YÅ{‘ô&ªjKíÝÚö=^m/Š¥VËá�ßÅœm½, ·lNÿ�%u‚vW^šÛÄPJnkù·ºG¼/˜«Œ÷°W©\8¾¼³“вӱÔÁ-a!ú<)èßK1éâ*è–Þ-G@OßÆÒ”¦ž=ù]÷õ¢aÅ ôYŸ*Ÿ÷àúw4™å…×»®|¹ú–¸üǹA›_uay†9´eQ¦;¯ö ð<‘“¹bNAixcé¶`e’e­1s/�f°ÿþáCcí`Ú–K£ÌCˆ²âÓÀ>k6­�U|ð¡6zjEô©Oüaâ2ÝàèîåEå�ÃvñùÎ5ùVœ Ùi·löGY‡r°šÐSEapttÞl>ç›k~t6M+E:ç(!ÇŸ%gÌ—)Zÿó» X*½$;u¹AëÑom Ìu’R—eâ��zZs§à5Cƽõ%nç‡t˜!¦wv€0¹;¥ 57qÛ ŸCO`?ÄÉÏA°SÿÈ¡-Çø ~Åvêåo›êV3¢�IÁýóÊóþ#FÊ.(´/êIàÛ¶,‰“àk™Û±Š¾CŽþò˜>¨ì¹:ôMG¢fÏVvñ^ö2ôË/Ÿsô0@ÇOÚ`UwVdïΓ—…IŒ¬ÙW3�sU‘¿zð%î\Œl.àv¡í˜�² ÁoV^¦S¸¤Ü,¼£&+ZhïŒr&ÝkÏ� 5�Ï‹,ï#%qÜéñÞ³é ù‡­j(«>í.f2 ÛOÁtWaáA‘óÞa�Ëßê#u@þs¼/' wˆ¢»�6È>}Bµ•ÄgÁ¹Ì’Êó&TtšÓ;‘Ñ}~¼rY51¬L¤å³Vdá]fóè‘bÛª«ìUйsè>Õü5mx*–™X‡ˆeaF‰¸7°R �›¼UEÚŒ_‡1cA®ò׵ܡB$õ–¾GÍáó ”™�ä/OãÞÖ%A…JÈë¬T²F óãÛª§V'ßWjZ“7í#[÷6D«Õ0Ì�«©�g«™æÐZÊãÜöÔ’P)^ûøÒ̽ê6MƱÀÿ-ÊžŽkOÜÚ xD7‘ ãtÉ!ErBN4ˆVüÊwéWØöØ–C¸þì ƒé(åüs˜Eü?W[ÒϘÄav¾J@AˆyU±Zèr1@Kåw"H*̾ºWÜ€ky×»¾ gŠ|màXÑæñ )ÅÇìIƒb¬: i8Këø3†œM­Ÿ¼4€¡4k(;ÂC@8º7˜cì%<ˆZ‹7ò'cÚP ÇUžSc0ŸÄÝÂÛ�m³ÞpŠ~¤+§ÌÌâÉÚ\‹6!ÖðŽÞ•ƒ¾`­Ï�äü¶ÃzÔÌ¡(kÌÓ‘ÞŠ€’)'¯è:*ôyj˜>�ØP�Ñõ:%ÎÞFuW+0�g0bɺ]‘�P~�Ö‡eTºwû¡Ö£ß¶¯Ïáz.‰l£5/;ˆ£0bñTõåWÿúÐTgW %C ™³ÒŠZK �1~jÁNôùc#Ô�¨Êº¤ý}W å ìË[ý.ab‡l½G5pa kC!„2W5q~‡Kˆž$2¶ ¤½Àay™¦bq˜¾·Üb=ŒðZ™÷2’žpt ! SQs¨LÒÄh®º•4s�S£A|'&~¸Îõ¾ó°T‘±ÿ?v®LñdCDÙ4ö¯5в«›gx€ŸúpÍÔëÏü“‹Tz}ï‹©hg'3Tcsj3×9‰œuFuŶ™,—…’Y_”e2cZpãˆ3xæN¯ Áþ�Ô�å•ذ„� Uˆ>TÚAf’ð°ôÅOr4Úk56ŽÌŠÀ?ß¶Œómt95÷v$ :…P¤ïIwRa‘k§¾ò^¾âc/ÐÏ}fé"“ Q§‹i\|A"Le ª,…oG1ƒMþs+xierz�Ý/_ª²¬È[‰œ3HÊH‚M…nh¤K‹Ò´t+ð[¥\çöV„yº‰Ú†™{Û«áȱ,·'Ω�Z¨A[²¸½�,�ÞUƨ=zàþܺòdâ 2÷,½¤\#!W1}ßÖº?ƒTB¼ ¼š™OL±¿ŸAÓ\cz¨S†¾z;"ÓóŒû:ÏnD´¨Q¨ÑÀHŒHÈ“ ¡y²È’!³“L׃«ŠÊ=³*¡žDúQ9ähAO;ÛÕ‰'t:Ÿ�¹Kgã«þš\(ŽVQÌ �XÈÝP|ãef|¨¤ˆùÑh²Jpt‡‹ÿE {m‚s ®+ÄMp¿{2¨l•óO{c4uÒ®öÚzµ‹ÍÃif}H< éMÄæˆ²_(¤a“^zÒiV*u÷Fׯ­é–¸v ½Ÿ3IŒ$– æk¤}¹þ&aîl ¹DüïBDz³í…e¾i¹�'Ó“TëÏãUÇ:ƃ@yb,J«™Júap '’ÀNëÿODƒA³³\ €=#ÛÂyèóf3ŒØšv;wØûxþsö ÚP±roê{‘·ÿ¦m<æ@Ÿ 3%vox8Ù]ËøÆ«£= ï§ÇÄ'uvî¶Î0*#?¡Nõ)¾#ÿ“£ 1îÂã/õŒp)ÐÝvnIµCÆ÷NQ8ÃMÚÎÓSD[æœM'¸‡Ç´[ܰ�ÐîìeCnÄ\:ì9À úTEB‡v{4úo ³Ä†“[+Ö¯ yÑqp, EÇ�SQ�>¾ÎíRÀCé {^Ê™¯ˆn�€;Ønêb‡‚ñ9ÚëYìÀãV+Ò»;j<³'æ�û9"!hiæ@»ßÉAà!é(¡˜x, ’ÎZfØ;—‰�¾Š±!�_”žÏQTG~¦·¬|ža~Þ—ÞŸ{ê)‰NQ’R¢°O`s’ïÖ GYõÝ»^M��Á¤5˜²óAke=ÂWRÝš€¨ôOyÙ�!‡ÿ:%¹£gä|ÖÛéÒóÍvªSüØ AœÁÌÀoÈB=¿)J醾¦ïw)�‰_Ãi©åVž²²ù“¦ÓS‰b³’ót�Z4ÒU†H3Ó·R?L騥(ÓŠmjÅåÁÏövyšt_ЮÐD?\�Ф ù[aÝ�Ç&¤DP¡¼åê&K¯G÷ŒóóÇŒžë—|>$­�¬;0¦ÕÎ\Œô Ø`ͪ,VC40àÇ“gKåäá6_½ÆߪŒ.`¼Î—댑¼|É,�Ù=E“ïÚØ*&p‡Ô¥›Ã÷‘åõMZÿ²€êñYÎÓ˜;|�•z"PÆ Q´�‰¼QÁ™Wzî+¹P_Ñõ‹cÆÅo¡wÿùqªÖ^èñšMXq­tÅmƒ[^ZÆ•ÿ4Åݾgÿó5AT„zÄ®Áô˜a6ó€CôZ¾‚BÊÌŒZf‚ƽûG Éá÷ïè£ïÍÿ·hA9ˆÞ‡4ªfºMèUÞèš1H%wîhQÅ:GŸ…ˆÐ 0?=éʾáChW4~Y \§‡+A¸¡ð—Ÿ›Y²”kØ›w�½á­’Ü)oÙçƒr¸Ü×»Db£s¢ðÃk—…�K®c³(š¢ýΜ¯–l\x¸ˆåY…ô‡. ~òÀ&"·ÈBwmBe.êÔ�¦ ¼Ã³É˜:*ù›èCH]p8øÆÎbiè ~r­GI)jÁ:Þò;Õý©ÝW~K�¶ûÅqÓOõ?Ö`D톳jèLØhL³hÏ'm¡gà‡€ª�D†V�o‡—{ÐŽY+£Ç(ŠPüÔïûoÜi&/Ò�Àu~ØûìîCî’/éü)¯Q.‘B†Ö#ð„Ÿº‘d…�ÍJ§ÏÞëhìÛ%ñdTsµb»˜ÛØ^ ÚÒ”TR$.±I†d«X+eÆ×»4ž˜åbCúŒÝ5+[3øÛtmÚ…¬×·…d” ³K=/ã%¯Ø¿­üÉ¿XIûwÃÓíÐÊ ÿ9ðÓÒ/):LHqq[Åà,™” ý1DvmÎYˆ\3«@ ôz‡�ü½Û¾åò=t˜Å�!ÇMÁ›Uu€K q_k~ зÌîìf6+ëRízíL+eøÍ¬–¾òAÃñþè^>¡bwÉs݇r…¼ùm‘EÖX)ÍVêKñCÁÞÐKT ˆçàäG—Á‚1êu‡â¡Xµ{×!×MÉ_=ä5¬!îâ¾ã9ñ.žN¥/™OBÌá„ßH‰äbʻЙxC…‘|r™Ø"PÀ/¶jy¸;æ·‡›Ù&%¾Cô`WPq%>SMT‹Û6yFØQ;‡+]qÛÃá2ŠDïúD´îowO�‚È&F‰w›Ñðq¶æPú š¤�€‹Ð®šª|‰´[i2kÖû«9Öt>ކ3Yw˜¯'Ò±ÛvŸ�ng¬FðÒ?»u�¶Ä®1ÇBƒ{«<ç›9èð,€u*݃ó›Ðè&‚Z®b {̼…üýêמ –Yïg*Yî/41øþp�œ¼aÕ»øÖ(8·˜ô™E .»‹"m×ÝØ¨pW€˜'�5œ3Œù;™³\N‘xåªÉ½v|öÔ©=Óœ¬§œ:CˆKàhyy÷q�õ”Äy_1À´L'„m¼j¦¼=²“ ¯–nE•+ŒP2gس�L³¼­ž@DT¿«75;”í=r]Q¬ÅhJºwK=©ö[N>{»E|ÎÚËçn¾æZ¦ÝÞÆÞ¬èëZ¡’’ÞuûJ}açòëÒDéVÓ &T¹ühÏ!�X�ÊÚ&Ñwª{›@ ²22a·]pȾ�Ø8ÆjûnÌ•Í<‰~f]‡žlf)48xD-”ÜâúyÚ¯Çû½ ¬¹OªAÙñî�I]H³ˆg©ú b¾=›‡ÎõzO,Ïï:úF‰ÐÚ�zì°þ�™ü}jQ ²2¬±‡?sø!.aê%HJŠ%ÔGÕ;F¿¢,Ðû·­Ïù¹�¥SÌõ/-¾Æ%+½CÙñ̆ȦJ6c"½�ÊvGJ+- ½k×tlE–\›J¯ZTÌ‘IP­°|B…U‡?iÌÝ™´×g ŠV“2Íá,ÿæÚó[—À졃)º¨‚{Ò-f2Íw=1sªÝ»¢s–O¼ågðhO Dp˜…oˆ t_fÌsæ„I'xj”ûß�d׊sr§+¨¾„Š£)Xõ¶ þ{BqŠåiúðª÷ù‘GxÝÈ`b!†Gnf¡¢DUÍ¿M Ù‰ÉM2¤J(ef�téÙÐØtÒº…ƒ†ãº ¬ ‡K#Ö!"¹ �é\’JëÎ: ~ìfÐ@s¹ò ö·¿×åQb·M¹Þ!éú.¿ÅäÞ¬Ò*¿hÒÜËú‹Rí”Í/„,®R–� ÷ÇÚ•·9 IŠºí™ctÝÆ Éw0Qfb�Øú÷¾ßœÍlÞ½cÂï«øï5ù[<úZ�ÑÒêÉétÔ'àØÅ7¹'~Ò9åW§V²Œºw~t:f9Óî¿+×›R87vÇîò:}aµr©šîf)Ê|„o°ìüRÀCNkpÃÑ? Ï�ªíVó¾5ç�’ÄÉ�ƒp3ž¾ª–ºp! }ú†v‰„³€¶½ºÕ³É'¥‰“ë·ã¨+:4�à­¶Š[¾‹ªpD[ËÈÒ!¾Aì6³ '„¹»;Cœ Åä㊵Vh¥£ÂÉÁ7À£"IüTKñ¯*€i wbJdàðæI*Ä1�  t¯Ï(ì��Àð“zmsÎÚÂŒøg™©Ð+°¨\“�ÚÆôpR´Ê>-,‹¿¦Ö>PÀÕ÷œÓU̶O„-•PÙöÜ{Y’è@{97´@¦p@âÈ É9áó ¾|ý6²Ä×$õ•Ô.¤å÷v+º!=Ö àÆû³Úç¹3ï(¦šð¬ãǬN”JPÃëY±ü4ðqæmIè-;w…fÆ"�õ�$¹…͵°‡¿Ñ¸ÓS®�ô8B‘¹¯§Œå7BáÂ1ê]ás®qúƒ724f}’K€Åõ¬f×[üôqÖ»LÛ“ô4QVJËZþ…¬�ÌïÙ°«Ó£T€ÖvX�E¼(“ße×oCV³µ”8¥v ¬7v­bÞ¦3¸ã.¦ëΫWËÑbª*ó¦ôÃÈo1�1K�œÑ&`H@KÛ¨Ï2R…faîÖ »º¶2rN2ÌQù¢(X1{þÏ•kôÛ”ÁÛš�yåd°"Gë³å­’R!Ñ5Àž²ŸÜâ–bï¤� 3Þ_ýèHCLoŸ@T•e×#�*ŠÂ üÆ”.JqGô:ÓK!½±^ ¶Uîf�/±SLž.t"r¡Y�«47¹à³ê Äy„Ê +Å¢*ns¡]ápèxáð×F+ôÕ*g`W1²�šTR«°1Sþëî7½/uhK²¶éq\›·O`ƒ$šOÒa‰¥hS^ ‘û´²‡®ÜY‘&ã¼ëi1¸õD€žnqôk�hQ.×l«Ðh”#07ròÆrÀÛ>'˜Bb­I²‘Ûf|Ft„=¥ñ@ÙÄ`î´Žî.7«€˜ÜÅ„½�oùÚÙ)v¼c[R[­æíE¾à:8Æ„áÛÖéŽÂ¡ã’ˆzâq½_z`Œ¾Ü’Qð‡™È¤Œì&à•£ùyÜÍùvêüÍ*¸r›3ôfâs×Ü$ÇăŒŠ/HoåòoˆIÓ-è_ò6)äeÃ6û£òJþ¼Ø•ËFi™ÔE�•ÝÇ‹5Ïw Š 8­>È•¨ŽŠÃv×8¥Ky½‚H`›Ë¡zÈ¢þßnÐ’éÙŒŽj¹çƒw"…äùÒÁºù!ÊõÇÔÕ=úÙv~�€¥<í8A[¯0P†Õx© $zË€YVA¥)¾°² ±gd î\[ººhélç¯ha.ïÆ| E û’S�Œ‘îÖÿeΤþ²i¿…½ü%e¼…hx…³ŒÓãp†=�Fˆòz€U´§3©™R÷ýMa» ŠŸ¦˜m:ªµ•v<6² <ô‰ŒB�™¦¶N&^¿ù�ÑÒð€²�Þˆ”A’DQì+Š4Í-š*·ÏÞ—tˆ.ëßDŽ"%Ø‹Áû).�G[·*ÞyX‡L�ý(Ca[2àúHxbJk2Ž_Þ¾šäSï2fîIŽ[±¿pPP‚ë�BƒÇoe`¦¦áüÃ&ã1/O\úhž‹6Þ˜f¢áåÚ¦ÛNM.1°! zÈméþeù^àŸzQÂäâ°‚Uˆf¦õƒb=_h¼?’$·~JOÓ`Q/Ò`ce�M­å¿q®™àTÀ’d ¦h1‰[�™ ev:ü¦TôË (˜OT[\Мu°UöË�O9u˜YÄÞ1ç#ý:³ÂÌY¸19 ¡â¦ �•Gþêñq d†ëœª„Y${ ¢ÄÐ?±Þ±•ÿ¨tóæ*‰Ã‰W˜Ô4è2Ò®îÂñù�¼±ú¦ñ°^寲4ïgx |ÚÏWGÆåI¡¦¿¦ÕÔ¾†§%Èš‹ÿp€rSå‰pÌ-™B4°xV`BßѾ÷äüµwt‡=¦µZ’ا@wVRWpSû דxo|.ÚU´„?œo°æøÔâš²<¯0\›o¬êïéþ?vá· Èñmi@¥ßdäö$¦è¸dÓ¾o ‰}(|M¿æ’H7�6ûg†õdH#nP°iC×l)Þ«:s júÔ…ÿ,”È2@Ž—‰ägÞ±²ù—T—�¾ k¥Ö¡àM~r5Ë•-Éçâ£mæßƒîâ EJ °Ïq��f0v+Ô÷c�ßñ‰°9/*³î4£X–t!7fâ¥Ò4!’5éM;¹‘+uꣂ�J÷¶%=£íqšó£Ôs}Ž¿2õ¬šš¡:%K‰Bt»9¾¶ÄÍÒ$ª†Üð…jtnÒ.ð#‚{çâ:*�Ýtù5†ƒÆhdˆ%6ùIQH±™ô¾†8q,e 0ê…k�Ut÷ÍŸÑð¾Ö?‚/ÃÈ„8-*s4¬È™£÷#)õS$5‚*·-§�Iìðø”ÉÙΘ=ã³_tïÆ€zƒ#lùÚ;þ�åý͇í‹jШàBž÷�ÅÏ=Sñ;ßÔü¹gXfùÞM]šW"â•׳”l)';.¬öè 6;œ ³(ünÙsÉ'p $ £ýýàvs›âØ´_¹´@ü."å Awb ˜~ÉhÉmTÚèê¦Û€`º(&Ke«ŽálœÓ/X6|°s9�¼uˆ­l½ßêDðˆì�áÉu.kjÌç’Q !„é¢á…�…µÞô/í7‚š_¸õœÙ)èÿ’ª·Ž¯xÎ�Þ£UvM?ö6ÕÙ Àh—w`­-â´¡o¦(‡ài?cվݒp®³2 l(Ü3öÁ”\]ÑÀr‡î¬wK?Õ5‘Îß@*µã˜†Ýì”9´¯(�äj`]ì././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/tests/data/archive.7z.0020000644000175100001640000006531100000000000022024 0ustar00runnerdocker00000000000000Ñ{H‡¯q2ù†lyýN«•Â.Àž5³÷(º¼ûÓj ü½=B—ŸÒ×ô9xæC(lT]€‹IçƒN¿%´×U¹>(ÐõÑ  ù|߂Ĵ`¸³x’ÕT 3}Êõëª#<¥]añÒ¥‰ÕO~a®°&Y‚‘4²’:#K�-Zá6�©2Ö�±ÇÍ‹˜J5¤R[ÑUó0{)0F—Eé:&3•[út¹lƒÈ�¡üøR;ZÁCVŠÑ2»ÉõNŵ킟�ƒ½â@%’A—— †;õ¨ßº[ sjž~�¿M@rž >éß&¨/¿È3X¤(®–î?áÄG¬ÌN%€Ñ“ó�”œ·Bð¹#ˆÔ§,fýMÀ­U}*A{ÅöV÷  @¦—tMWû¥3ß �Äߪ'¾9σ™lÃÿ)yûàÛjƒrzhæþ&¾Œ6,þ›J£7\Ù¶‘ªùÆ—ŽíBô¨ �^gP1“iXJ‰ã-¾Cú Ùî7r £~uôõ&*µZ ÙœwÐ4÷Å¡³Ý§w® Þ[Øå4—x/Ç0®�è: ‡¾®é׌êƒ]ÛåˆçCZž9Âð–[²'æZ¼¸HUKØ�…¹ H¥º^•� &Ù­GÈ/ +#§‹Ä†abkešïfçdƒ§“ƒà[rS©Ò6¬¹Éÿ RŸ‡A9×uþAP‘Áh‚ŸËq[bTdDãl•:(q¬rtùƒ„™{M/¸RMÓñ ] –jˆ<>¹OÁÚÓåÂ9ñ yn|¥ðß%»Ó8Ð`fOYŒ�–º"ɰ2lC=rßšÊ��ÊIû‘°i§)J¾%Ë ™ƒR{¦ˆ2Ú»Aï4Û©²k¤-dº âcÜd\n¼¦õº ì t{‘üÐòÎY�}#ÂÈ¢x¡æAæ\§§"…óju�4üYj¶óf£�ÚÌ–ögˆâßGPba<Å`!¢*ÿ‡:«g= ë�à�µöjƳ(È ¡Q§?ßWRf×…Ö¾·ab€þÙË^åqaLZæm!M|‹šãQhLÿõ.SËÏ óMÑ͵ð÷#£íڼŀd*N"<·<ƒØèùp]lT%‚�ÎINìê=ásÝ|$‘f Ä`a¢y®÷m¬).’Ý©&DÜâ9›Pyò'Þâ.sØCs}³v€e´>S*õYÙJoà4é½Nµ%²˜³�06™·b†êÌ$G¶øM)Ø“0ZqÿžQï v` ”-�ŠDÑ:$Žö@ÐmMrL‰“³Aã¥XƒrÁì€é&R� ÈyžÓ¾õ¾›6)y,Ø“ƒ„xiT?w@XEëä2åœ÷¨¥f!žFÂÓõe´a8T¦W=DOav/enjâRJkçÉIö¶F&¥î�;]®PŽœãÏØÜžWõd5Œø:)B2µ9j£‘dÞñS ¬XÌ:/�<Ô`4Xêæ`’‘šžVé–ÿËáÅü‡r·…ÌO\‹#Z/äê‡bX�*éî9�@�XƒT;ÝXð¨Æ/ˆL5ÔAA]q¿ºBDÛØÔH0ãÙzvk›^íúêW#Ýçé‚ ÈSs#�õ/”õ õê©Ú©ù4ÝV,±®ñêÀ$$ ¯LýíDåX_RYŽÞÛÑ/K¡#Ùã’wÓ×Ę8CØ<Ô�³R ²8ðu°ª–èWZ,ù¥Á3M¥#àôF+ ΡD¦ä‘,®ÛT.ƒøß&Sµ,hGjÀÃuéh·‰¢žTË ºgá5¯õš€ÁþeD¤Þ„%‚÷Õ/Ï—¶ûkJ8mº c�»$®�óõEç Géý‚�±ž£+îÖ‡€ºm™O:Ô˜ógÍF´µð tZ17„…½ùÃÃmñÇ6º{RÎ ²{�'„ÇO ÈVà Æaýoâ¬I.ÐÈÀžq¹éª�AUž~‹·¹À¼b¦³&y×ÜWu ôò.VLªšBe5¿{³jwèØ�wZ80÷'VxñuÙ¢# I®qéuî¤|éÇÐq8Ë…¹F‚¤Õì]Ñ�ûf|�ˆø!>å7‰�Rx[à�«kz7J@¸—‰z@Oã"òðt�>6BY 4^ @'9¥ß·[VÑÐW•r¼ÑùAáID€ÔŒ�õ³´Oq»›á/aT]&–Žp÷ì»êôÿ”/DîN½Û+ñSÓ嫼NýΡc@HC)|W1šmg&Ièš =,Ë÷ÇF’¸2¾Ÿf»¦ó,ì�„Qà£ÆT\cçf¬™� :Kþö,n_ãÜ�¡ä›èWÊP4aÙÞ|HÀçq°/Bb©ýêCó®Ò›žg¡ò²óVem"N‹�Ø«™êä=¨ÝÈ=æ¯À™ë»ìkÅk— Ë£1“ÑrÍ�õ¬He5--8þ˜Ü'�2½ýVÛr]LÁw¶xÒÄiŠ¢2(å3Ì»JѸ‘Xà"‹w¨{Ïò¶@ϾQ›Oks fÑm! '5L¯$®˜ºßwM"Oôµ„)xÛžŠí\±‘ µ“v0Jgš#€�á»M¤Ð·WHƙ‰i$Fpš%ypU³)O‚ǹî«45÷:êôãA$üQ—QãlY²à^îµÜDx|ÛvŠšÅ¢Ê²L†�AÄšÇìKåEÑÝ12‰ä/ué‘uÇùë�EÐðP¡I"¸¶¥èYº;D­ÓÄYŒ¿gC3wÐ<ã]¢Âf²NZ|ü•&°ÑLyÔûP9Š#ƒæ�LËÑnu–]¬ Œu…¡ª$£á?�õØ@zœA ŸWËíhÞâX)I$;"ùGd–x¢…XœöÁýxê×v ZO†ÛÑ»¿ÕÈÖàWÑ= +q˜doï°wèÂèHÖì3'šh�Óä“Pd»µµÑþä®à $ ™.­@k"ß�–qWóÅY¥G‚µä�Ñ:‰×¡ÅCN�™½ ¾åÑ™a¥–z<Çõ@Œ¶o‚3R, lÍ�ÓÓù%xµ¯WÞçØ©Ë“j`£ÕÖ… ø’ÄÄò^¯3ûÍ?.ɵ"Õü7à  ê¿ò\‹ñ­¨S ÞÉ÷œx3ž|cSD—[1T•J—uˆÑý‘2`à•b¯;Þe!³Þì>²Ùfn.NV¬A´žÍÌÏ’K„_Ã[âbjl"šì7@Žà‚ˆrPéí’Kõq8¡øro=BH’ÚÀðÜ„Bàlm1€eaw»3߉4fOõ/ÓÌZ¯ÔÙtƒM=`íó>ä´N'©hÉ?]b ŠÉ|‘Îõ#+Ú‘èßÃÉ–LP‡IJÄ){çKÀ¸¿±�è™ñôÆÏá=ìNýYÙŸV·’é9DG>~gÎiGDźù[¬lÍ(ÙŽéM/Ç#ãE*#0OråÃg;ˆ~4Æ\9*Ö9ŸæÑ_>ÏÖºE:¨\�{#`×ÿokãì÷Ž‹¨‚P˜£í›�`ç:§d’_J²’~lŒ!íôÙü4+È¡g¹ôÔÎà =u©Òšì•i#o úhŸO~ B:k�>zŒ šƒ ºaë ñ1ãOãBSÔØ^qáC Q>ê§ø1ù{ÚïYÒà÷ô/R j£qÙö ÉñÚKÞ p ³àrÔhf…þÀ9!sבÓÌ0EÝMEÔ)'«hU„éÄŽ¬$Y•î:«Æ[”¦êµóÞ΋¡aOþC/W$1ž¨ Ô é“õé»f90|Ž’è²8<þ·ãL ¸?1Õ°ÛÆé`óáPœØÃpTà S—uc•q`2ñq˜Uþ­¹ÕÉKÄ`r!Èè¹CäËž�%¢k[ÿC,B{crî´÷ah8„…›®$]ðqØë“ Þ¥Ù·Wj›ùÍ(ž·¨7Ög×ý~ZŽÿÜa¹ÎNÖª’çzÒ’^–—èsCéÛ£Ê��ÒÃIhïßÁ_¶>I§+Ÿã°“NìÁu6/Ž‚G˜?dšÀ4MÙ<"òE¶QàZÑv5~/1ùw:|t½�¼p#µiCzŽBÿ ¤ V` j™šäÓ$ Òêç„ÑÝ~·aÖrô 9rÑnŠºÄ ¥��É6€œàüQïÜ 'i5õ‡Úy-ˆîÙºlÐt÷4Œ|ç�t>4BOõ�ýW‹ôÒ^œ‚ª,¤‘/O#SLH[ZÑŒ�)?½ïß7dµ‰NRì±ú3¹áû[<ÌñCnvÜÁ²ÉŒõ •G9ñÛºl'çT涃¾Yòé$òlxººwW/�„ºÂΰ0ÕÄc'Ú‘j?òd¹ à >$d®ö!•Ž^ÐyÊRÈ„|Lµ~¨À]x›ßÀÅrEªØn7éNë�‚æÔ½ëúéôjS¾¤•Ý¿«oµ –€h�‡äA‚TĆⱦGöF-Mž„›Êó,€€+ä/Ç€—(ûShCÇ;ì)çé¼³N«5hüMáög¤H®w¾Ä9'ÅÊð{°2Å»“¡÷eÄE7¼zÖËŠÅ¢A£—È"NEk*;•¢ÔÂÚ<Ã5ë!`C‹OÄa\„æÈº‡”xàø¶+V*±¹KåôNg–»>÷³'zXÓ|t¢ •%¸ô}Ò‘Ã[Æ$|´‹^‰M‘`/«Þ¬ÓðÅú³;+�f¶"¨�)&K£‹ÇÇL×eJŠ‹ä2B!]�€�=Êylrw6C7 �\º|©­ä‘>J˜®Ð˜—-8.µ¯Ó1�v^Fæ×î…Æàv°oDAþvò\JfŠ‹™ëðÊ@t¨9¨©ODñ:³¹= ÙRìB$´8á±ÈÉ1ʆ»#F—ì¦vE Û°ŠÏœß× ŒüI@ÃÞ”ŽÅ‹%ךÆãCY…Áð¾Ê_áÇ‚Ëå�–‰¦’VÛ—Šõí8;òp(ฦ›ÛK�]JY$JP&ÂD¹mß9_§l hïOTõEÎþ7Ôèný‹ÜëŒcÝ�ƒÒ3œ[ú?©%%&¡É .ÀÈ�e›ATÏí#]ûT”¤¹Ýjn›@“)x˜m$’Þƒ¼Nó{èº�2t)­{¾(™ó‘ *Ëm¹×3ÓÅòX¬/ӲƻW‰±<´óöà(> ©ŠƒŒËýnæ£ÃzxJÞç.ˆGg®"2e%A±ËW<Ü…o½u¶úæšö]îþÞƒ[v geJQ»ö•s Uÿdê @’±Ú&‘†Œ~vÞ’óý©Í�Ëšdrïà ú³tþèCzDõ¤$;`“ç?‹^Ì%ýv ÑÉ͹A•ß"…²dU[�ž�QBƒÄ¬' O‚ÌFýõ?Wa›\ÞÓçOQº(³¨³¸Û(ͪÄ9Ú.Æg„-âiüg÷ã©� !Öªu(˜Œ<7ß_<Ûî8Ѥ„]’&ˆQ€¾í+½ `‹nââ3ÉO�*O|¿ê™±«ˆôÿµ¤±þû+õRaÃãà‚#ZÓ¹ ·î¯~uéÔ,LÜp ü…¸•®#Ãfÿ½`¾Íãßíÿ(40‘ѱñÄar:¨Ý�zâ»ãÑÀŠ9Õ;¶¼Dt‚º‘­ç¹Å]Mn›ø“®fÍõfV¯PÇëmz&môšµÇfYÜ„ÿ —ÉÅ”ª2íp¥Ü9;²kÐÓÖ!ùœøƒ)|ÅŠÝÌØy�Xª£‰Oí òÌø=išØ‡Ë–VØU¥jÅd,ÀÙÃb $Œ>4õ;A1_ZwÎ$ m"ƒ&ÿ .K6�¶þ«:–÷·5¸û]çhST)^t²Ãï]qCGzjÎ6yaP€èèa1]e—9'­Ìx‘^ÿ‚ŒÆ²µ™ÿ%oPw^qRM <um{’¡Æ1dvŸø9ó:Ï�r:—X7€¼$}Ž0kÊÒÙ$–ÎhBòÊ| ,!£|�lb`U8ã±¼Y¤ávn1IŠkä�cæÿУ+ÊÞÞOHêõ1Òó+ ¼�FÝhÝþ©±sŽd] ½F§ËgýÍ�õ7R:S�fŽ[´þ‡ê|c{R×ïyR®Á7ŒÇIÔ²Àk}¼Uör±öˆ-p°úCÒÒÆ�êtsÙPΩm°~‹­�Èr5œˆdè I’q×ûŸBQXÿEË”[ ««5ówK‡Y›5"‘bÚ_Ñ7òUÐÿÔS(MCÓ(-+…_¬Xv¼Áð»å„Ÿ(WÖ$£xc+ºÌGÇÀÑ·Ñ�rýŒÝÍ�iÔ•Qw›>¹Ø¬R¢#ÞüKèÓÁTkÓŸ¹q‰v>ƒ?×�÷ÅÚ*‹@w+£œmòoÓ’éJ{©Š§'My‡£,爲yÿk1bÓü´ úUÛ}Ê´G£\D¦ŠÆH#}‰|wÌ'�Û¦|øC%Ù|3×Û¸EÓ[ÕV·ˆW%œ6T›’tèܹ’o ¶¿2drYä)¡Ö“vw|-X=YÅÿÞó· «®>M<Þ,ƒ/-Ö&Û&¤98›Õ„BŒ'Ö?¬¤¨q>@]ø°¼Žºà‹'ÂC‡òy‘“OÑ¿�èÈšhdZ_ù1Ò­…¢–•e¿GLƒ~ž[‚ZË_KÝz}ì‰&¨O"­€ ý�DÓÀà[jÞð;uI`ð('kB^h†pš;E+‘¦€'´êx’¼€Îø‡Óå•_mÕ¡1a7öãBP›RëlH]­"ä'Àã*¸éQy¶'Sœk¼g§`™'Ž�_¹ù�äS˜¡éñ¿xÒZ–j!Íœ{)mo�÷êXúMð•‚fw#‹r6œËP•,¬ œ‰¼—n‹+¯ã#zFÔH×òðÎõ¥ÄZ Ë*âÉ]�¸ôí§n,áÝàmª„|éÇÐçÌ“ƒd›Å ² >N2‹“Áߌƒ`˜¬ø0�@y¶#ÖVªMUsÇq·Õ’nÛî¼B¢> ̓œ•ß��Ü@ƒK’$¤¤[…Wü’ªõ)/9DçûŠâµV:�Rðï1ÅÑP4‚æ$ÊXìþ8ˤÇÍ ž\ÅŒúœÏ1—‹Ré­eEú¦é¥Škô›múù› ¨²…rZ»ø^I˜›:ø€ÊæHç1ëÛ#uéý Fù‰3.¢�?ØXAÌ´>¿Âb¶ÎŸuÓyÇM~£u€ƒö ™%0ÄdÉ?PŒ7BTT¤ÀPyI�Î|�ÕÜvà„­Zÿ„ijª·¤8¼9©•¡ ¦wvDÝÏÂ3XbÒh,¬k¿¯±bÌ#ïEÔªüÔøŽ–nA…qž?.?óÙâ6çlåÅþ¯óEÊÿË3æ-˜ÓXs–Jó+à¥2/ù¹ƒ.]@$Îc³nn,ž(n~´$ˆle  Rè› ƒ| $/ésXÞš^‚'ã�ˆæ¥z<�ÄÕÇÞYjÊþ”(?–¥� ò}¹ ¨4rŸ—‰ ÃÌe]ª+¢h§Y7©gØlzM‰s¾8¡êO´ ó ¯•œfñAQHB@µYÚªØ~:"Eþ—íÁf7dëY³ÔE(ÈHÿ�é&,:*˜ì ]x¢“žùŽ\¤EŽVÛÝÃç‡üYH,uÌè²�Äþ$ß5£pÔi©Nnsr2§“Q˜‡}Ø�œz�BA³çÚ^å*Ìó%Q ƒ«_\EÕ6›,êsUƒÓ [ 8:Yös¤—ÖmÕ£Ä[)‚?Zäš&öÛZ{÷Ëþ[òd´©dΧp9¥Ï¾Z8ã4¨t‰™EË¢‘ÿ}a±öA9z¦ç”I,¸tÓÕSgСuëÄe–+ ÒÒ �Bd±Ûæ¤ F!�Žæ¼òJŽ 7‘Yãóûzˆï©“ò�0îáñÚ«‚ÄÓr,fBÃÚ&³�äT‚™+Æo»61ÖÄ¡ºgWÎ&i¸–Õ䡚q¼YY=žû`©ÇUGa°ö¡‚ í]øuí€} çМ™É�¼¤û€2šŒ w$cb›Íuó¥Ðé°¨P U=^B8жÌÞÊ®•IÆbž¡¦Ê¯¿WëRÔùË8S•À?]C ¹}:câÈ-LíÏþu6"[§%‡îF%‰íõéïFa)¹p?ôѶÝ_ µ²¬fqúÒÍIÎyGáÜIûMì`ïÙ¾x^Àu»Z¾ºµL[›ù–+F&ƒÎT�2NÆŒvG™£Ôž�)í#ÎÄ�k½ Õw,øèæù-ƒŽhz�Í U{ÕÒ|ØáT5ðdFû‰·ØJÇDóm þå¡|/YêPTÅx8ýÇ Ä^žqµîßr¯ráî�®»¨…+-Ž»ø+Á©æè‘xùæ™wQÎm.B½ñ=Hïw]3¸oSÝífLEmã`†:|ú0¿ž ¦ûi¨[§l5ßÒ÷scÜÙE —rõl ýÄ»i ia»¸‰òÂu«�íyíïÀDac×Úo‹‘©©½ñ¡½Ìà{{Ÿ—Í"k·ÃSåí֜²'Î=Xnäž<Õ:ð6LO6DúXÉ  Ýë£ÚÍl†Ä¨­¶0åš#¿øµ7Òñ8 åUZ'ýû"],4v'jÝ!cK›(;Ì¡-üøæÜMG~ªä ÌÑ5nAºœ xÛµÓ&ƒyÆV¦ t£«Èã»ç‚ij¨u�ü±—‡ß+ƒJYþ3XÉÒÑ» ÙÖ)$à ÂUT‰=UþÔ¡N:zÙYÏÎv3Já8…[Á-öHQâ€r\ƒ‘#º7î÷O ÃgYe b´;EC�W?�¿%η=&äyþç—'®Õ Mõÿq*uø™ëqÎ6ù8iºeO.“âÝ—b ŒÃxáÓÑ^jÛ^dHùT~²i^ÂÚnøƒ§éTl,Æ�ëõO[‰pEúÞÐ5ÌÐQÀ´G¿�yqЍâªä4\Q­·Áw¸ß ìÃŒ�ãhŸ·wV>ÅëÄy)0®Ýé´¿Ò!æµö®2˜ãÛï§àíËÊlp�ÿ£ t;±w³6fž�½µ2öXç2Üô™½@êëiÇ]ÿ"A3˜ßT[%t¥ƒ™Dá‘ÉŠÆDnbgºÇÚ|ðCw÷ÚñBóJÈñég* Jq[†]À[^ �Q2×ûòõ�èu‹!åc¥Š±ë{, ÁC•»á]Û 1¿Ïß¾ÎMVÒ\¢ðwKQÐXüÆ"ÑGὫ€Š|»–"0xûÒÁâRÁh�i0$,¸Ò¯dã¾&’¾’ `"6°"PJÀÅA¹î~AÊÛ#éM*Tò¡_›ë;¢!úÌÞãËPõÄ|žPLÅ�÷Erº˜ìÖÚ×öРLk™M©¯V 4µå¼ÞP„<ü�Sü¼ôuÞC¥»é“´@áÜ�™Ö‚$�œ7È's…o8ÕSŒQ°þDsˆ B¯à-™Gû†ê÷�ÜÞÉ€M8KæC¨,9M`ì,GtÅn�#˜¥î"Íg‚7 o71¼Ã뼸Ê�òÔÌùù¹0{.Ó°ì…@FèfçÇ�zž¶�ýð«ÚÞzÜ8Ž;Ø* §Ié¸=ú‡"¿�€·€ÆN°¤®Bû™|ºØÞì )&g;´Nɸ²omÚœ®Jâ+ÊÜ@�?åH„gÞ})‚ FèO'â—z�+8î‚«·}ªœeб´Ðá,këpšÊ�Ó?2&¸c¤ òQ¡RaÆ�sÖ1ƒ ¤MpB�d7{eÊðß³M&ïŶƒà.¢CÈë”%à&ÕÏ0p2J­;_Ûn99ÁÛ-¥mtòèήu’¡Ä£ÿ-Hã<–Œ®O9j:,£u¨®¢q×dyG ‚(—ø‰ïupD{a3~åeK6æ9Ÿ÷¾ñ@ ÔqéŠdy¬‰ë{ØúŸ�tö9LhFô:Íòƒ·LTV´7¤SkÁ|ÿ›ïéÃG�ÁöIÇ·Rûkç0DI[+g8@v9` ‚7Ídíî–£ Ä Å¤TpêçY†¡ŒêN|óß“YÀ;]Êé$·“E„Ñ!ÛoŒ�­èK� z·¯å¶w&ÌŽýº¨hPýðúÎ~r€Çľí0ÍÞþÇÁd– ±|¼/H1}ÍT€XÚûyØoÜ‘tˆ9CT¡§nò½nÓ;Å!êƒHêø2­dȈ?îv®ë{òµ!¢µâ|ë'~íÙ±ù–Àòjî‘€¬Ñ2Ŭ_£©âZ|Y lYšj6uq¨Ú+wX¤DóýGЉÌ#þ ½s€¬lÓ4ÆÈŽÔ²ÊvûK.�@@Ý(ˆ!1Ã<ï‰)Рç30¥lôftBŒ ]Ë7’Zxß[••>§ˆåmoÑ8–œ•dÔaIFnR»Ž‚ͼ‘$×Í'(ÇùÖÖú&ϸdC3íÙ§åFï Òy+ÿÃs 4¿Â•›(D:¹ƒl†ñ+¸ÙF�¾1ØØ3Q~ß®©h½ÜB¦,¥±'ùƒŠF!(Ö OòÒäÅE¨…]ùEœ_Ýh$ñ=/ØtcFÖ²¥v/–¸ `+?ã1ºa¶7:s��ÿÌñkùM|vϾs`R¹pgS¤mÖâqpN¯¿®ÔWÊ[—ü›á„·­·…!ªi5eßÄA€$áúü„N8Ê:ʉ™Še§¼à)Ga…)І5Ìq4Ç×I?­á¶/’°.ií­CF!©e;ÂsUAï±ãI €vñªl¤“è寤sñ]NìÒm·š’®4|É{!Tzy;‡ÝÃdtâS¼@j=nW=B8ìp6i{.ؘ}ì`Àè"¦O¯’vŽÍò[ëMô�í¬î£Oj½}øAFý‹*¶Ú(1p�FÓKN`5jÉ«ôÑWè§÷›§úzÊê£ÇÜØ·Ï×o@Ö>Ïyɯ[VçÉZØæ€F4N; ‘9KLZ2áN‘Ÿf�ÄDG(bJ+é�ívßíñ_ú~¿Ó¯Ò€ùfξÎ|¢)  ãÚïÕ ¾ÜØ 4Ìà³J¸ÞƲK«9­^¹ùv}Õ7Å $–uÎŽ-ù—¦ ~­ºý×õ¨“oxX-�îÈ©ÃØWãê39/ðˆ5Áã1¥Û±/OO«7 wI´pJu¦°2•Pý0)Ì‹ƒÈ£à�¤ÙA·´{Õ—¢Ýl•õØÜDùS¤Ü¤.AŒß¶P/µ'ÀöÅ×<Äûœ ^rQ@K: TooÁÛ,ÅÅúš/Š¥Ì¯h±�˜2£þÜÅ`·û‹9n4©¶õ¦Ì?eæàÂɯ®š‘æiÖô½³ÈÊ«S�ÓÖGü1 íºé��çMM×ÏªØÆWJ×rkŸ½¬t ª™ÕÃô’ÂÒ|¦�ÆÝ%›_HX‡¢±_þU„ÆÔƒµ…'-ùÈ!ýËgþ\ÕëW µÊXp¤O‘†»·o­¶ˆ“GX¶/¾í Áqš^(¬"§UŸ}žTÇí!ˆÍ*r­/™d£ÞôvÑNÓ> oáÇŸÐø Çrå²ï42øÉ+!Ϩaæû׊Ë3,om{ÅjsÎ',smó ;•†Øü)akI�Þj&žgSÞ@Ì»()Ú¯VåÛ{ÀšsŠ£0 ±È‚  Í7:ÝÞ�äÚ;[ŒóõÿLOR-'æsk—@X˜ÌÍ~ú’‘ø\“®_Ÿ™W. À%‘Ý�­á�ö·î0üäN�|JØò†�IŠéÒqL!6Òµ{º…X+,iac8ï.s”CŠÒgüA»¢h=(�ÃÛu×ïýK‰ùÔØô$PkÕ.“œEÙE’äÌUkwÞ\ Õ ±ýdšô„ŠðBQý:,ÑŒP¼2Ø ~†G9Z¸Ã[•·(uI±“‚˜¦óÉkZ£CMi¯bõÇØt &H�®J0&Í·¸±XõØà·k-lÁ÷¸ÓPYh!H! ŽgtH>²CCiƒ—qKSEz(£è1º\d¸8@CÒîׯ™\*öª—n´×èÎbKûTÒ¯(™ ©‡_Zìvã…µ`·„ê'Wt`‰m¿2‰³¼OÆú¼MÔSúÄ‹H<˜×ªèùÄZ‡Ë˜šIG@¸ACF‚Ü¡:Ò_€ûéU¨î¸yð] ²`ÔØŠëïÈEH!Á0`lˆ‡›mûül­=¡Ô�NN°&Ké‡n)Ç3¶ÒÞê<ÁJFGìú¯ÖA"Nc\ÇÙ„²~"'ï3pÚG/Ðgè*l2†'œk>ÆoÒãªýÅ“�;Ꜵ\u�Áÿ# PdKûö h-= g‚ŽQ(ìÀ+IK(#Ž$ƒzI0M§§ylVSgt�v«p•ž±ŠrÔ³XF·À Ǩ7›*gÒjÆ€EdC¶9!>ƒi”¥¥q&T80q!Ì”sɹy¬âTšÀUþåš„„p\,.X€Àä3ˆÀìk©V:¨›ø¥èñ_ÆTÖñü Eˆ”>2ñkhç:á|º}Z_U\}棢Æu^g%Ê)þœéçpäíËŒÈѵÇá]syâÒÜ_ËÀ¡�^†"¬pD#œ~EæÔ©tS¶@wmãªZ¯ñö³”‘€‘€©J¨ ìÅåéÉ•bFËì(ì¡&=áéwš�Žë•›#®äóÉ�†Nñ|ƒÙX|K =žatlôb]�ˆ,æfÛÄ&NßE8Jîãw®Ín\#жÎ$¶ßE÷«Ÿ¦-1ð ü_‡/dUáÍU£ˆýÚ#¦¦°f’ä*�­?ç¢�÷O õ|°ÍÁÌ2´M”tÚdSî°Ue rQ*‡Ÿ{Ô�ºyýTšûÔ„0Ïçrßõ…ðÅäö+r¢à‚ ãlqæ,Ñ£Vö@Heÿ‹-�ê×eV.nX 3�¿}C‹êo,huãÍæ£…â–žðÒavŠ"®c½ßGÞɲ09Ü%ŽñD#eí9PÊ#ðXJWA" ä-È«îpk�ºŠ º± ¥_xJ&vHͪBñ öGâ³M<}IsÒÕpµ®sßBë’šÜý¼§n¸Tߺ3DEc¾q;÷½Fö©ÑàÊûq3A†¥ÿî£�°en€‘\WÌbE§®ÅоíxÏ�òŸ7{‰‹çߓۺ�Ç9QÎÇç;­Å3ÔEU"h¿‚ QÎyþXïáÍ´ùÑÕx�§tU­'‹4³*î¼ÜaóA5õðo1;ˆD§yªfв�ÜúɦîV�‚/e«êæœð cÀ éöû ;t}³{8ÊÌÏ š«ZUš‚þ°îÀ€åi�'¦/÷OYœ¾(C§ÁFà5Au4ˆvè‚×/Ô{“ìbè½ Ñ—¯ïüõYþ§µÈ«#Ãg¤ ÑŽOÆÙヽw~’v ËøôÇ#NƒƼdÓ?ÄB¸¸Ž–oæO;î¸QúÊ—‹‡¡\ÖtjœJírâu2.ûuDD_ÞðQæoîâÏãΈ¢ÒžÄCçn?“ˆÎ*�§l½ªø.ƒ,¢r˜Ü†PAöÖ-Àœó¿ÞåÎ}²•ÎÓHEÊÜÊç+�ÔXáþù Àc¡vµç%!{J:£KîJtVÃVŒûŒª£K;åóÇt|÷Üæ£o›$ÜßÍ®Wòú²È°—ì&I‚ÎAS™€ê‚LãH”Ñÿ8^EÀøí‰*‡ÂªU¶zdÃéÍU×#ɸ2dñBŽ™ýÙUY°z®âeíjÆAû©k,Í´‹ðáä1¿‘ýA§·ŒÂLj°Ÿù’#ufqÑÚUªݟSñ$ î­>b‘zÛQwCV~Þ#q´‰øQKUWaú$œkP¥Þ}�6QéÎ[~eMŸ1oê­MMŒQJl|å`Ÿûv~rkt\(.…“l”V™º,ÓÏÀ‚?L_,7jÚ¶˜ìé))�nô‰>ă!p±ÁÏ–7ŸT§‘J OO}ôHRÙî†zQ ËÀþæI M–Juq6±püÛÊ$Ä617ÎYz…_÷�ŒDů¯ GœˆÀqˆ˜C/ͱeø u^”xUTÊ꛳‹Y]¢f¶ýÀßœ<¤m=ª˜�W�Ð+sìJEc¯+E—6S)¦:²ˆ$ç,äS‚‡EÚ]k„XÕ!:ó³† xüI¬7›Ã™Î"ê=ããug£Ýú�ØJ2|žVá.®}Ƹ²þ÷žÉŸŠOù>¸»MQ Éç“Å•ýRN,jÒÊ9ØÎÊýLÞ\÷YÉX9=�Z¡૩Šü•—g…D% E©¨àöÕ¿$¶ç¹Ý´Ù_­� où>Uº@h¤#'Ü̸’–S‹¸á±wù§š)(>eF§c�µiªá᤭éoÆL¡Ý<æ7+<þßÓÐ}„ ëØ›“’CÆ R„Ö$Ù¡EºÙëŸY¯OHê6Ð$®Å�†k~hb3z2OËdË>Íæ´.iXÜé ‘KlØî•ÀJzAÒ§ë=^þüßcºÍóJ±¥gýåyØueOtñi 6| ˆõ.Yd†�ž»]7ˆèKÕ!™OEFÌP£ßÿûöñ_>¬5”Þ³ÊI f‘ªK¤Œ¥Ž°ÃÓ»y{õ¯f0ÂÑdWC¡]š5ñªtE,‚„(¨êãƒ6M=&lu¡¹?x²&ä#˜25‹ AV³ôAž�1›aˆn-HLÒD~Ê»û„äõ ftE¦*&ë‹û:û×­ÃÒŠdþ0­ÓÂ�™zî E·lß)„‡”R‘Ÿñ1];X¿.Zƒ*AÙ$ÀjƒôçN[ ®SÝ3™r‡t„ në8CŒDšÜw‡sÈkPΈm¡ts;šj¿ƒa�z¥Äݢϕ͘I1Ñ13bÿMÍ—çXÃKK�Ò.ƒPY¤3^éÉ´V†œ§Ž¡,Å*€G�ÜEjwü> }VM¯Zðxy|/z¤Ö5)H´3˜øÓ §�d„üwP©ñ¿¿U‘µ迃Ò¸À�Êm,{œÇϯºÔ–غ£JDòõõUvø}¡GXIø/;ÊT(ØRäù38‘¦# œó>ùÙ¸Û´VX㲪ÍÑßTq1”è²µDb¾|!´ÛR%oó>¸OÉÁÜÆ‰8bƒ½ã¥ªIö˜7)Ýïƒ-N ÛúéÞÐ:ø)-IþýO挲ç…$Q^Ô/ÊBàâ¸m~k)ŒÐ‚z懲Ûl{ÉY/ýÙ(ù§Û-pg&_;ÄO5Š"œèKeR‡4 á€}åW§¬PNÄÈÐ�$ ‰–¬\ÓA\¥|kˆÍ-�õì�!Åð‰)aˆÖ»Üv›%^ùߺp¥ ›Bøë˜«¨¨Kë*Â.ÁSK/@é˜[f\„iS¾ë˜ºÚŒ»÷ɆlzŠ›sÌÑXв¬7'üXsš~n9m²‘ý~¡ÌËòþ"~ží Zæ‘°2ßÉ5lP@¥Õ©ÁO øVÛ2iý²'ûHf‚Y3³nŸ;è&ŽU7iO½_„$§‘þ ôaR[ˆ\>ëï® S¦uªH Ç@™+ùL[bÁU´701P(ΞKiŽ˜É�]/úŠy˜À—î®®³¯ó¥ëŸäÆ_Tì¦ÔÆÂ%ZÆpÊ~n�uJ6)¸àugc£ªLU¾´ØcëwŸ/½Š–œ!�Ù†ã6ÂeƒuŽØ@Ê®Kòα.?"[�G³$_„œ¨kì;9ˆ8“�oaÅRíwsUë 7CéÀÚÃé7�ÐÉb'›y½Eû$÷î°qÊÑ0rwU�Å?‹m؉âò—5LÃÐÁ•çb#¦Ìg«} "䉢"¤}?0öвIQ)×±�QÕêObQ¿Ñf[øáλٙ‘Í\ÕØvRƒYx7�ó8%ª6ÊÙ9�¶Fs^ÏC┃üÖ› ßÈþqIÚÛå#+'�œ¦ Öˆ1=¨A¶) E©ë´BˆtžVwµThw)4xh£%š,¬‘ Ëºƒ {¹î/I°¿!imùÍ»+×A_§ÇÒ\b?‚úÊ‘‘Ù×'8bâבˉ„8ù‘#Úžbw¤¥Î•õšùVB�#ó3Vž*¡�ù¼ÓãLVy®'ß—s)ì1‰gy‘;«ÊýŒ–’‚d`Ò"ßÑ÷,…µ»rWo=uߟfîÌ1¦3pVª˜ƒ¹ç²µ­…åkcÔ<ªIáCêÞNô/–ßâÕfÕWÆ:ÅÊ_ùÊ 3î±2pÓ)!gy〟SÄ¡Úó…ÍÊZX£d�6X‹¬O¼…»ž»-ȼëB€ã]¹]-ÞÚCeU_‚®²„õ Mûï”aLö Fwƒ‚ &]çÞ,;^Öï‰GN6TËwäÂÔ ¹¼ìrn\(8Ñb—_† t‰‹·�ÑL‹³%�7 È0ÐŽQÿ%5½¼.·Fm²¦æÏk½ÄþÑÀ¨²,š€öTL êÚòû¡›ÎáÆ¦è!5‰6õ(çSÜ '‡-nŒ jçå¨wž}ÞGÈÛº“¢‚L9¡ß�ýV­j~¸áø!j¢ù6;]ï¤HlâÛ¾Ì '‘6.;yMŒuL)b0jXM×/'¡„‹6E+Ý»Ãreô¨‘z( BÜèt!xAãï#<Ž µslIùV–̈*v\|¤ šº#ZÖÝfÔÞ]O¢k’Nu@6Õ'éU³¥õã�¸ô¿“t_³‚g¶òð¢ù®›II' rEÍ™í–},vü ì·½<Æé.*¸ç d—°ø¨ÑbJh‡9nÈ‚ô�aV\GÀqô•a¤)KYmX•¸½Ð„ã�RA’#ãKþ¼ù¬…•MÖϯå2 V©ZGÊœ8Ê«A©¬FKiŒ>« wmûÌ�Ó‡*Ь«ëÃåzdÏrß‹$ó!²f1L[®nÉhCª=4¦cæ]xÛ^jÇ*3×U†MOQôô !ý(¢i¼9òz)îØÄ<^Ï?‡0O‚­«>ÿ’Ÿ|»"þ¼äQ±ÿ£Lu,Î%Ö¹ž2ù”ŸàÏNNÚ”ù»]·š[dÈ Dæ +üA2ËŒ¾YÀ³ž&~Åøjú8ÑJKî.÷[­ý6ò‚Ãç¯ÛYPoœÅÇ2í‹1|»´Z{æŽ'Ll…h\²÷‡ã¡'šE#…\ÕJÞŠºJï@¹ãuYï0³ÞKýîtrNùzQ6}~ï븖†µ^ܪ¹uL#{Þý\?Hî„ù0¿ÊäD_ÚzO#7`„|å�Ó7 3d&‘ëÍ¥³/Ù¥Xî`Bì]Fa6š€7BJ¬„²þÿÛ½|§`ÉëQd]ß'í…É �a€° �=’åRä{yNÆÛ“n£-E;Š™ãhÛ…Z3q‡MѦÇÌ@&ÌÛíñå' ~ψ²¼c‹Í˜’Veñ´ÏèÜ®¨w‚&¿VïîŸp…w¾*:ŸæhQ¹‡@nv³0¡¾å¦Æ * —¸VQ‹pÖe/‡•2·ò™«Ó7-‹Öf«)_é.K”Í}>n"»©¿Kƒ±Ù!ºoîv(HÇǵƒåeÉ&+QžôÑÈ6[r�ˆu=Hu,zËWš±"aœe%¤XU#CÃЬül•’UNE�Z5DÈŽîp|ÛmKÜŒìÝf Ô£ƒ‡š»I†#\Lh�-ï¦8so»v"à�1CʼnŸ1kŽO°fJ7ë4Ö2ߤ;ÿ‘æÅð—n6¤M¼.€@eßW~kî¤ºÕ é}óÔ/õfþÃ~¡ê]cL7ÖDh. …¸µÙŽzÎ;î`è“sJÂgßÛ-\4*��ü‹&ia�Áí†H«�¤€ÕZŽ�2„Ö“t9n ç¦"GIý£yÐW°K ¡� ;—öõ_+Â)jòW“’‘"•ô�#rYœÚB0Ää<)-ÏœÆì¶Tö,xuå@˜c±þ]ÞäY`Å@ET^g«à7©uW4YÌTrœEfĬ—mØÎ|=sœfI@¿/�xãÅ7¸ü š@² US¦${c'žR¥¹@Rç›ßœºÁŽ) M¿RG°iŸ¸½CŸ�µ§Zð�Ñ+*1Î-Ù¨A™*'$%U4µÜe ME�eí£†heþ1O2ÆÞ$‡�oc;ûçzwAœ¡‡©£lËöЦÀÎNìd;–"‡(�Næé]GÄÒ$b+J>nY0c9CqÉU £ª6|„]aÀýY\@ )„Ö|Ï)oyF³MÙO€*‘xC ·Ý(ц`F=Ð:)7¾9‚Fäp~ £PÍ¡ÚÝ:f•S¡øXih¼«Õ$ý:B•ÆœK•ï<5[ éTÀ:ÅFê µ*~MÓvÖ…|}¬P“÷«•Æ£:ð'TðÉœÍôÐæÿ<ýd–¸¿™÷RµéÌ�{Ÿ´Ä�惖e˜e«²›ºa. EGef&˜ÓÃU³\Ò»4€j$›ü‹?üFÑÝo­¬®Õ§ì„‚È1T…}pб£šêØüê~™óFúS!;R3•ùúÆ(˜ì> RúW…ˆå�Ë��èù:DÖ4$Wz\™ŽÏWÄ üJËvŒ9 þy©¬ëêS�R…õΘ<"!CXZ+Y¢~¢½Ï�%Â�Sïü(óÒ¨ÎÝøS‰F1ß±½noÅ¢Š[à @ò²¶¼óÚ7¨jXÿª_Ä_Òž‰æ…«Õ™2Úz±gCÏ¡_ÉŠVÓr<«�”h©Å7›Å¤p5³Ý&¹¥ÈÇô?©{JÑ'(o»Æ²f}DpQÏΓ̱ŸÄ}’Iwd‰Z A};…wþrÞ\É$‘ònä”cǬ?“¿Ïg#ƒŠ£î9B¨–üc(:Œí¾{qDêÂc‡»9MÔÃMöŽ h:“d“#‚F¶uüZb¼èP`˜\×_Žº£õ콆ÛA{ä¿RŽy„²kutç[Z‚4.{v�ÉÄuGrÏ8“ÚáÓˆ|‹B ±`¿¾|[ÌD\'ѵ&à_šœÃ¹j„¿ÂF·Ê5mˆD‘ñ2F³öV¶ÊýAQœÞžTøÎ)±ÛîÐÁxóÆq=|û:)\?4•b@ó‰\e‡ïÔ¼¨[8é#C|ñé �ª)ßÇX’°Ý ±âÎè¼Ù°Ew“pÙ¾€q*¿ëç#ã಺Û͔˖cœkRñ"MžŽ·VÛÇch€¢N0)AO¤¸wj5#¤žëHpÓd¢¥§´Y¹�kê~õƒCÇWzÐŒ`/*} E^IˆGærÏ$ÄC¶Ù¢l�‚¢÷•À‰Õ_üâbvC”¬¼pQøÞÜx²Ísή­PÇ—_³Ë¥v͘Ià9*ÜQ¯ÊºçeÍÔÍÝ=uAS]µ¯oY±_à,-<Ì ôÿ`r:‘{&Z‚nÆÅ[CAyp¦á?”=òœ�·Š|¹q:«“\®Mf±TdFZZ¸««Bì –6SPÖùéÉQðˆÔ¬ÊõÄWÍùÕíZ{5cq³ nÔ'¹öX‚åÿÒ›ù‰“§ÄŸŒ¦°qÒ1}.|u¨ã¢§´Jnr–ZÜLÛd?¾hdd”irFqïŒÔGž¯ÜiuæÚOd¢ÝÜÐu÷ôv�Ia®‹2zâoÂ0P|Rˆ``®¥§%ƒ¸j?ÃsÜVØöŸØ6=eçP‰I�Ìã/=»pu0¢ô\eUo¨ y„·ß›|¬«u?-8)A4è °ˆr�kàþ3þ…øö›š¢%7còŒn ݵfÐ Áô¶ ÔQÅWäö@£þO—.pá&J̪€Õ�™sz¬Žõ#Ñ$¦Ç“‰YÞËê/•Ž �[�nS*¿ =´éw¨gj“¯Xé'_½÷LìbOЮ–77g]˜Ð:¹W®LOÐ(“ÅV;åX…à�IÊoÔÌ#4íwXq;µöµùKå.Ci¶Ð3ä+bÊ ;kù‘|žxõœ‡êBN ©Ñp|¯ÍZ™ÊFt±uÇŒ4!êbù)X%{žÑÕþÜCX«‹Ï÷— %;Æ5ŸW¡)‰hÖöƒMm[·¿ Õ1]G–ö[y×µ‘òæÏš:I€»$n4kÍ•�˜ ¬ ½{cÒÔÜnb7Ív&¬‘X·�,ù §àçCJËnvõ“³ Ûæz¹&>ãP‰¿”iöcØžH uiðóûûq +ùŒù\SéÓšžá‹tãQózfõË]ÙÔЦ`¿æ¿Ó€ê7ÃM)¤”#å¥8—eæ¥4•CÃÌdW&®�Í<%½ 3÷òP¶5|—=hú8†·Ç?oÜgyû °Ê&êÂ4Ž6¬Ö¾ ñEJ @×AT ÐiUvØYß+ÂçÉcµåF5�Ts)Å:ì4ÊRB9´}±oÿíéË|àÕå ÍN—ĨdgÞ¶|åÔÒ�l%–%0œ—•þ‹Åf Os5±=)ʽ—¸¶ “mKå›kâmH‰HN5‘ ­î&¬ø¡›Læ€0�J¯BB±ƒŠ&ýe,3WðûeÛ+ÃŽÕã/j^y£‘þ…€ºXôpûª½k}…¬�¼ ßöJ*/º¨:6yÂ~’ŸXàù›mÈ�R�_Žˆ� Ô¼gð¬.’ÌG·„qž5UmÿøQj´àm°›Î?*¾ZÛH |6Ïž¢~O¶RC«–%zýÌ×@$‰ýNoHF‚ö>o¦k+êt”`2FIMðÊoΦs1Ë¥}ãÂPÐ�ÔÓÀÖôÐX9œ|“�¼©�éËLÖè™ó²J=&ÞcU¬àš²Î&ïÚ²Xv(Æ¡HÑhÀuT˜ˆ[˜|œæ‡¡®•aµ:ÐÀ¹ÑÙ÷ !Cb¤9‰L�ìVìTÈE’ÂF„ó53-ÞNî�ÒÆA DÀ€ ¡Î¡¥Æ†½,\V>ºS»·XÚ,/�ÄŸ«ñÏUÛÀSþ³pMqƒb.ÁæZ´‡J 2Eµ™Sbéx†3‹Ÿ®óêazjÉ ½`1ÔäÜW}–Ð{ÜA¶7AT6®ŽÇ€3ÔíBœ”Tn‹¯Ö:}—Òç¡ô̧¨“;ôeQêØáa œ­€Í× v€4ûåݦö]2ÊR´®ÝWë¾R“ÃKˆ)»ˆøp�½sw‘é–1�ö”\Zm˜Ü¥fe›u¶#¤°hKMŠ�KiF—›–?Þ÷ê�àç€~\ï•yNû@¾†B¦ƒþìö:�h'䎂5“[¾¹žé¦´61Y¼5kÑ>6ÐlzXˆxòËÒJ³ÅJ¤7¿¹ç=OÏHÞ)5 „;1î‡ÄÜò9Ú÷�½%¹ßØÿ É¡téÄOú Þ3 áå"iá`½ø?n,Ü÷Î@õá¯Y Bû§JÁK?~3°}£š(¼úK©¨ÑŽÌðbÂ)HºÙš|ú ’™¾Èú<&§×“C‘Ͼ·qFg?È1u³À]7B‡‘<²ŒÑìlÍ †Áå»Ñ„–(çoÕ •ÜFÀUÞŽ4«Î›«G&s° ¾åj<èOž ‚z¾¶ðïÐ÷�k®C�fdä²Uñl§~æ¸8 :^ì¦*s·….† K%zh8+ü$òq›D´5s*¤pnÛð½@„¬Â`ûouNÛFæÃ|¯+Òê«Èäå8¤#ü õCç¥Uøœyb¤Nýd�ôBkª’rW…$Æ ;ßÊh˜ô%9s©HfqPšrå`*àZ ãO¼×–àA‘òð;Ãt¿€$NŽ0!µò{jC’ÖI(¶~Ò›5bï‚Èêü,¢Ý¡ü²’Ô¶þÎÝq¹ =tœEƒ/Oþ÷:\¡ n²÷G�>•5”`8Ww¯=_ŸÐoþƧ>d ñ.×€yÈT%U/øÒ…€OÏ·ö¨¤k¹òQ!ö�7«Òƒ �xå{A|TÊaÌÉø7EÖŠûjÙZ(‹]¹ �| ‰rb¡ÄÆ!î½oÒ'Åê/~…I ?èmï*,Ô¤­’‘oeu+‹¸ïQK¯Ô¡c:*Ã{¦ý·‚ßëê›àÜz-”—iG~kàRï"{’c Á²cdÄ�£}ĤAýå`YÓ·kEb¶C<Â^½ Õ§] “y· Øô�Ïå|w5�ÄC¦v��«Û.<V¨ænÌi+,¬u‡°“ºoòÙè¸ËE2ÑÇ›ÛÑ r£é›Û2ö‡Kòâu™ÇÓ½X ×½(Á|²ðYóIßñÞ:>0F¦ aܱV<õi±TÂf¬~±E]»°f€Œ½`*DèKrÂng&å[ŒxâºÏðOskdZ˜Z¼Ä÷Ϋë”¶Uï§‘9•ó£¨Xg§S6Ⱦé8bÏ‚[®áRä1åé±_t°dsN/fZJÛnŸ†:ñÌÂ8Ë“ZÄpº$ȳô.9t8l6§j/JÍ[Ër6ß)QçO5Þ÷Äü8#£ÏKEC¿úSÎ,Å¿â}*â\ÕøþƒHì-W§ãª®Þ»üT|Yê,Xx·áŒLEÒºJë-žL_,ÊYh[š÷ÍZñYííç^Ù€KÜP Â¥÷®¬Â†º.67KËF1£K6\­ÎÊ3rÖ'/rK�/Ï|~€šesU…F�WCƒÅR§\û¯yé@XU�’¬jÒ»­ñ›!ýÇâ…>ÑgSmk»"€ÐNgöp(Þrõõ,Sfñ­m×�ÙpûøvO°Û‡WBOˆ>-(Œpª=«-nJ(Ò€4ÊJ2xÀ.éŽV¶µ¨X”ú�l?­+Ur)úô,†{:‚ûü¤C¼ýòtº ´ÄBïW-dV1 ŽÎw¨6©<ŽèðgKò�…¥­|bE7ÉûR•nê´F—ÎEލ¸†gU6ñ–I’ؾ>)=j¿ÿÓ´[òœ-e=Eðq×Ä%É üìÊÓ-¶ÇU­ÒãÏí‡:óVIäot^¢n\äÍp¸Z;“ª[ÎUfú=ØtIËd´0†œÈävl{.=šüª�T?äëæÃ˰j7j\Uã ËøæêíÌ$^vÓƒ�I£³÷ã~Îd©.¼í©ò {©ë\²ÛžÖI:פ°ÁI~“>š+p_ ÿ¦d…^�œ)a4[:?kù{ƒí(×VF$ºc�jH·šTÑÅtVýº4L;VÓS’à ]C\F&§V}äÿ™´±®ßøN†Ñô¡;^C5—é^ á�tà"–´ò\”HýÛnê’_îÃñÔt¤S™¶ RSL£íÍØ^Ä’ÄáI¼„ÚÉ1Eÿ‹Â­¡EÜ@!µ˜c'�DMýø7réQÃÙì�x^ôÉšß0¥§�éï.s´ß�½óµlP&=z�¨G^žO›²®lœkѸ£¦ {«‹9X/Ùž’Å }û/© ¢§Ñò6ȲÍôUÿ‘æ‡-$\çxl Ç;’~Šñ«8ÞͰá¿ÜzZ`øC©j‘LÍÂ…Š bPšQ©ËÜ=„÷�߃ë8ˆŽ`ãQÒ$'TÐf6µ•‡Ru{›ü§€–’¿Êø�Ï€¹£µ�KG^·O;‘×^Z¼QM,s�î´íêF+$q„Ûúÿ}péÇÖ”ê½Ì™¦4mÂÚ¢2óxË»ÚèkÀ[ò¸ÉTŽíÓ�:vmEД`Žh‘]ø+tþéo3Oë’s|_V¹¿&AA/c”½[�+/½…½ÐIMZ³zsNÑPö0ÅðƒÂŽÄ%GÀ=kŠìEJBIg€ÿ›œ Ä>!²]À™ ˜GbÖu G¹Š^Z$Òm:l ùjm?…ßéj^x�—·Çk•€þG. 9Ÿ$×lm:on¾ã�Ëõð÷ý¿ŠXÊÚ ß»&ŒÉÐ ?‹°Ÿ½¨¦r £òw«Ÿ.fÑðP©OïClçÐSGJFQgSkXlPt¬œ×kû·Ð5™(:&ñ{|ˆª›u´O¹wÒ Pà¶(¤®7�ÑYÛ)9ÃFz…Òy÷—´}{ûÛB�€å‡KÔ¦Ž&ø»®3•50EHU*ß.¬Û�E�ª8­•bÞ¯`ZK”•…?÷úk�NÀFä@Û=Ê-�ÿ“k 81®Öß%àÍÔûxß Ø‚i“>Ƹì0[ŒYT|îQAl ƒà”Ù`¶Ï�˜’ vT…Ò¡ZwE£f x²Š†²rÊPIhiO‡~î ôEýg‡– t ^�¡6�=*t™5Í�p‰vð_)2JQJærC2‹…¡)º‘ÒÃ}qî'Vf‘uåü<„nÅ@Bc.÷Ç$u”¢±‘�K¦P´ó3Û.$O³€yvp³ v¬_‰~|}úi7)Þ8ÉõÑõ{8$Ͼ¸À<„J=k«ª¥bb;šô�LJ£ iÆiȲÒÔ'n ”}q@¬KÎby­ÕJ³n·“N¾^FÌ…®‰&”Ã4È›¬‰¨à$ƒ^MärgHdÀzõ¶ú¬wËMx]ü¤…‹Õ‰›ã±YV¡CÍ]£qç ïkã"ž²¢ ů¿'¸+_KPî”H³Ðc"dh:O®÷Cž;VÜóøÁ”~Ò°V!>+”VF84ÙvER"Zý.Qæê(ºZ‘Í9¸ã2ÁF¹yñ�Ç:nζµpþÕÞLöô”_?€å¢( ´òA`ב;¹¹áŠ.X®ÜuHÿ$"ö!Ö…}¥\S�p!)ª;2¢@;Ã5œ Zܼ›îïv!é*oj;Cù0bp^¸ùE †!B£9¿|ð袦Yg†•¬&¹ûàqN§E—˜:SÚæØâo7 ‹@JxK•L58Á;ÝO†A=þ [ÌK½Ø)7O‚ÀD$aä�PùyÚm˜Ê»â®ðb“ÝÏÙ×^Y,ä éáW@�ALQh±Êóµ¯(gÜë*Z¸CÎÂ�ß°Ãî T>†uŒf^‰KX=¹ô· ³�OS"Åøº›�æ®Ðm>Wìb<\íºÓÜpusþEì¯_#–ŸÝép:!¥¬ŒêO«SQ^Ù‘õ ¯ÚרZ­ó ¶2)5ü4¿Ñ,D¯âB-z²ÊD Æ]‚�o dOt1¸iTæãȲot ¦àÆ£îTy,«Ì`o•>´³7�“bRÕ—-)YY¯}Ê �Ý_ȇ;ò†™ƒâ%PÖ¢<Âü|ÞKYë•Bl4ÖzŸV,Í’®Å,>ð}<Ó¶ „OÄ+_Q}5… €"æ±€@ÖvoÓÆ3ëì–d½Šð$êûx¶ ¸KJa´•PÃïùPëóYµBÙˆ¬§žE[|Gq•MÖÛC7 ~óàƒ»h—¶È{bî: Rv}îßgÚdJÝÞdØTO œß‹XÀêï.~Gϵ³f‘N‚‡Œ×Œ¢·¶T"—_V« Mí¹/øƒlðË‹I0á[Ê.% D]›:ûô ¢à>cC9Ð=$-xoã\TÈ¡öm×úEŒÒ6ïA€Oƒ�¡è‹© ÆÐ/lE:NS?{Ò 1ígPd½Â(Ïǻމ¾Ê¨öâCËMV10BËÌÊlþÞ¢Iæ´jìÿ½òÕ´€ÜœÕ@ÚÁ>&�1àù¿w™½Ç¹,÷`§„ÙÛ2 ºÕŸ]`m•mÒFMO݉Œ=¶í -°«ûdžVËä‡VĶ@þ?2—u÷«Úߦ^Ïèa3¬Ìòõ²És�•¯‡bŽ£–— q8§Ž>¥·\‹±AàúCz/GŽÞö´þ,Æ„|¼¡úG­t†ð›zwb˜Áô’Ã!9Œó3p!*ío3ºEñŸ-¯Eróþm àøâúIÌå>�IH^P8HœÂɾ?ߟåù7ÿ–{Jü:|C+œv µ·çØm ûHγ%=á_EoöK ®×ãÙî ÂTÌ~y;Eظmòi«ÍhÐfí'/ÖFýú™+‰äÕ¼2)/Äî«2Õ¸ýÄ”ÐAr[Õo@¨ÜÚÞ›ŽY™Ï]•cDM‰‰48 ž ,͇\:ç˜áýµr¦÷?~¨Ä>æøÑ7^³»™3Øpo.îüS§âx®&8 2'„ ]§ótŠë‹JH`ËÍ&,S9»¤>y=ŽËÎÊxN„j-}ÝbrŠj�‡Nr¸ ›<þM2ÁU‰Æþd;^¿ô_�­YT„/\�¨,‘fDÌß¶êëh—j 5:N‹nLš3Žb®Ú$Í@áå»6Ô�–ë‚ ¶ÆTLÚŒ§!ØïÑýXO§ï/̰2 CÎVãÀõàv•梕W‚ÿyo24º1àu轡ò°ÎJvïE7ðw–«ÒöWÉÕöôü•Ë™,HûÁ#éé“ÛÊötÿðÑ!r¹¸¹~hŒCÌš…©1º±ÝŒL™.3'¤XÅÏ0 À�. P•à|ö,UŠ�ªÁ @ÄÙ´ ª†¥´Ò¼7í ž+®'S½´&º¤{[ é;fÍE/5‘¾eã×ÞÌx ·Í†®r†Jù÷öÙ\ݼ#e©²oD˜Î½ñˆ\žvÉì‡Y¸H´`{DèL¡ïÁ¥ë� A&ÙÁÜÒX¤ù91X®äÂÞ9t¼·{2‡…¿µÆ¢Ø1mfJ(9Rv“ÖuŒ±‡G©5Ã5aÏS³å�\s[°�€lâá>#h£L¶Od-¬“ì\ñͬƒPE«3¹‰CBÿûòv±i襯¹H Y¸³tàÑãšò†^E*'ê•8�Sà‹l·é©b:èYý¤ÌþB§’9„jr\dñ¢ü0’*ß^+µàÜ„ ‹(å×úŠ,ŒkÊá4〢&hû}áÀiê²J ž”ãCa°°L”DDñ»àÑÃ0xjái»¯(wî2 @�塈è!…tØ™î±>ÿ¨‚ƼHºŸDº¼'u$‘,Ošãt:¾xh£îl8aá(­ð ñ •Ä÷>`%~IO!q"Dè¼Ü_v�˜òÈ9Oü5Û#n!QõÞÌÏ6,kõ^h�·Á{Ò�?û6U¨Ü#CF™î×¾k›f[¡UÙÇ�4RÑWçèmåÀ1¦*û¸y”éäBtÄ}C5ûJÞ \«B\-üwH´©@ClhAq~ÐüÄçr„Â�‚ucŽ«O'¥-MFþ;˜ŸyŒ)SKpl�`ÖÉÚîž�>"BØUx»º†$Iê”ê ŒÕ2[é½}|:Àgõ¶fÜα—…¶t¦ªrÒÙM6S!7çºp„ža*­Ißžƒ8…õfl,‡Çs"uåd¥ë/(WÊWå^ð‡èVQªpéÇ;Ù–Bwt5y÷6ý\ãqËu.}|k�`tç«{³ *Ÿ¡ûÓÅšQ÷ŽX´`d4ÎÁôenagX�‡�åTÌ[È®è°Û £çmg 0):Í�Â!u·j¾²Ð.‰•F�l±\��ä]–iо"Àâ3}ƒ�Dôdµ`Ld®L󌈂%�=¨.Ý5ŸcÖ\JÊ\"ó‡Ï ™efñþÝ¥®^—ÞÞ‚Ö‡,ÓS-ç¿ÄÑœ€r%O °®HZh\CÀý æèeãÚ‰Õ~Û^-2™p¥0þ8�³“dáá�õ£+ŸR÷Øèf P~s1°šùÿ_«»“X[4a£¼V­€•ˆÕDRÞ¦¦l]ò6!¶A°m¼½y;ƒØÇ_2„A8Eç DØ|HGË”oýGë†,úÕp16‹MÖäœLiò8ò”{+ÎWÈóüD�!ðH(ËíªTCïu·E›ˆ.˜¡qú³¼±TO�Î6µ’C&/ÿÛÆ]]x&Ó„^\†me}&Èæ£r拵›á˜êþüFû[:¿Ó)ÅR©úFóVÙX(H€Û¹(ŸÑa<íû(ŽýI¤±Ê˜Ð!³ú^Žn;|ÃffÆð�3®1¡HU4ì¨SdõŒ‡;E‘”å�çÞcG¶v�ìË•¤:eÓ õßî]ãÛ<05³òø&ýÍ‚ Øà¨m´›"Nª6-ýmì2“1È Þdò�‹‹Ø�n�Ø Qj: >Ôºe&ʯ˜háÙ×”«ð<}›í�‡!€’úÖ_¨áW°c$fyÔMÓ)s¦ºÕ?@K+œ¼}þ¤ÔÇjÄgíx©Ž#")ضþy!ŒQUF:U¼F°,�Y5zÜe.ehÁÔ`›iŸ_¤Ý¿)f¶¥IW9%+ކ×ò“6O!FÎ5;F05zfaYà*¦wýí⧨@Qw\É®2Ì+÷éHiäíÊ~ÌœiŸlí%dnâ±´[é´µŸ§|0ÓíPuŽTpÒt+€¨¹6qKp÷1¥:_{Ö6*ßøúSÖKÙ›¬y ¥•Ê…ã,‹Õ(x׫´X¡'¶•Jê7£áSÞ£DHIsI3\ê?*_akÊ‚g$Ïí³Üo )ëߊž…Êc@›ÊÕOr1]YŠ#7ªTà LÈ^À8QRv~Å–ð1w ”Z´ÖHk*ºÏ6G[ÀkÊ � #] „ú Wʤ7././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/tests/test_fuzzer.py0000644000175100001640000000354500000000000021647 0ustar00runnerdocker00000000000000import io import os import pathlib import sys from hypothesis import given from hypothesis import strategies as st from pytest import fixture import multivolumefile as MV counter = 0 @fixture(scope="session") def basepath(tmp_path_factory): return tmp_path_factory.getbasetemp() def numbered_tempdir(base: pathlib.Path, common, suffix): global counter counter += 1 tmpdir = base.joinpath(common).joinpath("{0}{1}".format(suffix, counter)) os.makedirs(tmpdir, exist_ok=True) return tmpdir @given( obj=st.binary(min_size=10, max_size=10 << 10), volume=st.integers(min_value=5, max_value=1 << 10), ) def test_fuzzer_once(obj, volume, basepath): target = numbered_tempdir(basepath, "test_fuzzer", "once").joinpath("target.bin") with MV.open(target, mode="wb", volume=volume) as f: f.write(obj) with MV.open(target, mode="rb") as f: result = f.read() assert result == obj @given( obj=st.binary(min_size=10, max_size=10 << 10), volume=st.integers(min_value=5, max_value=1 << 10), wblock=st.integers(min_value=5, max_value=5 << 9), rblock=st.integers(min_value=5, max_value=5 << 9), ) def test_fuzzer_block(obj, volume, wblock, rblock, basepath): target = numbered_tempdir(basepath, "test_fuzzer", "block").joinpath("target.bin") src = io.BytesIO(obj) result = b"" with MV.open(target, mode="wb", volume=volume) as f: data = src.read(wblock) while len(data) > 0: f.write(data) data = src.read(wblock) with MV.open(target, mode="rb") as f: data = f.read(rblock) while len(data) > 0: result += data data = f.read(rblock) assert result == obj if __name__ == "__main__": import atheris # type: ignore # noqa atheris.Setup(sys.argv, test_fuzzer_block.hypothesis.fuzz_one_input) atheris.Fuzz() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/tests/test_multivolume.py0000644000175100001640000002732400000000000022705 0ustar00runnerdocker00000000000000import binascii import hashlib import os import shutil import pytest import multivolumefile as MV BLOCKSIZE = 8192 testdata_path = os.path.join(os.path.dirname(__file__), "data") os.umask(0o022) def test_read_check_sha1(): target = os.path.join(testdata_path, "archive.7z") mv = MV.open(target, mode="rb") sha = hashlib.sha256() data = mv.read(BLOCKSIZE) while len(data) > 0: sha.update(data) data = mv.read(BLOCKSIZE) mv.close() assert sha.digest() == binascii.unhexlify( "e0cfeb8010d105d0e2d56d2f94d2b786ead352cef5bca579cb7689d08b3614d1" ) def test_read_seek(): target = os.path.join(testdata_path, "archive.7z") mv = MV.open(target, mode="rb") assert mv.isatty() is False assert mv.seekable() mv.seek(40000) pos = mv.tell() assert pos == 40000 mv.seek(-1000, os.SEEK_CUR) pos = mv.tell() assert pos == 39000 mv.seek(-2337, os.SEEK_END) pos = mv.tell() assert pos == 50000 mv.close() assert mv.readable() is False mv.flush() def test_read_context(): target = os.path.join(testdata_path, "archive.7z") with MV.open(target, mode="rb") as mv: assert mv.readable() mv.seek(24900) data = mv.read(200) assert len(data) == 100 data = mv.read(200) assert len(data) == 200 def test_readinto(): target = os.path.join(testdata_path, "archive.7z") b = bytearray(200) with MV.open(target, mode="rb") as mv: mv.seek(24900) size = mv.readinto(b) assert size == 100 def test_read_boundary(): target = os.path.join(testdata_path, "archive.7z") with MV.open(target, mode="rb") as mv: mv.seek(24999) b = mv.read(200) assert len(b) == 1 def test_readinto_boundary(): target = os.path.join(testdata_path, "archive.7z") b = bytearray(200) with MV.open(target, mode="rb") as mv: mv.seek(25000) size = mv.readinto(b) assert size == 200 sha = hashlib.sha256(b) assert ( sha.digest() == b"6\xbc\x92\n\xa53tY\x97\xaa`!\xf3\xa7\xaa\xc3\\V\xac\xc1p\x97\xb0\xf5M\xc0)\x12\x0eD$\x9a" ) def test_readline(): target = os.path.join(testdata_path, "archive.7z") with pytest.raises(NotImplementedError): with MV.open(target, mode="rb") as mv: mv.readline() def test_readlines(): target = os.path.join(testdata_path, "archive.7z") with pytest.raises(NotImplementedError): with MV.open(target, mode="rb") as mv: mv.readlines() def test_readall(): target = os.path.join(testdata_path, "archive.7z") with MV.open(target, mode="rb") as mv: b = mv.readall() sha = hashlib.sha256(b) assert sha.digest() == binascii.unhexlify( "e0cfeb8010d105d0e2d56d2f94d2b786ead352cef5bca579cb7689d08b3614d1" ) def test_write(tmp_path): target = tmp_path.joinpath("target.7z") with MV.open(target, mode="wb", volume=10240) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) with open(os.path.join(testdata_path, "archive.7z.002"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) assert volume.seekable() volume.seek(0) volume.seek(51000) volume.flush() created = tmp_path.joinpath("target.7z.0001") assert created.exists() assert created.stat().st_size == 10240 def test_write_default_volume(tmp_path): target = tmp_path.joinpath("target.7z").as_posix() with MV.open(target, mode="wb") as volume: with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) with open(os.path.join(testdata_path, "archive.7z.002"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) assert volume.seekable() volume.seek(0) volume.seek(51000) volume.flush() created = tmp_path.joinpath("target.7z.0001") assert created.exists() assert created.stat().st_size == 52337 def test_write_posixpath(tmp_path): target = tmp_path.joinpath("target.7z").as_posix() with MV.open(target, mode="wb", volume=10240) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) with open(os.path.join(testdata_path, "archive.7z.002"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) assert volume.seekable() volume.seek(0) volume.seek(51000) volume.flush() created = tmp_path.joinpath("target.7z.0001") assert created.exists() assert created.stat().st_size == 10240 def test_write_boundary(tmp_path): target = tmp_path.joinpath("target.7z") with MV.open(target, mode="wb", volume=10240) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(10000) volume.write(data) data = r.read(250) volume.write(data) volume.flush() created = tmp_path.joinpath("target.7z.0002") assert created.exists() assert created.stat().st_size == 10 def test_write_exist(tmp_path): target = tmp_path.joinpath("target.7z") target_volume = tmp_path.joinpath("target.7z.0001") shutil.copyfile(os.path.join(testdata_path, "archive.7z.001"), target_volume) # with MV.open(target, mode="wb", volume=10240) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(10000) volume.write(data) volume.flush() created = tmp_path.joinpath("target.7z.0001") assert created.stat().st_size == 10000 def test_exclusive_write(tmp_path): target = tmp_path.joinpath("target.7z") with MV.open(target, mode="xb", volume=10240) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) with open(os.path.join(testdata_path, "archive.7z.002"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) assert volume.seekable() volume.seek(0) volume.seek(51000) volume.flush() created = tmp_path.joinpath("target.7z.0001") assert created.exists() assert created.stat().st_size == 10240 def test_exclusive_write_exist(tmp_path): target = tmp_path.joinpath("target.7z") target_volume = tmp_path.joinpath("target.7z.0001") shutil.copyfile(os.path.join(testdata_path, "archive.7z.001"), target_volume) with pytest.raises(FileExistsError): MV.open(target, "x") def test_write_append1(tmp_path): target_volume = tmp_path.joinpath("target.7z.0001") with target_volume.open(mode="wb") as target: with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as src: target.write(src.read(1000)) # target = tmp_path.joinpath("target.7z") with MV.open(target, mode="ab", volume=10240) as volume: assert volume.seekable() is False with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as src: src.seek(1000) volume.write(src.read(24000)) with open(os.path.join(testdata_path, "archive.7z.002"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) volume.flush() # existed = tmp_path.joinpath("target.7z.0001") assert existed.exists() assert existed.stat().st_size == 10240 created2 = tmp_path.joinpath("target.7z.0002") assert created2.exists() assert created2.stat().st_size == 10240 created6 = tmp_path.joinpath("target.7z.0006") assert created6.exists() assert created6.stat().st_size == 1137 def test_write_append2(tmp_path): target = tmp_path.joinpath("target.7z") target_volume = tmp_path.joinpath("target.7z.0001") shutil.copyfile(os.path.join(testdata_path, "archive.7z.001"), target_volume) # with MV.open(target, mode="ab", volume=10240) as volume: with open(os.path.join(testdata_path, "archive.7z.002"), "rb") as r: data = r.read(BLOCKSIZE) while len(data) > 0: volume.write(data) data = r.read(BLOCKSIZE) volume.flush() # existed = tmp_path.joinpath("target.7z.0001") assert existed.exists() assert existed.stat().st_size == 25000 created2 = tmp_path.joinpath("target.7z.0002") assert created2.exists() assert created2.stat().st_size == 10240 created4 = tmp_path.joinpath("target.7z.0004") assert created4.exists() assert created4.stat().st_size == 6857 # 52337 - 25000 - 10240 * 2 def test_read_double_close(): target = os.path.join(testdata_path, "archive.7z") mv = MV.open(target, mode="rb") assert not mv.closed mv.close() assert mv.closed mv.close() def test_read_fileno(): target = os.path.join(testdata_path, "archive.7z") mv = MV.open(target, mode="rb") with pytest.raises(RuntimeError): mv.fileno() mv.close() def test_write_short_digits(tmp_path): target = tmp_path.joinpath("target.7z") with MV.MultiVolume( target, mode="wb", volume=10240, ext_digits=3, ext_start=0 ) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: data = r.read(10000) volume.write(data) data = r.read(250) volume.write(data) volume.flush() created = tmp_path.joinpath("target.7z.001") assert created.exists() assert created.stat().st_size == 10 def test_write_hex_digits(tmp_path): target = tmp_path.joinpath("target.7z") with MV.MultiVolume( target, mode="wb", volume=800, hex=True, ext_digits=3, ext_start=0 ) as volume: assert volume.writable() with open(os.path.join(testdata_path, "archive.7z.001"), "rb") as r: for _ in range(5): data = r.read(2000) volume.write(data) data = r.read(250) volume.write(data) volume.flush() created = tmp_path.joinpath("target.7z.00c") assert created.exists() assert created.stat().st_size == 650 def test_unsupported_open_mode(tmp_path): target = tmp_path.joinpath("target.7z") with pytest.raises(NotImplementedError): with MV.MultiVolume(target, mode="qb", volume=800): pass def test_stat(): target = os.path.join(testdata_path, "archive.7z") first_target = os.path.join(testdata_path, "archive.7z.001") with MV.open(target, mode="rb") as mv: st = mv.stat() assert st.st_size == 52337 assert st.st_mtime == os.stat(first_target).st_mtime assert st.st_mtime_ns == os.stat(first_target).st_mtime_ns assert st.st_dev == os.stat(first_target).st_dev assert st.st_ino == 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1619698699.0 multivolumefile-0.2.3/tox.ini0000644000175100001640000000251300000000000017054 0ustar00runnerdocker00000000000000[tox] envlist = check, mypy, py38, report [testenv] passenv = TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* GITHUB_* PYTEST_ADDOPTS COVERALLS_* extras = test commands = python -m pytest -vv depends = py38: clean, check report: py38 [flake8] extend-ignore = E203, W503 ignore = F841 [pytest] basepython = py38: python3.8 python_files = tests/test_*.py timeout = 480 [testenv:check] basepython = python3.8 extras = check ignore_errors=true commands = check-manifest {toxinidir} flake8 multivolumefile tests setup.py isort --quiet --check-only --diff multivolumefile tests setup.py [testenv:mypy] basepython = python3.8 extras = type commands = mypy multivolumefile/ [isort] known_first_party = multivolumefile known_third_party = docutils,flake8,pyannotate_runtime,pytest,pytz,setuptools,sphinx,yaml multi_line_output = 3 include_trailing_comma = True force_grid_wrap = 0 use_parentheses = True ensure_newline_before_comments = True line_length = 125 [testenv:clean] deps = coverage[toml]>=5.2 skip_install = true commands = coverage erase [testenv:coveralls] deps = coveralls skip_install = true commands = coveralls [] [testenv:report] basepython = python3.8 deps = coverage[toml]>=5.2 skip_install = true commands = coverage report coverage html -d build/htmlcov [gh-actions] python = 3.8: py38, check