From a4ea73c0a8ef436fd84de7526948fd19ea6aa40f Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Tue, 16 Nov 2021 22:33:19 -0600 Subject: [PATCH 01/24] Add miniconda as a pyenv version for testing --- .python-version | 1 + 1 file changed, 1 insertion(+) diff --git a/.python-version b/.python-version index 0ee13f1..689382e 100644 --- a/.python-version +++ b/.python-version @@ -2,3 +2,4 @@ 3.9.7 3.8.12 3.7.12 +miniconda3-4.7.12 From 0a0c8a74711027bff7da33cff55d2668dab3a6e2 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Tue, 16 Nov 2021 22:34:36 -0600 Subject: [PATCH 02/24] Disable wordwrap my default for non python files --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9af49a7..de96703 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "editor.formatOnSave": true, + "editor.wordWrap": "off", "python.formatting.provider": "black", "python.linting.mypyEnabled": true, "python.linting.flake8Enabled": true, From 78c3d51df0677c70b5ab7f54b4c3b6295ecedf63 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Tue, 16 Nov 2021 22:39:56 -0600 Subject: [PATCH 03/24] Create a managers subpackage and a base manager class The current version of the pydev command is designed as a proof of concept, but isn't really extensible beyond my own personal preferences. The solution to that, as I see it, is to create a common API for all current and future supported environment managers to adhere to, which we can then use as an abstract base class for future environment managers to use. --- devwrangler/managers/__init__.py | 2 ++ devwrangler/managers/base.py | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 devwrangler/managers/__init__.py create mode 100644 devwrangler/managers/base.py diff --git a/devwrangler/managers/__init__.py b/devwrangler/managers/__init__.py new file mode 100644 index 0000000..8155cf1 --- /dev/null +++ b/devwrangler/managers/__init__.py @@ -0,0 +1,2 @@ +from .conda import CondaManager +from .venv import VenvManager diff --git a/devwrangler/managers/base.py b/devwrangler/managers/base.py new file mode 100644 index 0000000..01c6d1d --- /dev/null +++ b/devwrangler/managers/base.py @@ -0,0 +1,35 @@ +"""Defines an Abstract Base Class (ABC) to Standardize the API for various environment managers.""" +import abc +import platform +from pathlib import Path + +from ..utilities.shell import run_command + + +class BaseManager(abc.ABC): + """A standard API for various environment managers.""" + + def __init__(self, work_dir: Path): + """Initialize a virtual environment model with venv.""" + self.prefixes = { + 'windows': 'Scripts/python.exe', + } + self.venv_path = work_dir / ".venv" + self.cmd = run_command + + @property + def prefix(self) -> Path: + """Return the path to the python executable for the virtual environment.""" + return self.venv_path.joinpath( + self.prefixes.get(platform.system().lower(), "bin/python") + ) + + @abc.abstractmethod + def create(self): + """Create a sandboxed virtual environment with the specific manager.""" + pass + + @abc.abstractmethod + def install_dependencies(self, quiet: bool = True): + """Install dependencies into a created environment.""" + pass From 7af93c1a3700259beff621dbe804298c612ceb68 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Tue, 16 Nov 2021 22:41:28 -0600 Subject: [PATCH 04/24] Add tests for the forthcoming venv-based manager --- tests/managers/__init__.py | 0 tests/managers/test_venv.py | 53 +++++++++++++++++++++++++++++++++++++ tests/test_devwrangler.py | 18 ------------- 3 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 tests/managers/__init__.py create mode 100644 tests/managers/test_venv.py delete mode 100644 tests/test_devwrangler.py diff --git a/tests/managers/__init__.py b/tests/managers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/managers/test_venv.py b/tests/managers/test_venv.py new file mode 100644 index 0000000..e6a1190 --- /dev/null +++ b/tests/managers/test_venv.py @@ -0,0 +1,53 @@ +import os +from pathlib import Path +from typing import Tuple + +from pytest import fixture + +from devwrangler.managers import VenvManager + + +@fixture +def tmp_venv_path(tmpdir) -> Path: + """Returns a temporary directory to generate a virtual environment from.""" + return Path(tmpdir) + + +def test_venv_creation(tmp_venv_path: Path): + """Test environment creation with venv.""" + # Arrange + venv = VenvManager(tmp_venv_path) + assert not venv.venv_path.exists() + assert not venv.prefix.exists() + + # Act + venv.create() + + # Assert + assert Path(venv.venv_path).exists() + assert Path(venv.prefix).exists() + assert os.access(venv.prefix, mode=os.X_OK) + + +def test_dependency_install(tmp_venv_path: Path): + """Test that dependencies are installed as expected.""" + # Arrange + tmp_venv = VenvManager(tmp_venv_path) + tmp_venv.create() + + req_path = tmp_venv_path / "requirements.txt" + with open(req_path, "w") as req_file: + req_file.write("cowsay\n") + + cowsay_path = tmp_venv.venv_path.joinpath("bin/cowsay") + assert not cowsay_path.exists() + assert tmp_venv.prefix.exists() + + # Act + assert tmp_venv.prefix.exists() + tmp_venv.install_dependencies() + + # Assert + assert cowsay_path.exists() + assert cowsay_path.is_file() + assert os.access(cowsay_path, mode=os.X_OK) diff --git a/tests/test_devwrangler.py b/tests/test_devwrangler.py deleted file mode 100644 index 673a2f6..0000000 --- a/tests/test_devwrangler.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -"""Tests for `devwrangler` package.""" -import os -from pathlib import Path - -from devwrangler.devwrangler import create_virtual_environment - - -def test_create_virtualenv(tmpdir): - """Test that create_virtualenv creates a .venv directory.""" - # Setup - test_dir = tmpdir.mkdir('venv_test') - venv_dir = Path(test_dir.join('.venv')) - os.chdir(test_dir) - assert not venv_dir.exists() - assert Path(test_dir) == venv_dir.parent - create_virtual_environment(venv_dir) - assert venv_dir.exists() From 4593c21cea437058cdcf2a72a5c97286d86fff4e Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Tue, 16 Nov 2021 22:42:31 -0600 Subject: [PATCH 05/24] Create the venv-based manager, based on the base manager API --- devwrangler/managers/venv.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 devwrangler/managers/venv.py diff --git a/devwrangler/managers/venv.py b/devwrangler/managers/venv.py new file mode 100644 index 0000000..6e4975b --- /dev/null +++ b/devwrangler/managers/venv.py @@ -0,0 +1,32 @@ +"""Implement a venv specific manager for those who prefer to use venv.""" +import venv +from pathlib import Path + +from .base import BaseManager + + +class VenvManager(BaseManager): + """Manage virtual environments with Python's 'venv' module.""" + + def create(self): + """Create a virtual environment using venv.""" + venv.create( + self.venv_path, + with_pip=True, + prompt=self.venv_path.parent.name, + ) + + def install_dependencies(self, quiet: bool = True): + """Install environment dependencies.""" + minimal_dependencies = [ + str(self.prefix), + "-m", + "pip", + "install", + "-U", + "pip", + "setuptools", + ] + if quiet: + minimal_dependencies.append("-qqq") + self.cmd(minimal_dependencies) From 7e991c29dd7f8579f9a7f7e52adf29564acdca95 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Sat, 20 Nov 2021 18:06:08 -0600 Subject: [PATCH 06/24] Skip initial version of dependency installation tests --- devwrangler/managers/venv.py | 2 +- tests/managers/test_venv.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/devwrangler/managers/venv.py b/devwrangler/managers/venv.py index 6e4975b..90e5e3a 100644 --- a/devwrangler/managers/venv.py +++ b/devwrangler/managers/venv.py @@ -1,6 +1,5 @@ """Implement a venv specific manager for those who prefer to use venv.""" import venv -from pathlib import Path from .base import BaseManager @@ -27,6 +26,7 @@ def install_dependencies(self, quiet: bool = True): "pip", "setuptools", ] + if quiet: minimal_dependencies.append("-qqq") self.cmd(minimal_dependencies) diff --git a/tests/managers/test_venv.py b/tests/managers/test_venv.py index e6a1190..5d638e0 100644 --- a/tests/managers/test_venv.py +++ b/tests/managers/test_venv.py @@ -1,15 +1,15 @@ +"""Test the python -m venv based environment manager.""" import os from pathlib import Path -from typing import Tuple -from pytest import fixture +import pytest from devwrangler.managers import VenvManager -@fixture +@pytest.fixture def tmp_venv_path(tmpdir) -> Path: - """Returns a temporary directory to generate a virtual environment from.""" + """Return a temporary directory to generate a virtual environment from.""" return Path(tmpdir) @@ -29,8 +29,9 @@ def test_venv_creation(tmp_venv_path: Path): assert os.access(venv.prefix, mode=os.X_OK) +@pytest.mark.skip(reason="Currently unable to install more than minimal dependencies") def test_dependency_install(tmp_venv_path: Path): - """Test that dependencies are installed as expected.""" + """Test dependency installation.""" # Arrange tmp_venv = VenvManager(tmp_venv_path) tmp_venv.create() From 88edf4e8ebc15d5493523c3c768b29a981ca9b2a Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Sat, 20 Nov 2021 18:09:28 -0600 Subject: [PATCH 07/24] Add stubs for new (sub)package organization --- devwrangler/commands/__init__.py | 0 devwrangler/managers/conda.py | 30 ++++++++++ devwrangler/templates/requirements/base.in | 0 devwrangler/templates/requirements/dev.in | 2 + devwrangler/templates/requirements/doc.in | 2 + devwrangler/templates/requirements/test.in | 1 + devwrangler/templates/vscode/extensions.json | 12 ++++ devwrangler/templates/vscode/settings.json | 59 ++++++++++++++++++++ devwrangler/utilities/__init__.py | 0 devwrangler/utilities/config.py | 0 devwrangler/utilities/display.py | 0 devwrangler/utilities/shell.py | 25 +++++++++ tests/commands/__init__.py | 0 tests/managers/test_conda.py | 0 tests/utilities/__init__.py | 0 tests/utilities/config.py | 0 tests/utilities/display.py | 0 tests/utilities/shell.py | 0 18 files changed, 131 insertions(+) create mode 100644 devwrangler/commands/__init__.py create mode 100644 devwrangler/managers/conda.py create mode 100644 devwrangler/templates/requirements/base.in create mode 100644 devwrangler/templates/requirements/dev.in create mode 100644 devwrangler/templates/requirements/doc.in create mode 100644 devwrangler/templates/requirements/test.in create mode 100644 devwrangler/templates/vscode/extensions.json create mode 100644 devwrangler/templates/vscode/settings.json create mode 100644 devwrangler/utilities/__init__.py create mode 100644 devwrangler/utilities/config.py create mode 100644 devwrangler/utilities/display.py create mode 100644 devwrangler/utilities/shell.py create mode 100644 tests/commands/__init__.py create mode 100644 tests/managers/test_conda.py create mode 100644 tests/utilities/__init__.py create mode 100644 tests/utilities/config.py create mode 100644 tests/utilities/display.py create mode 100644 tests/utilities/shell.py diff --git a/devwrangler/commands/__init__.py b/devwrangler/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devwrangler/managers/conda.py b/devwrangler/managers/conda.py new file mode 100644 index 0000000..f01eec1 --- /dev/null +++ b/devwrangler/managers/conda.py @@ -0,0 +1,30 @@ +import shutil as sh + +from .base import BaseManager + + +class CondaManager(BaseManager): + """A manager for conda and it's environment.""" + + def create(self): + """Create a conda environment in the location specified by venv_path.""" + if not sh.which("conda"): + raise FileNotFoundError("No conda executable found in your $PATH") + + self.cmd(["conda", "env", "create", "-p", str(self.venv_path)]) + + def install_dependencies(self, quiet: bool = True): + """Install dependencies from conda's environment.yml file in the root of your project.""" + if not sh.which("conda"): + raise FileNotFoundError("No conda executable found in your $PATH") + self.cmd( + [ + "conda", + "env", + "update", + "--prefix", + str(self.venv_path.parent), + "--file" "environment.yml", + "--prune", + ] + ) diff --git a/devwrangler/templates/requirements/base.in b/devwrangler/templates/requirements/base.in new file mode 100644 index 0000000..e69de29 diff --git a/devwrangler/templates/requirements/dev.in b/devwrangler/templates/requirements/dev.in new file mode 100644 index 0000000..a8693c6 --- /dev/null +++ b/devwrangler/templates/requirements/dev.in @@ -0,0 +1,2 @@ +-r base.txt +-r test.txt diff --git a/devwrangler/templates/requirements/doc.in b/devwrangler/templates/requirements/doc.in new file mode 100644 index 0000000..a8693c6 --- /dev/null +++ b/devwrangler/templates/requirements/doc.in @@ -0,0 +1,2 @@ +-r base.txt +-r test.txt diff --git a/devwrangler/templates/requirements/test.in b/devwrangler/templates/requirements/test.in new file mode 100644 index 0000000..a3e81b8 --- /dev/null +++ b/devwrangler/templates/requirements/test.in @@ -0,0 +1 @@ +-r base.txt diff --git a/devwrangler/templates/vscode/extensions.json b/devwrangler/templates/vscode/extensions.json new file mode 100644 index 0000000..07f07f4 --- /dev/null +++ b/devwrangler/templates/vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "ms-python.python", + "ms-python.vscode-pylance", + "hbenl.vscode-test-explorer", + "littlefoxteam.vscode-python-test-adapter", + "ms-vscode.test-adapter-converter", + "samuelcolvin.jinjahtml", + "batisteo.vscode-django", + "bungcip.better-toml" + ] +} diff --git a/devwrangler/templates/vscode/settings.json b/devwrangler/templates/vscode/settings.json new file mode 100644 index 0000000..ca12412 --- /dev/null +++ b/devwrangler/templates/vscode/settings.json @@ -0,0 +1,59 @@ +{ + "editor.formatOnSave": true, + "files.associations": { + "**/*.html": "html", + {% if config["use_django"] %} + "**/templates/**/*": "django-txt", + "**/templates/**/*.html": "django-html", + {% else %} + "**/templates/**/*": "jinja", + {% for ext, kind in config["jinja"]["types"].items() %} + "**/templates/**/*.html": "jinja-{{ kind }}", + {% endfor %} + {% endif %} + "**/requirements{/**,*}.{txt,in}": "pip-requirements" + }, + "python.analysis.diagnosticPublishDelay": 1000, + "python.analysis.disabled": [], + "python.analysis.errors": [ + "inherit-non-class", + "no-cls-argument", + "no-self-argument", + "parameter-already-specified", + "parameter-missing", + "positional-argument-after-keyword", + "positional-only-named", + "return-in-init", + "typing-generic-arguments", + "typing-typevar-arguments", + "typing-newtype-arguments", + "unresolved-import", + "undefined-variable" + ], + "python.analysis.warnings": [ + "unknown-parameter-name", + "variable-not-defined-globally", + "variable-not-defined-nonlocal" + ], + "python.analysis.information": [ + "too-many-function-arguments", + "too-many-positional-arguments-before-star", + "no-method-argument" + ], + "python.autoComplete.addBrackets": true, + "python.formatting.provider": "black", + "python.languageServer": "Pylance", + "python.linting.banditEnabled": true, + "python.linting.flake8Enabled": true, + "python.linting.flake8Args": ["--max-line-length", "88"], + "python.linting.mypyEnabled": false, + "python.sortImports.path": "isort", + "python.sortImports.args": ["--profile", "black"], + "[python]": { + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + } +} diff --git a/devwrangler/utilities/__init__.py b/devwrangler/utilities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devwrangler/utilities/config.py b/devwrangler/utilities/config.py new file mode 100644 index 0000000..e69de29 diff --git a/devwrangler/utilities/display.py b/devwrangler/utilities/display.py new file mode 100644 index 0000000..e69de29 diff --git a/devwrangler/utilities/shell.py b/devwrangler/utilities/shell.py new file mode 100644 index 0000000..1f6b4c7 --- /dev/null +++ b/devwrangler/utilities/shell.py @@ -0,0 +1,25 @@ +import subprocess as sub +import sys +import warnings +from typing import Sequence + + +def run_command(command: Sequence[str]): + """Attempt to run a specific command in the users's shell. + + >>> run_command(['ls']) + """ + try: + sub.run( + command, + check=True, + encoding="utf-8", + ) + except sub.CalledProcessError: + warnings.warn( + ( + f"Problem encountered when running `{' '.join(command)}`\n\n" + f"Review the output above to manually debug the issue" + ) + ) + sys.exit(1) diff --git a/tests/commands/__init__.py b/tests/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/managers/test_conda.py b/tests/managers/test_conda.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utilities/__init__.py b/tests/utilities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utilities/config.py b/tests/utilities/config.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utilities/display.py b/tests/utilities/display.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utilities/shell.py b/tests/utilities/shell.py new file mode 100644 index 0000000..e69de29 From d9ca084334d6abb47c253f9554ca0c8a9f6f7ab2 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:20:04 -0600 Subject: [PATCH 08/24] Add module and package docstrings to silence linter warnings --- devwrangler/commands/__init__.py | 1 + devwrangler/managers/__init__.py | 1 + devwrangler/utilities/__init__.py | 1 + devwrangler/utilities/config.py | 1 + devwrangler/utilities/display.py | 1 + devwrangler/utilities/logging.py | 1 + devwrangler/utilities/shell.py | 1 + tests/commands/__init__.py | 1 + tests/managers/__init__.py | 1 + tests/utilities/__init__.py | 1 + tests/utilities/config.py | 1 + tests/utilities/display.py | 1 + tests/utilities/shell.py | 1 + 13 files changed, 13 insertions(+) create mode 100644 devwrangler/utilities/logging.py diff --git a/devwrangler/commands/__init__.py b/devwrangler/commands/__init__.py index e69de29..1f14095 100644 --- a/devwrangler/commands/__init__.py +++ b/devwrangler/commands/__init__.py @@ -0,0 +1 @@ +"""Devwrangler's CLI package: pydev.""" diff --git a/devwrangler/managers/__init__.py b/devwrangler/managers/__init__.py index 8155cf1..b4b99b9 100644 --- a/devwrangler/managers/__init__.py +++ b/devwrangler/managers/__init__.py @@ -1,2 +1,3 @@ +"""Managers exposed for use by devwrangler's CLI: pydev.""" from .conda import CondaManager from .venv import VenvManager diff --git a/devwrangler/utilities/__init__.py b/devwrangler/utilities/__init__.py index e69de29..b90be7b 100644 --- a/devwrangler/utilities/__init__.py +++ b/devwrangler/utilities/__init__.py @@ -0,0 +1 @@ +"""Functional utilities for devwrangler.""" diff --git a/devwrangler/utilities/config.py b/devwrangler/utilities/config.py index e69de29..8f4bc55 100644 --- a/devwrangler/utilities/config.py +++ b/devwrangler/utilities/config.py @@ -0,0 +1 @@ +"""Configuration utility functions for devwrangler.""" diff --git a/devwrangler/utilities/display.py b/devwrangler/utilities/display.py index e69de29..d4b96cd 100644 --- a/devwrangler/utilities/display.py +++ b/devwrangler/utilities/display.py @@ -0,0 +1 @@ +"""CLI and TUI display utilities for devwrangler.""" diff --git a/devwrangler/utilities/logging.py b/devwrangler/utilities/logging.py new file mode 100644 index 0000000..3ee77b8 --- /dev/null +++ b/devwrangler/utilities/logging.py @@ -0,0 +1 @@ +"""Application logging for devwrangler.""" diff --git a/devwrangler/utilities/shell.py b/devwrangler/utilities/shell.py index 1f6b4c7..e13e95b 100644 --- a/devwrangler/utilities/shell.py +++ b/devwrangler/utilities/shell.py @@ -1,3 +1,4 @@ +"""Shell command uitilities for devwrangler.""" import subprocess as sub import sys import warnings diff --git a/tests/commands/__init__.py b/tests/commands/__init__.py index e69de29..78ec069 100644 --- a/tests/commands/__init__.py +++ b/tests/commands/__init__.py @@ -0,0 +1 @@ +"""Test package for devwrangler.commands.""" diff --git a/tests/managers/__init__.py b/tests/managers/__init__.py index e69de29..16d6b2d 100644 --- a/tests/managers/__init__.py +++ b/tests/managers/__init__.py @@ -0,0 +1 @@ +"""Test package for devwrangler.managers.""" diff --git a/tests/utilities/__init__.py b/tests/utilities/__init__.py index e69de29..6efff2e 100644 --- a/tests/utilities/__init__.py +++ b/tests/utilities/__init__.py @@ -0,0 +1 @@ +"""Test package for devwrangler.utilities.""" diff --git a/tests/utilities/config.py b/tests/utilities/config.py index e69de29..53f7ab7 100644 --- a/tests/utilities/config.py +++ b/tests/utilities/config.py @@ -0,0 +1 @@ +"""Testing configuration and templating functionality for devwrangler.""" diff --git a/tests/utilities/display.py b/tests/utilities/display.py index e69de29..1e29a7f 100644 --- a/tests/utilities/display.py +++ b/tests/utilities/display.py @@ -0,0 +1 @@ +"""Testing the CLI and TUI display functions in devwrangler.utilities.display.""" diff --git a/tests/utilities/shell.py b/tests/utilities/shell.py index e69de29..73d45a6 100644 --- a/tests/utilities/shell.py +++ b/tests/utilities/shell.py @@ -0,0 +1 @@ +"""Testing shell related utilities for devwrangler.""" From 14003bc037ccec125ed43daaf662f026025ecb3c Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:21:40 -0600 Subject: [PATCH 09/24] Add tox-pyenv as a plugin/dependency for testing --- poetry.lock | 460 ++++++++++++++++++++++--------------------------- pyproject.toml | 3 +- 2 files changed, 209 insertions(+), 254 deletions(-) diff --git a/poetry.lock b/poetry.lock index 23fe339..65f78ba 100644 --- a/poetry.lock +++ b/poetry.lock @@ -19,36 +19,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.2.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [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"] +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"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] - -[[package]] -name = "backports.entry-points-selectable" -version = "1.1.0" -description = "Compatibility shim providing selectable entry points for older implementations" -category = "main" -optional = true -python-versions = ">=2.7" - -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"] +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"] [[package]] name = "black" -version = "21.10b0" +version = "21.12b0" description = "The uncompromising code formatter." category = "main" optional = true @@ -60,9 +45,8 @@ dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0,<1" platformdirs = ">=2" -regex = ">=2020.1.8" tomli = ">=0.2.6,<2.0.0" -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\""} +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\""}, {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, @@ -133,7 +117,7 @@ python-versions = ">=3.6.1" [[package]] name = "charset-normalizer" -version = "2.0.7" +version = "2.0.10" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = true @@ -175,7 +159,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "coverage" -version = "6.1.1" +version = "6.2" description = "Code coverage measurement for Python" category = "main" optional = true @@ -186,7 +170,7 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "35.0.0" +version = "36.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = true @@ -197,7 +181,7 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] sdist = ["setuptools_rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] @@ -213,7 +197,7 @@ python-versions = ">=3.6, <3.7" [[package]] name = "distlib" -version = "0.3.3" +version = "0.3.4" description = "Distribution utilities" category = "main" optional = true @@ -221,7 +205,7 @@ python-versions = "*" [[package]] name = "docutils" -version = "0.18" +version = "0.18.1" description = "Docutils -- Python Documentation Utilities" category = "main" optional = true @@ -229,7 +213,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "filelock" -version = "3.3.2" +version = "3.4.1" description = "A platform independent file lock." category = "main" optional = true @@ -281,14 +265,14 @@ dev = ["twine", "markdown", "flake8", "wheel"] [[package]] name = "identify" -version = "2.3.3" +version = "2.4.1" description = "File identification library for Python" category = "main" optional = true python-versions = ">=3.6.1" [package.extras] -license = ["editdistance-s"] +license = ["ukkonen"] [[package]] name = "idna" @@ -300,7 +284,7 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "4.8.1" +version = "4.8.3" description = "Read metadata from Python packages" category = "main" optional = false @@ -313,11 +297,11 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] name = "importlib-resources" -version = "5.4.0" +version = "5.2.3" description = "Read resources from Python packages" category = "main" optional = true @@ -340,7 +324,7 @@ python-versions = "*" [[package]] name = "isort" -version = "5.10.0" +version = "5.10.1" description = "A Python utility / library to sort Python imports." category = "main" optional = true @@ -366,7 +350,7 @@ trio = ["trio", "async-generator"] [[package]] name = "jinja2" -version = "3.0.2" +version = "3.0.3" description = "A very fast and expressive template engine." category = "main" optional = true @@ -380,7 +364,7 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "keyring" -version = "23.2.1" +version = "23.4.1" description = "Store and access your passwords safely." category = "main" optional = true @@ -393,19 +377,19 @@ pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_ SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [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)", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] [[package]] name = "markdown" -version = "3.3.4" +version = "3.3.6" description = "Python implementation of Markdown." category = "main" optional = true python-versions = ">=3.6" [package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} [package.extras] testing = ["coverage", "pyyaml"] @@ -557,14 +541,14 @@ python-versions = "*" [[package]] name = "packaging" -version = "21.2" +version = "21.3" description = "Core utilities for Python packages" category = "main" optional = true python-versions = ">=3.6" [package.dependencies] -pyparsing = ">=2.0.2,<3" +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" @@ -576,14 +560,14 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "pkginfo" -version = "1.7.1" +version = "1.8.2" description = "Query metadatdata from sdists / bdists / installed packages." category = "main" optional = true python-versions = "*" [package.extras] -testing = ["nose", "coverage"] +testing = ["coverage", "nose"] [[package]] name = "platformdirs" @@ -614,7 +598,7 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "2.15.0" +version = "2.16.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "main" optional = true @@ -624,7 +608,7 @@ python-versions = ">=3.6.1" cfgv = ">=2.0.0" identify = ">=1.0.0" importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -importlib-resources = {version = "*", markers = "python_version < \"3.7\""} +importlib-resources = {version = "<5.3", markers = "python_version < \"3.7\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" @@ -632,11 +616,11 @@ virtualenv = ">=20.0.8" [[package]] name = "py" -version = "1.10.0" +version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "main" optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycodestyle" @@ -648,7 +632,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = true @@ -678,7 +662,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.10.0" +version = "2.11.1" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false @@ -697,11 +681,14 @@ Markdown = ">=3.2" [[package]] name = "pyparsing" -version = "2.4.7" +version = "3.0.6" description = "Python parsing module" category = "main" optional = true -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = ">=3.6" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" @@ -798,11 +785,11 @@ pyyaml = "*" [[package]] name = "readme-renderer" -version = "30.0" +version = "32.0" description = "readme_renderer is a library for rendering \"readme\" descriptions for Warehouse" category = "main" optional = true -python-versions = "*" +python-versions = ">=3.6" [package.dependencies] bleach = ">=2.1.0" @@ -812,17 +799,9 @@ Pygments = ">=2.5.1" [package.extras] md = ["cmarkgfm (>=0.5.0,<0.7.0)"] -[[package]] -name = "regex" -version = "2021.11.2" -description = "Alternative regular expression module, to replace re." -category = "main" -optional = true -python-versions = "*" - [[package]] name = "requests" -version = "2.26.0" +version = "2.27.1" description = "Python HTTP for Humans." category = "main" optional = true @@ -862,7 +841,7 @@ idna2008 = ["idna"] [[package]] name = "rich" -version = "10.12.0" +version = "10.16.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "main" optional = false @@ -873,7 +852,7 @@ colorama = ">=0.4.0,<0.5.0" commonmark = ">=0.9.0,<0.10.0" dataclasses = {version = ">=0.7,<0.9", markers = "python_version < \"3.7\""} pygments = ">=2.6.0,<3.0.0" -typing-extensions = {version = ">=3.7.4,<4.0.0", markers = "python_version < \"3.8\""} +typing-extensions = {version = ">=3.7.4,<5.0", markers = "python_version < \"3.8\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] @@ -900,7 +879,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "snowballstemmer" -version = "2.1.0" +version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." category = "main" optional = true @@ -916,7 +895,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.2.2" +version = "1.2.3" description = "A lil' TOML parser" category = "main" optional = true @@ -924,7 +903,7 @@ python-versions = ">=3.6" [[package]] name = "tox" -version = "3.24.4" +version = "3.24.5" description = "tox is a generic virtualenv management and test command line tool" category = "main" optional = true @@ -943,7 +922,18 @@ virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2, [package.extras] docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] -testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)", "pytest-xdist (>=1.22.2)", "pathlib2 (>=2.3.3)"] +testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)", "psutil (>=5.6.1)", "pathlib2 (>=2.3.3)"] + +[[package]] +name = "tox-pyenv" +version = "1.1.0" +description = "tox plugin that makes tox use `pyenv which` to find python executables" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +tox = ">=2.0" [[package]] name = "tqdm" @@ -963,7 +953,7 @@ telegram = ["requests"] [[package]] name = "twine" -version = "3.5.0" +version = "3.7.1" description = "Collection of utilities for publishing packages on PyPI" category = "main" optional = true @@ -973,7 +963,7 @@ python-versions = ">=3.6" colorama = ">=0.4.3" importlib-metadata = ">=3.6" keyring = ">=15.1" -pkginfo = ">=1.4.2" +pkginfo = ">=1.8.1" readme-renderer = ">=21.0" requests = ">=2.20" requests-toolbelt = ">=0.8.0,<0.9.0 || >0.9.0" @@ -1028,14 +1018,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.10.0" +version = "20.13.0" description = "Virtual Python Environment builder" category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] -"backports.entry-points-selectable" = ">=1.0.4" distlib = ">=0.3.1,<1" filelock = ">=3.2,<4" importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -1079,14 +1068,14 @@ 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)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [extras] -dev = ["tox", "pre-commit", "virtualenv", "pip", "twine", "toml", "bump2version"] +dev = ["tox", "tox-pyenv", "pre-commit", "virtualenv", "pip", "twine", "toml", "bump2version"] doc = ["mkdocs", "mkdocs-include-markdown-plugin", "mkdocs-material", "mkdocstrings", "mkdocs-autorefs"] test = ["pytest", "black", "isort", "mypy", "flake8", "flake8-docstrings", "pytest-cov"] [metadata] lock-version = "1.1" python-versions = ">=3.6.2,<4.0" -content-hash = "8f57981225d02b791c1d569249172aecfa9170cfb5e45e9f4b3921758bed1c99" +content-hash = "0fff6b0188a06bffdab8f41cea7f3f9ca3bf14c8f4ff7a57e7e5f11a7748935b" [metadata.files] astunparse = [ @@ -1098,16 +1087,12 @@ atomicwrites = [ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] -"backports.entry-points-selectable" = [ - {file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"}, - {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] black = [ - {file = "black-21.10b0-py3-none-any.whl", hash = "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b"}, - {file = "black-21.10b0.tar.gz", hash = "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33"}, + {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, + {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, ] bleach = [ {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, @@ -1182,8 +1167,8 @@ cfgv = [ {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.7.tar.gz", hash = "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0"}, - {file = "charset_normalizer-2.0.7-py3-none-any.whl", hash = "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b"}, + {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"}, + {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"}, ] click = [ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, @@ -1198,90 +1183,91 @@ commonmark = [ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] coverage = [ - {file = "coverage-6.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:42a1fb5dee3355df90b635906bb99126faa7936d87dfc97eacc5293397618cb7"}, - {file = "coverage-6.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a00284dbfb53b42e35c7dd99fc0e26ef89b4a34efff68078ed29d03ccb28402a"}, - {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:51a441011a30d693e71dea198b2a6f53ba029afc39f8e2aeb5b77245c1b282ef"}, - {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e76f017b6d4140a038c5ff12be1581183d7874e41f1c0af58ecf07748d36a336"}, - {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7833c872718dc913f18e51ee97ea0dece61d9930893a58b20b3daf09bb1af6b6"}, - {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8186b5a4730c896cbe1e4b645bdc524e62d874351ae50e1db7c3e9f5dc81dc26"}, - {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bbca34dca5a2d60f81326d908d77313816fad23d11b6069031a3d6b8c97a54f9"}, - {file = "coverage-6.1.1-cp310-cp310-win32.whl", hash = "sha256:72bf437d54186d104388cbae73c9f2b0f8a3e11b6e8d7deb593bd14625c96026"}, - {file = "coverage-6.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:994ce5a7b3d20981b81d83618aa4882f955bfa573efdbef033d5632b58597ba9"}, - {file = "coverage-6.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ab6a0fe4c96f8058d41948ddf134420d3ef8c42d5508b5a341a440cce7a37a1d"}, - {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10ab138b153e4cc408b43792cb7f518f9ee02f4ff55cd1ab67ad6fd7e9905c7e"}, - {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7e083d32965d2eb6638a77e65b622be32a094fdc0250f28ce6039b0732fbcaa8"}, - {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:359a32515e94e398a5c0fa057e5887a42e647a9502d8e41165cf5cb8d3d1ca67"}, - {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:bf656cd74ff7b4ed7006cdb2a6728150aaad69c7242b42a2a532f77b63ea233f"}, - {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:dc5023be1c2a8b0a0ab5e31389e62c28b2453eb31dd069f4b8d1a0f9814d951a"}, - {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:557594a50bfe3fb0b1b57460f6789affe8850ad19c1acf2d14a3e12b2757d489"}, - {file = "coverage-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:9eb0a1923354e0fdd1c8a6f53f5db2e6180d670e2b587914bf2e79fa8acfd003"}, - {file = "coverage-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:04a92a6cf9afd99f9979c61348ec79725a9f9342fb45e63c889e33c04610d97b"}, - {file = "coverage-6.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:479228e1b798d3c246ac89b09897ee706c51b3e5f8f8d778067f38db73ccc717"}, - {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78287731e3601ea5ce9d6468c82d88a12ef8fe625d6b7bdec9b45d96c1ad6533"}, - {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c95257aa2ccf75d3d91d772060538d5fea7f625e48157f8ca44594f94d41cb33"}, - {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9ad5895938a894c368d49d8470fe9f519909e5ebc6b8f8ea5190bd0df6aa4271"}, - {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:326d944aad0189603733d646e8d4a7d952f7145684da973c463ec2eefe1387c2"}, - {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e7d5606b9240ed4def9cbdf35be4308047d11e858b9c88a6c26974758d6225ce"}, - {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:572f917267f363101eec375c109c9c1118037c7cc98041440b5eabda3185ac7b"}, - {file = "coverage-6.1.1-cp37-cp37m-win32.whl", hash = "sha256:35cd2230e1ed76df7d0081a997f0fe705be1f7d8696264eb508076e0d0b5a685"}, - {file = "coverage-6.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:65ad3ff837c89a229d626b8004f0ee32110f9bfdb6a88b76a80df36ccc60d926"}, - {file = "coverage-6.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:977ce557d79577a3dd510844904d5d968bfef9489f512be65e2882e1c6eed7d8"}, - {file = "coverage-6.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62512c0ec5d307f56d86504c58eace11c1bc2afcdf44e3ff20de8ca427ca1d0e"}, - {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2e5b9c17a56b8bf0c0a9477fcd30d357deb486e4e1b389ed154f608f18556c8a"}, - {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:666c6b32b69e56221ad1551d377f718ed00e6167c7a1b9257f780b105a101271"}, - {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fb2fa2f6506c03c48ca42e3fe5a692d7470d290c047ee6de7c0f3e5fa7639ac9"}, - {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f0f80e323a17af63eac6a9db0c9188c10f1fd815c3ab299727150cc0eb92c7a4"}, - {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:738e823a746841248b56f0f3bd6abf3b73af191d1fd65e4c723b9c456216f0ad"}, - {file = "coverage-6.1.1-cp38-cp38-win32.whl", hash = "sha256:8605add58e6a960729aa40c0fd9a20a55909dd9b586d3e8104cc7f45869e4c6b"}, - {file = "coverage-6.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:6e994003e719458420e14ffb43c08f4c14990e20d9e077cb5cad7a3e419bbb54"}, - {file = "coverage-6.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e3c4f5211394cd0bf6874ac5d29684a495f9c374919833dcfff0bd6d37f96201"}, - {file = "coverage-6.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e14bceb1f3ae8a14374be2b2d7bc12a59226872285f91d66d301e5f41705d4d6"}, - {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0147f7833c41927d84f5af9219d9b32f875c0689e5e74ac8ca3cb61e73a698f9"}, - {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1d0a1bce919de0dd8da5cff4e616b2d9e6ebf3bd1410ff645318c3dd615010a"}, - {file = "coverage-6.1.1-cp39-cp39-win32.whl", hash = "sha256:a11a2c019324fc111485e79d55907e7289e53d0031275a6c8daed30690bc50c0"}, - {file = "coverage-6.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4d8b453764b9b26b0dd2afb83086a7c3f9379134e340288d2a52f8a91592394b"}, - {file = "coverage-6.1.1-pp36-none-any.whl", hash = "sha256:3b270c6b48d3ff5a35deb3648028ba2643ad8434b07836782b1139cf9c66313f"}, - {file = "coverage-6.1.1-pp37-none-any.whl", hash = "sha256:ffa8fee2b1b9e60b531c4c27cf528d6b5d5da46b1730db1f4d6eee56ff282e07"}, - {file = "coverage-6.1.1-pp38-none-any.whl", hash = "sha256:4cd919057636f63ab299ccb86ea0e78b87812400c76abab245ca385f17d19fb5"}, - {file = "coverage-6.1.1.tar.gz", hash = "sha256:b8e4f15b672c9156c1154249a9c5746e86ac9ae9edc3799ee3afebc323d9d9e0"}, + {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"}, + {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"}, + {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"}, + {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"}, + {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"}, + {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"}, + {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"}, + {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"}, + {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"}, + {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"}, + {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"}, + {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"}, + {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"}, + {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"}, + {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"}, + {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"}, + {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"}, + {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"}, + {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"}, + {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, ] cryptography = [ - {file = "cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9"}, - {file = "cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6"}, - {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d"}, - {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6"}, - {file = "cryptography-35.0.0-cp36-abi3-win32.whl", hash = "sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8"}, - {file = "cryptography-35.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c"}, - {file = "cryptography-35.0.0.tar.gz", hash = "sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d"}, + {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, + {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"}, + {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"}, + {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"}, + {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"}, + {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"}, + {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"}, + {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"}, + {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"}, + {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"}, ] dataclasses = [ {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"}, ] distlib = [ - {file = "distlib-0.3.3-py2.py3-none-any.whl", hash = "sha256:c8b54e8454e5bf6237cc84c20e8264c3e991e824ef27e8f1e81049867d861e31"}, - {file = "distlib-0.3.3.zip", hash = "sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05"}, + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, ] docutils = [ - {file = "docutils-0.18-py2.py3-none-any.whl", hash = "sha256:a31688b2ea858517fa54293e5d5df06fbb875fb1f7e4c64529271b77781ca8fc"}, - {file = "docutils-0.18.tar.gz", hash = "sha256:c1d5dab2b11d16397406a282e53953fe495a46d69ae329f55aa98a5c4e3c5fbb"}, + {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, + {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, ] filelock = [ - {file = "filelock-3.3.2-py3-none-any.whl", hash = "sha256:bb2a1c717df74c48a2d00ed625e5a66f8572a3a30baacb7657add1d7bac4097b"}, - {file = "filelock-3.3.2.tar.gz", hash = "sha256:7afc856f74fa7006a289fd10fa840e1eebd8bbff6bffb69c26c54a0512ea8cf8"}, + {file = "filelock-3.4.1-py3-none-any.whl", hash = "sha256:a4bc51381e01502a30e9f06dd4fa19a1712eab852b6fb0f84fd7cce0793d8ca3"}, + {file = "filelock-3.4.1.tar.gz", hash = "sha256:0f12f552b42b5bf60dba233710bf71337d35494fc8bdd4fd6d9f6d082ad45e06"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, @@ -1296,44 +1282,44 @@ ghp-import = [ {file = "ghp_import-2.0.2-py3-none-any.whl", hash = "sha256:5f8962b30b20652cdffa9c5a9812f7de6bcb56ec475acac579807719bf242c46"}, ] identify = [ - {file = "identify-2.3.3-py2.py3-none-any.whl", hash = "sha256:ffab539d9121b386ffdea84628ff3eefda15f520f392ce11b393b0a909632cdf"}, - {file = "identify-2.3.3.tar.gz", hash = "sha256:b9ffbeb7ed87e96ce017c66b80ca04fda3adbceb5c74e54fc7d99281d27d0859"}, + {file = "identify-2.4.1-py2.py3-none-any.whl", hash = "sha256:0192893ff68b03d37fed553e261d4a22f94ea974093aefb33b29df2ff35fed3c"}, + {file = "identify-2.4.1.tar.gz", hash = "sha256:64d4885e539f505dd8ffb5e93c142a1db45480452b1594cacd3e91dca9a984e9"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, + {file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"}, + {file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"}, ] importlib-resources = [ - {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"}, - {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"}, + {file = "importlib_resources-5.2.3-py3-none-any.whl", hash = "sha256:ae35ed1cfe8c0d6c1a53ecd168167f01fa93b893d51a62cdf23aea044c67211b"}, + {file = "importlib_resources-5.2.3.tar.gz", hash = "sha256:203d70dda34cfbfbb42324a8d4211196e7d3e858de21a5eb68c6d1cdd99e4e98"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] isort = [ - {file = "isort-5.10.0-py3-none-any.whl", hash = "sha256:1a18ccace2ed8910bd9458b74a3ecbafd7b2f581301b0ab65cfdd4338272d76f"}, - {file = "isort-5.10.0.tar.gz", hash = "sha256:e52ff6d38012b131628cf0f26c51e7bd3a7c81592eefe3ac71411e692f1b9345"}, + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] jeepney = [ {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"}, {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"}, ] jinja2 = [ - {file = "Jinja2-3.0.2-py3-none-any.whl", hash = "sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c"}, - {file = "Jinja2-3.0.2.tar.gz", hash = "sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45"}, + {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, + {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, ] keyring = [ - {file = "keyring-23.2.1-py3-none-any.whl", hash = "sha256:bd2145a237ed70c8ce72978b497619ddfcae640b6dcf494402d5143e37755c6e"}, - {file = "keyring-23.2.1.tar.gz", hash = "sha256:6334aee6073db2fb1f30892697b1730105b5e9a77ce7e61fca6b435225493efe"}, + {file = "keyring-23.4.1-py3-none-any.whl", hash = "sha256:17e49fb0d6883c2b4445359434dba95aad84aabb29bbff044ad0ed7100232eca"}, + {file = "keyring-23.4.1.tar.gz", hash = "sha256:89cbd74d4683ed164c8082fb38619341097741323b3786905c6dac04d6915a55"}, ] markdown = [ - {file = "Markdown-3.3.4-py3-none-any.whl", hash = "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c"}, - {file = "Markdown-3.3.4.tar.gz", hash = "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49"}, + {file = "Markdown-3.3.6-py3-none-any.whl", hash = "sha256:9923332318f843411e9932237530df53162e29dc7a4e2b91e35764583c46c9a3"}, + {file = "Markdown-3.3.6.tar.gz", hash = "sha256:76df8ae32294ec39dcf89340382882dfa12975f87f45c3ed1ecdb1e8cefc7006"}, ] markupsafe = [ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, @@ -1341,6 +1327,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, @@ -1352,6 +1341,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1363,6 +1355,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, @@ -1375,6 +1370,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1387,6 +1385,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1457,16 +1458,16 @@ nodeenv = [ {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, ] packaging = [ - {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, - {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {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"}, ] pkginfo = [ - {file = "pkginfo-1.7.1-py2.py3-none-any.whl", hash = "sha256:37ecd857b47e5f55949c41ed061eb51a0bee97a87c969219d144c0e023982779"}, - {file = "pkginfo-1.7.1.tar.gz", hash = "sha256:e7432f81d08adec7297633191bbf0bd47faf13cd8724c3a13250e51d542635bd"}, + {file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"}, + {file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"}, ] platformdirs = [ {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, @@ -1477,20 +1478,20 @@ pluggy = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] pre-commit = [ - {file = "pre_commit-2.15.0-py2.py3-none-any.whl", hash = "sha256:a4ed01000afcb484d9eb8d504272e642c4c4099bbad3a6b27e519bd6a3e928a6"}, - {file = "pre_commit-2.15.0.tar.gz", hash = "sha256:3c25add78dbdfb6a28a651780d5c311ac40dd17f160eb3954a0c59da40a505a7"}, + {file = "pre_commit-2.16.0-py2.py3-none-any.whl", hash = "sha256:758d1dc9b62c2ed8881585c254976d66eae0889919ab9b859064fc2fe3c7743e"}, + {file = "pre_commit-2.16.0.tar.gz", hash = "sha256:fe9897cac830aa7164dbd02a4e7b90cae49630451ce88464bca73db486ba9f65"}, ] py = [ - {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, - {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pycodestyle = [ {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pydocstyle = [ {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, @@ -1501,16 +1502,16 @@ pyflakes = [ {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] pygments = [ - {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, - {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, + {file = "Pygments-2.11.1-py3-none-any.whl", hash = "sha256:9135c1af61eec0f650cd1ea1ed8ce298e54d56bcd8cc2ef46edd7702c171337c"}, + {file = "Pygments-2.11.1.tar.gz", hash = "sha256:59b895e326f0fb0d733fd28c6839bd18ad0687ba20efc26d4277fd1d30b971f4"}, ] pymdown-extensions = [ {file = "pymdown-extensions-8.2.tar.gz", hash = "sha256:b6daa94aad9e1310f9c64c8b1f01e4ce82937ab7eb53bfc92876a97aca02a6f4"}, {file = "pymdown_extensions-8.2-py3-none-any.whl", hash = "sha256:141452d8ed61165518f2c923454bf054866b85cf466feedb0eb68f04acdc2560"}, ] pyparsing = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, + {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, + {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, ] pytest = [ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, @@ -1572,63 +1573,12 @@ pyyaml-env-tag = [ {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, ] readme-renderer = [ - {file = "readme_renderer-30.0-py2.py3-none-any.whl", hash = "sha256:3286806450d9961d6e3b5f8a59f77e61503799aca5155c8d8d40359b4e1e1adc"}, - {file = "readme_renderer-30.0.tar.gz", hash = "sha256:8299700d7a910c304072a7601eafada6712a5b011a20139417e1b1e9f04645d8"}, -] -regex = [ - {file = "regex-2021.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:897c539f0f3b2c3a715be651322bef2167de1cdc276b3f370ae81a3bda62df71"}, - {file = "regex-2021.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:886f459db10c0f9d17c87d6594e77be915f18d343ee138e68d259eb385f044a8"}, - {file = "regex-2021.11.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:075b0fdbaea81afcac5a39a0d1bb91de887dd0d93bf692a5dd69c430e7fc58cb"}, - {file = "regex-2021.11.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6238d30dcff141de076344cf7f52468de61729c2f70d776fce12f55fe8df790"}, - {file = "regex-2021.11.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fab29411d75c2eb48070020a40f80255936d7c31357b086e5931c107d48306e"}, - {file = "regex-2021.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0148988af0182a0a4e5020e7c168014f2c55a16d11179610f7883dd48ac0ebe"}, - {file = "regex-2021.11.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be30cd315db0168063a1755fa20a31119da91afa51da2907553493516e165640"}, - {file = "regex-2021.11.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e9cec3a62d146e8e122d159ab93ac32c988e2ec0dcb1e18e9e53ff2da4fbd30c"}, - {file = "regex-2021.11.2-cp310-cp310-win32.whl", hash = "sha256:41c66bd6750237a8ed23028a6c9173dc0c92dc24c473e771d3bfb9ee817700c3"}, - {file = "regex-2021.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:0075fe4e2c2720a685fef0f863edd67740ff78c342cf20b2a79bc19388edf5db"}, - {file = "regex-2021.11.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0ed3465acf8c7c10aa2e0f3d9671da410ead63b38a77283ef464cbb64275df58"}, - {file = "regex-2021.11.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab1fea8832976ad0bebb11f652b692c328043057d35e9ebc78ab0a7a30cf9a70"}, - {file = "regex-2021.11.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cb1e44d860345ab5d4f533b6c37565a22f403277f44c4d2d5e06c325da959883"}, - {file = "regex-2021.11.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9486ebda015913909bc28763c6b92fcc3b5e5a67dee4674bceed112109f5dfb8"}, - {file = "regex-2021.11.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20605bfad484e1341b2cbfea0708e4b211d233716604846baa54b94821f487cb"}, - {file = "regex-2021.11.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f20f9f430c33597887ba9bd76635476928e76cad2981643ca8be277b8e97aa96"}, - {file = "regex-2021.11.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1d85ca137756d62c8138c971453cafe64741adad1f6a7e63a22a5a8abdbd19fa"}, - {file = "regex-2021.11.2-cp36-cp36m-win32.whl", hash = "sha256:af23b9ca9a874ef0ec20e44467b8edd556c37b0f46f93abfa93752ea7c0e8d1e"}, - {file = "regex-2021.11.2-cp36-cp36m-win_amd64.whl", hash = "sha256:070336382ca92c16c45b4066c4ba9fa83fb0bd13d5553a82e07d344df8d58a84"}, - {file = "regex-2021.11.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ef4e53e2fdc997d91f5b682f81f7dc9661db9a437acce28745d765d251902d85"}, - {file = "regex-2021.11.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35ed5714467fc606551db26f80ee5d6aa1f01185586a7bccd96f179c4b974a11"}, - {file = "regex-2021.11.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee36d5113b6506b97f45f2e8447cb9af146e60e3f527d93013d19f6d0405f3b"}, - {file = "regex-2021.11.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4fba661a4966adbd2c3c08d3caad6822ecb6878f5456588e2475ae23a6e47929"}, - {file = "regex-2021.11.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77f9d16f7970791f17ecce7e7f101548314ed1ee2583d4268601f30af3170856"}, - {file = "regex-2021.11.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6a28e87ba69f3a4f30d775b179aac55be1ce59f55799328a0d9b6df8f16b39d"}, - {file = "regex-2021.11.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9267e4fba27e6dd1008c4f2983cc548c98b4be4444e3e342db11296c0f45512f"}, - {file = "regex-2021.11.2-cp37-cp37m-win32.whl", hash = "sha256:d4bfe3bc3976ccaeb4ae32f51e631964e2f0e85b2b752721b7a02de5ce3b7f27"}, - {file = "regex-2021.11.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2bb7cae741de1aa03e3dd3a7d98c304871eb155921ca1f0d7cc11f5aade913fd"}, - {file = "regex-2021.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:23f93e74409c210de4de270d4bf88fb8ab736a7400f74210df63a93728cf70d6"}, - {file = "regex-2021.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d8ee91e1c295beb5c132ebd78616814de26fedba6aa8687ea460c7f5eb289b72"}, - {file = "regex-2021.11.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e3ff69ab203b54ce5c480c3ccbe959394ea5beef6bd5ad1785457df7acea92e"}, - {file = "regex-2021.11.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e3c00cb5c71da655e1e5161481455479b613d500dd1bd252aa01df4f037c641f"}, - {file = "regex-2021.11.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4abf35e16f4b639daaf05a2602c1b1d47370e01babf9821306aa138924e3fe92"}, - {file = "regex-2021.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb11c982a849dc22782210b01d0c1b98eb3696ce655d58a54180774e4880ac66"}, - {file = "regex-2021.11.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e3755e0f070bc31567dfe447a02011bfa8444239b3e9e5cca6773a22133839"}, - {file = "regex-2021.11.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0621c90f28d17260b41838b22c81a79ff436141b322960eb49c7b3f91d1cbab6"}, - {file = "regex-2021.11.2-cp38-cp38-win32.whl", hash = "sha256:8fbe1768feafd3d0156556677b8ff234c7bf94a8110e906b2d73506f577a3269"}, - {file = "regex-2021.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:f9ee98d658a146cb6507be720a0ce1b44f2abef8fb43c2859791d91aace17cd5"}, - {file = "regex-2021.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3794cea825f101fe0df9af8a00f9fad8e119c91e39a28636b95ee2b45b6c2e5"}, - {file = "regex-2021.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3576e173e7b4f88f683b4de7db0c2af1b209bb48b2bf1c827a6f3564fad59a97"}, - {file = "regex-2021.11.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48b4f4810117a9072a5aa70f7fea5f86fa9efbe9a798312e0a05044bd707cc33"}, - {file = "regex-2021.11.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f5930d334c2f607711d54761956aedf8137f83f1b764b9640be21d25a976f3a4"}, - {file = "regex-2021.11.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:956187ff49db7014ceb31e88fcacf4cf63371e6e44d209cf8816cd4a2d61e11a"}, - {file = "regex-2021.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17e095f7f96a4b9f24b93c2c915f31a5201a6316618d919b0593afb070a5270e"}, - {file = "regex-2021.11.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a56735c35a3704603d9d7b243ee06139f0837bcac2171d9ba1d638ce1df0742a"}, - {file = "regex-2021.11.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adf35d88d9cffc202e6046e4c32e1e11a1d0238b2fcf095c94f109e510ececea"}, - {file = "regex-2021.11.2-cp39-cp39-win32.whl", hash = "sha256:30fe317332de0e50195665bc61a27d46e903d682f94042c36b3f88cb84bd7958"}, - {file = "regex-2021.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:85289c25f658e3260b00178757c87f033f3d4b3e40aa4abdd4dc875ff11a94fb"}, - {file = "regex-2021.11.2.tar.gz", hash = "sha256:5e85dcfc5d0f374955015ae12c08365b565c6f1eaf36dd182476a4d8e5a1cdb7"}, + {file = "readme_renderer-32.0-py3-none-any.whl", hash = "sha256:a50a0f2123a4c1145ac6f420e1a348aafefcc9211c846e3d51df05fe3d865b7d"}, + {file = "readme_renderer-32.0.tar.gz", hash = "sha256:b512beafa6798260c7d5af3e1b1f097e58bfcd9a575da7c4ddd5e037490a5b85"}, ] requests = [ - {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, - {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, ] requests-toolbelt = [ {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, @@ -1639,8 +1589,8 @@ rfc3986 = [ {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, ] rich = [ - {file = "rich-10.12.0-py3-none-any.whl", hash = "sha256:c30d6808d1cd3defd56a7bd2d587d13e53b5f55de6cf587f035bcbb56bc3f37b"}, - {file = "rich-10.12.0.tar.gz", hash = "sha256:83fb3eff778beec3c55201455c17cccde1ccdf66d5b4dade8ef28f56b50c4bd4"}, + {file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"}, + {file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"}, ] secretstorage = [ {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, @@ -1651,28 +1601,32 @@ six = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] snowballstemmer = [ - {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, - {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ - {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, - {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, + {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, + {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, ] tox = [ - {file = "tox-3.24.4-py2.py3-none-any.whl", hash = "sha256:5e274227a53dc9ef856767c21867377ba395992549f02ce55eb549f9fb9a8d10"}, - {file = "tox-3.24.4.tar.gz", hash = "sha256:c30b57fa2477f1fb7c36aa1d83292d5c2336cd0018119e1b1c17340e2c2708ca"}, + {file = "tox-3.24.5-py2.py3-none-any.whl", hash = "sha256:be3362472a33094bce26727f5f771ca0facf6dafa217f65875314e9a6600c95c"}, + {file = "tox-3.24.5.tar.gz", hash = "sha256:67e0e32c90e278251fea45b696d0fef3879089ccbe979b0c556d35d5a70e2993"}, +] +tox-pyenv = [ + {file = "tox-pyenv-1.1.0.tar.gz", hash = "sha256:916c2213577aec0b3b5452c5bfb32fd077f3a3196f50a81ad57d7ef3fc2599e4"}, + {file = "tox_pyenv-1.1.0-py2.py3-none-any.whl", hash = "sha256:e470c18af115fe52eeff95e7e3cdd0793613eca19709966fc2724b79d55246cb"}, ] tqdm = [ {file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"}, {file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"}, ] twine = [ - {file = "twine-3.5.0-py3-none-any.whl", hash = "sha256:3725b79a6f1cfe84a134544ae1894706e60719ab28547cb6c6de781b9f72706d"}, - {file = "twine-3.5.0.tar.gz", hash = "sha256:218c42324121d4417cbcbbda59c623b8acc4becfce3daa545e6b6dd48bd21385"}, + {file = "twine-3.7.1-py3-none-any.whl", hash = "sha256:8c120845fc05270f9ee3e9d7ebbed29ea840e41f48cd059e04733f7e1d401345"}, + {file = "twine-3.7.1.tar.gz", hash = "sha256:28460a3db6b4532bde6a5db6755cf2dce6c5020bada8a641bb2c5c7a9b1f35b8"}, ] typed-ast = [ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, @@ -1720,8 +1674,8 @@ urllib3 = [ {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, ] virtualenv = [ - {file = "virtualenv-20.10.0-py2.py3-none-any.whl", hash = "sha256:4b02e52a624336eece99c96e3ab7111f469c24ba226a53ec474e8e787b365814"}, - {file = "virtualenv-20.10.0.tar.gz", hash = "sha256:576d05b46eace16a9c348085f7d0dc8ef28713a2cabaa1cf0aea41e8f12c9218"}, + {file = "virtualenv-20.13.0-py2.py3-none-any.whl", hash = "sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09"}, + {file = "virtualenv-20.13.0.tar.gz", hash = "sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"}, ] watchdog = [ {file = "watchdog-2.1.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9693f35162dc6208d10b10ddf0458cc09ad70c30ba689d9206e02cd836ce28a3"}, diff --git a/pyproject.toml b/pyproject.toml index 8d6fbd6..ddaae86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ mypy = {version = "^0.900", optional = true} pytest = { version = "^6.2.4", optional = true} pytest-cov = { version = "^2.12.0", optional = true} tox = { version = "^3.20.1", optional = true} +tox-pyenv = { version = "^1.1.0", optional = true } virtualenv = { version = "^20.2.2", optional = true} pip = { version = "^20.3.1", optional = true} mkdocs = { version = "^1.2.3", optional = true} @@ -64,7 +65,7 @@ test = [ "pytest-cov" ] -dev = ["tox", "pre-commit", "virtualenv", "pip", "twine", "toml", "bump2version"] +dev = ["tox", "tox-pyenv", "pre-commit", "virtualenv", "pip", "twine", "toml", "bump2version"] doc = [ "mkdocs", From 9b5ee1e69aef0aabd7ae4797f4a9e93262e4b817 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:23:21 -0600 Subject: [PATCH 10/24] Configure tox-pyenv with a conda specific test environment This may not be necessary, it appears that all of the 'local' pyenv versions are available in all testenvs. However, in an ideal world, this would allow us to run the tests associated with a specific manager in a specific environment only. --- setup.cfg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 683de6b..71867f1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,8 @@ exclude_lines = [tox:tox] isolated_build = true -envlist = py37, py38, py39, py310, format, lint, build +envlist = py37, py38, py39, py310, miniconda3, format, lint, build +tox_pyenv_fallback=False [gh-actions] python = @@ -48,6 +49,7 @@ python = 3.9: py39 3.8: py38 3.7: py37 + conda: miniconda3 [testenv] allowlist_externals = pytest From 19eb04b2b8f491117802ca00ed44a68a936fb676 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:25:41 -0600 Subject: [PATCH 11/24] Change the kwarg on install_dependencies from 'quiet' to 'verbose' As I was starting to work with and reason about the API for devwrangler it occurred to me that we want things to be quiet by default. With that in mind, it made more sense to make verbose logging *opt-in* rather than allowing the 'quiet' flag to be *opt-out*. --- devwrangler/managers/base.py | 2 +- devwrangler/managers/conda.py | 2 +- devwrangler/managers/venv.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/devwrangler/managers/base.py b/devwrangler/managers/base.py index 01c6d1d..0d58f0c 100644 --- a/devwrangler/managers/base.py +++ b/devwrangler/managers/base.py @@ -30,6 +30,6 @@ def create(self): pass @abc.abstractmethod - def install_dependencies(self, quiet: bool = True): + def install_dependencies(self, verbose: bool = False): """Install dependencies into a created environment.""" pass diff --git a/devwrangler/managers/conda.py b/devwrangler/managers/conda.py index f01eec1..1a9bf2e 100644 --- a/devwrangler/managers/conda.py +++ b/devwrangler/managers/conda.py @@ -13,7 +13,7 @@ def create(self): self.cmd(["conda", "env", "create", "-p", str(self.venv_path)]) - def install_dependencies(self, quiet: bool = True): + def install_dependencies(self, verbose: bool = False): """Install dependencies from conda's environment.yml file in the root of your project.""" if not sh.which("conda"): raise FileNotFoundError("No conda executable found in your $PATH") diff --git a/devwrangler/managers/venv.py b/devwrangler/managers/venv.py index 90e5e3a..7295f8d 100644 --- a/devwrangler/managers/venv.py +++ b/devwrangler/managers/venv.py @@ -15,7 +15,7 @@ def create(self): prompt=self.venv_path.parent.name, ) - def install_dependencies(self, quiet: bool = True): + def install_dependencies(self, verbose: bool = False): """Install environment dependencies.""" minimal_dependencies = [ str(self.prefix), From 39350adb708999937c5e17960b5e90ba4635b1e8 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:26:49 -0600 Subject: [PATCH 12/24] Update local variables in VenvManager to match CondaManager style --- devwrangler/managers/venv.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/devwrangler/managers/venv.py b/devwrangler/managers/venv.py index 7295f8d..9be69c8 100644 --- a/devwrangler/managers/venv.py +++ b/devwrangler/managers/venv.py @@ -17,7 +17,7 @@ def create(self): def install_dependencies(self, verbose: bool = False): """Install environment dependencies.""" - minimal_dependencies = [ + PIP_CMD = [ str(self.prefix), "-m", "pip", @@ -27,6 +27,7 @@ def install_dependencies(self, verbose: bool = False): "setuptools", ] - if quiet: - minimal_dependencies.append("-qqq") - self.cmd(minimal_dependencies) + if not verbose: + PIP_CMD.append("-qqq") + + self.cmd(PIP_CMD) From 6b1550fba4353b2472e3942fe2318b23be657999 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:28:40 -0600 Subject: [PATCH 13/24] Remove custom pytest fixture in favor of tmp_path It turns out that the old tmpdir fixture actually had a replacement using the pathlib.Path object just like I wanted, and I didn't have to create that fixture on my own. With that in mind, I can simplify things considerably. --- tests/managers/test_venv.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/managers/test_venv.py b/tests/managers/test_venv.py index 5d638e0..3f0e7be 100644 --- a/tests/managers/test_venv.py +++ b/tests/managers/test_venv.py @@ -7,16 +7,10 @@ from devwrangler.managers import VenvManager -@pytest.fixture -def tmp_venv_path(tmpdir) -> Path: - """Return a temporary directory to generate a virtual environment from.""" - return Path(tmpdir) - - -def test_venv_creation(tmp_venv_path: Path): +def test_venv_creation(tmp_path: Path): """Test environment creation with venv.""" # Arrange - venv = VenvManager(tmp_venv_path) + venv = VenvManager(tmp_path) assert not venv.venv_path.exists() assert not venv.prefix.exists() @@ -30,13 +24,13 @@ def test_venv_creation(tmp_venv_path: Path): @pytest.mark.skip(reason="Currently unable to install more than minimal dependencies") -def test_dependency_install(tmp_venv_path: Path): +def test_dependency_install(tmp_path: Path): """Test dependency installation.""" # Arrange - tmp_venv = VenvManager(tmp_venv_path) + tmp_venv = VenvManager(tmp_path) tmp_venv.create() - req_path = tmp_venv_path / "requirements.txt" + req_path = tmp_path / "requirements.txt" with open(req_path, "w") as req_file: req_file.write("cowsay\n") From fb9d5dfd0cd5b3871c1638ce64f777363769a30f Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:29:12 -0600 Subject: [PATCH 14/24] Make docstring for the devwrangler.managers.venv module more consistent --- devwrangler/managers/venv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devwrangler/managers/venv.py b/devwrangler/managers/venv.py index 9be69c8..d5622d6 100644 --- a/devwrangler/managers/venv.py +++ b/devwrangler/managers/venv.py @@ -1,4 +1,4 @@ -"""Implement a venv specific manager for those who prefer to use venv.""" +"""A wrapper for creating a venv-based dev environment.""" import venv from .base import BaseManager From 48e817d29839937407213e9fd4fd1f8fc1b6c053 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:31:22 -0600 Subject: [PATCH 15/24] Write initial test for the devwrangler.managers.conda:CondaManager class Ultimately, this basic check ensures that the manager itself: 1. Works (i.e. actually creates a conda environment where we expect it to) 2. Provides access to a default Python once the environment is created --- tests/managers/test_conda.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/managers/test_conda.py b/tests/managers/test_conda.py index e69de29..51eca89 100644 --- a/tests/managers/test_conda.py +++ b/tests/managers/test_conda.py @@ -0,0 +1,28 @@ +"""Tests for the devwrangler.managers.conda module.""" + +import os +import shutil +from pathlib import Path + +import pytest + +from devwrangler.managers import CondaManager + +if not shutil.which('conda'): + pytest.skip("skipping conda-only tests", allow_module_level=True) + + +def test_conda_blank_env_create(tmp_path: Path): + """Test Conda environment creation in empty folder.""" + # Arrange + env = CondaManager(tmp_path) + assert not env.venv_path.exists() + assert not env.prefix.exists() + + # Act + env.create() + + # Assert + assert Path(env.venv_path).exists() + assert Path(env.prefix).exists() + assert os.access(env.prefix, mode=os.X_OK) From 0f1e09d9f0373b3c6c346428894aede8b942e3da Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:32:07 -0600 Subject: [PATCH 16/24] Implement the Anaconda based environment manager --- devwrangler/managers/conda.py | 44 ++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/devwrangler/managers/conda.py b/devwrangler/managers/conda.py index 1a9bf2e..06fa92e 100644 --- a/devwrangler/managers/conda.py +++ b/devwrangler/managers/conda.py @@ -1,4 +1,6 @@ +"""A wrapper for creating an Anaconda-based dev environment.""" import shutil as sh +from pathlib import Path from .base import BaseManager @@ -11,20 +13,40 @@ def create(self): if not sh.which("conda"): raise FileNotFoundError("No conda executable found in your $PATH") - self.cmd(["conda", "env", "create", "-p", str(self.venv_path)]) - - def install_dependencies(self, verbose: bool = False): - """Install dependencies from conda's environment.yml file in the root of your project.""" - if not sh.which("conda"): - raise FileNotFoundError("No conda executable found in your $PATH") self.cmd( [ "conda", - "env", - "update", + "create", + "-y", + "--quiet", "--prefix", - str(self.venv_path.parent), - "--file" "environment.yml", - "--prune", + str(self.venv_path), + "python", ] ) + + def install_dependencies(self, verbose: bool = False): + """Install dependencies from conda's environment.yml file in the root of your project.""" + if not sh.which("conda"): + raise FileNotFoundError("No conda executable found in your $PATH") + + if not (Path.cwd() / "environment.yml").exists(): + raise FileNotFoundError( + "No environment.yml file round in the project directory" + ) + + CONDA_CMD = [ + "conda", + "env", + "update", + "--prefix", + str(self.venv_path), + "--file", + "environment.yml", + "--prune", + ] + + if not verbose: + CONDA_CMD.append("--quiet") + + self.cmd(CONDA_CMD) From f89fcaf10f7b596295d7752ff561a008aca80589 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 10:01:10 -0600 Subject: [PATCH 17/24] Configure logging for devwrangler and pydev --- devwrangler/utilities/logging.py | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/devwrangler/utilities/logging.py b/devwrangler/utilities/logging.py index 3ee77b8..36ca62f 100644 --- a/devwrangler/utilities/logging.py +++ b/devwrangler/utilities/logging.py @@ -1 +1,36 @@ """Application logging for devwrangler.""" +import logging +import os +from logging.config import dictConfig + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': True, + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' + }, + 'simple': {'format': '%(message)s'}, + }, + 'filters': {}, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'formatter': 'simple', + 'class': "rich.logging.RichHandler", + 'rich_tracebacks': True, + 'markup': True, + 'tracebacks_show_locals': True, + }, + }, + 'loggers': { + 'devwrangler': { + 'handlers': ['console'], + 'propagate': True, + 'level': os.environ.setdefault("DW_LOG_LEVEL", "WARNING"), + }, + }, +} + +LOG = logging.getLogger('devwrangler') +dictConfig(LOGGING) From 1f6183e6d32bdaf6d1da9c0469e64fa0dc90e854 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:10:29 -0600 Subject: [PATCH 18/24] Refactor shell:run_command utility for better logging and flexibility --- devwrangler/managers/conda.py | 2 +- devwrangler/managers/venv.py | 2 +- devwrangler/utilities/shell.py | 28 +++++++++++++++++++--------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/devwrangler/managers/conda.py b/devwrangler/managers/conda.py index 06fa92e..1eca407 100644 --- a/devwrangler/managers/conda.py +++ b/devwrangler/managers/conda.py @@ -49,4 +49,4 @@ def install_dependencies(self, verbose: bool = False): if not verbose: CONDA_CMD.append("--quiet") - self.cmd(CONDA_CMD) + self.cmd(CONDA_CMD, critical=True) diff --git a/devwrangler/managers/venv.py b/devwrangler/managers/venv.py index d5622d6..a4ad766 100644 --- a/devwrangler/managers/venv.py +++ b/devwrangler/managers/venv.py @@ -30,4 +30,4 @@ def install_dependencies(self, verbose: bool = False): if not verbose: PIP_CMD.append("-qqq") - self.cmd(PIP_CMD) + self.cmd(PIP_CMD, critical=True) diff --git a/devwrangler/utilities/shell.py b/devwrangler/utilities/shell.py index e13e95b..170ea08 100644 --- a/devwrangler/utilities/shell.py +++ b/devwrangler/utilities/shell.py @@ -1,26 +1,36 @@ """Shell command uitilities for devwrangler.""" import subprocess as sub import sys -import warnings from typing import Sequence +from .logging import LOG -def run_command(command: Sequence[str]): + +def run_command(command: str | Sequence[str], critical: bool = False, **kwargs): """Attempt to run a specific command in the users's shell. - >>> run_command(['ls']) + >>> run_command('ls') """ try: - sub.run( + command_process = sub.run( command, + shell=True, check=True, encoding="utf-8", + capture_output=True, + **kwargs, ) - except sub.CalledProcessError: - warnings.warn( + LOG.critical("Are we getting here?") + LOG.debug(command_process.stdout) + except sub.CalledProcessError as err: + LOG.error( ( - f"Problem encountered when running `{' '.join(command)}`\n\n" - f"Review the output above to manually debug the issue" + f"Problem encountered when running " + f"`{' '.join(command) if type(command)=='list' else command}`" ) ) - sys.exit(1) + LOG.error(err.output) + + if critical: + LOG.critical("Required command failed, exiting with status code 1") + sys.exit(1) From 5a938bbbb4a300f13b165ebad1d3a76949c645e7 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Fri, 14 Jan 2022 12:52:46 -0600 Subject: [PATCH 19/24] Add current working directory as default work_dir in Base manager --- devwrangler/managers/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devwrangler/managers/base.py b/devwrangler/managers/base.py index 0d58f0c..6ee9bf1 100644 --- a/devwrangler/managers/base.py +++ b/devwrangler/managers/base.py @@ -9,7 +9,7 @@ class BaseManager(abc.ABC): """A standard API for various environment managers.""" - def __init__(self, work_dir: Path): + def __init__(self, work_dir: Path = Path.cwd()): """Initialize a virtual environment model with venv.""" self.prefixes = { 'windows': 'Scripts/python.exe', From eb0e7622e8dfa95f6069f10303f7612da89a259c Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Fri, 14 Jan 2022 12:54:26 -0600 Subject: [PATCH 20/24] Add display utilities using Rich --- devwrangler/utilities/display.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/devwrangler/utilities/display.py b/devwrangler/utilities/display.py index d4b96cd..85cef8a 100644 --- a/devwrangler/utilities/display.py +++ b/devwrangler/utilities/display.py @@ -1 +1,5 @@ """CLI and TUI display utilities for devwrangler.""" +from rich.console import Console + +STD_OUT = Console() +STD_ERR = Console(stderr=True, style="bold red") From eb2dcd9334d4df96de4e521d5a11ea334c8fc563 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:41:17 -0600 Subject: [PATCH 21/24] Create first pass on new CLI api --- devwrangler/commands/__init__.py | 24 +++++++++++++++++ devwrangler/commands/configure.py | 42 ++++++++++++++++++++++++++++++ devwrangler/commands/create.py | 43 +++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 devwrangler/commands/configure.py create mode 100644 devwrangler/commands/create.py diff --git a/devwrangler/commands/__init__.py b/devwrangler/commands/__init__.py index 1f14095..38d0656 100644 --- a/devwrangler/commands/__init__.py +++ b/devwrangler/commands/__init__.py @@ -1 +1,25 @@ """Devwrangler's CLI package: pydev.""" +import typer + +from devwrangler.commands.configure import config_app +from devwrangler.commands.create import create_app +from devwrangler.utilities.display import STD_ERR, STD_OUT + +app = typer.Typer(name="devwrangler") +app.add_typer(create_app, name='create', invoke_without_command=True) +app.add_typer(config_app, name="configure", invoke_without_command=True) + + +@app.callback(invoke_without_command=True) +def main(ctx: typer.Context): + """Bringing Peace, Justice, and Security to your Python empire.""" + if ctx.invoked_subcommand is None: + with STD_OUT.status("Generating environment..."): + STD_OUT.print("Gathering configuration from environment...") + STD_ERR.print("NO CONFIGURATION FOUND") + ctx.invoke(app.registered_groups) + ctx.invoke(config_app.registered_callback) + + +if __name__ == '__main__': + app() diff --git a/devwrangler/commands/configure.py b/devwrangler/commands/configure.py new file mode 100644 index 0000000..0cbff35 --- /dev/null +++ b/devwrangler/commands/configure.py @@ -0,0 +1,42 @@ +"""Typer command module for the `configure` command.""" +from enum import Enum + +import typer + +from ..utilities.display import STD_OUT + +config_app = typer.Typer() + + +class Editor(Enum): + """Enum of valid editor options.""" + + vscode = "vscode" + + +def parse_extras(extras: str) -> tuple: + """Parse a comma separated options list provided by the user.""" + return tuple(s.strip() for s in extras.split(',')) + + +@config_app.callback('configure') +def configure( + editor: Editor = typer.Option( + 'vscode', + metavar="e", + help="The editor you'd like configured for development", + ), + extras: str = typer.Option( + "black,bandit,flake8,jinja2,mypy,isort", + metavar="x", + help="Extras to enable and configure in your editor (see docs for supported options)", + callback=parse_extras, + ), +): + """Configure an editor to use an already configured dev environment.""" + STD_OUT.print("Configuring VS Code...") + STD_OUT.print(f"Configuring extras {extras} in {editor.value}") + + +if __name__ == '__main__': + config_app() diff --git a/devwrangler/commands/create.py b/devwrangler/commands/create.py new file mode 100644 index 0000000..0e82fef --- /dev/null +++ b/devwrangler/commands/create.py @@ -0,0 +1,43 @@ +"""Typer command module for the Create command.""" +from enum import Enum +from pathlib import Path + +import typer + +from ..managers import CondaManager, VenvManager +from ..utilities.display import STD_OUT + +PROJECT_ROOT = Path.cwd() +VENV_PATH = PROJECT_ROOT / ".venv" + +create_app = typer.Typer() + + +class Manager(Enum): + """An Enum containing the valid managers a user may pick from.""" + + conda = "conda" + venv = "venv" + + +@create_app.callback() +def main( + env: Manager = typer.Option( + 'venv', + metavar="e", + ) +): + """Create a developer environment.""" + STD_OUT.print(f"[bold green]Creating {env.value} environment...[/]") + if env == Manager.venv: + venv = VenvManager() + venv.create() + venv.install_dependencies() + elif env == Manager.conda: + conda = CondaManager() + conda.create() + conda.install_dependencies() + + +if __name__ == '__main__': + create_app() From 5e53592a77797f5e89ca569bd8e30317c915bc39 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:47:01 -0600 Subject: [PATCH 22/24] Erase old CLI code and expose the new typer app in the CLI module --- devwrangler/cli.py | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/devwrangler/cli.py b/devwrangler/cli.py index adb9044..8ac533a 100644 --- a/devwrangler/cli.py +++ b/devwrangler/cli.py @@ -1,39 +1,5 @@ """Typer-based CLI for devwrangler.""" -from pathlib import Path - -import typer - -from .devwrangler import ( - create_virtual_environment, - parse_config_file, - set_workspace_settings, -) - -APP_NAME = 'devwrangler' - -PROJECT_ROOT = Path.cwd() -VENV_PATH = PROJECT_ROOT / ".venv" - - -def main( - req_file: str = typer.Argument('requirements-dev.txt'), - dev: bool = typer.Argument(True), -): - """CLI main function.""" - app_dir = typer.get_app_dir(APP_NAME, force_posix=True) - config_file_path: Path = Path(app_dir) / 'config.json' - - # check if config data exists, if not, proceed with default config - if not config_file_path.exists(): - typer.echo(f"Config file not found at {config_file_path}") - typer.echo("Using our default configuration") - config_data = parse_config_file() - else: - config_data = parse_config_file(config_file_path) - - create_virtual_environment(VENV_PATH, logger=typer.echo) - set_workspace_settings(config_data, workspace_path=(PROJECT_ROOT / '.vscode')) - +from .commands import app if __name__ == '__main__': - main() + app() From 7f9dd5228dc357b7a94fc61dae7c9c3026e8db33 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:47:36 -0600 Subject: [PATCH 23/24] Add basic ergonomic usage example --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index f86ffb3..96fcc27 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,19 @@ Bringing peace, freedom, justice, and security to your Python empire * your Python project's virtual environment * your project's VS Code settings +## Basic Usage + +```shell +$ pydev +$ pydev create +$ pydev create --env venv +$ pydev create --env conda +$ pyenv configure +$ pydev configure --editor vscode +$ pydev configure --editor vscode --extras django,jinja2 +``` + + ## Credits This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and the [waynerv/cookiecutter-pypackage](https://github.com/waynerv/cookiecutter-pypackage) project template. From 9cf9a8a0afc39153b971edf9a82f453c9fca2d84 Mon Sep 17 00:00:00 2001 From: Nick Cannariato <434063+birdcar@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:48:18 -0600 Subject: [PATCH 24/24] Replace the application specified by pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ddaae86..9ae7575 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ packages = [ ] [tool.poetry.scripts] -pydev = "devwrangler.cli:main" +pydev = "devwrangler.commands:app" [tool.poetry.dependencies] python = ">=3.6.2,<4.0"