pax_global_header00006660000000000000000000000064146365332550014526gustar00rootroot0000000000000052 comment=2e6ec6dc34268c8e804aef343216807dc0d8d3f1 p1c2u-jsonschema-path-148d7a4/000077500000000000000000000000001463653325500161005ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/.bumpversion.cfg000066400000000000000000000005631463653325500212140ustar00rootroot00000000000000[bumpversion] current_version = 0.3.3 tag = True tag_name = {new_version} commit = True message = Version {new_version} parse = (?P\d+)\.(?P\d+)\.(?P\d+) serialize = {major}.{minor}.{patch} [bumpversion:file:jsonschema_path/__init__.py] [bumpversion:file:pyproject.toml] search = version = "{current_version}" replace = version = "{new_version}" p1c2u-jsonschema-path-148d7a4/.github/000077500000000000000000000000001463653325500174405ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/.github/FUNDING.yml000066400000000000000000000000201463653325500212450ustar00rootroot00000000000000github: [p1c2u] p1c2u-jsonschema-path-148d7a4/.github/dependabot.yml000066400000000000000000000001531463653325500222670ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" p1c2u-jsonschema-path-148d7a4/.github/workflows/000077500000000000000000000000001463653325500214755ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/.github/workflows/python-publish.yml000066400000000000000000000015351463653325500252110ustar00rootroot00000000000000# This workflow will upload a Python Package using Twine when a release is created # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries name: Publish python packages on: workflow_dispatch: release: types: - published jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.x' - name: Set up poetry uses: Gr1N/setup-poetry@v8 - name: Build run: poetry build - name: Publish env: POETRY_HTTP_BASIC_PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: poetry publish p1c2u-jsonschema-path-148d7a4/.github/workflows/python-test.yml000066400000000000000000000057001463653325500245200ustar00rootroot00000000000000# This workflow will install Python dependencies, run tests and lint with a variety of Python versions # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions name: Test python code on: push: pull_request: types: [opened, synchronize] jobs: test: name: "Tests" runs-on: ubuntu-latest strategy: matrix: python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] fail-fast: false steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Get full Python version id: full-python-version run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Set up poetry uses: Gr1N/setup-poetry@v8 - name: Configure poetry run: poetry config virtualenvs.in-project true - name: Set up cache uses: actions/cache@v2 id: cache with: path: .venv key: venv-${{ github.event_name }}-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' shell: bash run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies run: poetry install --all-extras - name: Test env: PYTEST_ADDOPTS: "--color=yes" run: poetry run pytest - name: Static type check run: poetry run mypy - name: Check dependencies run: poetry run deptry . - name: Upload coverage uses: codecov/codecov-action@v1 static-checks: name: "Static checks" runs-on: ubuntu-latest steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" uses: actions/checkout@v2 - name: "Setup Python" uses: actions/setup-python@v2 with: python-version: 3.9 - name: Get full Python version id: full-python-version run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Set up poetry uses: Gr1N/setup-poetry@v8 - name: Configure poetry run: poetry config virtualenvs.in-project true - name: Set up cache uses: actions/cache@v2 id: cache with: path: .venv key: venv-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies run: poetry install - name: Run static checks run: poetry run pre-commit run -a p1c2u-jsonschema-path-148d7a4/.gitignore000066400000000000000000000034071463653325500200740ustar00rootroot00000000000000# 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/ pip-wheel-metadata/ 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/ # 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 target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .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/ p1c2u-jsonschema-path-148d7a4/.pre-commit-config.yaml000066400000000000000000000017551463653325500223710ustar00rootroot00000000000000--- default_stages: [commit, push] default_language_version: # force all unspecified python hooks to run python3 python: python3 minimum_pre_commit_version: "1.20.0" repos: - repo: meta hooks: - id: check-hooks-apply - repo: https://github.com/asottile/pyupgrade rev: v2.38.4 hooks: - id: pyupgrade args: ["--py36-plus"] - repo: local hooks: - id: flynt name: Convert to f-strings with flynt entry: flynt language: python additional_dependencies: ['flynt==0.76'] - id: black name: black entry: black language: system require_serial: true types: [python] - id: isort name: isort entry: isort args: ['--filter-files'] language: system require_serial: true types: [python] - id: pyflakes name: pyflakes entry: pyflakes language: system require_serial: true types: [python] p1c2u-jsonschema-path-148d7a4/LICENSE000066400000000000000000000261351463653325500171140ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. p1c2u-jsonschema-path-148d7a4/MANIFEST.in000066400000000000000000000001041463653325500176310ustar00rootroot00000000000000include LICENSE include README.rst include jsonschema_path/py.typed p1c2u-jsonschema-path-148d7a4/README.rst000066400000000000000000000060611463653325500175720ustar00rootroot00000000000000*************** JSONSchema Path *************** .. image:: https://img.shields.io/pypi/v/jsonschema-path.svg :target: https://pypi.python.org/pypi/jsonschema-path .. image:: https://travis-ci.org/p1c2u/jsonschema-path.svg?branch=master :target: https://travis-ci.org/p1c2u/jsonschema-path .. image:: https://img.shields.io/codecov/c/github/p1c2u/jsonschema-path/master.svg?style=flat :target: https://codecov.io/github/p1c2u/jsonschema-path?branch=master .. image:: https://img.shields.io/pypi/pyversions/jsonschema-path.svg :target: https://pypi.python.org/pypi/jsonschema-path .. image:: https://img.shields.io/pypi/format/jsonschema-path.svg :target: https://pypi.python.org/pypi/jsonschema-path .. image:: https://img.shields.io/pypi/status/jsonschema-path.svg :target: https://pypi.python.org/pypi/jsonschema-path About ##### Object-oriented JSONSchema Key features ############ * Traverse schema like paths * Access schema on demand with separate dereferencing accessor layer Installation ############ .. code-block:: console pip install jsonschema-path Alternatively you can download the code and install from the repository: .. code-block:: console pip install -e git+https://github.com/p1c2u/jsonschema-path.git#egg=jsonschema_path Usage ##### .. code-block:: python >>> from jsonschema_path import SchemaPath >>> d = { ... "properties": { ... "info": { ... "$ref": "#/$defs/Info", ... }, ... }, ... "$defs": { ... "Info": { ... "properties": { ... "title": { ... "$ref": "http://example.com", ... }, ... "version": { ... "type": "string", ... "default": "1.0", ... }, ... }, ... }, ... }, ... } >>> path = SchemaPath.from_dict(d) >>> # Stat keys >>> "properties" in path True >>> # Concatenate paths with / >>> info_path = path / "properties" / "info" >>> # Stat keys with implicit dereferencing >>> "properties" in info_path True >>> # Concatenate paths with implicit dereferencing >>> version_path = info_path / "properties" / "version" >>> # Open content with implicit dereferencing >>> with version_path.open() as contents: ... print(contents) {'type': 'string', 'default': '1.0'} Related projects ################ * `openapi-core `__ Python library that adds client-side and server-side support for the OpenAPI. * `openapi-spec-validator `__ Python library that validates OpenAPI Specs against the OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0 specification * `openapi-schema-validator `__ Python library that validates schema against the OpenAPI Schema Specification v3.0. License ####### Copyright (c) 2017-2022, Artur Maciag, All rights reserved. Apache-2.0 p1c2u-jsonschema-path-148d7a4/jsonschema_path/000077500000000000000000000000001463653325500212465ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/jsonschema_path/__init__.py000066400000000000000000000006001463653325500233530ustar00rootroot00000000000000from jsonschema_path.accessors import SchemaAccessor from jsonschema_path.handlers import default_handlers from jsonschema_path.paths import SchemaPath __author__ = "Artur Maciag" __email__ = "maciag.artur@gmail.com" __version__ = "0.3.3" __url__ = "https://github.com/p1c2u/jsonschema-path" __license__ = "Apache-2.0" __all__ = ["SchemaAccessor", "SchemaPath", "default_handlers"] p1c2u-jsonschema-path-148d7a4/jsonschema_path/accessors.py000066400000000000000000000060501463653325500236060ustar00rootroot00000000000000"""JSONSchema spec accessors module.""" from collections import deque from contextlib import contextmanager from typing import Any from typing import Deque from typing import Hashable from typing import Iterator from typing import List from typing import Optional from typing import Union from pathable.accessors import LookupAccessor from referencing import Registry from referencing import Specification from referencing._core import Resolved from referencing._core import Resolver from referencing.jsonschema import DRAFT202012 from jsonschema_path.handlers import default_handlers from jsonschema_path.retrievers import SchemaRetriever from jsonschema_path.typing import Lookup from jsonschema_path.typing import ResolverHandlers from jsonschema_path.typing import Schema from jsonschema_path.utils import is_ref class ResolverAccessor(LookupAccessor): def __init__(self, lookup: Lookup, resolver: Resolver[Lookup]): super().__init__(lookup) self.resolver = resolver class SchemaAccessor(ResolverAccessor): @classmethod def from_schema( cls, schema: Schema, specification: Specification[Schema] = DRAFT202012, base_uri: str = "", handlers: ResolverHandlers = default_handlers, ) -> "SchemaAccessor": retriever = SchemaRetriever(handlers, specification) base_resource = specification.create_resource(schema) registry: Registry[Schema] = Registry( retrieve=retriever, # type: ignore ) registry = registry.with_resource(base_uri, base_resource) resolver = registry.resolver(base_uri=base_uri) return cls(schema, resolver) @contextmanager def open(self, parts: List[Hashable]) -> Iterator[Union[Schema, Any]]: parts_deque = deque(parts) try: resolved = self._resolve(self.lookup, parts_deque) yield resolved.contents finally: pass @contextmanager def resolve(self, parts: List[Hashable]) -> Iterator[Resolved[Any]]: parts_deque = deque(parts) try: yield self._resolve(self.lookup, parts_deque) finally: pass def _resolve( self, contents: Schema, parts_deque: Deque[Hashable], resolver: Optional[Resolver[Schema]] = None, ) -> Resolved[Any]: resolver = resolver or self.resolver if is_ref(contents): ref = contents["$ref"] resolved = resolver.lookup(ref) self.resolver = self.resolver._evolve( self.resolver._base_uri, registry=resolved.resolver._registry, ) return self._resolve( resolved.contents, parts_deque, resolver=resolved.resolver, ) try: part = parts_deque.popleft() except IndexError: return Resolved(contents=contents, resolver=resolver) # type: ignore else: target = contents[part] return self._resolve(target, parts_deque, resolver=resolver) p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/000077500000000000000000000000001463653325500230465ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/__init__.py000066400000000000000000000013711463653325500251610ustar00rootroot00000000000000from typing import TYPE_CHECKING from jsonschema_path.handlers.file import FileHandler from jsonschema_path.handlers.urllib import UrllibHandler if TYPE_CHECKING: from jsonschema_path.handlers.urllib import UrllibHandler as UrlHandler else: try: from jsonschema_path.handlers.requests import ( UrlRequestsHandler as UrlHandler, ) except ImportError: from jsonschema_path.handlers.urllib import UrllibHandler as UrlHandler __all__ = ["FileHandler", "UrlHandler"] file_handler = FileHandler() all_urls_handler = UrllibHandler("http", "https", "file") default_handlers = { "": all_urls_handler, "http": UrlHandler("http"), "https": UrlHandler("https"), "file": UrllibHandler("file"), } p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/file.py000066400000000000000000000040111463653325500243330ustar00rootroot00000000000000"""JSONSchema spec handlers file module.""" from json import dumps from json import loads from typing import Any from typing import ContextManager from typing import Optional from typing import Tuple from urllib.parse import urlparse from yaml import load from jsonschema_path.handlers.protocols import SupportsRead from jsonschema_path.handlers.utils import uri_to_path from jsonschema_path.loaders import JsonschemaSafeLoader class FileHandler: """File-like object handler.""" def __init__(self, loader: Any = JsonschemaSafeLoader): self.loader = loader def __call__(self, stream: SupportsRead) -> Any: data = self._load(stream) return loads(dumps(data)) def _load(self, stream: SupportsRead) -> Any: return load(stream, self.loader) class BaseFilePathHandler: """Base file path handler.""" allowed_schemes: Tuple[str, ...] = NotImplemented def __init__( self, *allowed_schemes: str, file_handler: Optional[FileHandler] = None ): self.allowed_schemes = allowed_schemes or self.allowed_schemes self.file_handler = file_handler or FileHandler() def __call__(self, uri: str) -> Any: parsed_url = urlparse(uri) if parsed_url.scheme not in self.allowed_schemes: raise ValueError(f"Scheme {parsed_url.scheme} not allowed") with self._open(uri) as stream: return self.file_handler(stream) def _open(self, uri: str) -> ContextManager[SupportsRead]: raise NotImplementedError class FilePathHandler(BaseFilePathHandler): """File path handler.""" allowed_schemes = ("file",) def __init__( self, *allowed_schemes: str, file_handler: Optional[FileHandler] = None, encoding: str = "utf-8", ): super().__init__(*allowed_schemes, file_handler=file_handler) self.encoding = encoding def _open(self, uri: str) -> ContextManager[SupportsRead]: filepath = uri_to_path(uri) return open(filepath, encoding=self.encoding) p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/protocols.py000066400000000000000000000002221463653325500254400ustar00rootroot00000000000000from typing import Optional from typing import Protocol class SupportsRead(Protocol): def read(self, amount: Optional[int] = 0) -> str: ... p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/requests.py000066400000000000000000000020361463653325500252740ustar00rootroot00000000000000"""JSONSchema spec handlers requests module.""" from contextlib import closing from io import StringIO from typing import ContextManager from typing import Optional from typing import Union import requests from jsonschema_path.handlers.file import BaseFilePathHandler from jsonschema_path.handlers.file import FileHandler from jsonschema_path.handlers.protocols import SupportsRead class UrlRequestsHandler(BaseFilePathHandler): """URL (requests) scheme handler.""" def __init__( self, *allowed_schemes: str, file_handler: Optional[FileHandler] = None, timeout: int = 10, verify: Optional[Union[bool, str]] = True, ): super().__init__(*allowed_schemes, file_handler=file_handler) self.timeout = timeout self.verify = verify def _open(self, uri: str) -> ContextManager[SupportsRead]: response = requests.get(uri, timeout=self.timeout, verify=self.verify) response.raise_for_status() data = StringIO(response.text) return closing(data) p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/urllib.py000066400000000000000000000014501463653325500247110ustar00rootroot00000000000000"""JSONSchema spec handlers urllib module.""" from contextlib import closing from typing import ContextManager from typing import Optional from urllib.request import urlopen from jsonschema_path.handlers.file import BaseFilePathHandler from jsonschema_path.handlers.file import FileHandler from jsonschema_path.handlers.protocols import SupportsRead class UrllibHandler(BaseFilePathHandler): """URL (urllib) scheme handler.""" def __init__( self, *allowed_schemes: str, file_handler: Optional[FileHandler] = None, timeout: int = 10 ): super().__init__(*allowed_schemes, file_handler=file_handler) self.timeout = timeout def _open(self, uri: str) -> ContextManager[SupportsRead]: return closing(urlopen(uri, timeout=self.timeout)) p1c2u-jsonschema-path-148d7a4/jsonschema_path/handlers/utils.py000066400000000000000000000005511463653325500245610ustar00rootroot00000000000000import os.path import urllib.parse import urllib.request def uri_to_path(uri: str) -> str: parsed = urllib.parse.urlparse(uri) host = "{0}{0}{mnt}{0}".format(os.path.sep, mnt=parsed.netloc) return os.path.normpath( os.path.join( host, urllib.request.url2pathname(urllib.parse.unquote(parsed.path)), ) ) p1c2u-jsonschema-path-148d7a4/jsonschema_path/loaders.py000066400000000000000000000025301463653325500232510ustar00rootroot00000000000000# Use CSafeFile if available from typing import TYPE_CHECKING from typing import Any from typing import Dict from typing import Iterable from typing import Tuple if TYPE_CHECKING: from yaml import SafeLoader else: try: from yaml import CSafeLoader as SafeLoader except ImportError: from yaml import SafeLoader __all__ = [ "SafeLoader", ] class LimitedSafeLoader(type): """Meta YAML loader that skips the resolution of the specified YAML tags.""" def __new__( cls, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any], exclude_resolvers: Iterable[str], ) -> "LimitedSafeLoader": exclude_resolvers = set(exclude_resolvers) implicit_resolvers = { key: [ (tag, regex) for tag, regex in mappings if tag not in exclude_resolvers ] for key, mappings in SafeLoader.yaml_implicit_resolvers.items() } return super().__new__( cls, name, (SafeLoader, *bases), {**namespace, "yaml_implicit_resolvers": implicit_resolvers}, ) class JsonschemaSafeLoader( metaclass=LimitedSafeLoader, exclude_resolvers={"tag:yaml.org,2002:timestamp"}, ): """A safe YAML loader that leaves timestamps as strings.""" p1c2u-jsonschema-path-148d7a4/jsonschema_path/paths.py000066400000000000000000000076521463653325500227510ustar00rootroot00000000000000"""JSONSchema spec paths module.""" import warnings from contextlib import contextmanager from pathlib import Path from typing import Any from typing import Iterator from typing import Optional from typing import Type from typing import TypeVar from pathable.paths import AccessorPath from referencing import Specification from referencing._core import Resolved from referencing.jsonschema import DRAFT202012 from jsonschema_path.accessors import SchemaAccessor from jsonschema_path.handlers import default_handlers from jsonschema_path.handlers.protocols import SupportsRead from jsonschema_path.readers import FilePathReader from jsonschema_path.readers import FileReader from jsonschema_path.readers import PathReader from jsonschema_path.typing import ResolverHandlers from jsonschema_path.typing import Schema TSpec = TypeVar("TSpec", bound="SchemaPath") SPEC_SEPARATOR = "#" class SchemaPath(AccessorPath): def __init__(self, accessor: SchemaAccessor, *args: Any, **kwargs: Any): super().__init__(accessor, *args, **kwargs) self._resolved_cached: Optional[Resolved[Any]] = None @classmethod def from_dict( cls: Type[TSpec], data: Schema, *args: Any, separator: str = SPEC_SEPARATOR, specification: Specification[Schema] = DRAFT202012, base_uri: str = "", handlers: ResolverHandlers = default_handlers, spec_url: Optional[str] = None, ref_resolver_handlers: Optional[ResolverHandlers] = None, ) -> TSpec: if spec_url is not None: warnings.warn( "spec_url parameter is deprecated. " "Use base_uri instead.", DeprecationWarning, ) base_uri = spec_url if ref_resolver_handlers is not None: warnings.warn( "ref_resolver_handlers parameter is deprecated. " "Use handlers instead.", DeprecationWarning, ) handlers = ref_resolver_handlers accessor: SchemaAccessor = SchemaAccessor.from_schema( data, specification=specification, base_uri=base_uri, handlers=handlers, ) return cls(accessor, *args, separator=separator) @classmethod def from_path( cls: Type[TSpec], path: Path, ) -> TSpec: reader = PathReader(path) data, base_uri = reader.read() return cls.from_dict(data, base_uri=base_uri) @classmethod def from_file_path( cls: Type[TSpec], file_path: str, ) -> TSpec: reader = FilePathReader(file_path) data, base_uri = reader.read() return cls.from_dict(data, base_uri=base_uri) @classmethod def from_file( cls: Type[TSpec], fileobj: SupportsRead, base_uri: str = "", spec_url: Optional[str] = None, ) -> TSpec: reader = FileReader(fileobj) data, _ = reader.read() return cls.from_dict(data, base_uri=base_uri, spec_url=spec_url) def contents(self) -> Any: with self.open() as d: return d def exists(self) -> bool: try: self.contents() except KeyError: return False else: return True def as_uri(self) -> str: return f"#/{str(self)}" @contextmanager def open(self) -> Any: """Open the path.""" # Cached path content with self.resolve() as resolved: yield resolved.contents @contextmanager def resolve(self) -> Iterator[Resolved[Any]]: """Resolve the path.""" # Cached path content if self._resolved_cached is None: self._resolved_cached = self._get_resolved() yield self._resolved_cached def _get_resolved(self) -> Resolved[Any]: assert isinstance(self.accessor, SchemaAccessor) with self.accessor.resolve(self.parts) as resolved: return resolved p1c2u-jsonschema-path-148d7a4/jsonschema_path/py.typed000066400000000000000000000000001463653325500227330ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/jsonschema_path/readers.py000066400000000000000000000021501463653325500232430ustar00rootroot00000000000000"""JSONSchema spec readers module.""" from pathlib import Path from typing import Any from typing import Hashable from typing import Mapping from typing import Tuple from jsonschema_path.handlers import all_urls_handler from jsonschema_path.handlers import file_handler from jsonschema_path.handlers.protocols import SupportsRead class BaseReader: def read(self) -> Tuple[Mapping[Hashable, Any], str]: raise NotImplementedError class FileReader(BaseReader): def __init__(self, fileobj: SupportsRead): self.fileobj = fileobj def read(self) -> Tuple[Mapping[Hashable, Any], str]: return file_handler(self.fileobj), "" class PathReader(BaseReader): def __init__(self, path: Path): self.path = path def read(self) -> Tuple[Mapping[Hashable, Any], str]: if not self.path.is_file(): raise OSError(f"No such file: {self.path}") uri = self.path.as_uri() return all_urls_handler(uri), uri class FilePathReader(PathReader): def __init__(self, file_path: str): path = Path(file_path).absolute() super().__init__(path) p1c2u-jsonschema-path-148d7a4/jsonschema_path/retrievers.py000066400000000000000000000026771463653325500240260ustar00rootroot00000000000000from json import loads from urllib.parse import urlsplit from urllib.request import urlopen from referencing import Resource from referencing import Specification from referencing.typing import URI from referencing.typing import Retrieve from jsonschema_path.typing import ResolverHandlers from jsonschema_path.typing import Schema USE_REQUESTS = False try: import requests except ImportError: pass else: USE_REQUESTS = True class SchemaRetriever(Retrieve[Schema]): def __init__( self, handlers: ResolverHandlers, specification: Specification[Schema] ): self.handlers = handlers self.specification = specification def __call__(self, uri: URI) -> Resource[Schema]: scheme = urlsplit(uri).scheme if scheme in self.handlers: handler = self.handlers[scheme] contents = handler(uri) return self.specification.create_resource(contents) else: if scheme in ["http", "https"] and USE_REQUESTS: # Requests has support for detecting the correct encoding of # json over http contents = requests.get(uri).json() return self.specification.create_resource(contents) # Otherwise, pass off to urllib and assume utf-8 with urlopen(uri) as url: contents = loads(url.read().decode("utf-8")) return self.specification.create_resource(contents) p1c2u-jsonschema-path-148d7a4/jsonschema_path/typing.py000066400000000000000000000002651463653325500231350ustar00rootroot00000000000000from typing import Any from typing import Hashable from typing import Mapping Lookup = Mapping[Hashable, Any] ResolverHandlers = Mapping[str, Any] Schema = Mapping[Hashable, Any] p1c2u-jsonschema-path-148d7a4/jsonschema_path/utils.py000066400000000000000000000003671463653325500227660ustar00rootroot00000000000000from typing import Any from typing import Hashable from typing import Mapping from typing import Optional def is_ref(item: Optional[Mapping[Hashable, Any]]) -> bool: return isinstance(item, dict) and "$ref" in item and item["$ref"].__hash__ p1c2u-jsonschema-path-148d7a4/poetry.lock000066400000000000000000002131461463653325500203030ustar00rootroot00000000000000# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "astor" version = "0.8.1" description = "Read/rewrite/write Python ASTs" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" files = [ {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, ] [[package]] name = "attrs" version = "22.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.6" files = [ {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, ] [package.extras] cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] dev = ["attrs[docs,tests]"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] tests = ["attrs[tests-no-zope]", "zope.interface"] tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] [[package]] name = "black" version = "24.4.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ {file = "black-24.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6ad001a9ddd9b8dfd1b434d566be39b1cd502802c8d38bbb1ba612afda2ef436"}, {file = "black-24.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3a3a092b8b756c643fe45f4624dbd5a389f770a4ac294cf4d0fce6af86addaf"}, {file = "black-24.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dae79397f367ac8d7adb6c779813328f6d690943f64b32983e896bcccd18cbad"}, {file = "black-24.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:71d998b73c957444fb7c52096c3843875f4b6b47a54972598741fe9a7f737fcb"}, {file = "black-24.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e5537f456a22cf5cfcb2707803431d2feeb82ab3748ade280d6ccd0b40ed2e8"}, {file = "black-24.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64e60a7edd71fd542a10a9643bf369bfd2644de95ec71e86790b063aa02ff745"}, {file = "black-24.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cd5b4f76056cecce3e69b0d4c228326d2595f506797f40b9233424e2524c070"}, {file = "black-24.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:64578cf99b6b46a6301bc28bdb89f9d6f9b592b1c5837818a177c98525dbe397"}, {file = "black-24.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f95cece33329dc4aa3b0e1a771c41075812e46cf3d6e3f1dfe3d91ff09826ed2"}, {file = "black-24.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4396ca365a4310beef84d446ca5016f671b10f07abdba3e4e4304218d2c71d33"}, {file = "black-24.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44d99dfdf37a2a00a6f7a8dcbd19edf361d056ee51093b2445de7ca09adac965"}, {file = "black-24.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:21f9407063ec71c5580b8ad975653c66508d6a9f57bd008bb8691d273705adcd"}, {file = "black-24.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:652e55bb722ca026299eb74e53880ee2315b181dfdd44dca98e43448620ddec1"}, {file = "black-24.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f2966b9b2b3b7104fca9d75b2ee856fe3fdd7ed9e47c753a4bb1a675f2caab8"}, {file = "black-24.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bb9ca06e556a09f7f7177bc7cb604e5ed2d2df1e9119e4f7d2f1f7071c32e5d"}, {file = "black-24.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4e71cdebdc8efeb6deaf5f2deb28325f8614d48426bed118ecc2dcaefb9ebf3"}, {file = "black-24.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6644f97a7ef6f401a150cca551a1ff97e03c25d8519ee0bbc9b0058772882665"}, {file = "black-24.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:75a2d0b4f5eb81f7eebc31f788f9830a6ce10a68c91fbe0fade34fff7a2836e6"}, {file = "black-24.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb949f56a63c5e134dfdca12091e98ffb5fd446293ebae123d10fc1abad00b9e"}, {file = "black-24.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:7852b05d02b5b9a8c893ab95863ef8986e4dda29af80bbbda94d7aee1abf8702"}, {file = "black-24.4.0-py3-none-any.whl", hash = "sha256:74eb9b5420e26b42c00a3ff470dc0cd144b80a766128b1771d07643165e08d0e"}, {file = "black-24.4.0.tar.gz", hash = "sha256:f07b69fda20578367eaebbd670ff8fc653ab181e1ff95d84497f9fa20e7d0641"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bump2version" version = "1.0.1" description = "Version-bump your software with a single command!" optional = false python-versions = ">=3.5" files = [ {file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"}, {file = "bump2version-1.0.1.tar.gz", hash = "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"}, ] [[package]] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] [[package]] name = "cfgv" version = "3.3.1" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.6.1" files = [ {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] [[package]] name = "chardet" version = "5.1.0" description = "Universal encoding detector for Python 3" optional = false python-versions = ">=3.7" files = [ {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, ] [[package]] name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] [[package]] name = "click" version = "8.1.3" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] name = "coverage" version = "7.1.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.7" files = [ {file = "coverage-7.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b946bbcd5a8231383450b195cfb58cb01cbe7f8949f5758566b881df4b33baf"}, {file = "coverage-7.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec8e767f13be637d056f7e07e61d089e555f719b387a7070154ad80a0ff31801"}, {file = "coverage-7.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a5a5879a939cb84959d86869132b00176197ca561c664fc21478c1eee60d75"}, {file = "coverage-7.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b643cb30821e7570c0aaf54feaf0bfb630b79059f85741843e9dc23f33aaca2c"}, {file = "coverage-7.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32df215215f3af2c1617a55dbdfb403b772d463d54d219985ac7cd3bf124cada"}, {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:33d1ae9d4079e05ac4cc1ef9e20c648f5afabf1a92adfaf2ccf509c50b85717f"}, {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:29571503c37f2ef2138a306d23e7270687c0efb9cab4bd8038d609b5c2393a3a"}, {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:63ffd21aa133ff48c4dff7adcc46b7ec8b565491bfc371212122dd999812ea1c"}, {file = "coverage-7.1.0-cp310-cp310-win32.whl", hash = "sha256:4b14d5e09c656de5038a3f9bfe5228f53439282abcab87317c9f7f1acb280352"}, {file = "coverage-7.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:8361be1c2c073919500b6601220a6f2f98ea0b6d2fec5014c1d9cfa23dd07038"}, {file = "coverage-7.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:da9b41d4539eefd408c46725fb76ecba3a50a3367cafb7dea5f250d0653c1040"}, {file = "coverage-7.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5b15ed7644ae4bee0ecf74fee95808dcc34ba6ace87e8dfbf5cb0dc20eab45a"}, {file = "coverage-7.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d12d076582507ea460ea2a89a8c85cb558f83406c8a41dd641d7be9a32e1274f"}, {file = "coverage-7.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2617759031dae1bf183c16cef8fcfb3de7617f394c813fa5e8e46e9b82d4222"}, {file = "coverage-7.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4e4881fa9e9667afcc742f0c244d9364d197490fbc91d12ac3b5de0bf2df146"}, {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9d58885215094ab4a86a6aef044e42994a2bd76a446dc59b352622655ba6621b"}, {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2"}, {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3baf5f126f30781b5e93dbefcc8271cb2491647f8283f20ac54d12161dff080e"}, {file = "coverage-7.1.0-cp311-cp311-win32.whl", hash = "sha256:ded59300d6330be27bc6cf0b74b89ada58069ced87c48eaf9344e5e84b0072f7"}, {file = "coverage-7.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:6a43c7823cd7427b4ed763aa7fb63901ca8288591323b58c9cd6ec31ad910f3c"}, {file = "coverage-7.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a726d742816cb3a8973c8c9a97539c734b3a309345236cd533c4883dda05b8d"}, {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc7c85a150501286f8b56bd8ed3aa4093f4b88fb68c0843d21ff9656f0009d6a"}, {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8"}, {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddb726cb861c3117a553f940372a495fe1078249ff5f8a5478c0576c7be12050"}, {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:51b236e764840a6df0661b67e50697aaa0e7d4124ca95e5058fa3d7cbc240b7c"}, {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7ee5c9bb51695f80878faaa5598040dd6c9e172ddcf490382e8aedb8ec3fec8d"}, {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c31b75ae466c053a98bf26843563b3b3517b8f37da4d47b1c582fdc703112bc3"}, {file = "coverage-7.1.0-cp37-cp37m-win32.whl", hash = "sha256:3b155caf3760408d1cb903b21e6a97ad4e2bdad43cbc265e3ce0afb8e0057e73"}, {file = "coverage-7.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2a60d6513781e87047c3e630b33b4d1e89f39836dac6e069ffee28c4786715f5"}, {file = "coverage-7.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06"}, {file = "coverage-7.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beeb129cacea34490ffd4d6153af70509aa3cda20fdda2ea1a2be870dfec8d52"}, {file = "coverage-7.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851"}, {file = "coverage-7.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef382417db92ba23dfb5864a3fc9be27ea4894e86620d342a116b243ade5d35d"}, {file = "coverage-7.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c7c0d0827e853315c9bbd43c1162c006dd808dbbe297db7ae66cd17b07830f0"}, {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e5cdbb5cafcedea04924568d990e20ce7f1945a1dd54b560f879ee2d57226912"}, {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9817733f0d3ea91bea80de0f79ef971ae94f81ca52f9b66500c6a2fea8e4b4f8"}, {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:218fe982371ac7387304153ecd51205f14e9d731b34fb0568181abaf7b443ba0"}, {file = "coverage-7.1.0-cp38-cp38-win32.whl", hash = "sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab"}, {file = "coverage-7.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8ae125d1134bf236acba8b83e74c603d1b30e207266121e76484562bc816344c"}, {file = "coverage-7.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2bf1d5f2084c3932b56b962a683074a3692bce7cabd3aa023c987a2a8e7612f6"}, {file = "coverage-7.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:98b85dd86514d889a2e3dd22ab3c18c9d0019e696478391d86708b805f4ea0fa"}, {file = "coverage-7.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38da2db80cc505a611938d8624801158e409928b136c8916cd2e203970dde4dc"}, {file = "coverage-7.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3164d31078fa9efe406e198aecd2a02d32a62fecbdef74f76dad6a46c7e48311"}, {file = "coverage-7.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db61a79c07331e88b9a9974815c075fbd812bc9dbc4dc44b366b5368a2936063"}, {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ccb092c9ede70b2517a57382a601619d20981f56f440eae7e4d7eaafd1d1d09"}, {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:33ff26d0f6cc3ca8de13d14fde1ff8efe1456b53e3f0273e63cc8b3c84a063d8"}, {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d47dd659a4ee952e90dc56c97d78132573dc5c7b09d61b416a9deef4ebe01a0c"}, {file = "coverage-7.1.0-cp39-cp39-win32.whl", hash = "sha256:d248cd4a92065a4d4543b8331660121b31c4148dd00a691bfb7a5cdc7483cfa4"}, {file = "coverage-7.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:7ed681b0f8e8bcbbffa58ba26fcf5dbc8f79e7997595bf071ed5430d8c08d6f3"}, {file = "coverage-7.1.0-pp37.pp38.pp39-none-any.whl", hash = "sha256:755e89e32376c850f826c425ece2c35a4fc266c081490eb0a841e7c1cb0d3bda"}, {file = "coverage-7.1.0.tar.gz", hash = "sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265"}, ] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] toml = ["tomli"] [[package]] name = "deptry" version = "0.14.2" description = "A command line utility to check for unused, missing and transitive dependencies in a Python project." optional = false python-versions = ">=3.8, <4.0" files = [ {file = "deptry-0.14.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6f451ac26990bcb3e4d517271b87f1f02e7272da6644e47755aa72bbb649a8dd"}, {file = "deptry-0.14.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:7b3eeeace8c3cdb2eafe14d7a0261bb2ec410d1887a4152091e9dcb73325b452"}, {file = "deptry-0.14.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb4988bff104bfd3c0b13841f18dbddc6c818b88101cad97f662acc5827209ac"}, {file = "deptry-0.14.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f61a6c1165e91753d029c2a598d0ff37b7e6cb436beff5cc3ba6c7b8b4acf93"}, {file = "deptry-0.14.2-cp38-abi3-win_amd64.whl", hash = "sha256:65d20f7316b2f2ff545430dd3c2dea6dc668cd6ee3b866dffdf78d39c3b07ee8"}, {file = "deptry-0.14.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:95901237482a390611370522d707931eeb1ea7172a56fe1bf84f0d4624b1dd4c"}, {file = "deptry-0.14.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f531fd1cdcc980438647cc8c95115989f0a7efbf3456611174cfd54db721657"}, {file = "deptry-0.14.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54182741d343bcca73116a13eb905b5bded80ef72e2d13cdb23081c72a486f17"}, {file = "deptry-0.14.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6c9a2949d2c0c580981e22c8ceff0461e77e632b94dacd02307f81caaa35f93f"}, {file = "deptry-0.14.2.tar.gz", hash = "sha256:1c585d4a5f9ddc75ed0cb27f99e998edda4720d050ba7214503a2bfe5e85d7df"}, ] [package.dependencies] chardet = ">=4.0.0" click = ">=8.0.0,<9" colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} pathspec = ">=0.9.0" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [[package]] name = "distlib" version = "0.3.6" description = "Distribution utilities" optional = false python-versions = "*" files = [ {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, ] [[package]] name = "exceptiongroup" version = "1.1.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, ] [package.extras] test = ["pytest (>=6)"] [[package]] name = "filelock" version = "3.9.0" description = "A platform independent file lock." optional = false python-versions = ">=3.7" files = [ {file = "filelock-3.9.0-py3-none-any.whl", hash = "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"}, {file = "filelock-3.9.0.tar.gz", hash = "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de"}, ] [package.extras] docs = ["furo (>=2022.12.7)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] testing = ["covdefaults (>=2.2.2)", "coverage (>=7.0.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] [[package]] name = "flake8" version = "5.0.4" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.6.1" files = [ {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.9.0,<2.10.0" pyflakes = ">=2.5.0,<2.6.0" [[package]] name = "flynt" version = "1.0.1" description = "CLI tool to convert a python project's %-formatted strings to f-strings." optional = false python-versions = ">=3.7" files = [ {file = "flynt-1.0.1-py3-none-any.whl", hash = "sha256:65d1c546434827275123222a98408e9561bcd67db832dd58f530ff17b8329ec1"}, {file = "flynt-1.0.1.tar.gz", hash = "sha256:988aac00672a5469726cc0a17cef7d1178c284a9fe8563458db2475d0aaed965"}, ] [package.dependencies] astor = "*" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [package.extras] dev = ["build", "pre-commit", "pytest", "pytest-cov", "twine"] [[package]] name = "identify" version = "2.5.17" description = "File identification library for Python" optional = false python-versions = ">=3.7" files = [ {file = "identify-2.5.17-py2.py3-none-any.whl", hash = "sha256:7d526dd1283555aafcc91539acc061d8f6f59adb0a7bba462735b0a318bff7ed"}, {file = "identify-2.5.17.tar.gz", hash = "sha256:93cc61a861052de9d4c541a7acb7e3dcc9c11b398a2144f6e52ae5285f5f4f06"}, ] [package.extras] license = ["ukkonen"] [[package]] name = "idna" version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] name = "isort" version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] colors = ["colorama (>=0.4.6)"] [[package]] name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] [[package]] name = "mypy" version = "1.9.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] name = "nodeenv" version = "1.7.0" description = "Node.js virtual environment builder" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, ] [package.dependencies] setuptools = "*" [[package]] name = "packaging" version = "23.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, ] [[package]] name = "pathable" version = "0.4.3" description = "Object-oriented paths" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ {file = "pathable-0.4.3-py3-none-any.whl", hash = "sha256:cdd7b1f9d7d5c8b8d3315dbf5a86b2596053ae845f056f57d97c0eefff84da14"}, {file = "pathable-0.4.3.tar.gz", hash = "sha256:5c869d315be50776cc8a993f3af43e0c60dc01506b399643f919034ebf4cdcab"}, ] [[package]] name = "pathspec" version = "0.11.0" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.7" files = [ {file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"}, {file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"}, ] [[package]] name = "platformdirs" version = "2.6.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, ] [package.extras] docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" version = "3.5.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.8" files = [ {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, ] [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" [[package]] name = "pycodestyle" version = "2.9.1" description = "Python style guide checker" optional = false python-versions = ">=3.6" files = [ {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, ] [[package]] name = "pyflakes" version = "2.5.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.6" files = [ {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, ] [[package]] name = "pytest" version = "8.2.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=1.5,<2.0" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" version = "5.0.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.8" files = [ {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [package.dependencies] coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-flake8" version = "1.1.1" description = "pytest plugin to check FLAKE8 requirements" optional = false python-versions = "*" files = [ {file = "pytest-flake8-1.1.1.tar.gz", hash = "sha256:ba4f243de3cb4c2486ed9e70752c80dd4b636f7ccb27d4eba763c35ed0cd316e"}, {file = "pytest_flake8-1.1.1-py2.py3-none-any.whl", hash = "sha256:e0661a786f8cbf976c185f706fdaf5d6df0b1667c3bcff8e823ba263618627e7"}, ] [package.dependencies] flake8 = ">=4.0" pytest = ">=7.0" [[package]] name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.6" files = [ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] name = "referencing" version = "0.35.1" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, ] [package.dependencies] attrs = ">=22.2.0" rpds-py = ">=0.7.0" [[package]] name = "requests" version = "2.32.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ {file = "requests-2.32.0-py3-none-any.whl", hash = "sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5"}, {file = "requests-2.32.0.tar.gz", hash = "sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "responses" version = "0.25.0" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" files = [ {file = "responses-0.25.0-py3-none-any.whl", hash = "sha256:2f0b9c2b6437db4b528619a77e5d565e4ec2a9532162ac1a131a83529db7be1a"}, {file = "responses-0.25.0.tar.gz", hash = "sha256:01ae6a02b4f34e39bffceb0fc6786b67a25eae919c6368d05eabc8d9576c2a66"}, ] [package.dependencies] pyyaml = "*" requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "rpds-py" version = "0.7.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ {file = "rpds_py-0.7.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:e5ce9ded54dee1f179e9240a983779d5e3bef20249ae4419b671af549b077879"}, {file = "rpds_py-0.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fdc103711cba081c8896476d99479b462fc584091f9979c3c17fedca7558d4d2"}, {file = "rpds_py-0.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b442a4155631cd1c53cb1cd83b815c828cdbb8c0c9a1eb9b8791c5a19bf55692"}, {file = "rpds_py-0.7.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c1423f3cddc86b54682d5df905664737300cdf316b1a4fa3056c45b47d44790"}, {file = "rpds_py-0.7.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:648a6e46674764eb0179cff6312aade65bb26f370d8af6fc089ab5bf713a7870"}, {file = "rpds_py-0.7.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e95544c9293bd0f1fa6ecab06472d7b982acfcfaca37df6a1dce113f26e67d66"}, {file = "rpds_py-0.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:083990eb24bf99a0ae92505b24ab4d4c9110d2569e60437d3c721d8807403471"}, {file = "rpds_py-0.7.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97c4507d1b4aaa097f076194606bab723adf7c73c517f09c967818808fc198d4"}, {file = "rpds_py-0.7.1-cp310-none-win32.whl", hash = "sha256:b27301965f076257abea084d245364b3aff01f75a202b36922a09b519dc8359d"}, {file = "rpds_py-0.7.1-cp310-none-win_amd64.whl", hash = "sha256:9ffed319ab2adc2d426160355311686780eea3f063f2b169fa5a9a17bc24e20f"}, {file = "rpds_py-0.7.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:fa7d3cc9c6684cc4e04b9c138c16ff77f4eb3a51ab1b2239964ae8a3b9456a2b"}, {file = "rpds_py-0.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c0502cec5d672b62547c3f5b1e2efc177db0b982cf7742cb23b50c2933739a4b"}, {file = "rpds_py-0.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89d87f5ff7604c25795c369823531b07ac36d62b6c1b743135106f5819051147"}, {file = "rpds_py-0.7.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a5b0f8c81f89ec23d59733dce9724b244003be2367653e1e53095cf643f8c8b"}, {file = "rpds_py-0.7.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18cd993d5b63450abd3a9eab70af4bbecb6d315a5f167ed3b228cba6b5bc18e4"}, {file = "rpds_py-0.7.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99009264ec0992e69f478b3f59b1e411e0d75c1361cf41b1aef397f89d020666"}, {file = "rpds_py-0.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9995693d151387d8a95774f6e464118002d7054fade70ea24942caa0f2dcfa8"}, {file = "rpds_py-0.7.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ffaca17ce98a61a6a7fd7b1aecfe38cc360a97f85cd7b5ffc4e6c17570bcd377"}, {file = "rpds_py-0.7.1-cp311-none-win32.whl", hash = "sha256:457345279898d5156b9de9986c650847c2ee0b205b1fea3f4fe4e8e9f8fe318e"}, {file = "rpds_py-0.7.1-cp311-none-win_amd64.whl", hash = "sha256:51fe912d2356f3a0e63f5557a704407357ee403cb6dbde4f86e339d50a2110b9"}, {file = "rpds_py-0.7.1-cp38-abi3-macosx_10_7_x86_64.whl", hash = "sha256:858604fe5d7eb50e91b1096bcbcb421f2cb3101454244afda92b4d768d0cb4ce"}, {file = "rpds_py-0.7.1-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:e16c02923726307d960e908b61d4d833939f322877d2957c001fca23b644914e"}, {file = "rpds_py-0.7.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:311a57cc972481bd220af28cf4309141c680a356b2359f163daac030d0c2318d"}, {file = "rpds_py-0.7.1-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b6db70c2ab847229fa9cff3a5eb641c33ab3f981ee8b99d326a7deb8989e4ce"}, {file = "rpds_py-0.7.1-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34007442d36980c4aab3f4044c1fd05a736c8ae09d47b8a42112deab5d6b5a10"}, {file = "rpds_py-0.7.1-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d1d4078d60ca47f0eb6bdddbf79f00a72d41ee3148aba1dcf9b980f73a8d26e"}, {file = "rpds_py-0.7.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:025b8101dbf39d77cf41ac3c737e4c713e0b2728a516443b382e66b9d492ff98"}, {file = "rpds_py-0.7.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cc6ff891c3814d8cd92549cb385353a922518d433aaf1d2d0d99e98e59915370"}, {file = "rpds_py-0.7.1-cp38-abi3-win32.whl", hash = "sha256:cbdc8ab6108b8bb260ee68fb2de83fb1c481d3a77355156049a8a49ea47eacf6"}, {file = "rpds_py-0.7.1-cp38-abi3-win_amd64.whl", hash = "sha256:5eda3aba0cd291de9d4bb138db45814bac24bc4c07e0f38b0544374b6104c488"}, {file = "rpds_py-0.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf13f4ed0fd7691cbf10371a65cd6b4aeeed2d04f09e96f8aa52db36a794c7d4"}, {file = "rpds_py-0.7.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d64ef19ea4f65782a09209a2287fea795ca7858375e6e9d87e955dfbbadaed15"}, {file = "rpds_py-0.7.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5551e5583f341867fb6499d9ca4ce3999209b8e30636c6cf48f204120415dbef"}, {file = "rpds_py-0.7.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:794ca22915fb1e4d08d4cafb81c0227d05a75f4dcd3ce463abaf851ba6b14f9c"}, {file = "rpds_py-0.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6decbef9ca15a8fef5840ff350fe53fc2cefbabb34c81bce2576c553fdb33eba"}, {file = "rpds_py-0.7.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b71420bbba0f04c82374196467159e960043089f2931227353d9d51d71cd65a7"}, {file = "rpds_py-0.7.1-cp38-none-win32.whl", hash = "sha256:2f7fe606eb4742f2d2f0ada4e3ee168e809514a39527fce8ee33b2ce908ede00"}, {file = "rpds_py-0.7.1-cp38-none-win_amd64.whl", hash = "sha256:de1e2eb6fe8ab72256aaf83e0d1969a39271a70fa70a27a45b53d270ecfcc7db"}, {file = "rpds_py-0.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b62f9f9bf523f8baea794cc996dc0ba47676bca0517860664e6419f65e533da"}, {file = "rpds_py-0.7.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:453bfdf4a4c618ea24714b6c25bd56d91bfc43c6fd5a34add66c1b92737c5283"}, {file = "rpds_py-0.7.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad2237e4335d6d8a3d678c9106a100c228b1edc92bc5ea6af0be99d1acafd84b"}, {file = "rpds_py-0.7.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f8ab0fd88fc2a8ecc543b72c293d70ffa3f448e85e6fb7dee009629154d683e"}, {file = "rpds_py-0.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:737ea1ee132c89265609ef1951a29a0f4caec57c974715f305587973d63dc439"}, {file = "rpds_py-0.7.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:130cfa21a10a60f5fc8ec59fb5f8b4a649cbc26302c7f487d7798f7969a1e763"}, {file = "rpds_py-0.7.1-cp39-none-win32.whl", hash = "sha256:c96f87e14208058dd92dd9e726beeb4a572ead402fedeb230d151575fb39ad93"}, {file = "rpds_py-0.7.1-cp39-none-win_amd64.whl", hash = "sha256:bd15a7b913b5228711d479dd26af9db3c12280ef7df55f48037d0bc9bf042617"}, {file = "rpds_py-0.7.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:038249d2bbaf91aa65c4108a40ee076f657654261b1a246ab99726710bfb77de"}, {file = "rpds_py-0.7.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2a5c672b1cd382973bf414518ddc9d743d06bcee751fa65256d84ba412192b0b"}, {file = "rpds_py-0.7.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:453e62d679d8de32c5e00ba27f8c8c45a456e5d6db6fa6f67fdd3e12f1658833"}, {file = "rpds_py-0.7.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0bcb162f5549408125ec986bfed1a66f2036ac2910d3fb0a6afda0f97bc6ea15"}, {file = "rpds_py-0.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b54a47e670093b8bf7d1a0222d0af26dac19314a0e79ac478e447357396a2d"}, {file = "rpds_py-0.7.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f53f65cf56bb60355681431d04bc04dbe709452dd85eebf537035dc145bd36c9"}, {file = "rpds_py-0.7.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e8f2cedc65198248a14d716125016fd0816f63f216a82c2209a0686d5447cf"}, {file = "rpds_py-0.7.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8391420714e84ae9f4c6d4e4d52eb4209ca8d66abfbe4b2ba4892221be1c6f5"}, {file = "rpds_py-0.7.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c7bd3a381c4a5fe7e0fc4dff554bd1ce2b0be12ba0193c176c291b7dc1e8bea0"}, {file = "rpds_py-0.7.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c38d17af73aa03686d701686628e37c114a459650233c0d5f0492dad3a76e3e0"}, {file = "rpds_py-0.7.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:014828cd68b4cdee84ab66adaf5bfe1f137656a7a588c31fdca04ba0768ef62d"}, {file = "rpds_py-0.7.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33a2a15b641bc17bc6574f9600976374a085ff81ac8dddd4bde6c451e9e9e58d"}, {file = "rpds_py-0.7.1.tar.gz", hash = "sha256:d940b5644f14e49b1c6e7902b9ec8a0c7584109fbf380fa18115831a641927c8"}, ] [[package]] name = "setuptools" version = "67.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.7" files = [ {file = "setuptools-67.0.0-py3-none-any.whl", hash = "sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d"}, {file = "setuptools-67.0.0.tar.gz", hash = "sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.7" files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] [[package]] name = "types-pyyaml" version = "6.0.12.20240311" description = "Typing stubs for PyYAML" optional = false python-versions = ">=3.8" files = [ {file = "types-PyYAML-6.0.12.20240311.tar.gz", hash = "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342"}, {file = "types_PyYAML-6.0.12.20240311-py3-none-any.whl", hash = "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6"}, ] [[package]] name = "types-requests" version = "2.31.0.20240406" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ {file = "types-requests-2.31.0.20240406.tar.gz", hash = "sha256:4428df33c5503945c74b3f42e82b181e86ec7b724620419a2966e2de604ce1a1"}, {file = "types_requests-2.31.0.20240406-py3-none-any.whl", hash = "sha256:6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5"}, ] [package.dependencies] urllib3 = ">=2" [[package]] name = "typing-extensions" version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] name = "urllib3" version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" version = "20.16.2" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.6" files = [ {file = "virtualenv-20.16.2-py2.py3-none-any.whl", hash = "sha256:635b272a8e2f77cb051946f46c60a54ace3cb5e25568228bd6b57fc70eca9ff3"}, {file = "virtualenv-20.16.2.tar.gz", hash = "sha256:0ef5be6d07181946891f5abc8047fda8bc2f0b4b9bf222c64e6e8963baee76db"}, ] [package.dependencies] distlib = ">=0.3.1,<1" filelock = ">=3.2,<4" platformdirs = ">=2,<3" [package.extras] docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] [metadata] lock-version = "2.0" python-versions = "^3.8.0" content-hash = "95f62596cb82a0e5144a59c67ef77741d6e2595fedf5084dfe468d92269978be" p1c2u-jsonschema-path-148d7a4/pyproject.toml000066400000000000000000000040251463653325500210150ustar00rootroot00000000000000[build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.coverage.run] branch = true source =["jsonschema_path"] [tool.coverage.xml] output = "reports/coverage.xml" [tool.mypy] files = "jsonschema_path" strict = true [[tool.mypy.overrides]] module = "jsonschema_specifications" ignore_missing_imports = true [tool.poetry] name = "jsonschema-path" version = "0.3.3" description = "JSONSchema Spec with object-oriented paths" authors = ["Artur Maciag "] license = "Apache-2.0" readme = "README.rst" repository = "https://github.com/p1c2u/jsonschema-path" keywords = ["jsonschema", "swagger", "spec"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Software Development :: Libraries", ] [tool.poetry.dependencies] pathable = "^0.4.1" python = "^3.8.0" PyYAML = ">=5.1" requests = {version = "^2.31.0", optional = true} referencing = ">=0.28.0,<0.36.0" [tool.poetry.dev-dependencies] pre-commit = "*" pytest = "^8.2.1" pytest-flake8 = "=1.1.1" pytest-cov = "^5.0.0" isort = "^5.13.2" black = "^24.4.0" flynt = "1.0.1" mypy = "^1.9.0" types-PyYAML = "^6.0.12" types-requests = "^2.31.0" typing-extensions = "^4.10.0" # required by responses. See https://github.com/p1c2u/jsonschema-path/issues/44 responses = "^0.25.0" deptry = "^0.14.2" pyflakes = "^2.5.0" bump2version = "^1.0.1" [tool.pytest.ini_options] addopts = """ --capture=no --verbose --showlocals --junitxml=reports/junit.xml --cov=jsonschema_path --cov-report=term-missing --cov-report=xml """ [tool.black] line-length = 79 [tool.isort] profile = "black" line_length = 79 force_single_line = true p1c2u-jsonschema-path-148d7a4/tests/000077500000000000000000000000001463653325500172425ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/conftest.py000066400000000000000000000006511463653325500214430ustar00rootroot00000000000000from json import dumps from os import unlink from tempfile import NamedTemporaryFile import pytest @pytest.fixture def create_file(): files = [] def create(schema): contents = dumps(schema).encode("utf-8") with NamedTemporaryFile(delete=False) as tf: files.append(tf) tf.write(contents) return tf.name yield create for tf in files: unlink(tf.name) p1c2u-jsonschema-path-148d7a4/tests/integration/000077500000000000000000000000001463653325500215655ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/conftest.py000066400000000000000000000010001463653325500237530ustar00rootroot00000000000000from os import path import pytest @pytest.fixture def data_resource_path_getter(): def get_full_path(data_file): directory = path.abspath(path.dirname(__file__)) return path.join(directory, data_file) return get_full_path @pytest.fixture(scope="session") def defs(): return { "Info": { "properties": { "version": { "type": "string", "default": "1.0", }, }, }, } p1c2u-jsonschema-path-148d7a4/tests/integration/data/000077500000000000000000000000001463653325500224765ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/000077500000000000000000000000001463653325500231645ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/datetime.yaml000066400000000000000000000005561463653325500256520ustar00rootroot00000000000000openapi: 3.0.0 info: title: Example OpenAPI version: 0.0.1 paths: /mypath: get: parameters: - name: myparam in: query schema: format: date-time type: string example: 1997-07-16T19:20:30.45Z responses: '200': description: Success p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/000077500000000000000000000000001463653325500264115ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/common.yaml000066400000000000000000000004621463653325500305670ustar00rootroot00000000000000schemas: Model: type: object required: - id properties: id: type: integer format: int32 Error: type: object required: - code - message properties: code: type: integer format: int32 message: type: stringp1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/openapi.yaml000066400000000000000000000016521463653325500307340ustar00rootroot00000000000000openapi: "3.0.0" info: version: 1.0.0 title: OpenAPI Petstore license: name: MIT servers: - url: http://petstore.swagger.io/v1 paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - $ref: "recursive.yaml#/parameters/RecursiveReference" - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: '200': description: Expected response to a valid request content: application/json: schema: $ref: "spec/components.yaml#/schemas/Pet" default: description: unexpected error content: application/json: schema: $ref: "common.yaml#/schemas/Error" p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/recursive.yaml000066400000000000000000000001361463653325500313040ustar00rootroot00000000000000parameters: RecursiveReference: $ref : "recursive2.yaml#/parameters/RecursiveReference" p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/recursive2.yaml000066400000000000000000000002371463653325500313700ustar00rootroot00000000000000parameters: RecursiveReference: name: sampleParameter in: query description: Tests recursion required: false schema: type: boolean p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/spec/000077500000000000000000000000001463653325500273435ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/parent-reference/spec/components.yaml000066400000000000000000000003061463653325500324130ustar00rootroot00000000000000schemas: Pet: type: object allOf: - $ref: "../common.yaml#/schemas/Model" required: - name properties: name: type: string tag: type: string p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/000077500000000000000000000000001463653325500266335ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/common/000077500000000000000000000000001463653325500301235ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/common/schemas/000077500000000000000000000000001463653325500315465ustar00rootroot00000000000000Error.yaml000066400000000000000000000001771463653325500334510ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/common/schemastype: object required: - code - message properties: code: type: integer format: int32 message: type: stringp1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/spec/000077500000000000000000000000001463653325500275655ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/spec/openapi.yaml000066400000000000000000000037651463653325500321170ustar00rootroot00000000000000openapi: "3.0.0" info: version: 1.0.0 title: Swagger Petstore license: name: MIT servers: - url: http://petstore.swagger.io/v1 paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: '200': description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "schemas/Pets.yaml" default: description: unexpected error content: application/json: schema: $ref: "../common/schemas/Error.yaml" post: summary: Create a pet operationId: createPets tags: - pets responses: '201': description: Null response default: description: unexpected error content: application/json: schema: $ref: "../common/schemas/Error.yaml" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: '200': description: Expected response to a valid request content: application/json: schema: $ref: "schemas/Pets.yaml" default: description: unexpected error content: application/json: schema: $ref: "../common/schemas/Error.yaml"p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/spec/schemas/000077500000000000000000000000001463653325500312105ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/spec/schemas/Pet.yaml000066400000000000000000000002001463653325500326140ustar00rootroot00000000000000required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: stringp1c2u-jsonschema-path-148d7a4/tests/integration/data/v3.0/petstore-separate/spec/schemas/Pets.yaml000066400000000000000000000000451463653325500330060ustar00rootroot00000000000000type: array items: $ref: "Pet.yaml"p1c2u-jsonschema-path-148d7a4/tests/integration/test_schema_path.py000066400000000000000000000244711463653325500254620ustar00rootroot00000000000000from io import BytesIO from json import dumps from unittest import mock import responses from jsonschema_path import SchemaPath class TestSchemaPathFromDict: def test_dict(self): schema = { "properties": { "info": { "type": "object", "properties": {}, }, }, } path = SchemaPath.from_dict(schema) assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path class TestSchemaPathFromFilePath: def test_file_path(self, data_resource_path_getter): fp = data_resource_path_getter( "data/v3.0/petstore-separate/spec/openapi.yaml" ) path = SchemaPath.from_file_path(fp) assert "paths" in path def test_file_path_relative(self): fp = "tests/integration/data/v3.0/petstore-separate/spec/openapi.yaml" path = SchemaPath.from_file_path(fp) assert "paths" in path class TestSchemaPathFromFile: def test_ref_recursive(self, data_resource_path_getter): fp = data_resource_path_getter( "data/v3.0/parent-reference/openapi.yaml" ) base_uri = "file://" + fp with open(fp) as f: path = SchemaPath.from_file(f, base_uri=base_uri) assert "paths" in path class TestSchemaPathExists: def test_existing(self): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, } path = SchemaPath.from_dict(schema, "properties") assert path.exists() is True def test_non_existing(self): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, } path = SchemaPath.from_dict(schema, "invalid") assert path.exists() is False class TestSchemaPathAsUri: def test_root(self): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, } path = SchemaPath.from_dict(schema) assert path.as_uri() == "#/" def test_simple(self): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, } path = SchemaPath.from_dict(schema, "properties", "info") assert path.as_uri() == "#/properties#info" def test_non_existing(self): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, } path = SchemaPath.from_dict(schema, "properties", "info", "properties") assert path.as_uri() == "#/properties#info#properties" class TestSchemaPathOpen: def test_dict(self, defs): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, "$defs": defs, } path = SchemaPath.from_dict(schema) assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path version_path = info_path / "properties" / "version" expected_contents = {"type": "string", "default": "1.0"} with version_path.resolve() as resolved, version_path.open() as contents: assert resolved.contents == expected_contents assert contents == expected_contents assert id(resolved.contents) == id(contents) def test_file(self, defs, create_file): defs_file = create_file(defs) schema = { "properties": { "info": { "$ref": f"{defs_file}#/Info", }, }, } path = SchemaPath.from_dict(schema, base_uri="file:///") assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path version_path = info_path / "properties" / "version" expected_contents = {"type": "string", "default": "1.0"} with version_path.resolve() as resolved, version_path.open() as contents: assert resolved.contents == expected_contents assert contents == expected_contents assert id(resolved.contents) == id(contents) @responses.activate def test_remote(self, defs): schema = { "properties": { "info": { "$ref": "https://example.com/defs.json#/Info", }, }, } responses.add( responses.GET, "https://example.com/defs.json", json=defs, ) path = SchemaPath.from_dict(schema) assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path version_path = info_path / "properties" / "version" expected_contents = {"type": "string", "default": "1.0"} with version_path.resolve() as resolved, version_path.open() as contents: assert resolved.contents == expected_contents assert contents == expected_contents assert id(resolved.contents) == id(contents) @responses.activate def test_remote_fallback_requests(self, defs): schema = { "properties": { "info": { "$ref": "https://example.com/defs.json#/Info", }, }, } responses.add( responses.GET, "https://example.com/defs.json", json=defs, ) path = SchemaPath.from_dict(schema, handlers={}) assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path version_path = info_path / "properties" / "version" expected_contents = {"type": "string", "default": "1.0"} with version_path.resolve() as resolved, version_path.open() as contents: assert resolved.contents == expected_contents assert contents == expected_contents assert id(resolved.contents) == id(contents) @mock.patch("jsonschema_path.retrievers.USE_REQUESTS", False) @mock.patch("jsonschema_path.retrievers.urlopen") def test_remote_fallback_urllib(self, mock_urlopen, defs): schema = { "properties": { "info": { "$ref": "https://example.com/defs.json#/Info", }, }, } data_bytes = dumps(defs).encode() mock_urlopen.side_effect = lambda m: BytesIO(data_bytes) path = SchemaPath.from_dict(schema, handlers={}) assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path version_path = info_path / "properties" / "version" expected_contents = {"type": "string", "default": "1.0"} with version_path.resolve() as resolved, version_path.open() as contents: assert resolved.contents == expected_contents assert contents == expected_contents assert id(resolved.contents) == id(contents) def test_file_ref(self, data_resource_path_getter): fp = data_resource_path_getter( "data/v3.0/petstore-separate/spec/openapi.yaml" ) path = SchemaPath.from_file_path(fp) paths = path / "paths" for _, path in paths.items(): properties = ( path / "get#responses#default#content#application/json#schema#properties" ) with properties.open() as properties_dict: assert properties_dict == { "code": { "format": "int32", "type": "integer", }, "message": { "type": "string", }, } def test_double_ref(self, data_resource_path_getter): fp = data_resource_path_getter( "data/v3.0/petstore-separate/spec/openapi.yaml" ) path = SchemaPath.from_file_path(fp) paths_path = path / "paths" for _, path_path in paths_path.items(): properties_path = ( path_path / "get#responses#200#content#application/json#schema#items#properties" ) with properties_path.open() as contents: assert contents == { "id": { "type": "integer", "format": "int64", }, "name": { "type": "string", }, "tag": { "type": "string", }, } def test_ref_recursive(self, data_resource_path_getter): fp = data_resource_path_getter( "data/v3.0/parent-reference/openapi.yaml" ) base_uri = "file://" + fp with open(fp) as f: path = SchemaPath.from_file(f, base_uri=base_uri) property_schema_path = path._make_child( [ "paths", "/pets", "get", "parameters", 0, "schema", ] ) expected_contents = {"type": "boolean"} with property_schema_path.resolve() as resolved: assert resolved.contents == expected_contents with property_schema_path.open() as contents: assert contents == expected_contents class TestSchemaPathContents: def test_dict(self, defs): schema = { "properties": { "info": { "$ref": "#/$defs/Info", }, }, "$defs": defs, } path = SchemaPath.from_dict(schema) assert "properties" in path info_path = path / "properties" / "info" assert "properties" in info_path version_path = info_path / "properties" / "version" expected_contents = {"type": "string", "default": "1.0"} contents = version_path.contents() assert contents == expected_contents p1c2u-jsonschema-path-148d7a4/tests/unit/000077500000000000000000000000001463653325500202215ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/unit/conftest.py000066400000000000000000000040401463653325500224160ustar00rootroot00000000000000import pytest from referencing import Registry from referencing._core import Resolver from referencing.jsonschema import DRAFT202012 from jsonschema_path.accessors import SchemaAccessor from jsonschema_path.handlers import default_handlers from jsonschema_path.paths import SPEC_SEPARATOR from jsonschema_path.retrievers import SchemaRetriever @pytest.fixture def assert_ra(): def func( sa, schema, base_uri="", handlers=default_handlers, specification=DRAFT202012, ): assert sa.lookup == schema resolver = sa.resolver assert type(resolver) is Resolver assert resolver._base_uri == base_uri registry = resolver._registry assert type(registry) is Registry assert type(registry._retrieve) is SchemaRetriever assert registry._retrieve.handlers == handlers assert registry._retrieve.specification == specification return func @pytest.fixture def assert_sa(): def func( sa, schema, base_uri="", handlers=default_handlers, specification=DRAFT202012, ): assert type(sa) is SchemaAccessor assert sa.lookup == schema resolver = sa.resolver assert type(resolver) is Resolver assert resolver._base_uri == base_uri registry = resolver._registry assert type(registry) is Registry assert type(registry._retrieve) is SchemaRetriever assert registry._retrieve.handlers == handlers assert registry._retrieve.specification == specification return func @pytest.fixture def assert_sp(assert_sa): def func( sp, schema, separator=SPEC_SEPARATOR, base_uri="", handlers=default_handlers, specification=DRAFT202012, ): assert sp.separator == separator assert sp.parts == [] assert_sa( sp.accessor, schema, base_uri=base_uri, handlers=handlers, specification=specification, ) return func p1c2u-jsonschema-path-148d7a4/tests/unit/handlers/000077500000000000000000000000001463653325500220215ustar00rootroot00000000000000p1c2u-jsonschema-path-148d7a4/tests/unit/handlers/test_file.py000066400000000000000000000010141463653325500243450ustar00rootroot00000000000000from pathlib import Path import pytest from jsonschema_path.handlers.file import FilePathHandler class TestFilePathHandler: def test_invalid_scheme(self): uri = "invalid:///" handler = FilePathHandler() with pytest.raises(ValueError): handler(uri) def test_valid(self, create_file): test_file = create_file({}) test_file_uri = Path(test_file).as_uri() handler = FilePathHandler() result = handler(test_file_uri) assert result == {} p1c2u-jsonschema-path-148d7a4/tests/unit/test_accessors.py000066400000000000000000000013651463653325500236240ustar00rootroot00000000000000from unittest.mock import Mock from jsonschema_path.accessors import SchemaAccessor class TestSchemaAccessorOpen: def test_dereferences_once(self): retrieve = Mock(return_value={"value": "tested"}) accessor = SchemaAccessor.from_schema( { "one": { "$ref": "x://testref", }, "two": { "$ref": "x://testref", }, }, handlers={"x": retrieve}, ) with accessor.open(["one", "value"]) as opened: assert opened == "tested" with accessor.open(["two", "value"]) as opened: assert opened == "tested" retrieve.assert_called_once_with("x://testref") p1c2u-jsonschema-path-148d7a4/tests/unit/test_paths.py000066400000000000000000000100421463653325500227460ustar00rootroot00000000000000from pathlib import Path from unittest import mock import pytest from referencing import Specification from jsonschema_path.paths import SchemaPath class TestSchemaPathFromDict: def test_no_kwargs(self, assert_sp): schema = mock.sentinel.schema sp = SchemaPath.from_dict(schema) assert_sp(sp, schema) def test_separator(self, assert_sp): schema = mock.sentinel.schema separator = mock.sentinel.separator sp = SchemaPath.from_dict(schema, separator=separator) assert_sp(sp, schema, separator=separator) def test_specification(self, assert_sp): schema = mock.sentinel.schema specification = mock.Mock(spec=Specification) sp = SchemaPath.from_dict(schema, specification=specification) assert_sp(sp, schema, specification=specification) def test_base_uri(self, assert_sp): schema = mock.sentinel.schema base_uri = "mock.sentinel.base_uri" sp = SchemaPath.from_dict(schema, base_uri=base_uri) assert_sp(sp, schema, base_uri=base_uri) def test_handlers(self, assert_sp): schema = mock.sentinel.schema handlers = mock.sentinel.handlers sp = SchemaPath.from_dict(schema, handlers=handlers) assert_sp(sp, schema, handlers=handlers) def test_spec_url(self, assert_sp): schema = mock.sentinel.schema spec_url = "mock.sentinel.spec_url" with pytest.warns(DeprecationWarning): sp = SchemaPath.from_dict(schema, spec_url=spec_url) assert_sp(sp, schema, base_uri=spec_url) def test_ref_resolver_handlers(self, assert_sp): schema = mock.sentinel.schema handlers = mock.sentinel.handlers with pytest.warns(DeprecationWarning): sp = SchemaPath.from_dict(schema, ref_resolver_handlers=handlers) assert_sp(sp, schema, handlers=handlers) class TestSchemaPathFromFile: def test_no_kwargs(self, create_file, assert_sp): schema = {"type": "integer"} schema_file_path_str = create_file(schema) schema_file_path = Path(schema_file_path_str) schema_file_obj = schema_file_path.open() sp = SchemaPath.from_file(schema_file_obj) assert_sp(sp, schema) def test_base_uri(self, create_file, assert_sp): schema = {"type": "integer"} schema_file_path_str = create_file(schema) schema_file_path = Path(schema_file_path_str) schema_file_obj = schema_file_path.open() base_uri = "mock.sentinel.base_uri" sp = SchemaPath.from_file(schema_file_obj, base_uri=base_uri) assert_sp(sp, schema, base_uri=base_uri) def test_spec_url(self, create_file, assert_sp): schema = {"type": "integer"} schema_file_path_str = create_file(schema) schema_file_path = Path(schema_file_path_str) schema_file_obj = schema_file_path.open() spec_url = "mock.sentinel.spec_url" with pytest.warns(DeprecationWarning): sp = SchemaPath.from_file(schema_file_obj, spec_url=spec_url) assert_sp(sp, schema, base_uri=spec_url) class TestSchemaPathFromPath: def test_file_no_exist(self, create_file): schema_file_path_str = "/invalid/file" schema_file_path = Path(schema_file_path_str) with pytest.raises(OSError): SchemaPath.from_path(schema_file_path) def test_no_kwargs(self, create_file, assert_sp): schema = {"type": "integer"} schema_file_path_str = create_file(schema) schema_file_path = Path(schema_file_path_str) schema_file_uri = schema_file_path.as_uri() sp = SchemaPath.from_path(schema_file_path) assert_sp(sp, schema, base_uri=schema_file_uri) class TestSchemaPathFromFilePath: def test_no_kwargs(self, create_file, assert_sp): schema = {"type": "integer"} schema_file_path_str = create_file(schema) schema_file_uri = Path(schema_file_path_str).as_uri() sp = SchemaPath.from_file_path(schema_file_path_str) assert_sp(sp, schema, base_uri=schema_file_uri)