diff --git a/.github/workflows/doc-deploy.yml b/.github/workflows/doc-deploy.yml index 19cc672..cf8e8c4 100644 --- a/.github/workflows/doc-deploy.yml +++ b/.github/workflows/doc-deploy.yml @@ -9,7 +9,7 @@ jobs: doc-deploy: name: Deploy document pages runs-on: ubuntu-latest - container: 'python:3.9-slim' + container: 'python:3.10-slim' steps: - name: Install host dependencies run: | diff --git a/.github/workflows/foss_cli_tests.yml b/.github/workflows/foss_cli_tests.yml index c24f078..6a08c31 100644 --- a/.github/workflows/foss_cli_tests.yml +++ b/.github/workflows/foss_cli_tests.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest container: - image: python:3.9-slim + image: python:3.10-slim volumes: - /tmp:/tmp @@ -46,19 +46,20 @@ jobs: run: | poetry run coverage run --source=fossology -m pytest tests/test_foss_cli*.py poetry run coverage report -m + continue-on-error: true test-last_release: - name: foss_cli tests (Fossology 3.10.0) + name: foss_cli tests (Fossology 4.1.0) runs-on: ubuntu-latest container: - image: python:3.9-slim + image: python:3.10-slim volumes: - /tmp:/tmp services: fossology: - image: fossology/fossology:3.10.0 + image: fossology/fossology:4.1.0 ports: - 8081:80 volumes: diff --git a/.github/workflows/fossologytests.yml b/.github/workflows/fossologytests.yml index f40b2f5..7c76586 100644 --- a/.github/workflows/fossologytests.yml +++ b/.github/workflows/fossologytests.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest container: - image: python:3.9-slim + image: python:3.10-slim volumes: - /tmp:/tmp @@ -47,23 +47,24 @@ jobs: export API_LATEST=true poetry run coverage run --source=fossology -m pytest poetry run coverage report -m + continue-on-error: true - name: upload codecoverage results only if we are on the repository fossology/fossology-python if: ${{ github.repository == 'fossology/fossology-python' }} run: poetry run codecov -t ${{ secrets.CODECOV_TOKEN }} test-last-release: - name: Integration Tests (Fossology 4.0.0) + name: Integration Tests (Fossology 4.1.0) runs-on: ubuntu-latest container: - image: python:3.9-slim + image: python:3.10-slim volumes: - /tmp:/tmp services: fossology: - image: fossology/fossology:4.0.0 + image: fossology/fossology:4.1.0 ports: - 8081:80 volumes: diff --git a/.github/workflows/staticchecks.yml b/.github/workflows/staticchecks.yml index a06b4a4..a0d1ca5 100644 --- a/.github/workflows/staticchecks.yml +++ b/.github/workflows/staticchecks.yml @@ -14,6 +14,7 @@ jobs: - 'python:3.7-slim' - 'python:3.8-slim' - 'python:3.9-slim' + - 'python:3.10-slim' container: ${{ matrix.container }} diff --git a/README.rst b/README.rst index 0a82338..be70b17 100644 --- a/README.rst +++ b/README.rst @@ -27,6 +27,13 @@ See `the OpenAPI specification >> filename = "my_base-files_11.tar.xz" @@ -124,7 +124,7 @@ upload it to the server. ... description="Test upload via fossology-python lib", ... group=group_name, ... access_level=AccessLevel.PUBLIC, -... ) +... ) Start default scan jobs @@ -199,3 +199,22 @@ report downloaded... >>> print(f"report was written to file {name}.") # doctest: +ELLIPSIS report was written to file... + +Delete folder +============= + +Cleanup existing folder and all included data. + +>>> foss.delete_folder(test_folder) +>>> print(f"Folder {test_folder.name} has been deleted") +Folder AwesomeFossFolder has been deleted + + +Clean up +======== + +Cleanup created report and token files + +>>> os.unlink(name) +>>> os.unlink(path_to_upload_file) +>>> os.unlink(path_to_token_file) diff --git a/fossology/foss_cli.py b/fossology/foss_cli.py index 6a44879..5b9f7e6 100644 --- a/fossology/foss_cli.py +++ b/fossology/foss_cli.py @@ -136,7 +136,7 @@ def check_get_access_level(level: str): def needs_later_initialization_of_foss_instance(ctx): - """Check if lateron a Fossology Instance will be created. + """Check if later on a Fossology Instance will be created. :param ctx: click context :type ctx: click.core.Context @@ -580,6 +580,7 @@ def upload_file( file=upload_file, description=description if description else "upload via foss-cli", access_level=the_access_level, + wait_time=10, ) ctx.obj["UPLOAD"] = the_upload @@ -602,6 +603,56 @@ def upload_file( ) +@cli.command("delete_folder") +@click.argument("folder_name") +@click.pass_context +def delete_folder( + ctx: click.core.Context, + folder_name: str, +): + """The foss_cli delete_folder command.""" + + logger.debug(f"Try to delete folder {folder_name}") + foss = ctx.obj["FOSS"] + + folder = None + for f in foss.list_folders(): + if f.name == folder_name: + folder = f + logger.debug(f"Found folder to delete: {folder}") + break + + if not folder: + logger.fatal(f"Unable to find folder {folder_name}.") + ctx.exit(1) + + foss.delete_folder(folder) + logger.debug(f"Delete command was send to {foss.host} for folder {folder}") + + +@cli.command("delete_upload") +@click.argument("upload_name") +@click.pass_context +def delete_upload( + ctx: click.core.Context, + upload_name: str, +): + """The foss_cli folder_id command.""" + + logger.debug(f"Try to delete upload {upload_name}") + foss = ctx.obj["FOSS"] + + upload = None + for u in foss.list_uploads(all_pages=True)[0]: + if u.uploadname == upload_name: + upload = u + logger.debug(f"Found upload to delete: {upload}") + break + + foss.delete_upload(upload) + logger.debug(f"Delete command was send to {foss.host} for upload {upload}") + + @cli.command("start_workflow") @click.argument( "file_name", @@ -695,6 +746,7 @@ def start_workflow( # noqa: C901 file=file_name, description=file_description, access_level=the_access_level, + wait_time=10, ) logger.debug(f"Finished upload for {file_name}") diff --git a/fossology/jobs.py b/fossology/jobs.py index 0bd1ea8..e9901f1 100644 --- a/fossology/jobs.py +++ b/fossology/jobs.py @@ -15,7 +15,9 @@ class Jobs: """Class dedicated to all "jobs" related endpoints""" - def list_jobs(self, upload=None, page_size=100, page=1, all_pages=False): + def list_jobs( + self, upload=None, page_size=100, page=1, all_pages=False + ) -> tuple[list, int]: """Get all available jobs API Endpoint: GET /jobs @@ -66,8 +68,8 @@ def list_jobs(self, upload=None, page_size=100, page=1, all_pages=False): logger.info(f"Retrieved all {x_total_pages} pages of jobs") return jobs_list, x_total_pages - def detail_job(self, job_id, wait=False, timeout=30): - """Get detailled information about a job + def detail_job(self, job_id, wait=False, timeout=30) -> Job: + """Get detailed information about a job API Endpoint: GET /jobs/{id} @@ -102,7 +104,9 @@ def detail_job(self, job_id, wait=False, timeout=30): description = f"Error while getting details for job {job_id}" raise FossologyApiError(description, response) - def schedule_jobs(self, folder, upload, spec, group=None, wait=False, timeout=30): + def schedule_jobs( + self, folder, upload, spec, group=None, wait=False, timeout=30 + ) -> Job: """Schedule jobs for a specific upload API Endpoint: POST /jobs diff --git a/fossology/obj.py b/fossology/obj.py index fc8639e..c24ec38 100644 --- a/fossology/obj.py +++ b/fossology/obj.py @@ -80,6 +80,22 @@ class ClearingStatus(Enum): REJECTED = "Rejected" +class JobStatus(Enum): + """Job statuses: + + COMPLETED + FAILED + QUEUED + PROCESSING + + """ + + COMPLETED = "Completed" + FAILED = "Failed" + QUEUED = "Queued" + PROCESSING = "Processing" + + class LicenseType(Enum): """License types: @@ -793,6 +809,37 @@ def from_json(cls, json_dict): return cls(**json_dict) +class FossologyServer(object): + + """FOSSology server info. + + :param version: version of the FOSSology server (e.g. 4.0.0) + :param branchName: branch deployed on the FOSSology server + :param commitHash: hash of commit deployed on the FOSSology server + :param commitDate: date of commit deployed on the FOSSology server in ISO8601 format + :param buildDate: date on which packages were built in ISO8601 format + :type version: string + :type branchName: string + :type commitHash: string + :type commitDate: string + :type buildDate: string + """ + + def __init__(self, version, branchName, commitHash, commitDate, buildDate): + self.version = version + self.branchName = branchName + self.commitHash = commitHash + self.commitDate = commitDate + self.buildDate = buildDate + + def __str__(self): + return f"Fossology server version {self.version} (branch {self.branchName} - {self.commitHash})" + + @classmethod + def from_json(cls, json_dict): + return cls(**json_dict) + + class ApiInfo(object): """FOSSology API info. @@ -805,17 +852,27 @@ class ApiInfo(object): :param security: security methods allowed :param contact: email contact from the API documentation :param license: licensing of the API + :param fossology: information about FOSSology server :type name: string :type description: string :type version: string :type security: list :type contact: string :type license: ApiLicense object + :type fossology: FossologyServer object :type kwargs: key word argument """ def __init__( - self, name, description, version, security, contact, license, **kwargs + self, + name, + description, + version, + security, + contact, + license, + fossology, + **kwargs, ): self.name = name self.description = description @@ -823,10 +880,11 @@ def __init__( self.security = security self.contact = contact self.license = ApiLicense.from_json(license) + self.fossology = FossologyServer.from_json(fossology) self.additional_info = kwargs def __str__(self): - return f"FOSSology API {self.name} is deployed with version {self.version}" + return f"{self.name} is deployed with version {self.version}" @classmethod def from_json(cls, json_dict): diff --git a/fossology/uploads.py b/fossology/uploads.py index c186bd4..e96f378 100644 --- a/fossology/uploads.py +++ b/fossology/uploads.py @@ -4,10 +4,10 @@ import logging import re import time -import fossology from tenacity import TryAgain, retry, retry_if_exception_type, stop_after_attempt +import fossology from fossology.exceptions import ( AuthorizationError, FossologyApiError, @@ -125,16 +125,17 @@ def detail_upload( def upload_file( # noqa: C901 self, - folder, - file=None, - vcs=None, - url=None, - server=None, - description=None, - access_level=None, - ignore_scm=False, - group=None, - wait_time=0, + folder: Folder, + file: str = None, + vcs: dict = None, + url: dict = None, + server: dict = None, + description: str = None, + access_level: str = None, + apply_global: bool = False, + ignore_scm: bool = False, + group: str = None, + wait_time: int = 0, ): """Upload a package to FOSSology @@ -209,6 +210,7 @@ def upload_file( # noqa: C901 :param server: the SERVER specification to upload from fossology server :param description: description of the upload (default: None) :param access_level: access permissions of the upload (default: protected) + :param apply_global: apply global decisions for current upload (default: False) :param ignore_scm: ignore SCM files (Git, SVN, TFS) (default: True) :param group: the group name to chose while uploading the file (default: None) :param wait_time: use a customized upload wait time instead of Retry-After (in seconds, default: 0) @@ -219,6 +221,7 @@ def upload_file( # noqa: C901 :type server: dict() :type description: string :type access_level: AccessLevel + :type apply_global: boolean :type ignore_scm: boolean :type group: string :type wait_time: int @@ -232,8 +235,10 @@ def upload_file( # noqa: C901 headers["uploadDescription"] = description if access_level: headers["public"] = access_level.value + if apply_global: + headers["applyGlobal"] = "true" if ignore_scm: - headers["ignoreScm"] = "false" + headers["ignoreScm"] = "true" if group: headers["groupName"] = group @@ -589,7 +594,9 @@ def update_upload( raise AuthorizationError(description, response) else: - description = f"Unable to update upload {upload.uploadname} with status {status.value}" + description = ( + f"Unable to update upload {upload.uploadname} with status {status}" + ) raise FossologyApiError(description, response) def move_upload(self, upload: Upload, folder: Folder, action: str): @@ -604,6 +611,7 @@ def move_upload(self, upload: Upload, folder: Folder, action: str): :type folder: Folder :type action: str :raises FossologyApiError: if the REST call failed + :raises AuthorizationError: if the user can't access the upload or folder """ if fossology.versiontuple(self.version) < fossology.versiontuple("1.4.0"): description = f"Endpoint PUT /uploads is not supported by your Fossology API version {self.version}" diff --git a/poetry.lock b/poetry.lock index 85ac711..980cf45 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,31 +6,23 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - [[package]] name = "attrs" -version = "21.4.0" +version = "22.1.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.5" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] +docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] +tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] -name = "babel" -version = "2.10.1" +name = "Babel" +version = "2.10.3" description = "Internationalization utilities" category = "dev" optional = false @@ -41,7 +33,7 @@ pytz = ">=2015.7" [[package]] name = "black" -version = "22.3.0" +version = "22.8.0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -52,7 +44,7 @@ click = ">=8.0.0" mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} @@ -64,26 +56,26 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2021.10.8" +version = "2022.9.14" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "charset-normalizer" -version = "2.0.12" +version = "2.1.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.5.0" +python-versions = ">=3.6.0" [package.extras] unicode_backport = ["unicodedata2"] [[package]] name = "click" -version = "8.1.2" +version = "8.1.3" description = "Composable command line interface toolkit" category = "main" optional = false @@ -107,15 +99,26 @@ requests = ">=2.7.9" [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.5" description = "Cross-platform colored terminal text." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + [[package]] name = "coverage" -version = "6.3.2" +version = "6.4.4" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -134,21 +137,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "flake8" -version = "4.0.1" +version = "5.0.4" description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.6.1" [package.dependencies] -importlib-metadata = {version = "<4.3", markers = "python_version < \"3.8\""} -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" +importlib-metadata = {version = ">=1.1.0,<4.3", markers = "python_version < \"3.8\""} +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.9.0,<2.10.0" +pyflakes = ">=2.5.0,<2.6.0" [[package]] name = "idna" -version = "3.3" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -156,7 +159,7 @@ python-versions = ">=3.5" [[package]] name = "imagesize" -version = "1.3.0" +version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" category = "dev" optional = false @@ -175,8 +178,8 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] [[package]] name = "iniconfig" @@ -195,14 +198,14 @@ optional = false python-versions = ">=3.6.1,<4.0" [package.extras] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] -requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] plugins = ["setuptools"] +requirements_deprecated_finder = ["pip-api", "pipreqs"] [[package]] -name = "jinja2" -version = "3.1.1" +name = "Jinja2" +version = "3.1.2" description = "A very fast and expressive template engine." category = "dev" optional = false @@ -227,7 +230,7 @@ six = "*" tornado = {version = "*", markers = "python_version > \"2.7\""} [[package]] -name = "markupsafe" +name = "MarkupSafe" version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" @@ -236,11 +239,11 @@ python-versions = ">=3.7" [[package]] name = "mccabe" -version = "0.6.1" +version = "0.7.0" description = "McCabe checker, plugin for flake8" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "mypy-extensions" @@ -263,11 +266,11 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" -version = "0.9.0" +version = "0.10.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" [[package]] name = "platformdirs" @@ -278,8 +281,8 @@ optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] -test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] [[package]] name = "pluggy" @@ -306,49 +309,66 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycodestyle" -version = "2.8.0" +version = "2.9.1" description = "Python style guide checker" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" + +[[package]] +name = "pydantic" +version = "1.10.2" +description = "Data validation and settings management using python type hints" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +typing-extensions = ">=4.1.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] [[package]] name = "pyflakes" -version = "2.4.0" +version = "2.5.0" description = "passive checker of Python programs" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [[package]] -name = "pygments" -version = "2.11.2" +name = "Pygments" +version = "2.13.0" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" + +[package.extras] +plugins = ["importlib-metadata"] [[package]] name = "pyparsing" -version = "3.0.8" +version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "dev" optional = false python-versions = ">=3.6.8" [package.extras] -diagrams = ["railroad-diagrams", "jinja2"] +diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.1.1" +version = "7.1.3" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -363,7 +383,7 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. [[package]] name = "pytz" -version = "2022.1" +version = "2022.2.1" description = "World timezone definitions, modern and historical" category = "dev" optional = false @@ -371,25 +391,36 @@ python-versions = "*" [[package]] name = "requests" -version = "2.27.1" +version = "2.28.1" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7, <4" [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-toolbelt" +version = "0.9.1" +description = "A utility belt for advanced users of python-requests" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" [[package]] name = "responses" -version = "0.20.0" +version = "0.21.0" description = "A utility library for mocking out the `requests` Python library." category = "dev" optional = false @@ -397,14 +428,31 @@ python-versions = ">=3.7" [package.dependencies] requests = ">=2.0,<3.0" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} urllib3 = ">=1.25.10" [package.extras] -tests = ["pytest (>=7.0.0)", "coverage (>=6.0.0)", "pytest-cov", "pytest-asyncio", "pytest-localserver", "flake8", "types-mock", "types-requests", "mypy"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-localserver", "types-mock", "types-requests"] + +[[package]] +name = "rich" +version = "12.5.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "dev" +optional = false +python-versions = ">=3.6.3,<4.0.0" + +[package.dependencies] +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] [[package]] name = "rstcheck" -version = "5.0.0" +version = "6.1.0" description = "Checks syntax of reStructuredText and code blocks nested within it" category = "dev" optional = false @@ -412,12 +460,60 @@ python-versions = ">=3.7,<4.0" [package.dependencies] docutils = ">=0.7,<0.19" +importlib-metadata = {version = ">=1.6,<5.0", markers = "python_version < \"3.8\""} +pydantic = ">=1.2,<2.0" +rstcheck-core = ">=1.0.2,<2.0.0" +typer = {version = ">=0.4.1,<0.7", extras = ["all"]} types-docutils = ">=0.18,<0.19" -typing-extensions = ">=4.1,<5" +typing-extensions = {version = ">=3.7.4,<5.0", markers = "python_version < \"3.8\""} + +[package.extras] +docs = ["m2r2 (>=0.3.2)", "sphinx", "sphinx-autobuild (==2021.3.14)", "sphinx-click (>=4.0.3,<5.0.0)", "sphinx-rtd-dark-mode (>=1.2.4,<2.0.0)", "sphinx-rtd-theme (<1)", "sphinxcontrib-spelling (>=7.3)"] +sphinx = ["sphinx"] +testing = ["coverage-conditional-plugin (>=0.5)", "coverage[toml] (>=6.0)", "pytest (>=6.0)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.0)", "pytest-sugar (>=0.9.5)"] +toml = ["tomli"] + +[[package]] +name = "rstcheck-core" +version = "1.0.2" +description = "Checks syntax of reStructuredText and code blocks nested within it" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +docutils = ">=0.7,<0.19" +importlib-metadata = {version = ">=1.6,<5.0", markers = "python_version < \"3.8\""} +pydantic = ">=1.2,<2.0" +types-docutils = ">=0.18,<0.19" +typing-extensions = {version = ">=3.7.4,<5.0", markers = "python_version < \"3.8\""} + +[package.extras] +docs = ["m2r2 (>=0.3.2)", "sphinx (>=4.0,<6.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-autodoc-typehints (>=1.15)", "sphinx-rtd-dark-mode (>=1.2.4,<2.0.0)", "sphinx-rtd-theme (<1)", "sphinxcontrib-apidoc (>=0.3)", "sphinxcontrib-spelling (>=7.3)"] +sphinx = ["sphinx (>=4.0,<6.0)"] +testing = ["coverage-conditional-plugin (>=0.5)", "coverage[toml] (>=6.0)", "mock (>=4.0)", "pytest (>=6.0)", "pytest-cov (>=3.0)", "pytest-mock (>=3.7)", "pytest-randomly (>=3.0)"] +toml = ["tomli (>=2.0,<3.0)"] + +[[package]] +name = "setuptools" +version = "65.3.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" [package.extras] -sphinx = ["sphinx (>=4,<5)"] -testing = ["pytest (>=6)", "pytest-xdist[psutil] (>=2.5)", "pytest-randomly (>=3)"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "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)", "mock", "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-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 = "shellingham" +version = "1.5.0" +description = "Tool to Detect Surrounding Shell" +category = "dev" +optional = false +python-versions = ">=3.4" [[package]] name = "six" @@ -436,7 +532,7 @@ optional = false python-versions = "*" [[package]] -name = "sphinx" +name = "Sphinx" version = "4.3.2" description = "Python documentation generator" category = "dev" @@ -453,6 +549,7 @@ Jinja2 = ">=2.3" packaging = "*" Pygments = ">=2.0" requests = ">=2.5.0" +setuptools = "*" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" @@ -463,8 +560,8 @@ sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.920)", "docutils-stubs", "types-typed-ast", "types-pkg-resources", "types-requests"] -test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.920)", "types-pkg-resources", "types-requests", "types-typed-ast"] +test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] [[package]] name = "sphinx-autobuild" @@ -491,7 +588,7 @@ optional = false python-versions = ">=3.5" [package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] +lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] @@ -503,7 +600,7 @@ optional = false python-versions = ">=3.5" [package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] +lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] @@ -515,8 +612,8 @@ optional = false python-versions = ">=3.6" [package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] -test = ["pytest", "html5lib"] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] [[package]] name = "sphinxcontrib-jsmath" @@ -527,7 +624,7 @@ optional = false python-versions = ">=3.5" [package.extras] -test = ["pytest", "flake8", "mypy"] +test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" @@ -538,7 +635,7 @@ optional = false python-versions = ">=3.5" [package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] +lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] @@ -550,12 +647,12 @@ optional = false python-versions = ">=3.5" [package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] +lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "tenacity" -version = "8.0.1" +version = "8.1.0" description = "Retry code until it succeeds" category = "main" optional = false @@ -574,20 +671,40 @@ python-versions = ">=3.7" [[package]] name = "tornado" -version = "6.1" +version = "6.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." category = "dev" optional = false -python-versions = ">= 3.5" +python-versions = ">= 3.7" [[package]] name = "typed-ast" -version = "1.5.3" +version = "1.5.4" description = "a fork of Python 2 and 3 ast modules with type comment support" category = "dev" optional = false python-versions = ">=3.6" +[[package]] +name = "typer" +version = "0.6.1" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""} +rich = {version = ">=10.11.0,<13.0.0", optional = true, markers = "extra == \"all\""} +shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""} + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + [[package]] name = "types-docutils" version = "0.18.3" @@ -598,7 +715,7 @@ python-versions = "*" [[package]] name = "typing-extensions" -version = "4.2.0" +version = "4.3.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false @@ -606,87 +723,83 @@ python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.9" +version = "1.26.12" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" [package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "zipp" -version = "3.8.0" +version = "3.8.1" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] +docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] +testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "95c60d6aa958cc8b011de23f8313564bf389628e8f435cc8569b34ca8971ebb1" +content-hash = "fd0e1aa5bc2cbcfc8223c16a78ce16a62b8b49e07fceaa476114daa38f5d8cfd" [metadata.files] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] -babel = [ - {file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"}, - {file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"}, +Babel = [ + {file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"}, + {file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"}, ] black = [ - {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, - {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, - {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, - {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, - {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, - {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, - {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, - {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, - {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, - {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, - {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, - {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, - {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, - {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, - {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, - {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, - {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, - {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, - {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, + {file = "black-22.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd"}, + {file = "black-22.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27"}, + {file = "black-22.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747"}, + {file = "black-22.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869"}, + {file = "black-22.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90"}, + {file = "black-22.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe"}, + {file = "black-22.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342"}, + {file = "black-22.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab"}, + {file = "black-22.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3"}, + {file = "black-22.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e"}, + {file = "black-22.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16"}, + {file = "black-22.8.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c"}, + {file = "black-22.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5"}, + {file = "black-22.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411"}, + {file = "black-22.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3"}, + {file = "black-22.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"}, + {file = "black-22.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c"}, + {file = "black-22.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497"}, + {file = "black-22.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c"}, + {file = "black-22.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41"}, + {file = "black-22.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec"}, + {file = "black-22.8.0-py3-none-any.whl", hash = "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4"}, + {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, ] certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, + {file = "certifi-2022.9.14-py3-none-any.whl", hash = "sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516"}, + {file = "certifi-2022.9.14.tar.gz", hash = "sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, - {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, ] click = [ - {file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"}, - {file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"}, + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] codecov = [ {file = "codecov-2.1.12-py2.py3-none-any.whl", hash = "sha256:585dc217dc3d8185198ceb402f85d5cb5dbfa0c5f350a5abcdf9e347776a5b47"}, @@ -694,67 +807,80 @@ codecov = [ {file = "codecov-2.1.12.tar.gz", hash = "sha256:a0da46bb5025426da895af90938def8ee12d37fcbcbbbc15b6dc64cf7ebc51c1"}, ] colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] +commonmark = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] coverage = [ - {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, - {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, - {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"}, - {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"}, - {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"}, - {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"}, - {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"}, - {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"}, - {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"}, - {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"}, - {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"}, - {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"}, - {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"}, - {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"}, - {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"}, - {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"}, - {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"}, - {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"}, - {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"}, - {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"}, - {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"}, - {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"}, - {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"}, - {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"}, - {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"}, - {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"}, - {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"}, - {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"}, - {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"}, - {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"}, - {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"}, - {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"}, - {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"}, - {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"}, - {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"}, - {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"}, - {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"}, - {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"}, - {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"}, - {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, - {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, + {file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"}, + {file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"}, + {file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"}, + {file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"}, + {file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"}, + {file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"}, + {file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"}, + {file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"}, + {file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"}, + {file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"}, + {file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"}, + {file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"}, + {file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"}, + {file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"}, + {file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"}, + {file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"}, + {file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"}, + {file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"}, + {file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"}, + {file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"}, ] docutils = [ {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, ] flake8 = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, + {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, + {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, ] idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] imagesize = [ - {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, - {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] importlib-metadata = [ {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, @@ -768,14 +894,14 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -jinja2 = [ - {file = "Jinja2-3.1.1-py3-none-any.whl", hash = "sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119"}, - {file = "Jinja2-3.1.1.tar.gz", hash = "sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"}, +Jinja2 = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] livereload = [ {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, ] -markupsafe = [ +MarkupSafe = [ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, @@ -818,8 +944,8 @@ markupsafe = [ {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, ] mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -830,8 +956,8 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, ] platformdirs = [ {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, @@ -846,40 +972,98 @@ py = [ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pycodestyle = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, + {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, + {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, +] +pydantic = [ + {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"}, + {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"}, + {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"}, + {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"}, + {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"}, + {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"}, + {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"}, + {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"}, + {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"}, + {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"}, + {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"}, + {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"}, + {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"}, + {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"}, + {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"}, + {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"}, + {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"}, + {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"}, + {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"}, + {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"}, + {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"}, + {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"}, + {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"}, + {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"}, + {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"}, + {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"}, + {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"}, + {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"}, + {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"}, + {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"}, + {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"}, + {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"}, + {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"}, + {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"}, + {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"}, + {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"}, ] pyflakes = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, + {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, + {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, ] -pygments = [ - {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, - {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, +Pygments = [ + {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, + {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, ] pyparsing = [ - {file = "pyparsing-3.0.8-py3-none-any.whl", hash = "sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"}, - {file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"}, + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pytest = [ - {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"}, - {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"}, + {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, + {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, ] pytz = [ - {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, - {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, + {file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"}, + {file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"}, ] requests = [ - {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, - {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] +requests-toolbelt = [ + {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, + {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, ] responses = [ - {file = "responses-0.20.0-py3-none-any.whl", hash = "sha256:18831bc2d72443b67664d98038374a6fa1f27eaaff4dd9a7d7613723416fea3c"}, - {file = "responses-0.20.0.tar.gz", hash = "sha256:644905bc4fb8a18fa37e3882b2ac05e610fe8c2f967d327eed669e314d94a541"}, + {file = "responses-0.21.0-py3-none-any.whl", hash = "sha256:2dcc863ba63963c0c3d9ee3fa9507cbe36b7d7b0fccb4f0bdfd9e96c539b1487"}, + {file = "responses-0.21.0.tar.gz", hash = "sha256:b82502eb5f09a0289d8e209e7bad71ef3978334f56d09b444253d5ad67bf5253"}, +] +rich = [ + {file = "rich-12.5.1-py3-none-any.whl", hash = "sha256:2eb4e6894cde1e017976d2975ac210ef515d7548bc595ba20e195fb9628acdeb"}, + {file = "rich-12.5.1.tar.gz", hash = "sha256:63a5c5ce3673d3d5fbbf23cd87e11ab84b6b451436f1b7f19ec54b6bc36ed7ca"}, ] rstcheck = [ - {file = "rstcheck-5.0.0-py3-none-any.whl", hash = "sha256:8fba7f864e3fc09e3a6eac640a809cac89838f72eb1845ef21b37b13f71e7421"}, - {file = "rstcheck-5.0.0.tar.gz", hash = "sha256:c0c4e44ebb630a7f1ff61d8fc26adc7d49c16fcd4ba85e3ea5542b864cf982e4"}, + {file = "rstcheck-6.1.0-py3-none-any.whl", hash = "sha256:156a63612ed58676b5686ddcde6bb3fe67b6ee090141483a92e56b5bb5f8b617"}, + {file = "rstcheck-6.1.0.tar.gz", hash = "sha256:1d32f50d2131a43a39e0287d1b1854fcc0e98ab1513f0318df2ecab25bec54ab"}, +] +rstcheck-core = [ + {file = "rstcheck-core-1.0.2.tar.gz", hash = "sha256:b06bee11f3679b283cbd6abf707bfe4d5fd2cf480cfa3ffe6d5c9238c6d4ae89"}, + {file = "rstcheck_core-1.0.2-py3-none-any.whl", hash = "sha256:6d75e858441644b9a0ad7a89a6c0a9012920be7dc4fad34f95579ae2a97a2d5e"}, +] +setuptools = [ + {file = "setuptools-65.3.0-py3-none-any.whl", hash = "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82"}, + {file = "setuptools-65.3.0.tar.gz", hash = "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57"}, +] +shellingham = [ + {file = "shellingham-1.5.0-py2.py3-none-any.whl", hash = "sha256:a8f02ba61b69baaa13facdba62908ca8690a94b8119b69f5ec5873ea85f7391b"}, + {file = "shellingham-1.5.0.tar.gz", hash = "sha256:72fb7f5c63103ca2cb91b23dee0c71fe8ad6fbfd46418ef17dbe40db51592dad"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -889,7 +1073,7 @@ snowballstemmer = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] -sphinx = [ +Sphinx = [ {file = "Sphinx-4.3.2-py3-none-any.whl", hash = "sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851"}, {file = "Sphinx-4.3.2.tar.gz", hash = "sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c"}, ] @@ -922,95 +1106,69 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] tenacity = [ - {file = "tenacity-8.0.1-py3-none-any.whl", hash = "sha256:f78f4ea81b0fabc06728c11dc2a8c01277bfc5181b321a4770471902e3eb844a"}, - {file = "tenacity-8.0.1.tar.gz", hash = "sha256:43242a20e3e73291a28bcbcacfd6e000b02d3857a9a9fff56b297a27afdc932f"}, + {file = "tenacity-8.1.0-py3-none-any.whl", hash = "sha256:35525cd47f82830069f0d6b73f7eb83bc5b73ee2fff0437952cedf98b27653ac"}, + {file = "tenacity-8.1.0.tar.gz", hash = "sha256:e48c437fdf9340f5666b92cd7990e96bc5fc955e1298baf4a907e3972067a445"}, ] tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tornado = [ - {file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"}, - {file = "tornado-6.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c"}, - {file = "tornado-6.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05"}, - {file = "tornado-6.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910"}, - {file = "tornado-6.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b"}, - {file = "tornado-6.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675"}, - {file = "tornado-6.1-cp35-cp35m-win32.whl", hash = "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5"}, - {file = "tornado-6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68"}, - {file = "tornado-6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb"}, - {file = "tornado-6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c"}, - {file = "tornado-6.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921"}, - {file = "tornado-6.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558"}, - {file = "tornado-6.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c"}, - {file = "tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085"}, - {file = "tornado-6.1-cp36-cp36m-win32.whl", hash = "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575"}, - {file = "tornado-6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795"}, - {file = "tornado-6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f"}, - {file = "tornado-6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102"}, - {file = "tornado-6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4"}, - {file = "tornado-6.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd"}, - {file = "tornado-6.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01"}, - {file = "tornado-6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d"}, - {file = "tornado-6.1-cp37-cp37m-win32.whl", hash = "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df"}, - {file = "tornado-6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37"}, - {file = "tornado-6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95"}, - {file = "tornado-6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a"}, - {file = "tornado-6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5"}, - {file = "tornado-6.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288"}, - {file = "tornado-6.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f"}, - {file = "tornado-6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6"}, - {file = "tornado-6.1-cp38-cp38-win32.whl", hash = "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326"}, - {file = "tornado-6.1-cp38-cp38-win_amd64.whl", hash = "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c"}, - {file = "tornado-6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5"}, - {file = "tornado-6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe"}, - {file = "tornado-6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea"}, - {file = "tornado-6.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2"}, - {file = "tornado-6.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0"}, - {file = "tornado-6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd"}, - {file = "tornado-6.1-cp39-cp39-win32.whl", hash = "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c"}, - {file = "tornado-6.1-cp39-cp39-win_amd64.whl", hash = "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4"}, - {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"}, + {file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"}, + {file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"}, + {file = "tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"}, + {file = "tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"}, + {file = "tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"}, + {file = "tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"}, + {file = "tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"}, + {file = "tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"}, + {file = "tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"}, + {file = "tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"}, + {file = "tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"}, ] typed-ast = [ - {file = "typed_ast-1.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ad3b48cf2b487be140072fb86feff36801487d4abb7382bb1929aaac80638ea"}, - {file = "typed_ast-1.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:542cd732351ba8235f20faa0fc7398946fe1a57f2cdb289e5497e1e7f48cfedb"}, - {file = "typed_ast-1.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc2c11ae59003d4a26dda637222d9ae924387f96acae9492df663843aefad55"}, - {file = "typed_ast-1.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd5df1313915dbd70eaaa88c19030b441742e8b05e6103c631c83b75e0435ccc"}, - {file = "typed_ast-1.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:e34f9b9e61333ecb0f7d79c21c28aa5cd63bec15cb7e1310d7d3da6ce886bc9b"}, - {file = "typed_ast-1.5.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f818c5b81966d4728fec14caa338e30a70dfc3da577984d38f97816c4b3071ec"}, - {file = "typed_ast-1.5.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3042bfc9ca118712c9809201f55355479cfcdc17449f9f8db5e744e9625c6805"}, - {file = "typed_ast-1.5.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4fff9fdcce59dc61ec1b317bdb319f8f4e6b69ebbe61193ae0a60c5f9333dc49"}, - {file = "typed_ast-1.5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:8e0b8528838ffd426fea8d18bde4c73bcb4167218998cc8b9ee0a0f2bfe678a6"}, - {file = "typed_ast-1.5.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ef1d96ad05a291f5c36895d86d1375c0ee70595b90f6bb5f5fdbee749b146db"}, - {file = "typed_ast-1.5.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed44e81517364cb5ba367e4f68fca01fba42a7a4690d40c07886586ac267d9b9"}, - {file = "typed_ast-1.5.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f60d9de0d087454c91b3999a296d0c4558c1666771e3460621875021bf899af9"}, - {file = "typed_ast-1.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9e237e74fd321a55c90eee9bc5d44be976979ad38a29bbd734148295c1ce7617"}, - {file = "typed_ast-1.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ee852185964744987609b40aee1d2eb81502ae63ee8eef614558f96a56c1902d"}, - {file = "typed_ast-1.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27e46cdd01d6c3a0dd8f728b6a938a6751f7bd324817501c15fb056307f918c6"}, - {file = "typed_ast-1.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d64dabc6336ddc10373922a146fa2256043b3b43e61f28961caec2a5207c56d5"}, - {file = "typed_ast-1.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8cdf91b0c466a6c43f36c1964772918a2c04cfa83df8001ff32a89e357f8eb06"}, - {file = "typed_ast-1.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:9cc9e1457e1feb06b075c8ef8aeb046a28ec351b1958b42c7c31c989c841403a"}, - {file = "typed_ast-1.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e20d196815eeffb3d76b75223e8ffed124e65ee62097e4e73afb5fec6b993e7a"}, - {file = "typed_ast-1.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:37e5349d1d5de2f4763d534ccb26809d1c24b180a477659a12c4bde9dd677d74"}, - {file = "typed_ast-1.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f1a27592fac87daa4e3f16538713d705599b0a27dfe25518b80b6b017f0a6d"}, - {file = "typed_ast-1.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8831479695eadc8b5ffed06fdfb3e424adc37962a75925668deeb503f446c0a3"}, - {file = "typed_ast-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:20d5118e494478ef2d3a2702d964dae830aedd7b4d3b626d003eea526be18718"}, - {file = "typed_ast-1.5.3.tar.gz", hash = "sha256:27f25232e2dd0edfe1f019d6bfaaf11e86e657d9bdb7b0956db95f560cceb2b3"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, + {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, + {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, + {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, + {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, + {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, + {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, + {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, + {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, +] +typer = [ + {file = "typer-0.6.1-py3-none-any.whl", hash = "sha256:54b19e5df18654070a82f8c2aa1da456a4ac16a2a83e6dcd9f170e291c56338e"}, + {file = "typer-0.6.1.tar.gz", hash = "sha256:2d5720a5e63f73eaf31edaa15f6ab87f35f0690f8ca233017d7d23d743a91d73"}, ] types-docutils = [ {file = "types-docutils-0.18.3.tar.gz", hash = "sha256:a0ef831dc20635f350fa9cff591231c31d27e75771e59fd6c979b6c0c7e03292"}, {file = "types_docutils-0.18.3-py3-none-any.whl", hash = "sha256:b54b6fd599914093a5aab08dbf1cba96eb107cdeb4210bbe4ccd233fe3a71d9b"}, ] typing-extensions = [ - {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, - {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, + {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, + {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, ] urllib3 = [ - {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, - {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, ] zipp = [ - {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, - {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, + {file = "zipp-3.8.1-py3-none-any.whl", hash = "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"}, + {file = "zipp-3.8.1.tar.gz", hash = "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2"}, ] diff --git a/pyproject.toml b/pyproject.toml index 5a6ff5d..2059c52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "fossology" -version = "1.5.0" +version = "2.0.0" description = "A library to automate Fossology from Python scripts" authors = ["Marion Deveaud "] license = "MIT License" @@ -26,22 +26,23 @@ addopts = "--doctest-glob='*.rst' --doctest-modules" [tool.poetry.dependencies] python = "^3.7" -requests = ">=2.27.1" -tenacity = ">=8.0.0" -click = "^8.1.2" +requests = ">=2.28.1" +tenacity = ">=8.1.0" +click = "^8.1.3" [tool.poetry.dev-dependencies] -flake8 = ">=4.0.1" +flake8 = ">=5.0.4" sphinx = ">=4.3.2" -black = "^22.3.0" -coverage = "^6.3.2" +black = "^22.8.0" +coverage = "^6.4.4" codecov = "^2.1.12" -pyflakes = "^2.4.0" -pytest = "^7.1.1" -responses = "^0.20.0" +pyflakes = "^2.5.0" +pytest = "^7.1.3" +responses = "^0.21.0" isort = "^5.10.1" sphinx-autobuild = "^2021.3.14" -rstcheck = "^5.0.0" +rstcheck = "^6.1.0" +requests-toolbelt = "^0.9.1" [tool.poetry.scripts] foss_cli = "fossology.foss_cli:main" diff --git a/tests/conftest.py b/tests/conftest.py index 648d369..19dbd97 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,7 +12,7 @@ import fossology from fossology.exceptions import AuthenticationError, FossologyApiError -from fossology.obj import AccessLevel, Agents, Folder, TokenScope, Upload +from fossology.obj import AccessLevel, Agents, Folder, JobStatus, TokenScope, Upload logger = logging.getLogger("fossology") console = logging.StreamHandler() @@ -22,6 +22,19 @@ logger.addHandler(console) +def jobs_lookup(foss: fossology.Fossology, upload: Upload): + for job in foss.list_jobs(upload=upload)[0]: + if job.status == JobStatus.FAILED.value: + logger.debug(f"Job {job.name} failed to complete, checking next job") + continue + while job.status != JobStatus.COMPLETED.value: + logger.debug( + f"Waiting for job {job.name} with status {job.status} to complete (eta: {job.eta})" + ) + job = foss.detail_job(job.id) + time.sleep(5) + + @pytest.fixture(scope="session") def foss_server() -> str: return "http://fossology/repo" @@ -136,7 +149,7 @@ def test_file_path() -> str: @pytest.fixture(scope="session") def upload_folder(foss: fossology.Fossology) -> Folder: - name = "FossPythonTestUploads" + name = "UploadFolderTest" desc = "Created via the Fossology Python API" folder = foss.create_folder(foss.rootFolder, name, description=desc) yield folder @@ -153,32 +166,39 @@ def move_folder(foss: fossology.Fossology) -> Folder: @pytest.fixture(scope="session") -def upload(foss: fossology.Fossology, test_file_path: str) -> Upload: - test_upload = foss.upload_file( +def upload( + foss: fossology.Fossology, + test_file_path: str, +) -> Upload: + upload = foss.upload_file( foss.rootFolder, file=test_file_path, description="Test upload via fossology-python lib", access_level=AccessLevel.PUBLIC, + wait_time=5, ) - time.sleep(3) - yield test_upload - foss.delete_upload(test_upload) + jobs_lookup(foss, upload) + yield upload + foss.delete_upload(upload) + time.sleep(5) @pytest.fixture(scope="session") -def scanned_upload( - foss: fossology.Fossology, test_file_path: str, foss_schedule_agents: Dict +def upload_with_jobs( + foss: fossology.Fossology, test_file_path: str, foss_schedule_agents: dict ) -> Upload: - test_upload = foss.upload_file( + upload = foss.upload_file( foss.rootFolder, file=test_file_path, - description="Test upload via fossology-python lib", + description="Test upload_with_jobs via fossology-python lib", access_level=AccessLevel.PUBLIC, + wait_time=5, ) - time.sleep(3) - foss.schedule_jobs(foss.rootFolder, test_upload, foss_schedule_agents) - yield test_upload - foss.delete_upload(test_upload) + foss.schedule_jobs(foss.rootFolder, upload, foss_schedule_agents) + jobs_lookup(foss, upload) + yield upload + foss.delete_upload(upload) + time.sleep(5) # foss_cli specific diff --git a/tests/test_foss_cli_create_cmds.py b/tests/test_foss_cli_create_cmds.py index 7468ba0..52d9c92 100644 --- a/tests/test_foss_cli_create_cmds.py +++ b/tests/test_foss_cli_create_cmds.py @@ -1,5 +1,7 @@ __doc__ = """Test 'create_*' sub commands of foss_cli""" +import time + from fossology import foss_cli @@ -20,6 +22,19 @@ def test_create_folder(runner, click_test_dict): ) assert result.exit_code == 0 assert d["VERBOSE"] == 2 + time.sleep(2) + # cleanup + result = runner.invoke( + foss_cli.cli, + [ + "-vv", + "delete_folder", + "FossFolder", + ], + obj=d, + catch_exceptions=False, + ) + assert result.exit_code == 0 def test_create_group(runner, click_test_dict): diff --git a/tests/test_foss_cli_flow_cmds.py b/tests/test_foss_cli_flow_cmds.py index a5a8e43..b689383 100644 --- a/tests/test_foss_cli_flow_cmds.py +++ b/tests/test_foss_cli_flow_cmds.py @@ -1,6 +1,7 @@ __doc__ = """Test the "workflow" sub commands of foss_cli""" import configparser import os +import time from pathlib import PurePath from fossology import foss_cli @@ -28,6 +29,18 @@ def test_upload_file(runner, click_test_file_path, click_test_file, click_test_d assert d["DEBUG"] assert d["UPLOAD"].uploadname == click_test_file assert "Summary of upload" in result.output + time.sleep(2) + result = runner.invoke( + foss_cli.cli, + [ + "-vv", + "delete_upload", + click_test_file, + ], + obj=d, + catch_exceptions=False, + ) + assert result.exit_code == 0 def test_create_config_file_with_wrong_token_scope_uses_default_read( diff --git a/tests/test_foss_cli_start_workflow.py b/tests/test_foss_cli_start_workflow.py index 564a846..97e61ce 100644 --- a/tests/test_foss_cli_start_workflow.py +++ b/tests/test_foss_cli_start_workflow.py @@ -61,7 +61,7 @@ def test_start_workflow_reuse_newest_job( runner, click_test_file_path, click_test_file, click_test_dict ): d = click_test_dict - # first upload is the initial one + # first upload is the initial one # - it uploads # - it triggers a job on the upload q_path = PurePath(click_test_file_path, click_test_file) @@ -109,3 +109,15 @@ def test_start_workflow_reuse_newest_job( assert "Report downloaded" in result.output assert "Report written to file: " in result.output assert result.exit_code == 0 + # cleanup + result = runner.invoke( + foss_cli.cli, + [ + "-vv", + "delete_upload", + click_test_file, + ], + obj=d, + catch_exceptions=False, + ) + assert result.exit_code == 0 diff --git a/tests/test_init.py b/tests/test_init.py index 5aa81f6..f4c0c96 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -4,21 +4,18 @@ import pytest import responses -from fossology import Fossology, versiontuple +from fossology import Fossology from fossology.exceptions import FossologyApiError def test_get_info(foss: Fossology): - if versiontuple(foss.version) >= versiontuple("1.3.3"): - assert foss.info.name == "FOSSology API" - assert foss.info.license.name == "GPL-2.0-only" + assert foss.info.name == "FOSSology API" + assert foss.info.license.name == "GPL-2.0-only" + assert foss.info.fossology.version @responses.activate def test_info_does_not_return_200(foss_server: str, foss: Fossology): - if versiontuple(foss.version) < versiontuple("1.3.3"): - return - responses.add( responses.GET, f"{foss_server}/api/v1/info", @@ -30,17 +27,13 @@ def test_info_does_not_return_200(foss_server: str, foss: Fossology): def test_get_health(foss: Fossology): - if versiontuple(foss.version) >= versiontuple("1.3.3"): - assert foss.health.status == "OK" - assert foss.health.scheduler.status == "OK" - assert foss.health.db.status == "OK" + assert foss.health.status == "OK" + assert foss.health.scheduler.status == "OK" + assert foss.health.db.status == "OK" @responses.activate def test_health_does_not_return_200(foss_server: str, foss: Fossology): - if versiontuple(foss.version) < versiontuple("1.3.3"): - return - responses.add( responses.GET, f"{foss_server}/api/v1/health", diff --git a/tests/test_jobs.py b/tests/test_jobs.py index cda64ab..e0b3442 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -7,9 +7,9 @@ import pytest import responses -from fossology import Fossology, versiontuple +from fossology import Fossology from fossology.exceptions import AuthorizationError, FossologyApiError -from fossology.obj import Upload +from fossology.obj import JobStatus, Upload def test_unpack_jobs(foss: Fossology, upload: Upload): @@ -24,22 +24,24 @@ def test_nogroup_jobs(foss: Fossology, upload: Upload, foss_schedule_agents: Dic assert "Scheduling job for group test not authorized" in str(excinfo.value) -def test_schedule_jobs(foss: Fossology, upload: Upload, foss_schedule_agents: Dict): - job = foss.schedule_jobs(foss.rootFolder, upload, foss_schedule_agents) - assert job.name == upload.uploadname +def test_schedule_jobs( + foss: Fossology, upload_with_jobs: Upload, foss_schedule_agents: Dict +): + job = foss.schedule_jobs(foss.rootFolder, upload_with_jobs, foss_schedule_agents) + assert job.name == upload_with_jobs.uploadname - jobs, _ = foss.list_jobs(upload=upload) - assert len(jobs) == 2 + jobs, _ = foss.list_jobs(upload=upload_with_jobs) + assert len(jobs) == 3 job = foss.detail_job(jobs[1].id, wait=True, timeout=30) - assert job.status == "Completed" + assert job.status == JobStatus.COMPLETED.value assert ( f"Job '{job.name}' ({job.id}) queued on {job.queueDate} (Status: {job.status} ETA: {job.eta})" in str(job) ) # Use pagination - jobs, _ = foss.list_jobs(upload=upload, page_size=1, page=2) + jobs, _ = foss.list_jobs(upload=upload_with_jobs, page_size=1, page=2) assert len(jobs) == 1 assert jobs[0].id == job.id @@ -75,23 +77,21 @@ def test_detail_job_error(foss_server: str, foss: Fossology): assert f"Error while getting details for job {job_id}" in str(excinfo.value) -def test_paginated_list_jobs(foss: Fossology, scanned_upload: Upload): - # Versions prior to 1.3.2 return corrupt number of pages - if versiontuple(foss.version) > versiontuple("1.3.1"): - jobs, total_pages = foss.list_jobs(upload=scanned_upload, page_size=1, page=1) - assert len(jobs) == 1 - assert total_pages == 2 +def test_paginated_list_jobs(foss: Fossology, upload_with_jobs: Upload): + jobs, total_pages = foss.list_jobs(upload=upload_with_jobs, page_size=1, page=1) + assert len(jobs) == 1 + assert total_pages == 3 - jobs, total_pages = foss.list_jobs(upload=scanned_upload, page_size=1, page=2) - assert len(jobs) == 1 - assert total_pages == 2 + jobs, total_pages = foss.list_jobs(upload=upload_with_jobs, page_size=1, page=2) + assert len(jobs) == 1 + assert total_pages == 3 - jobs, total_pages = foss.list_jobs(upload=scanned_upload, page_size=2, page=1) - assert len(jobs) == 2 - assert total_pages == 1 + jobs, total_pages = foss.list_jobs(upload=upload_with_jobs, page_size=2, page=1) + assert len(jobs) == 2 + assert total_pages == 2 - jobs, total_pages = foss.list_jobs( - upload=scanned_upload, page_size=1, all_pages=True - ) - assert len(jobs) == 2 - assert total_pages == 2 + jobs, total_pages = foss.list_jobs( + upload=upload_with_jobs, page_size=1, all_pages=True + ) + assert len(jobs) == 3 + assert total_pages == 3 diff --git a/tests/test_search.py b/tests/test_search.py index 5ab603d..0903f41 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -85,16 +85,16 @@ def test_search_error(foss_server: str, foss: Fossology): assert "Unable to get a result with the given search criteria" in str(excinfo.value) -def test_filesearch(foss: Fossology, scanned_upload: Upload): +def test_filesearch(foss: Fossology, upload: Upload): if versiontuple(foss.version) > versiontuple("1.0.16"): filelist = [ {"md5": "F921793D03CC6D63EC4B15E9BE8FD3F8"}, - {"sha1": scanned_upload.hash.sha1}, + {"sha1": upload.hash.sha1}, ] search_result = foss.filesearch(filelist=filelist) assert len(search_result) == 2 assert ( - f"File with SHA1 {scanned_upload.hash.sha1} doesn't have any concluded license yet" + f"File with SHA1 {upload.hash.sha1} doesn't have any concluded license yet" in str(search_result[1]) ) diff --git a/tests/test_upload_from.py b/tests/test_upload_from.py new file mode 100644 index 0000000..57551fa --- /dev/null +++ b/tests/test_upload_from.py @@ -0,0 +1,81 @@ +# Copyright 2019-2021 Siemens AG +# SPDX-License-Identifier: MIT + +from fossology import Fossology +from fossology.exceptions import FossologyApiError +from fossology.obj import AccessLevel, SearchTypes, Upload + + +def delete_upload(foss: Fossology, upload: Upload): + foss.delete_upload(upload) + try: + foss.detail_upload(upload, wait_time=2) + except FossologyApiError: + # Upload has been deleted + pass + + +def test_upload_from_vcs(foss: Fossology): + vcs = { + "vcsType": "git", + "vcsUrl": "https://github.com/fossology/fossology-python", + "vcsName": "fossology-python-github-master", + "vcsUsername": "", + "vcsPassword": "", + } + vcs_upload = foss.upload_file( + foss.rootFolder, + vcs=vcs, + description="Test upload from github repository via python lib", + access_level=AccessLevel.PUBLIC, + ignore_scm=False, + wait_time=5, + ) + assert vcs_upload.uploadname == vcs["vcsName"] + # FIXME option ignore_scm does not work currently + search_result = foss.search( + searchType=SearchTypes.DIRECTORIES, + filename=".git", + ) + assert not search_result + # Cleanup + delete_upload(foss, vcs_upload) + + +def test_upload_from_url(foss: Fossology): + url = { + "url": "https://github.com/fossology/fossology-python/archive/master.zip", + "name": "fossology-python-master.zip", + "accept": "zip", + "reject": "", + "maxRecursionDepth": "1", + } + url_upload = foss.upload_file( + foss.rootFolder, + url=url, + description="Test upload from url via python lib", + access_level=AccessLevel.PUBLIC, + wait_time=5, + ) + assert url_upload.uploadname == url["name"] + # Cleanup + delete_upload(foss, url_upload) + + +def test_upload_from_server(foss: Fossology): + server = { + "path": "/tmp/base-files-11", + "name": "base-files-11", + } + server_upload = foss.upload_file( + foss.rootFolder, + server=server, + description="Test upload from server via python lib", + access_level=AccessLevel.PUBLIC, + apply_global=True, + wait_time=5, + ) + assert server_upload.uploadname == server["name"] + + # Cleanup + delete_upload(foss, server_upload) diff --git a/tests/test_uploads.py b/tests/test_uploads.py index 7eaf750..61b2513 100644 --- a/tests/test_uploads.py +++ b/tests/test_uploads.py @@ -4,37 +4,31 @@ import secrets import time from datetime import date, timedelta +from unittest.mock import Mock import pytest import responses -from fossology import Fossology, versiontuple +from fossology import Fossology from fossology.exceptions import ( AuthorizationError, FossologyApiError, FossologyUnsupported, ) -from fossology.obj import AccessLevel, ClearingStatus, Folder, SearchTypes, Upload +from fossology.obj import AccessLevel, ClearingStatus, Folder, Upload def test_upload_sha1(foss: Fossology, upload: Upload): assert upload.uploadname == "base-files_11.tar.xz" - if versiontuple(foss.version) > versiontuple("1.0.16"): - assert upload.hash.sha1 == "D4D663FC2877084362FB2297337BE05684869B00" - assert str(upload) == ( - f"Upload '{upload.uploadname}' ({upload.id}, {upload.hash.size}B, {upload.hash.sha1}) " - f"in folder {upload.foldername} ({upload.folderid})" - ) - assert str(upload.hash) == ( - f"File SHA1: {upload.hash.sha1} MD5 {upload.hash.md5} " - f"SH256 {upload.hash.sha256} Size {upload.hash.size}B" - ) - else: - assert upload.filesha1 == "D4D663FC2877084362FB2297337BE05684869B00" - assert str(upload) == ( - f"Upload '{upload.uploadname}' ({upload.id}, {upload.filesize}B, {upload.filesha1}) " - f"in folder {upload.foldername} ({upload.folderid})" - ) + assert upload.hash.sha1 == "D4D663FC2877084362FB2297337BE05684869B00" + assert str(upload) == ( + f"Upload '{upload.uploadname}' ({upload.id}, {upload.hash.size}B, {upload.hash.sha1}) " + f"in folder {upload.foldername} ({upload.folderid})" + ) + assert str(upload.hash) == ( + f"File SHA1: {upload.hash.sha1} MD5 {upload.hash.md5} " + f"SH256 {upload.hash.sha256} Size {upload.hash.size}B" + ) def test_get_upload_unauthorized(foss: Fossology, upload: Upload): @@ -75,7 +69,8 @@ def test_upload_nogroup(foss: Fossology, upload_folder: Folder, test_file_path: in str(excinfo.value) ) - # Get get upload unknown group + +def test_list_upload_unknown_group(foss: Fossology): with pytest.raises(AuthorizationError) as excinfo: foss.list_uploads(group="test") assert "Retrieving list of uploads for group test not authorized" in str( @@ -83,126 +78,36 @@ def test_upload_nogroup(foss: Fossology, upload_folder: Folder, test_file_path: ) -def test_get_uploads(foss: Fossology, upload_folder: Folder, test_file_path: str): - name = "FossPythonTestUploadsSubfolder" +def test_get_uploads( + foss: Fossology, upload: Upload, upload_folder: Folder, test_file_path: str +): + name = "UploadSubfolderTest" desc = "Created via the Fossology Python API" upload_subfolder = foss.create_folder(upload_folder, name, description=desc) - foss.upload_file( - upload_folder, - file=test_file_path, - description="Test upload from github repository via python lib", - ) foss.upload_file( upload_subfolder, file=test_file_path, - description="Test upload from github repository via python lib", + description="Test upload in subdirectory", + wait_time=5, ) - # Folder listing is still unstable in version 1.0.16 - # Let's skip it since it has been fixed in newest versions - if versiontuple(foss.version) > versiontuple("1.0.16"): - assert len(foss.list_uploads(folder=upload_folder)[0]) == 2 - assert len(foss.list_uploads(folder=upload_folder, recursive=False)[0]) == 1 - assert len(foss.list_uploads(folder=upload_subfolder)[0]) == 1 + assert len(foss.list_uploads()[0]) == 3 + assert len(foss.list_uploads(folder=foss.rootFolder)[0]) == 3 + assert len(foss.list_uploads(folder=foss.rootFolder, recursive=False)[0]) == 2 + assert len(foss.list_uploads(folder=upload_subfolder)[0]) == 1 + foss.delete_folder(upload_subfolder) def test_filter_uploads(foss: Fossology, upload: Upload): today = date.today().isoformat() tomorrow = (date.today() + timedelta(days=1)).isoformat() - # Uploads filtering has been enhance with API version 1.3.4 - if versiontuple(foss.version) >= versiontuple("1.3.4"): - assert len(foss.list_uploads(assignee="-me-")[0]) == 0 - assert len(foss.list_uploads(assignee="-unassigned-")[0]) >= 1 - assert len(foss.list_uploads(name="Non-existing upload")[0]) == 0 - assert len(foss.list_uploads(name="Test upload")[0]) >= 1 - assert len(foss.list_uploads(status=ClearingStatus.CLOSED)[0]) == 0 - assert len(foss.list_uploads(status=ClearingStatus.OPEN)[0]) >= 1 - assert len(foss.list_uploads(since=tomorrow)[0]) == 0 - assert len(foss.list_uploads(since=today)[0]) >= 1 - - -def test_upload_from_vcs(foss: Fossology): - vcs = { - "vcsType": "git", - "vcsUrl": "https://github.com/fossology/fossology-python", - "vcsName": "fossology-python-github-master", - "vcsUsername": "", - "vcsPassword": "", - } - vcs_upload = foss.upload_file( - foss.rootFolder, - vcs=vcs, - description="Test upload from github repository via python lib", - access_level=AccessLevel.PUBLIC, - ) - assert vcs_upload.uploadname == vcs["vcsName"] - search_result = foss.search( - searchType=SearchTypes.DIRECTORIES, - filename=".git", - ) - assert not search_result - foss.delete_upload(vcs_upload) - - -def test_upload_ignore_scm(foss: Fossology): - vcs = { - "vcsType": "git", - "vcsUrl": "https://github.com/fossology/fossology-python", - "vcsName": "fossology-python-github-master", - "vcsUsername": "", - "vcsPassword": "", - } - vcs_upload = foss.upload_file( - foss.rootFolder, - vcs=vcs, - description="Test upload with ignore_scm flag", - ignore_scm=False, - access_level=AccessLevel.PUBLIC, - ) - assert vcs_upload.uploadname == vcs["vcsName"] - # FIXME: shall be fixed in the next release - # assert foss.search( - # searchType=SearchTypes.DIRECTORIES, filename=".git", - # ) == $something - - # Cleanup - foss.delete_upload(vcs_upload) - - -def test_upload_from_url(foss: Fossology): - url = { - "url": "https://github.com/fossology/fossology-python/archive/master.zip", - "name": "fossology-python-master.zip", - "accept": "zip", - "reject": "", - "maxRecursionDepth": "1", - } - url_upload = foss.upload_file( - foss.rootFolder, - url=url, - description="Test upload from url via python lib", - access_level=AccessLevel.PUBLIC, - ) - assert url_upload.uploadname == url["name"] - - # Cleanup - foss.delete_upload(url_upload) - - -def test_upload_from_server(foss: Fossology): - server = { - "path": "/tmp/base-files-11", - "name": "base-files-11", - } - server_upload = foss.upload_file( - foss.rootFolder, - server=server, - description="Test upload from server via python lib", - access_level=AccessLevel.PUBLIC, - ) - assert server_upload.uploadname == server["name"] - - # Cleanup - foss.delete_upload(server_upload) + assert len(foss.list_uploads(assignee="-me-")[0]) == 0 + assert len(foss.list_uploads(assignee="-unassigned-")[0]) >= 1 + assert len(foss.list_uploads(name="Non-existing upload")[0]) == 0 + assert len(foss.list_uploads(name="Test upload")[0]) >= 1 + assert len(foss.list_uploads(status=ClearingStatus.CLOSED)[0]) == 0 + assert len(foss.list_uploads(status=ClearingStatus.OPEN)[0]) >= 1 + assert len(foss.list_uploads(since=tomorrow)[0]) == 0 + assert len(foss.list_uploads(since=today)[0]) >= 1 def test_empty_upload(foss: Fossology): @@ -231,78 +136,81 @@ def test_upload_error(foss: Fossology, foss_server: str, test_file_path: str): assert f"Upload {description} could not be performed" in str(excinfo.value) -def test_move_upload(foss: Fossology): - upload = foss.upload_file( - foss.rootFolder, - file="tests/files/base-files_11.tar.xz", - description="Test upload via fossology-python lib", - access_level=AccessLevel.PUBLIC, - ) - move_upload_folder = foss.create_folder(foss.rootFolder, "MoveUploadFolder") - if versiontuple(foss.version) < versiontuple("1.4.0"): - with pytest.raises(FossologyUnsupported): - foss.move_upload(upload, move_upload_folder, "move") - else: - foss.move_upload(upload, move_upload_folder, "move") - moved_upload = foss.detail_upload(upload.id) - assert moved_upload.folderid == move_upload_folder.id - foss.delete_folder(move_upload_folder) +def test_move_upload_unsupported_version(foss: Fossology): + real_version = foss.version + foss.version = "1.3.9" + with pytest.raises(FossologyUnsupported): + foss.move_upload(Mock(), Mock(), "move") + foss.version = real_version + + +def test_move_upload(foss: Fossology, upload: Upload, move_folder: Folder): + foss.move_upload(upload, move_folder, "move") + moved_upload = foss.detail_upload(upload.id) + assert moved_upload.folderid == move_folder.id def test_copy_upload(foss: Fossology, upload: Upload): copy_upload_folder = foss.create_folder(foss.rootFolder, "CopyUploadFolder") - if versiontuple(foss.version) < versiontuple("1.4.0"): - with pytest.raises(FossologyUnsupported): - foss.move_upload(upload, copy_upload_folder, "copy") - else: - foss.move_upload(upload, copy_upload_folder, "copy") - copied_upload = foss.detail_upload(upload.id) - assert copied_upload - # Upload should be visible twice but it isn't - # Bug or Feature? - foss.delete_folder(copy_upload_folder) + foss.move_upload(upload, copy_upload_folder, "copy") + copied_upload = foss.detail_upload(upload.id) + assert copied_upload + # Upload should be visible twice but it isn't + # Bug or Feature? + foss.delete_folder(copy_upload_folder) def test_move_upload_to_non_existing_folder(foss: Fossology, upload: Upload): - move_upload_folder = foss.create_folder(foss.rootFolder, "MoveUploadFolder") - if versiontuple(foss.version) < versiontuple("1.4.0"): - with pytest.raises(FossologyUnsupported): - foss.move_upload(upload, move_upload_folder, "move") - else: - non_folder = Folder(secrets.randbelow(1000), "Non folder", "", foss.rootFolder) - with pytest.raises(AuthorizationError): - foss.move_upload(upload, non_folder, "move") - - -def test_update_upload(foss: Fossology, scanned_upload: Upload): - if versiontuple(foss.version) < versiontuple("1.4.0"): - with pytest.raises(FossologyUnsupported): - foss.update_upload(scanned_upload) - else: - foss.update_upload( - scanned_upload, ClearingStatus.INPROGRESS, "I am taking over", foss.user - ) - summary = foss.upload_summary(scanned_upload) - assert summary.clearingStatus == "InProgress" - assert summary.additional_info["assignee"] == foss.user.id + non_folder = Folder(secrets.randbelow(1000), "Non folder", "", foss.rootFolder) + with pytest.raises(AuthorizationError): + foss.move_upload(upload, non_folder, "move") -def test_update_upload_with_unknown_group_raises_error( - foss: Fossology, scanned_upload: Upload -): - if versiontuple(foss.version) < versiontuple("1.4.0"): - with pytest.raises(FossologyUnsupported): - foss.update_upload(scanned_upload) - else: - with pytest.raises(AuthorizationError) as excinfo: - foss.update_upload(scanned_upload, group="test") - assert f"Updating upload {scanned_upload.id} not authorized" in str( - excinfo.value - ) +@responses.activate +def test_move_upload_error(foss: Fossology, foss_server: str, upload: Upload): + responses.add( + responses.PUT, + f"{foss_server}/api/v1/uploads/{upload.id}", + status=500, + ) + with pytest.raises(FossologyApiError): + foss.move_upload(upload, Mock(), "move") + + +def test_update_upload_unsupported_version(foss: Fossology): + real_version = foss.version + foss.version = "1.3.9" + with pytest.raises(FossologyUnsupported): + foss.update_upload(Mock()) + foss.version = real_version -def test_upload_summary(foss: Fossology, scanned_upload: Upload): - summary = foss.upload_summary(scanned_upload) +def test_update_upload(foss: Fossology, upload: Upload): + foss.update_upload(upload, ClearingStatus.INPROGRESS, "I am taking over", foss.user) + summary = foss.upload_summary(upload) + assert summary.clearingStatus == "InProgress" + assert summary.additional_info["assignee"] == foss.user.id + + +def test_update_upload_with_unknown_group_raises_error(foss: Fossology, upload: Upload): + with pytest.raises(AuthorizationError) as excinfo: + foss.update_upload(upload, group="test") + assert f"Updating upload {upload.id} not authorized" in str(excinfo.value) + + +@responses.activate +def test_update_upload_error(foss: Fossology, foss_server: str, upload: Upload): + responses.add( + responses.PATCH, + f"{foss_server}/api/v1/uploads/{upload.id}", + status=500, + ) + with pytest.raises(FossologyApiError): + foss.update_upload(upload) + + +def test_upload_summary(foss: Fossology, upload: Upload): + summary = foss.upload_summary(upload) assert summary.clearingStatus == "InProgress" assert not summary.mainLicense assert str(summary) == ( @@ -311,63 +219,84 @@ def test_upload_summary(foss: Fossology, scanned_upload: Upload): ) +@responses.activate +def test_upload_summary_500_error(foss: Fossology, foss_server: str, upload: Upload): + responses.add( + responses.GET, + f"{foss_server}/api/v1/uploads/{upload.id}/summary", + status=500, + ) + with pytest.raises(FossologyApiError): + foss.upload_summary(upload) + + def test_upload_summary_with_unknown_group_raises_authorization_error( - foss: Fossology, scanned_upload: Upload + foss: Fossology, upload: Upload ): with pytest.raises(AuthorizationError) as excinfo: - foss.upload_summary(scanned_upload, group="test") + foss.upload_summary(upload, group="test") assert ( - f"Getting summary of upload {scanned_upload.id} for group test not authorized" + f"Getting summary of upload {upload.id} for group test not authorized" in str(excinfo.value) ) -def test_upload_licenses(foss: Fossology, scanned_upload: Upload): +def test_upload_licenses(foss: Fossology, upload_with_jobs: Upload): # Default agent "nomos" - licenses = foss.upload_licenses(scanned_upload) + licenses = foss.upload_licenses(upload_with_jobs) assert len(licenses) == 56 - licenses = foss.upload_licenses(scanned_upload, containers=True) + licenses = foss.upload_licenses(upload_with_jobs, containers=True) assert len(licenses) == 56 # Specific agent "ojo" - licenses = foss.upload_licenses(scanned_upload, agent="ojo") + licenses = foss.upload_licenses(upload_with_jobs, agent="ojo") assert len(licenses) == 9 # Specific agent "monk" - licenses = foss.upload_licenses(scanned_upload, agent="monk") + licenses = foss.upload_licenses(upload_with_jobs, agent="monk") assert len(licenses) == 23 # Unknown group with pytest.raises(AuthorizationError) as excinfo: - foss.upload_licenses(scanned_upload, group="test") + foss.upload_licenses(upload_with_jobs, group="test") assert ( - f"Getting license for upload {scanned_upload.id} for group test not authorized" + f"Getting license for upload {upload_with_jobs.id} for group test not authorized" in str(excinfo.value) ) +@responses.activate +def test_upload_licenses_412_error(foss: Fossology, foss_server: str, upload: Upload): + responses.add( + responses.GET, + f"{foss_server}/api/v1/uploads/{upload.id}/licenses", + status=412, + ) + with pytest.raises(FossologyApiError): + foss.upload_licenses(upload) + + +@responses.activate +def test_upload_licenses_500_error(foss: Fossology, foss_server: str, upload: Upload): + responses.add( + responses.GET, + f"{foss_server}/api/v1/uploads/{upload.id}/licenses", + status=500, + ) + with pytest.raises(FossologyApiError): + foss.upload_licenses(upload) + + def test_delete_unknown_upload_unknown_group(foss: Fossology): - if versiontuple(foss.version) > versiontuple("1.0.16"): - upload = Upload( - foss.rootFolder, - "Root Folder", - secrets.randbelow(1000), - "", - "Non Upload", - "2020-05-05", - hash={"sha1": None, "md5": None, "sha256": None, "size": None}, - ) - else: - upload = Upload( - foss.rootFolder, - "Root Folder", - secrets.randbelow(1000), - "", - "Non Upload", - "2020-05-05", - filesize="1024", - filesha1="597d209fd962f401866f12db9fa1f7301aee15a9", - ) + upload = Upload( + foss.rootFolder, + "Root Folder", + secrets.randbelow(1000), + "", + "Non Upload", + "2020-05-05", + hash={"sha1": None, "md5": None, "sha256": None, "size": None}, + ) with pytest.raises(FossologyApiError): foss.delete_upload(upload) @@ -379,15 +308,13 @@ def test_delete_unknown_upload_unknown_group(foss: Fossology): def test_paginated_list_uploads(foss: Fossology, upload: Upload, test_file_path: str): - if versiontuple(foss.version) < versiontuple("1.1.1"): - # Upload pagination not available yet - return # Add a second upload second_upload = foss.upload_file( foss.rootFolder, file=test_file_path, description="Test second upload via fossology-python lib", access_level=AccessLevel.PUBLIC, + wait_time=5, ) time.sleep(3) uploads, _ = foss.list_uploads(page_size=1, page=1) @@ -410,3 +337,14 @@ def test_paginated_list_uploads(foss: Fossology, upload: Upload, test_file_path: assert num_known_uploads >= 2 foss.delete_upload(second_upload) + + +@responses.activate +def test_list_uploads_500_error(foss: Fossology, foss_server: str, upload: Upload): + responses.add( + responses.GET, + f"{foss_server}/api/v1/uploads", + status=500, + ) + with pytest.raises(FossologyApiError): + foss.list_uploads()