diff --git a/poetry.lock b/poetry.lock index 8b99dca0..86d5d545 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,10 @@ [[package]] -name = "aiohttp" -version = "3.7.2" -description = "Async http client/server framework (asyncio)" category = "main" +description = "Async http client/server framework (asyncio)" +name = "aiohttp" optional = false python-versions = ">=3.6" +version = "3.7.2" [package.dependencies] async-timeout = ">=3.0,<4.0" @@ -18,106 +18,107 @@ yarl = ">=1.0,<2.0" speedups = ["aiodns", "brotlipy", "cchardet"] [[package]] -name = "aioresponses" -version = "0.7.1" -description = "Mock out requests made by ClientSession from aiohttp package" category = "dev" +description = "Mock out requests made by ClientSession from aiohttp package" +name = "aioresponses" optional = false python-versions = "*" +version = "0.7.1" [package.dependencies] aiohttp = ">=2.0.0,<4.0.0" [[package]] -name = "alabaster" -version = "0.7.12" -description = "A configurable sidebar-enabled Sphinx theme" category = "dev" +description = "A configurable sidebar-enabled Sphinx theme" +name = "alabaster" optional = false python-versions = "*" +version = "0.7.12" [[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" optional = false python-versions = "*" +version = "1.4.4" [[package]] -name = "aspy.refactor-imports" -version = "2.1.1" -description = "Utilities for refactoring imports in python-like syntax." category = "dev" +description = "Utilities for refactoring imports in python-like syntax." +name = "aspy.refactor-imports" optional = false python-versions = ">=3.6.1" +version = "2.1.1" [package.dependencies] cached-property = "*" [[package]] -name = "async-timeout" -version = "3.0.1" -description = "Timeout context manager for asyncio programs" category = "main" +description = "Timeout context manager for asyncio programs" +name = "async-timeout" optional = false python-versions = ">=3.5.3" +version = "3.0.1" [[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." category = "dev" +description = "Atomic file writes." +marker = "sys_platform == \"win32\"" +name = "atomicwrites" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.4.0" [[package]] -name = "attrs" -version = "20.2.0" -description = "Classes Without Boilerplate" category = "main" +description = "Classes Without Boilerplate" +name = "attrs" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.2.0" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] +dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] [[package]] -name = "babel" -version = "2.8.0" -description = "Internationalization utilities" category = "dev" +description = "Internationalization utilities" +name = "babel" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.8.0" [package.dependencies] pytz = ">=2015.7" [[package]] -name = "bandit" -version = "1.6.2" -description = "Security oriented static analyser for python code." category = "dev" +description = "Security oriented static analyser for python code." +name = "bandit" optional = false python-versions = "*" +version = "1.6.2" [package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} GitPython = ">=1.0.1" PyYAML = ">=3.13" +colorama = ">=0.3.9" six = ">=1.10.0" stevedore = ">=1.20.0" [[package]] -name = "black" -version = "20.8b1" -description = "The uncompromising code formatter." category = "dev" +description = "The uncompromising code formatter." +name = "black" optional = false python-versions = ">=3.6" +version = "20.8b1" [package.dependencies] appdirs = "*" @@ -134,98 +135,101 @@ colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] [[package]] -name = "cached-property" -version = "1.5.2" -description = "A decorator for caching properties in classes." category = "dev" +description = "A decorator for caching properties in classes." +name = "cached-property" optional = false python-versions = "*" +version = "1.5.2" [[package]] -name = "certifi" -version = "2020.6.20" -description = "Python package for providing Mozilla's CA Bundle." category = "dev" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" optional = false python-versions = "*" +version = "2020.6.20" [[package]] -name = "cfgv" -version = "3.2.0" -description = "Validate configuration and produce human readable error messages." category = "dev" +description = "Validate configuration and produce human readable error messages." +name = "cfgv" optional = false python-versions = ">=3.6.1" +version = "3.2.0" [[package]] -name = "chardet" -version = "3.0.4" -description = "Universal encoding detector for Python 2 and 3" category = "main" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" optional = false python-versions = "*" +version = "3.0.4" [[package]] -name = "click" -version = "7.1.2" -description = "Composable command line interface toolkit" category = "main" +description = "Composable command line interface toolkit" +name = "click" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.2" [[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." category = "dev" +description = "Cross-platform colored terminal text." +marker = "platform_system == \"Windows\" or sys_platform == \"win32\" or platform_system == \"Windows\"" +name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.4.4" [[package]] -name = "coverage" -version = "5.3" -description = "Code coverage measurement for Python" category = "dev" +description = "Code coverage measurement for Python" +name = "coverage" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "5.3" [package.dependencies] -toml = {version = "*", optional = true, markers = "extra == \"toml\""} +[package.dependencies.toml] +optional = true +version = "*" [package.extras] toml = ["toml"] [[package]] -name = "darglint" -version = "1.5.5" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." category = "dev" +description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +name = "darglint" optional = false python-versions = ">=3.5,<4.0" +version = "1.5.5" [[package]] -name = "distlib" -version = "0.3.1" -description = "Distribution utilities" category = "dev" +description = "Distribution utilities" +name = "distlib" optional = false python-versions = "*" +version = "0.3.1" [[package]] -name = "docutils" -version = "0.16" -description = "Docutils -- Python Documentation Utilities" category = "dev" +description = "Docutils -- Python Documentation Utilities" +name = "docutils" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.16" [[package]] -name = "dparse" -version = "0.5.1" -description = "A parser for Python dependency files" category = "dev" +description = "A parser for Python dependency files" +name = "dparse" optional = false python-versions = ">=3.5" +version = "0.5.1" [package.dependencies] packaging = "*" @@ -236,34 +240,37 @@ toml = "*" pipenv = ["pipenv"] [[package]] -name = "filelock" -version = "3.0.12" -description = "A platform independent file lock." category = "dev" +description = "A platform independent file lock." +name = "filelock" optional = false python-versions = "*" +version = "3.0.12" [[package]] -name = "flake8" -version = "3.8.4" -description = "the modular source code checker: pep8 pyflakes and co" category = "dev" +description = "the modular source code checker: pep8 pyflakes and co" +name = "flake8" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "3.8.4" [package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.6.0a1,<2.7.0" pyflakes = ">=2.2.0,<2.3.0" +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + [[package]] -name = "flake8-bandit" -version = "2.1.2" -description = "Automated security testing with bandit and flake8." category = "dev" +description = "Automated security testing with bandit and flake8." +name = "flake8-bandit" optional = false python-versions = "*" +version = "2.1.2" [package.dependencies] bandit = "*" @@ -272,108 +279,109 @@ flake8-polyfill = "*" pycodestyle = "*" [[package]] -name = "flake8-bugbear" -version = "20.1.4" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." category = "dev" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +name = "flake8-bugbear" optional = false python-versions = ">=3.6" +version = "20.1.4" [package.dependencies] attrs = ">=19.2.0" flake8 = ">=3.0.0" [[package]] -name = "flake8-docstrings" -version = "1.5.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" category = "dev" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +name = "flake8-docstrings" optional = false python-versions = "*" +version = "1.5.0" [package.dependencies] flake8 = ">=3" pydocstyle = ">=2.1" [[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" category = "dev" +description = "Polyfill package for Flake8 plugins" +name = "flake8-polyfill" optional = false python-versions = "*" +version = "1.0.2" [package.dependencies] flake8 = "*" [[package]] -name = "flake8-rst-docstrings" -version = "0.0.14" -description = "Python docstring reStructuredText (RST) validator" category = "dev" +description = "Python docstring reStructuredText (RST) validator" +name = "flake8-rst-docstrings" optional = false python-versions = "*" +version = "0.0.14" [package.dependencies] flake8 = ">=3.0.0" restructuredtext_lint = "*" [[package]] -name = "gitdb" -version = "4.0.5" -description = "Git Object Database" category = "dev" +description = "Git Object Database" +name = "gitdb" optional = false python-versions = ">=3.4" +version = "4.0.5" [package.dependencies] smmap = ">=3.0.1,<4" [[package]] -name = "gitpython" -version = "3.1.11" -description = "Python Git Library" category = "dev" +description = "Python Git Library" +name = "gitpython" optional = false python-versions = ">=3.4" +version = "3.1.11" [package.dependencies] gitdb = ">=4.0.1,<5" [[package]] -name = "identify" -version = "1.5.9" -description = "File identification library for Python" category = "dev" +description = "File identification library for Python" +name = "identify" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "1.5.9" [package.extras] license = ["editdistance"] [[package]] -name = "idna" -version = "2.10" -description = "Internationalized Domain Names in Applications (IDNA)" category = "main" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.10" [[package]] -name = "imagesize" -version = "1.2.0" -description = "Getting image size from png/jpeg/jpeg2000/gif file" category = "dev" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +name = "imagesize" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.2.0" [[package]] -name = "importlib-metadata" -version = "2.0.0" -description = "Read metadata from Python packages" category = "dev" +description = "Read metadata from Python packages" +marker = "python_version < \"3.8\"" +name = "importlib-metadata" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "2.0.0" [package.dependencies] zipp = ">=0.5" @@ -383,20 +391,20 @@ docs = ["sphinx", "rst.linker"] testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [[package]] -name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" category = "dev" +description = "iniconfig: brain-dead simple config-ini parsing" +name = "iniconfig" optional = false python-versions = "*" +version = "1.1.1" [[package]] -name = "jinja2" -version = "2.11.2" -description = "A very fast and expressive template engine." category = "dev" +description = "A very fast and expressive template engine." +name = "jinja2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -405,48 +413,85 @@ MarkupSafe = ">=0.23" i18n = ["Babel (>=0.8)"] [[package]] -name = "livereload" -version = "2.6.3" -description = "Python LiveReload is an awesome tool for web developers" category = "dev" +description = "Python LiveReload is an awesome tool for web developers" +name = "livereload" optional = false python-versions = "*" +version = "2.6.3" [package.dependencies] six = "*" -tornado = {version = "*", markers = "python_version > \"2.7\""} + +[package.dependencies.tornado] +python = ">=2.8" +version = "*" [[package]] -name = "markupsafe" -version = "1.1.1" -description = "Safely add untrusted strings to HTML/XML markup." category = "dev" +description = "Safely add untrusted strings to HTML/XML markup." +name = "markupsafe" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.1.1" + +[[package]] +category = "main" +description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +name = "marshmallow" +optional = false +python-versions = ">=3.5" +version = "3.9.1" + +[package.extras] +dev = ["pytest", "pytz", "simplejson", "mypy (0.790)", "flake8 (3.8.4)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox"] +docs = ["sphinx (3.3.0)", "sphinx-issues (1.2.0)", "alabaster (0.7.12)", "sphinx-version-warning (1.1.2)", "autodocsumm (0.2.1)"] +lint = ["mypy (0.790)", "flake8 (3.8.4)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"] +tests = ["pytest", "pytz", "simplejson"] + +[[package]] +category = "main" +description = "Python library to convert dataclasses into marshmallow schemas." +name = "marshmallow-dataclass" +optional = false +python-versions = ">=3.6" +version = "8.2.0" + +[package.dependencies] +marshmallow = ">=3.0.0,<4.0" +typing-inspect = "*" + +[package.extras] +dev = ["marshmallow-enum", "typeguard", "pre-commit (>=1.18,<2.0)", "sphinx", "pytest (>=5.4)", "pytest-mypy-plugins (>=1.2.0)", "typing-extensions (>=3.7.2,<3.8.0)"] +docs = ["sphinx"] +enum = ["marshmallow-enum"] +lint = ["pre-commit (>=1.18,<2.0)"] +tests = ["pytest (>=5.4)", "pytest-mypy-plugins (>=1.2.0)", "typing-extensions (>=3.7.2,<3.8.0)"] +union = ["typeguard"] [[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" category = "dev" +description = "McCabe checker, plugin for flake8" +name = "mccabe" optional = false python-versions = "*" +version = "0.6.1" [[package]] -name = "multidict" -version = "5.0.0" -description = "multidict implementation" category = "main" +description = "multidict implementation" +name = "multidict" optional = false python-versions = ">=3.5" +version = "5.0.0" [[package]] -name = "mypy" -version = "0.790" -description = "Optional static typing for Python" category = "dev" +description = "Optional static typing for Python" +name = "mypy" optional = false python-versions = ">=3.5" +version = "0.790" [package.dependencies] mypy-extensions = ">=0.4.3,<0.5.0" @@ -457,184 +502,192 @@ typing-extensions = ">=3.7.4" dmypy = ["psutil (>=4.0)"] [[package]] -name = "mypy-extensions" -version = "0.4.3" +category = "main" description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" +name = "mypy-extensions" optional = false python-versions = "*" +version = "0.4.3" [[package]] -name = "nodeenv" -version = "1.5.0" -description = "Node.js virtual environment builder" category = "dev" +description = "Node.js virtual environment builder" +name = "nodeenv" optional = false python-versions = "*" +version = "1.5.0" [[package]] -name = "packaging" -version = "20.4" -description = "Core utilities for Python packages" category = "dev" +description = "Core utilities for Python packages" +name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" six = "*" [[package]] -name = "pathspec" -version = "0.8.0" -description = "Utility library for gitignore style pattern matching of file paths." category = "dev" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.8.0" [[package]] -name = "pbr" -version = "5.5.1" -description = "Python Build Reasonableness" category = "dev" +description = "Python Build Reasonableness" +name = "pbr" optional = false python-versions = ">=2.6" +version = "5.5.1" [[package]] -name = "pep8-naming" -version = "0.11.1" -description = "Check PEP-8 naming conventions, plugin for flake8" category = "dev" +description = "Check PEP-8 naming conventions, plugin for flake8" +name = "pep8-naming" optional = false python-versions = "*" +version = "0.11.1" [package.dependencies] flake8-polyfill = ">=1.0.2,<2" [[package]] -name = "pluggy" -version = "0.13.1" -description = "plugin and hook calling mechanisms for python" category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.13.1" [package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" [package.extras] dev = ["pre-commit", "tox"] [[package]] -name = "pre-commit" -version = "2.8.2" -description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +name = "pre-commit" optional = false python-versions = ">=3.6.1" +version = "2.8.2" [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" virtualenv = ">=20.0.8" +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + [[package]] -name = "pre-commit-hooks" -version = "3.3.0" -description = "Some out-of-the-box hooks for pre-commit." category = "dev" +description = "Some out-of-the-box hooks for pre-commit." +name = "pre-commit-hooks" optional = false python-versions = ">=3.6.1" +version = "3.3.0" [package.dependencies] "ruamel.yaml" = ">=0.15" toml = "*" [[package]] -name = "py" -version = "1.9.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "py" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pycodestyle" -version = "2.6.0" -description = "Python style guide checker" +version = "1.9.0" + +[[package]] category = "dev" +description = "Python style guide checker" +name = "pycodestyle" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.6.0" [[package]] -name = "pydocstyle" -version = "5.1.1" -description = "Python docstring style checker" category = "dev" +description = "Python docstring style checker" +name = "pydocstyle" optional = false python-versions = ">=3.5" +version = "5.1.1" [package.dependencies] snowballstemmer = "*" [[package]] -name = "pyflakes" -version = "2.2.0" -description = "passive checker of Python programs" category = "dev" +description = "passive checker of Python programs" +name = "pyflakes" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.2.0" [[package]] -name = "pygments" -version = "2.7.2" -description = "Pygments is a syntax highlighting package written in Python." category = "dev" +description = "Pygments is a syntax highlighting package written in Python." +name = "pygments" optional = false python-versions = ">=3.5" +version = "2.7.2" [[package]] -name = "pyparsing" -version = "2.4.7" -description = "Python parsing module" category = "dev" +description = "Python parsing module" +name = "pyparsing" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.4.7" [[package]] -name = "pytest" -version = "6.1.2" -description = "pytest: simple powerful testing with Python" category = "dev" +description = "pytest: simple powerful testing with Python" +name = "pytest" optional = false python-versions = ">=3.5" +version = "6.1.2" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +atomicwrites = ">=1.0" attrs = ">=17.4.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +colorama = "*" iniconfig = "*" packaging = "*" pluggy = ">=0.12,<1.0" py = ">=1.8.2" toml = "*" +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + [package.extras] -checkqa_mypy = ["mypy (==0.780)"] +checkqa_mypy = ["mypy (0.780)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] -name = "pytest-asyncio" -version = "0.14.0" -description = "Pytest support for asyncio." category = "dev" +description = "Pytest support for asyncio." +name = "pytest-asyncio" optional = false python-versions = ">= 3.5" +version = "0.14.0" [package.dependencies] pytest = ">=5.4.0" @@ -643,47 +696,47 @@ pytest = ">=5.4.0" testing = ["async-generator (>=1.3)", "coverage", "hypothesis (>=5.7.1)"] [[package]] -name = "pytz" -version = "2020.4" -description = "World timezone definitions, modern and historical" category = "dev" +description = "World timezone definitions, modern and historical" +name = "pytz" optional = false python-versions = "*" +version = "2020.4" [[package]] -name = "pyyaml" -version = "5.3.1" -description = "YAML parser and emitter for Python" category = "dev" +description = "YAML parser and emitter for Python" +name = "pyyaml" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "5.3.1" [[package]] -name = "regex" -version = "2020.10.28" -description = "Alternative regular expression module, to replace re." category = "dev" +description = "Alternative regular expression module, to replace re." +name = "regex" optional = false python-versions = "*" +version = "2020.10.28" [[package]] -name = "reorder-python-imports" -version = "2.3.6" -description = "Tool for reordering python imports" category = "dev" +description = "Tool for reordering python imports" +name = "reorder-python-imports" optional = false python-versions = ">=3.6.1" +version = "2.3.6" [package.dependencies] "aspy.refactor-imports" = ">=2.1.0" [[package]] -name = "requests" -version = "2.24.0" -description = "Python HTTP for Humans." category = "dev" +description = "Python HTTP for Humans." +name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.24.0" [package.dependencies] certifi = ">=2017.4.17" @@ -693,98 +746,103 @@ urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" [package.extras] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] -name = "restructuredtext-lint" -version = "1.3.1" -description = "reStructuredText linter" category = "dev" +description = "reStructuredText linter" +name = "restructuredtext-lint" optional = false python-versions = "*" +version = "1.3.1" [package.dependencies] docutils = ">=0.11,<1.0" [[package]] -name = "ruamel.yaml" -version = "0.16.12" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" category = "dev" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +name = "ruamel.yaml" optional = false python-versions = "*" +version = "0.16.12" [package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.1.2", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.9\""} +[package.dependencies."ruamel.yaml.clib"] +python = "<3.9" +version = ">=0.1.2" [package.extras] docs = ["ryd"] jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] [[package]] -name = "ruamel.yaml.clib" -version = "0.2.2" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" category = "dev" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +marker = "platform_python_implementation == \"CPython\" and python_version < \"3.9\"" +name = "ruamel.yaml.clib" optional = false python-versions = "*" +version = "0.2.2" [[package]] -name = "safety" -version = "1.9.0" -description = "Checks installed dependencies for known vulnerabilities." category = "dev" +description = "Checks installed dependencies for known vulnerabilities." +name = "safety" optional = false python-versions = ">=3.5" +version = "1.9.0" [package.dependencies] Click = ">=6.0" dparse = ">=0.5.1" packaging = "*" requests = "*" +setuptools = "*" [[package]] -name = "six" -version = "1.15.0" -description = "Python 2 and 3 compatibility utilities" category = "dev" +description = "Python 2 and 3 compatibility utilities" +name = "six" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "1.15.0" [[package]] -name = "smmap" -version = "3.0.4" -description = "A pure Python implementation of a sliding window memory map manager" category = "dev" +description = "A pure Python implementation of a sliding window memory map manager" +name = "smmap" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.0.4" [[package]] -name = "snowballstemmer" -version = "2.0.0" -description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." category = "dev" +description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." +name = "snowballstemmer" optional = false python-versions = "*" +version = "2.0.0" [[package]] -name = "sphinx" -version = "3.3.1" -description = "Python documentation generator" category = "dev" +description = "Python documentation generator" +name = "sphinx" optional = false python-versions = ">=3.5" +version = "3.3.1" [package.dependencies] +Jinja2 = ">=2.3" +Pygments = ">=2.0" alabaster = ">=0.7,<0.8" babel = ">=1.3" -colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +colorama = ">=0.3.5" docutils = ">=0.12" imagesize = "*" -Jinja2 = ">=2.3" packaging = "*" -Pygments = ">=2.0" requests = ">=2.5.0" +setuptools = "*" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" @@ -799,12 +857,12 @@ lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.790)", "docutils-s test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"] [[package]] -name = "sphinx-autobuild" -version = "2020.9.1" -description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." category = "dev" +description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +name = "sphinx-autobuild" optional = false python-versions = ">=3.6" +version = "2020.9.1" [package.dependencies] livereload = "*" @@ -814,24 +872,24 @@ sphinx = "*" test = ["pytest", "pytest-cov"] [[package]] -name = "sphinx-click" -version = "2.5.0" -description = "Sphinx extension that automatically documents click applications" category = "dev" +description = "Sphinx extension that automatically documents click applications" +name = "sphinx-click" optional = false python-versions = "*" +version = "2.5.0" [package.dependencies] pbr = ">=2.0" sphinx = ">=1.5,<4.0" [[package]] -name = "sphinx-rtd-theme" -version = "0.5.0" -description = "Read the Docs theme for Sphinx" category = "dev" +description = "Read the Docs theme for Sphinx" +name = "sphinx-rtd-theme" optional = false python-versions = "*" +version = "0.5.0" [package.dependencies] sphinx = "*" @@ -840,177 +898,202 @@ sphinx = "*" dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] [[package]] -name = "sphinxcontrib-applehelp" -version = "1.0.2" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" category = "dev" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +name = "sphinxcontrib-applehelp" optional = false python-versions = ">=3.5" +version = "1.0.2" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." category = "dev" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +name = "sphinxcontrib-devhelp" optional = false python-versions = ">=3.5" +version = "1.0.2" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -name = "sphinxcontrib-htmlhelp" -version = "1.0.3" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" category = "dev" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +name = "sphinxcontrib-htmlhelp" optional = false python-versions = ">=3.5" +version = "1.0.3" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest", "html5lib"] [[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" category = "dev" +description = "A sphinx extension which renders display math in HTML via JavaScript" +name = "sphinxcontrib-jsmath" optional = false python-versions = ">=3.5" +version = "1.0.1" [package.extras] test = ["pytest", "flake8", "mypy"] [[package]] -name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." category = "dev" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +name = "sphinxcontrib-qthelp" optional = false python-versions = ">=3.5" +version = "1.0.3" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -name = "sphinxcontrib-serializinghtml" -version = "1.1.4" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." category = "dev" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +name = "sphinxcontrib-serializinghtml" optional = false python-versions = ">=3.5" +version = "1.1.4" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -name = "stevedore" -version = "3.2.2" -description = "Manage dynamic plugins for Python applications" category = "dev" +description = "Manage dynamic plugins for Python applications" +name = "stevedore" optional = false python-versions = ">=3.6" +version = "3.2.2" [package.dependencies] -importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} pbr = ">=2.0.0,<2.1.0 || >2.1.0" +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=1.7.0" + [[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" category = "dev" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "0.10.2" [[package]] -name = "tornado" -version = "6.1" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." category = "dev" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +marker = "python_version > \"2.7\"" +name = "tornado" optional = false python-versions = ">= 3.5" +version = "6.1" [[package]] -name = "typed-ast" -version = "1.4.1" -description = "a fork of Python 2 and 3 ast modules with type comment support" category = "dev" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" optional = false python-versions = "*" +version = "1.4.1" [[package]] -name = "typeguard" -version = "2.10.0" -description = "Run-time type checker for Python" category = "dev" +description = "Run-time type checker for Python" +name = "typeguard" optional = false python-versions = ">=3.5.3" +version = "2.10.0" [package.extras] doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] test = ["pytest", "typing-extensions"] [[package]] +category = "main" +description = "Backported and Experimental Type Hints for Python 3.5+" name = "typing-extensions" +optional = false +python-versions = "*" version = "3.7.4.3" -description = "Backported and Experimental Type Hints for Python 3.5+" + +[[package]] category = "main" +description = "Runtime inspection utilities for typing module." +name = "typing-inspect" optional = false python-versions = "*" +version = "0.6.0" + +[package.dependencies] +mypy-extensions = ">=0.3.0" +typing-extensions = ">=3.7.4" [[package]] -name = "urllib3" -version = "1.25.11" -description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.11" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] -name = "virtualenv" -version = "20.1.0" -description = "Virtual Python Environment builder" category = "dev" +description = "Virtual Python Environment builder" +name = "virtualenv" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "20.1.0" [package.dependencies] appdirs = ">=1.4.3,<2" distlib = ">=0.3.1,<1" filelock = ">=3.0.0,<4" -importlib-metadata = {version = ">=0.12,<3", markers = "python_version < \"3.8\""} six = ">=1.9.0,<2" +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12,<3" + [package.extras] docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "pytest-xdist (>=1.31.0)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] [[package]] -name = "xdoctest" -version = "0.15.0" -description = "A rewrite of the builtin doctest module" category = "dev" +description = "A rewrite of the builtin doctest module" +name = "xdoctest" optional = false python-versions = "*" +version = "0.15.0" [package.dependencies] -colorama = {version = "*", optional = true, markers = "platform_system == \"Windows\" and extra == \"colors\""} -Pygments = {version = "*", optional = true, markers = "extra == \"colors\""} six = "*" +[package.dependencies.Pygments] +optional = true +version = "*" + +[package.dependencies.colorama] +optional = true +version = "*" + [package.extras] all = ["six", "pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "pygments", "colorama", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] colors = ["pygments", "colorama"] @@ -1019,34 +1102,38 @@ optional = ["pygments", "colorama", "nbformat", "nbconvert", "jupyter-client", " tests = ["pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] [[package]] -name = "yarl" -version = "1.6.2" -description = "Yet another URL library" category = "main" +description = "Yet another URL library" +name = "yarl" optional = false python-versions = ">=3.6" +version = "1.6.2" [package.dependencies] idna = ">=2.0" multidict = ">=4.0" -typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} + +[package.dependencies.typing-extensions] +python = "<3.8" +version = ">=3.7.4" [[package]] -name = "zipp" -version = "3.4.0" -description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" +description = "Backport of pathlib-compatible object wrapper for zip files" +marker = "python_version < \"3.8\"" +name = "zipp" optional = false python-versions = ">=3.6" +version = "3.4.0" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [metadata] -lock-version = "1.1" +content-hash = "2fc16768a9de2ce5461d55b3cb00ddef219daff783eac4ec64f951e508eb7b44" +lock-version = "1.0" python-versions = "^3.7.1" -content-hash = "1a5fcbee79b2164f57f45c703b0c069a6508e349279cfd204f17bb2d7109fc7d" [metadata.files] aiohttp = [ @@ -1295,6 +1382,14 @@ markupsafe = [ {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] +marshmallow = [ + {file = "marshmallow-3.9.1-py2.py3-none-any.whl", hash = "sha256:e26763201474b588d144dae9a32bdd945cd26a06c943bc746a6882e850475378"}, + {file = "marshmallow-3.9.1.tar.gz", hash = "sha256:73facc37462dfc0b27f571bdaffbef7709e19f7a616beb3802ea425b07843f4e"}, +] +marshmallow-dataclass = [ + {file = "marshmallow_dataclass-8.2.0-py3-none-any.whl", hash = "sha256:5f854dead81e2eb3e2734d0d65568a953d7487be314be3eefebae5ad1239396e"}, + {file = "marshmallow_dataclass-8.2.0.tar.gz", hash = "sha256:8d004657724a7266c4aef62e2c06f5a82bdf2d6d25707d994b35e7f3ea5d077e"}, +] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -1438,44 +1533,28 @@ pyyaml = [ regex = [ {file = "regex-2020.10.28-cp27-cp27m-win32.whl", hash = "sha256:4b5a9bcb56cc146c3932c648603b24514447eafa6ce9295234767bf92f69b504"}, {file = "regex-2020.10.28-cp27-cp27m-win_amd64.whl", hash = "sha256:c13d311a4c4a8d671f5860317eb5f09591fbe8259676b86a85769423b544451e"}, - {file = "regex-2020.10.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c454ad88e56e80e44f824ef8366bb7e4c3def12999151fd5c0ea76a18fe9aa3e"}, {file = "regex-2020.10.28-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c8a2b7ccff330ae4c460aff36626f911f918555660cc28163417cb84ffb25789"}, {file = "regex-2020.10.28-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4afa350f162551cf402bfa3cd8302165c8e03e689c897d185f16a167328cc6dd"}, {file = "regex-2020.10.28-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b88fa3b8a3469f22b4f13d045d9bd3eda797aa4e406fde0a2644bc92bbdd4bdd"}, {file = "regex-2020.10.28-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f43109822df2d3faac7aad79613f5f02e4eab0fc8ad7932d2e70e2a83bd49c26"}, - {file = "regex-2020.10.28-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:de7fd57765398d141949946c84f3590a68cf5887dac3fc52388df0639b01eda4"}, - {file = "regex-2020.10.28-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:9b6305295b6591e45f069d3553c54d50cc47629eb5c218aac99e0f7fafbf90a1"}, - {file = "regex-2020.10.28-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:bd904c0dec29bbd0769887a816657491721d5f545c29e30fd9d7a1a275dc80ab"}, {file = "regex-2020.10.28-cp36-cp36m-win32.whl", hash = "sha256:8092a5a06ad9a7a247f2a76ace121183dc4e1a84c259cf9c2ce3bbb69fac3582"}, {file = "regex-2020.10.28-cp36-cp36m-win_amd64.whl", hash = "sha256:49461446b783945597c4076aea3f49aee4b4ce922bd241e4fcf62a3e7c61794c"}, - {file = "regex-2020.10.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:297116e79074ec2a2f885d22db00ce6e88b15f75162c5e8b38f66ea734e73c64"}, {file = "regex-2020.10.28-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8ca9dca965bd86ea3631b975d63b0693566d3cc347e55786d5514988b6f5b84c"}, {file = "regex-2020.10.28-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ea37320877d56a7f0a1e6a625d892cf963aa7f570013499f5b8d5ab8402b5625"}, {file = "regex-2020.10.28-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:3a5f08039eee9ea195a89e180c5762bfb55258bfb9abb61a20d3abee3b37fd12"}, {file = "regex-2020.10.28-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:cb905f3d2e290a8b8f1579d3984f2cfa7c3a29cc7cba608540ceeed18513f520"}, - {file = "regex-2020.10.28-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:96f99219dddb33e235a37283306834700b63170d7bb2a1ee17e41c6d589c8eb9"}, - {file = "regex-2020.10.28-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:227a8d2e5282c2b8346e7f68aa759e0331a0b4a890b55a5cfbb28bd0261b84c0"}, - {file = "regex-2020.10.28-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:2564def9ce0710d510b1fc7e5178ce2d20f75571f788b5197b3c8134c366f50c"}, {file = "regex-2020.10.28-cp37-cp37m-win32.whl", hash = "sha256:a62162be05edf64f819925ea88d09d18b09bebf20971b363ce0c24e8b4aa14c0"}, {file = "regex-2020.10.28-cp37-cp37m-win_amd64.whl", hash = "sha256:03855ee22980c3e4863dc84c42d6d2901133362db5daf4c36b710dd895d78f0a"}, - {file = "regex-2020.10.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf4f896c42c63d1f22039ad57de2644c72587756c0cfb3cc3b7530cfe228277f"}, {file = "regex-2020.10.28-cp38-cp38-manylinux1_i686.whl", hash = "sha256:625116aca6c4b57c56ea3d70369cacc4d62fead4930f8329d242e4fe7a58ce4b"}, {file = "regex-2020.10.28-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2dc522e25e57e88b4980d2bdd334825dbf6fa55f28a922fc3bfa60cc09e5ef53"}, {file = "regex-2020.10.28-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:119e0355dbdd4cf593b17f2fc5dbd4aec2b8899d0057e4957ba92f941f704bf5"}, {file = "regex-2020.10.28-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:cfcf28ed4ce9ced47b9b9670a4f0d3d3c0e4d4779ad4dadb1ad468b097f808aa"}, - {file = "regex-2020.10.28-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b45bab9f224de276b7bc916f6306b86283f6aa8afe7ed4133423efb42015a898"}, - {file = "regex-2020.10.28-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:52e83a5f28acd621ba8e71c2b816f6541af7144b69cc5859d17da76c436a5427"}, - {file = "regex-2020.10.28-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:aacc8623ffe7999a97935eeabbd24b1ae701d08ea8f874a6ff050e93c3e658cf"}, {file = "regex-2020.10.28-cp38-cp38-win32.whl", hash = "sha256:06b52815d4ad38d6524666e0d50fe9173533c9cc145a5779b89733284e6f688f"}, {file = "regex-2020.10.28-cp38-cp38-win_amd64.whl", hash = "sha256:c3466a84fce42c2016113101018a9981804097bacbab029c2d5b4fcb224b89de"}, - {file = "regex-2020.10.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:127a9e0c0d91af572fbb9e56d00a504dbd4c65e574ddda3d45b55722462210de"}, {file = "regex-2020.10.28-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c2c6c56ee97485a127555c9595c069201b5161de9d05495fbe2132b5ac104786"}, {file = "regex-2020.10.28-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1ec66700a10e3c75f1f92cbde36cca0d3aaee4c73dfa26699495a3a30b09093c"}, {file = "regex-2020.10.28-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:11116d424734fe356d8777f89d625f0df783251ada95d6261b4c36ad27a394bb"}, {file = "regex-2020.10.28-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f1fce1e4929157b2afeb4bb7069204d4370bab9f4fc03ca1fbec8bd601f8c87d"}, - {file = "regex-2020.10.28-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:3dfca201fa6b326239e1bccb00b915e058707028809b8ecc0cf6819ad233a740"}, - {file = "regex-2020.10.28-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:b8a686a6c98872007aa41fdbb2e86dc03b287d951ff4a7f1da77fb7f14113e4d"}, - {file = "regex-2020.10.28-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:c32c91a0f1ac779cbd73e62430de3d3502bbc45ffe5bb6c376015acfa848144b"}, {file = "regex-2020.10.28-cp39-cp39-win32.whl", hash = "sha256:832339223b9ce56b7b15168e691ae654d345ac1635eeb367ade9ecfe0e66bee0"}, {file = "regex-2020.10.28-cp39-cp39-win_amd64.whl", hash = "sha256:654c1635f2313d0843028487db2191530bca45af61ca85d0b16555c399625b0e"}, {file = "regex-2020.10.28.tar.gz", hash = "sha256:dd3e6547ecf842a29cf25123fbf8d2461c53c8d37aa20d87ecee130c89b7079b"}, @@ -1669,6 +1748,11 @@ typing-extensions = [ {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, ] +typing-inspect = [ + {file = "typing_inspect-0.6.0-py2-none-any.whl", hash = "sha256:de08f50a22955ddec353876df7b2545994d6df08a2f45d54ac8c05e530372ca0"}, + {file = "typing_inspect-0.6.0-py3-none-any.whl", hash = "sha256:3b98390df4d999a28cf5b35d8b333425af5da2ece8a4ea9e98f71e7591347b4f"}, + {file = "typing_inspect-0.6.0.tar.gz", hash = "sha256:8f1b1dd25908dbfd81d3bebc218011531e7ab614ba6e5bf7826d887c834afab7"}, +] urllib3 = [ {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"}, {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"}, diff --git a/pyproject.toml b/pyproject.toml index eeea32f0..f89e4950 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ Changelog = "https://github.com/hacf-fr/renault-api/releases" python = "^3.7.1" click = "^7.0" aiohttp = "3.7.2" +marshmallow-dataclass = "^8.2.0" [tool.poetry.dev-dependencies] pytest = "^6.1.2" diff --git a/src/renault_api/exceptions.py b/src/renault_api/exceptions.py index ffa5cb32..7a343c96 100644 --- a/src/renault_api/exceptions.py +++ b/src/renault_api/exceptions.py @@ -1,7 +1,24 @@ """Exceptions for Renault API.""" +from typing import Optional class RenaultException(Exception): """Base class for Renault API errors.""" pass + + +# Gigya exceptions +class GigyaException(RenaultException): + """Base exception for Gigya errors.""" + + pass + + +class GigyaResponseException(GigyaException): + """Gigya returned a parsable errors.""" + + def __init__(self, error_code: int, error_details: Optional[str]): + """Initialise GigyaResponseException.""" + self.error_code = error_code + self.error_details = error_details diff --git a/src/renault_api/model/__init__.py b/src/renault_api/model/__init__.py new file mode 100644 index 00000000..b3ead963 --- /dev/null +++ b/src/renault_api/model/__init__.py @@ -0,0 +1,11 @@ +"""Models for Renault API.""" +import marshmallow + + +class BaseSchema(marshmallow.Schema): + """Base schema for Gigya models to exclude unknown fields.""" + + class Meta: + """Force unknown fields to 'exclude'.""" + + unknown = marshmallow.EXCLUDE diff --git a/src/renault_api/model/gigya.py b/src/renault_api/model/gigya.py new file mode 100644 index 00000000..9ceeca3a --- /dev/null +++ b/src/renault_api/model/gigya.py @@ -0,0 +1,67 @@ +"""Gigya models.""" +from dataclasses import dataclass +from typing import Optional + +import marshmallow_dataclass + +from . import BaseSchema +from renault_api.exceptions import GigyaResponseException + + +@dataclass +class GigyaResponse: + """Gigya response.""" + + errorCode: int # noqa: N815 + errorDetails: Optional[str] # noqa: N815 + + def raise_for_error_code(self) -> None: + """Checks the response information.""" + if self.errorCode > 0: + raise GigyaResponseException(self.errorCode, self.errorDetails) + + +@dataclass +class GigyaLoginSessionInfo: + """Gigya Login sessionInfo data.""" + + cookieValue: Optional[str] # noqa: N815 + + +@dataclass +class GigyaLoginResponse(GigyaResponse): + """Gigya response to POST on /accounts.login.""" + + sessionInfo: Optional[GigyaLoginSessionInfo] # noqa: N815 + + +@dataclass +class GigyaGetAccountInfoData: + """Gigya Login sessionInfo data.""" + + personId: Optional[str] # noqa: N815 + + +@dataclass +class GigyaGetAccountInfoResponse(GigyaResponse): + """Gigya response to POST on /accounts.getAccountInfo.""" + + data: Optional[GigyaGetAccountInfoData] + + +@dataclass +class GigyaGetJWTResponse(GigyaResponse): + """Gigya response to POST on /accounts.getJWT.""" + + id_token: Optional[str] + + +GigyaLoginResponseSchema = marshmallow_dataclass.class_schema( + GigyaLoginResponse, base_schema=BaseSchema +)() +GigyaGetAccountInfoResponseSchema = marshmallow_dataclass.class_schema( + GigyaGetAccountInfoResponse, base_schema=BaseSchema +)() +GigyaGetJWTResponseSchema = marshmallow_dataclass.class_schema( + GigyaGetJWTResponse, base_schema=BaseSchema +)() diff --git a/tests/fixtures/gigya/account_info.json b/tests/fixtures/gigya/account_info.json new file mode 100644 index 00000000..6eec3ca1 --- /dev/null +++ b/tests/fixtures/gigya/account_info.json @@ -0,0 +1,40 @@ +{ + "callId": "callId", + "errorCode": 0, + "apiVersion": 2, + "statusCode": 200, + "statusReason": "OK", + "time": "2020-11-10T08:31:02.748Z", + "registeredTimestamp": 1556570377000, + "UID": "UID", + "UIDSignature": "UIDSignature=", + "signatureTimestamp": "1604997062", + "created": "2019-04-29T20:39:36.880Z", + "createdTimestamp": 1556570376000, + "data": { + "personId": "person-id-1", + "gigyaDataCenter": "gigyaDataCenter" + }, + "preferences": {}, + "emails": { + "verified": ["email@email.com"], + "unverified": [] + }, + "isActive": true, + "isRegistered": true, + "isVerified": true, + "lastLogin": "2020-11-10T08:31:02.595Z", + "lastLoginTimestamp": 1604997062000, + "lastUpdated": "2019-04-29T20:40:39.441Z", + "lastUpdatedTimestamp": 1556570439441, + "loginProvider": "site", + "oldestDataUpdated": "2019-04-29T20:39:36.880Z", + "oldestDataUpdatedTimestamp": 1556570376880, + "profile": { + "email": "email@email.com" + }, + "registered": "2019-04-29T20:39:37.022Z", + "socialProviders": "site", + "verified": "2019-04-29T20:40:39.441Z", + "verifiedTimestamp": 1556570439441 +} diff --git a/tests/fixtures/gigya/account_info.txt b/tests/fixtures/gigya/account_info.txt deleted file mode 100644 index 8667c41b..00000000 --- a/tests/fixtures/gigya/account_info.txt +++ /dev/null @@ -1 +0,0 @@ -{'callId': 'callId', 'errorCode': 0, 'apiVersion': 2, 'statusCode': 200, 'statusReason': 'OK', 'time': '2020-11-10T08:31:02.748Z', 'registeredTimestamp': 1556570377000, 'UID': 'UID', 'UIDSignature': 'UIDSignature=', 'signatureTimestamp': '1604997062', 'created': '2019-04-29T20:39:36.880Z', 'createdTimestamp': 1556570376000, 'data': {'personId': 'person-id-1', 'gigyaDataCenter': 'gigyaDataCenter'}, 'preferences': {}, 'emails': {'verified': ['email@email.com'], 'unverified': []}, 'isActive': True, 'isRegistered': True, 'isVerified': True, 'lastLogin': '2020-11-10T08:31:02.595Z', 'lastLoginTimestamp': 1604997062000, 'lastUpdated': '2019-04-29T20:40:39.441Z', 'lastUpdatedTimestamp': 1556570439441, 'loginProvider': 'site', 'oldestDataUpdated': '2019-04-29T20:39:36.880Z', 'oldestDataUpdatedTimestamp': 1556570376880, 'profile': {'email': 'email@email.com'}, 'registered': '2019-04-29T20:39:37.022Z', 'socialProviders': 'site', 'verified': '2019-04-29T20:40:39.441Z', 'verifiedTimestamp': 1556570439441} diff --git a/tests/fixtures/gigya/account_info_corrupted.txt b/tests/fixtures/gigya/account_info_corrupted.txt deleted file mode 100644 index 800a8880..00000000 --- a/tests/fixtures/gigya/account_info_corrupted.txt +++ /dev/null @@ -1 +0,0 @@ -{'callId': 'callId', 'errorCode': 0, 'apiVersion': 2, 'statusCode': 200, 'statusReason': 'OK', 'time': '2020-11-10T08:31:02.748Z', 'registeredTimestamp': 1556570377000, 'UID': 'UID', 'UIDSignature': 'UIDSignature=', 'signatureTimestamp': '1604997062', 'created': '2019-04-29T20:39:36.880Z', 'createdTimestamp': 1556570376000, 'preferences': {}, 'emails': {'verified': ['email@email.com'], 'unverified': []}, 'isActive': True, 'isRegistered': True, 'isVerified': True, 'lastLogin': '2020-11-10T08:31:02.595Z', 'lastLoginTimestamp': 1604997062000, 'lastUpdated': '2019-04-29T20:40:39.441Z', 'lastUpdatedTimestamp': 1556570439441, 'loginProvider': 'site', 'oldestDataUpdated': '2019-04-29T20:39:36.880Z', 'oldestDataUpdatedTimestamp': 1556570376880, 'profile': {'email': 'email@email.com'}, 'registered': '2019-04-29T20:39:37.022Z', 'socialProviders': 'site', 'verified': '2019-04-29T20:40:39.441Z', 'verifiedTimestamp': 1556570439441} diff --git a/tests/fixtures/gigya/get_jwt.json b/tests/fixtures/gigya/get_jwt.json new file mode 100644 index 00000000..1ab17ecf --- /dev/null +++ b/tests/fixtures/gigya/get_jwt.json @@ -0,0 +1,10 @@ +{ + "callId": "callId", + "errorCode": 0, + "apiVersion": 2, + "statusCode": 200, + "statusReason": "OK", + "time": "2020-11-10T08:31:02.872Z", + "ignoredFields": "", + "id_token": "sample-jwt-token" +} diff --git a/tests/fixtures/gigya/get_jwt.txt b/tests/fixtures/gigya/get_jwt.txt deleted file mode 100644 index 1433bbbb..00000000 --- a/tests/fixtures/gigya/get_jwt.txt +++ /dev/null @@ -1 +0,0 @@ -{'callId': 'callId', 'errorCode': 0, 'apiVersion': 2, 'statusCode': 200, 'statusReason': 'OK', 'time': '2020-11-10T08:31:02.872Z', 'ignoredFields': '', 'id_token': 'id_token'} diff --git a/tests/fixtures/gigya/get_jwt_corrupted.txt b/tests/fixtures/gigya/get_jwt_corrupted.txt deleted file mode 100644 index 92e978fd..00000000 --- a/tests/fixtures/gigya/get_jwt_corrupted.txt +++ /dev/null @@ -1 +0,0 @@ -{'callId': 'callId', 'errorCode': 0, 'apiVersion': 2, 'statusCode': 200, 'statusReason': 'OK', 'time': '2020-11-10T08:31:02.872Z', 'ignoredFields': ''} diff --git a/tests/fixtures/gigya/login.json b/tests/fixtures/gigya/login.json new file mode 100644 index 00000000..b1c8d6d0 --- /dev/null +++ b/tests/fixtures/gigya/login.json @@ -0,0 +1,36 @@ +{ + "callId": "callId", + "errorCode": 0, + "apiVersion": 2, + "statusCode": 200, + "statusReason": "OK", + "time": "2020-11-10T08:31:02.637Z", + "registeredTimestamp": 1556570377, + "UID": "UID", + "UIDSignature": "UIDSignature=", + "signatureTimestamp": "1604997062", + "created": "2019-04-29T20:39:36.880Z", + "createdTimestamp": 1556570376, + "isActive": true, + "isRegistered": true, + "isVerified": true, + "lastLogin": "2020-11-10T08:31:02.595Z", + "lastLoginTimestamp": 1604997062, + "lastUpdated": "2019-04-29T20:40:39.441Z", + "lastUpdatedTimestamp": 1556570439441, + "loginProvider": "site", + "oldestDataUpdated": "2019-04-29T20:39:36.880Z", + "oldestDataUpdatedTimestamp": 1556570376880, + "profile": { + "email": "email@email.com" + }, + "registered": "2019-04-29T20:39:37.022Z", + "socialProviders": "site", + "verified": "2019-04-29T20:40:39.441Z", + "verifiedTimestamp": 1556570439441, + "newUser": false, + "sessionInfo": { + "cookieName": "cookieName", + "cookieValue": "sample-cookie-value" + } +} diff --git a/tests/fixtures/gigya/login.txt b/tests/fixtures/gigya/login.txt deleted file mode 100644 index 967dd0b1..00000000 --- a/tests/fixtures/gigya/login.txt +++ /dev/null @@ -1 +0,0 @@ -{'callId': 'callId', 'errorCode': 0, 'apiVersion': 2, 'statusCode': 200, 'statusReason': 'OK', 'time': '2020-11-10T08:31:02.637Z', 'registeredTimestamp': 1556570377, 'UID': 'UID', 'UIDSignature': 'UIDSignature=', 'signatureTimestamp': '1604997062', 'created': '2019-04-29T20:39:36.880Z', 'createdTimestamp': 1556570376, 'isActive': True, 'isRegistered': True, 'isVerified': True, 'lastLogin': '2020-11-10T08:31:02.595Z', 'lastLoginTimestamp': 1604997062, 'lastUpdated': '2019-04-29T20:40:39.441Z', 'lastUpdatedTimestamp': 1556570439441, 'loginProvider': 'site', 'oldestDataUpdated': '2019-04-29T20:39:36.880Z', 'oldestDataUpdatedTimestamp': 1556570376880, 'profile': {'email': 'email@email.com'}, 'registered': '2019-04-29T20:39:37.022Z', 'socialProviders': 'site', 'verified': '2019-04-29T20:40:39.441Z', 'verifiedTimestamp': 1556570439441, 'newUser': False, 'sessionInfo': {'cookieName': 'cookieName', 'cookieValue': 'cookieValue'}} diff --git a/tests/fixtures/gigya/login_failed.json b/tests/fixtures/gigya/login_failed.json new file mode 100644 index 00000000..b44b2367 --- /dev/null +++ b/tests/fixtures/gigya/login_failed.json @@ -0,0 +1,10 @@ +{ + "callId": "callId", + "errorCode": 403042, + "errorDetails": "invalid loginID or password", + "errorMessage": "Invalid LoginID", + "apiVersion": 2, + "statusCode": 403, + "statusReason": "Forbidden", + "time": "2020-11-17T08:22:36.561Z" +} diff --git a/tests/fixtures/gigya/login_failed.txt b/tests/fixtures/gigya/login_failed.txt deleted file mode 100644 index 779ba274..00000000 --- a/tests/fixtures/gigya/login_failed.txt +++ /dev/null @@ -1 +0,0 @@ -{'callId': 'callId', 'errorCode': 403042, 'errorDetails': 'invalid loginID or password', 'errorMessage': 'Invalid LoginID', 'apiVersion': 2, 'statusCode': 403, 'statusReason': 'Forbidden', 'time': '2020-11-17T08:22:36.561Z'} diff --git a/tests/model/test_gigya.py b/tests/model/test_gigya.py new file mode 100644 index 00000000..1fad7ddc --- /dev/null +++ b/tests/model/test_gigya.py @@ -0,0 +1,58 @@ +"""Tests for RenaultClient.""" +from typing import Any +from typing import Type + +import pytest +from marshmallow.schema import Schema + +from renault_api.exceptions import GigyaResponseException +from renault_api.model.gigya import GigyaGetAccountInfoResponse +from renault_api.model.gigya import GigyaGetAccountInfoResponseSchema +from renault_api.model.gigya import GigyaGetJWTResponse +from renault_api.model.gigya import GigyaGetJWTResponseSchema +from renault_api.model.gigya import GigyaLoginResponse +from renault_api.model.gigya import GigyaLoginResponseSchema + + +def get_response_content(path: str, schema: Type[Schema]) -> Any: + """Read fixture text file as string.""" + with open(f"tests/fixtures/gigya/{path}", "r") as file: + content = file.read() + return schema.loads(content) + + +def test_login_response() -> None: + """Test login response.""" + response: GigyaLoginResponse = get_response_content( + "login.json", GigyaLoginResponseSchema + ) + assert response.sessionInfo.cookieValue == "sample-cookie-value" + + +def test_login_failed_response() -> None: + """Test login response.""" + response: GigyaLoginResponse = get_response_content( + "login_failed.json", GigyaLoginResponseSchema + ) + with pytest.raises(GigyaResponseException) as excinfo: + response.raise_for_error_code() + assert excinfo.value.error_code == 403042 + assert excinfo.value.error_details == "invalid loginID or password" + + +def test_get_account_info_response() -> None: + """Test login response.""" + response: GigyaGetAccountInfoResponse = get_response_content( + "account_info.json", GigyaGetAccountInfoResponseSchema + ) + response.raise_for_error_code() + assert response.data.personId == "person-id-1" + + +def test_get_jwt_response() -> None: + """Test login response.""" + response: GigyaGetJWTResponse = get_response_content( + "get_jwt.json", GigyaGetJWTResponseSchema + ) + response.raise_for_error_code() + assert response.id_token == "sample-jwt-token"