diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ed055722b64..8459a54e0e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,7 +28,7 @@ jobs: strategy: matrix: os: [Ubuntu, macOS, Windows] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11-dev"] + python-version: ["3.7", "3.8", "3.9", "3.10"] include: - os: Ubuntu image: ubuntu-22.04 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5708dd2452a..eeac4684d91 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,32 +27,32 @@ repos: - id: python-check-blanket-noqa - repo: https://github.com/asottile/yesqa - rev: v1.3.0 + rev: v1.4.0 hooks: - id: yesqa additional_dependencies: &flake8_deps - flake8-annotations==2.9.0 - - flake8-broken-line==0.4.0 - - flake8-bugbear==22.4.25 + - flake8-broken-line==0.5.0 + - flake8-bugbear==22.7.1 - flake8-comprehensions==3.10.0 - - flake8-eradicate==1.2.1 + - flake8-eradicate==1.3.0 - flake8-quotes==3.3.1 - - flake8-simplify==0.19.2 + - flake8-simplify==0.19.3 - flake8-tidy-imports==4.8.0 - - flake8-type-checking==1.5.0 + - flake8-type-checking==2.1.2 - flake8-typing-imports==1.12.0 - - flake8-use-fstring==1.3 - - pep8-naming==0.12.1 + - flake8-use-fstring==1.4 + - pep8-naming==0.13.1 - repo: https://github.com/asottile/pyupgrade - rev: v2.37.1 + rev: v2.37.3 hooks: - id: pyupgrade args: [--py37-plus] exclude: ^(install|get)-poetry.py$ - repo: https://github.com/hadialqattan/pycln - rev: v2.0.4 + rev: v2.1.1 hooks: - id: pycln args: [--all] @@ -80,7 +80,7 @@ repos: - id: black - repo: https://github.com/pycqa/flake8 - rev: 4.0.1 + rev: 5.0.4 hooks: - id: flake8 additional_dependencies: *flake8_deps diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e9725ab964..0e79ef31953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,12 @@ $ poetry cache clear pypi --all - Improved autocompletion documentation ([#5879](https://github.com/python-poetry/poetry/pull/5879)) - Improved `scripts` definition documentation ([#5884](https://github.com/python-poetry/poetry/pull/5884)) +## [1.1.14] - 2022-07-08 + +## Fixed + +- Fixed an issue where dependencies hashes could not be retrieved when locking due to a breaking change on PyPI JSON API ([#5973](https://github.com/python-poetry/poetry/pull/5973)) + ## [1.2.0b2] - 2022-06-07 ### Added @@ -261,6 +267,7 @@ $ poetry cache clear pypi --all - Fixed the detection of the system environment when the setting `virtualenvs.create` is deactivated. ([#4507](https://github.com/python-poetry/poetry/pull/4507)) - Fixed an issue where unsafe parameters could be passed to `git` commands. ([python-poetry/poetry-core#203](https://github.com/python-poetry/poetry-core/pull/203)) - Fixed an issue where the wrong `git` executable could be used on Windows. ([python-poetry/poetry-core#205](https://github.com/python-poetry/poetry-core/pull/205)) + ## [1.1.8] - 2021-08-19 ### Fixed @@ -1446,6 +1453,7 @@ Initial release [1.2.0b1]: https://github.com/python-poetry/poetry/releases/tag/1.2.0b1 [1.2.0a2]: https://github.com/python-poetry/poetry/releases/tag/1.2.0a2 [1.2.0a1]: https://github.com/python-poetry/poetry/releases/tag/1.2.0a1 +[1.1.14]: https://github.com/python-poetry/poetry/releases/tag/1.1.14 [1.1.13]: https://github.com/python-poetry/poetry/releases/tag/1.1.13 [1.1.12]: https://github.com/python-poetry/poetry/releases/tag/1.1.12 [1.1.11]: https://github.com/python-poetry/poetry/releases/tag/1.1.11 diff --git a/docs/dependency-specification.md b/docs/dependency-specification.md index 2feeb6e5563..ed35104c8d5 100644 --- a/docs/dependency-specification.md +++ b/docs/dependency-specification.md @@ -145,6 +145,20 @@ flask = { git = "https://github.com/pallets/flask.git", rev = "38eb5d3b" } numpy = { git = "https://github.com/numpy/numpy.git", tag = "v0.13.2" } ``` +In cases where the package you want to install is located in a subdirectory of the VCS repository, you can use the `subdirectory` option, similarly to what [pip](https://pip.pypa.io/en/stable/topics/vcs-support/#url-fragments) provides: + +```toml +[tool.poetry.dependencies] +# Install a package named `subdir_package` from a folder called `subdir` within the repository +subdir_package = { git = "https://github.com/myorg/mypackage_with_subdirs.git", subdirectory = "subdir" } +``` + +with the corresponding `add` call: + +```bash +poetry add "https://github.com/myorg/mypackage_with_subdirs.git#subdirectory=subdir" +``` + To use an SSH connection, for example in the case of private repositories, use the following example syntax: ```toml diff --git a/docs/repositories.md b/docs/repositories.md index 8ef13b5e433..1b4128fabe0 100644 --- a/docs/repositories.md +++ b/docs/repositories.md @@ -344,7 +344,7 @@ Keyring support is enabled using the [keyring library](https://pypi.org/project/ {{% note %}} Poetry will fallback to Pip style use of keyring so that backends like -Microsoft's [artifacts-keyring](https://pypi.org/project/artifacts-keyring/) get a change to retrieve +Microsoft's [artifacts-keyring](https://pypi.org/project/artifacts-keyring/) get a chance to retrieve valid credentials. It will need to be properly installed into Poetry's virtualenv, preferably by installing a plugin. diff --git a/poetry.lock b/poetry.lock index 31f6a0bc61c..6ac107aefa9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,6 +1,6 @@ [[package]] name = "atomicwrites" -version = "1.4.0" +version = "1.4.1" description = "Atomic file writes." category = "dev" optional = false @@ -8,17 +8,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.4.0" +version = "22.1.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.5" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "cachecontrol" @@ -52,7 +52,7 @@ msgpack = ["msgpack-python (>=0.5,<0.6)"] [[package]] name = "certifi" -version = "2022.5.18.1" +version = "2022.6.15" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -60,7 +60,7 @@ python-versions = ">=3.6" [[package]] name = "cffi" -version = "1.15.0" +version = "1.15.1" description = "Foreign Function Interface for Python calling C code." category = "main" optional = false @@ -79,11 +79,11 @@ python-versions = ">=3.6.1" [[package]] name = "charset-normalizer" -version = "2.0.12" +version = "2.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.5.0" +python-versions = ">=3.6.0" [package.extras] unicode_backport = ["unicodedata2"] @@ -102,7 +102,7 @@ pylev = ">=1.3.0,<2.0.0" [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.5" description = "Cross-platform colored terminal text." category = "dev" optional = false @@ -110,7 +110,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.4.2" +version = "6.4.4" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -132,7 +132,7 @@ python-versions = ">=3.6,<4.0" [[package]] name = "cryptography" -version = "37.0.2" +version = "37.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false @@ -165,7 +165,7 @@ cli = ["click (==8.0.3)", "pyyaml (==5.4.1)", "toml (==0.10.2)", "clevercsv (==0 [[package]] name = "distlib" -version = "0.3.4" +version = "0.3.5" description = "Distribution utilities" category = "main" optional = false @@ -173,7 +173,7 @@ python-versions = "*" [[package]] name = "dulwich" -version = "0.20.44" +version = "0.20.45" description = "Python Git Library" category = "main" optional = false @@ -202,15 +202,15 @@ testing = ["pre-commit"] [[package]] name = "filelock" -version = "3.7.1" +version = "3.8.0" description = "A platform independent file lock." category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] -testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] +docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] [[package]] name = "flatdict" @@ -248,7 +248,7 @@ python-versions = ">=3" [[package]] name = "identify" -version = "2.5.1" +version = "2.5.3" description = "File identification library for Python" category = "dev" optional = false @@ -267,7 +267,7 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "4.11.4" +version = "4.12.0" description = "Read metadata from Python packages" category = "main" optional = false @@ -280,7 +280,7 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" @@ -304,21 +304,21 @@ trio = ["trio", "async-generator"] [[package]] name = "keyring" -version = "23.5.1" +version = "23.8.2" description = "Store and access your passwords safely." category = "main" optional = false python-versions = ">=3.7" [package.dependencies] -importlib-metadata = ">=3.6" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_platform == \"win32\""} SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [package.extras] docs = ["sphinx", "jaraco.packaging (>=9)", "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 (>=0.9.1)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [[package]] name = "lockfile" @@ -338,7 +338,7 @@ python-versions = "*" [[package]] name = "mypy" -version = "0.961" +version = "0.971" description = "Optional static typing for Python" category = "dev" optional = false @@ -365,11 +365,11 @@ python-versions = "*" [[package]] name = "nodeenv" -version = "1.6.0" +version = "1.7.0" description = "Node.js virtual environment builder" category = "dev" optional = false -python-versions = "*" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" [[package]] name = "ordered-set" @@ -406,14 +406,14 @@ ptyprocess = ">=0.5" [[package]] name = "pkginfo" -version = "1.8.2" +version = "1.8.3" description = "Query metadatdata from sdists / bdists / installed packages." category = "main" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] -testing = ["coverage", "nose"] +testing = ["nose", "coverage"] [[package]] name = "platformdirs" @@ -444,7 +444,7 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "poetry-core" -version = "1.1.0b3" +version = "1.1.0rc1" description = "Poetry PEP 517 Build Backend" category = "main" optional = false @@ -455,18 +455,19 @@ importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} [[package]] name = "poetry-plugin-export" -version = "1.0.5" +version = "1.0.6" description = "Poetry plugin to export the dependencies to various formats" category = "main" optional = false python-versions = ">=3.7,<4.0" [package.dependencies] -poetry = ">=1.2.0b1dev0,<2.0.0" +poetry = ">=1.2.0b3,<2.0.0" +poetry-core = ">=1.1.0b3,<2.0.0" [[package]] name = "pre-commit" -version = "2.19.0" +version = "2.20.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -586,7 +587,7 @@ pytest = ">=3.10" [[package]] name = "pytest-mock" -version = "3.7.0" +version = "3.8.2" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false @@ -612,7 +613,7 @@ pytest = "*" [[package]] name = "pytest-sugar" -version = "0.9.4" +version = "0.9.5" description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." category = "dev" optional = false @@ -660,21 +661,21 @@ python-versions = ">=3.6" [[package]] name = "requests" -version = "2.27.1" +version = "2.28.1" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7, <4" [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-toolbelt" @@ -689,7 +690,7 @@ requests = ">=2.0.1,<3.0.0" [[package]] name = "secretstorage" -version = "3.3.2" +version = "3.3.3" description = "Python bindings to FreeDesktop.org Secret Service API" category = "main" optional = false @@ -701,11 +702,11 @@ jeepney = ">=0.6" [[package]] name = "shellingham" -version = "1.4.0" +version = "1.5.0" description = "Tool to Detect Surrounding Shell" category = "main" optional = false -python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,>=2.6" +python-versions = ">=3.4" [[package]] name = "six" @@ -741,7 +742,7 @@ python-versions = ">=3.7" [[package]] name = "tomlkit" -version = "0.11.1" +version = "0.11.4" description = "Style preserving TOML library" category = "main" optional = false @@ -749,7 +750,7 @@ python-versions = ">=3.6,<4.0" [[package]] name = "tox" -version = "3.25.0" +version = "3.25.1" description = "tox is a generic virtualenv management and test command line tool" category = "dev" optional = false @@ -780,7 +781,7 @@ python-versions = ">=3.6" [[package]] name = "types-html5lib" -version = "1.1.7" +version = "1.1.9" description = "Typing stubs for html5lib" category = "dev" optional = false @@ -788,7 +789,7 @@ python-versions = "*" [[package]] name = "types-jsonschema" -version = "4.4.8" +version = "4.9.0" description = "Typing stubs for jsonschema" category = "dev" optional = false @@ -796,7 +797,7 @@ python-versions = "*" [[package]] name = "types-requests" -version = "2.27.30" +version = "2.28.8" description = "Typing stubs for requests" category = "dev" optional = false @@ -807,7 +808,7 @@ types-urllib3 = "<1.27" [[package]] name = "types-urllib3" -version = "1.26.15" +version = "1.26.22" description = "Typing stubs for urllib3" category = "dev" optional = false @@ -815,7 +816,7 @@ python-versions = "*" [[package]] name = "typing-extensions" -version = "4.2.0" +version = "4.3.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false @@ -823,11 +824,11 @@ python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.9" +version = "1.26.11" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" [package.extras] brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] @@ -836,22 +837,21 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.14.1" +version = "20.16.3" description = "Virtual Python Environment builder" category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.6" [package.dependencies] -distlib = ">=0.3.1,<1" -filelock = ">=3.2,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -platformdirs = ">=2,<3" -six = ">=1.9.0,<2" +distlib = ">=0.3.5,<1" +filelock = ">=3.4.1,<4" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.8\""} +platformdirs = ">=2.4,<3" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] +docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] +testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] [[package]] name = "webencodings" @@ -874,29 +874,28 @@ cffi = ">=1.0" [[package]] name = "zipp" -version = "3.8.0" +version = "3.8.1" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "15542c18243196724e924f1145d082c3997843f33743544474a56747d144e480" +content-hash = "b6828c80df3b7298c9bd1a2fd4df6cddcbf148f20226b51765ebad1e603b815e" [metadata.files] atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, + {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, ] attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] cachecontrol = [ {file = "CacheControl-0.12.11-py2.py3-none-any.whl", hash = "sha256:2c75d6a8938cb1933c75c50184549ad42728a27e9f6b92fd677c3151aa72555b"}, @@ -907,186 +906,209 @@ cachy = [ {file = "cachy-0.3.0.tar.gz", hash = "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1"}, ] certifi = [ - {file = "certifi-2022.5.18.1-py3-none-any.whl", hash = "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"}, - {file = "certifi-2022.5.18.1.tar.gz", hash = "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7"}, + {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, + {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, ] cffi = [ - {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, - {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, - {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, - {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, - {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, - {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, - {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, - {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, - {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, - {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, - {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, - {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, - {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, - {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, - {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, - {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, - {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, ] cfgv = [ {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, - {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, + {file = "charset-normalizer-2.1.0.tar.gz", hash = "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"}, + {file = "charset_normalizer-2.1.0-py3-none-any.whl", hash = "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5"}, ] cleo = [ {file = "cleo-1.0.0a5-py3-none-any.whl", hash = "sha256:ff53056589300976e960f75afb792dfbfc9c78dcbb5a448e207a17b643826360"}, {file = "cleo-1.0.0a5.tar.gz", hash = "sha256:097c9d0e0332fd53cc89fc11eb0a6ba0309e6a3933c08f7b38558555486925d3"}, ] colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] coverage = [ - {file = "coverage-6.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a9032f9b7d38bdf882ac9f66ebde3afb8145f0d4c24b2e600bc4c6304aafb87e"}, - {file = "coverage-6.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e0524adb49c716ca763dbc1d27bedce36b14f33e6b8af6dba56886476b42957c"}, - {file = "coverage-6.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4548be38a1c810d79e097a38107b6bf2ff42151900e47d49635be69943763d8"}, - {file = "coverage-6.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23876b018dfa5d3e98e96f5644b109090f16a4acb22064e0f06933663005d39"}, - {file = "coverage-6.4.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fe75dcfcb889b6800f072f2af5a331342d63d0c1b3d2bf0f7b4f6c353e8c9c0"}, - {file = "coverage-6.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2f8553878a24b00d5ab04b7a92a2af50409247ca5c4b7a2bf4eabe94ed20d3ee"}, - {file = "coverage-6.4.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d774d9e97007b018a651eadc1b3970ed20237395527e22cbeb743d8e73e0563d"}, - {file = "coverage-6.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d56f105592188ce7a797b2bd94b4a8cb2e36d5d9b0d8a1d2060ff2a71e6b9bbc"}, - {file = "coverage-6.4.2-cp310-cp310-win32.whl", hash = "sha256:d230d333b0be8042ac34808ad722eabba30036232e7a6fb3e317c49f61c93386"}, - {file = "coverage-6.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:5ef42e1db047ca42827a85e34abe973971c635f83aed49611b7f3ab49d0130f0"}, - {file = "coverage-6.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:25b7ec944f114f70803d6529394b64f8749e93cbfac0fe6c5ea1b7e6c14e8a46"}, - {file = "coverage-6.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bb00521ab4f99fdce2d5c05a91bddc0280f0afaee0e0a00425e28e209d4af07"}, - {file = "coverage-6.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dff52b3e7f76ada36f82124703f4953186d9029d00d6287f17c68a75e2e6039"}, - {file = "coverage-6.4.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:147605e1702d996279bb3cc3b164f408698850011210d133a2cb96a73a2f7996"}, - {file = "coverage-6.4.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:422fa44070b42fef9fb8dabd5af03861708cdd6deb69463adc2130b7bf81332f"}, - {file = "coverage-6.4.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8af6c26ba8df6338e57bedbf916d76bdae6308e57fc8f14397f03b5da8622b4e"}, - {file = "coverage-6.4.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5336e0352c0b12c7e72727d50ff02557005f79a0b8dcad9219c7c4940a930083"}, - {file = "coverage-6.4.2-cp37-cp37m-win32.whl", hash = "sha256:0f211df2cba951ffcae210ee00e54921ab42e2b64e0bf2c0befc977377fb09b7"}, - {file = "coverage-6.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a13772c19619118903d65a91f1d5fea84be494d12fd406d06c849b00d31bf120"}, - {file = "coverage-6.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f7bd0ffbcd03dc39490a1f40b2669cc414fae0c4e16b77bb26806a4d0b7d1452"}, - {file = "coverage-6.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0895ea6e6f7f9939166cc835df8fa4599e2d9b759b02d1521b574e13b859ac32"}, - {file = "coverage-6.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e7ced84a11c10160c0697a6cc0b214a5d7ab21dfec1cd46e89fbf77cc66fae"}, - {file = "coverage-6.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80db4a47a199c4563d4a25919ff29c97c87569130375beca3483b41ad5f698e8"}, - {file = "coverage-6.4.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3def6791adf580d66f025223078dc84c64696a26f174131059ce8e91452584e1"}, - {file = "coverage-6.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4f89d8e03c8a3757aae65570d14033e8edf192ee9298303db15955cadcff0c63"}, - {file = "coverage-6.4.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6d0b48aff8e9720bdec315d67723f0babd936a7211dc5df453ddf76f89c59933"}, - {file = "coverage-6.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2b20286c2b726f94e766e86a3fddb7b7e37af5d0c635bdfa7e4399bc523563de"}, - {file = "coverage-6.4.2-cp38-cp38-win32.whl", hash = "sha256:d714af0bdba67739598849c9f18efdcc5a0412f4993914a0ec5ce0f1e864d783"}, - {file = "coverage-6.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:5f65e5d3ff2d895dab76b1faca4586b970a99b5d4b24e9aafffc0ce94a6022d6"}, - {file = "coverage-6.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a697977157adc052284a7160569b36a8bbec09db3c3220642e6323b47cec090f"}, - {file = "coverage-6.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c77943ef768276b61c96a3eb854eba55633c7a3fddf0a79f82805f232326d33f"}, - {file = "coverage-6.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54d8d0e073a7f238f0666d3c7c0d37469b2aa43311e4024c925ee14f5d5a1cbe"}, - {file = "coverage-6.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f22325010d8824594820d6ce84fa830838f581a7fd86a9235f0d2ed6deb61e29"}, - {file = "coverage-6.4.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b04d305ea172ccb21bee5bacd559383cba2c6fcdef85b7701cf2de4188aa55"}, - {file = "coverage-6.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:866ebf42b4c5dbafd64455b0a1cd5aa7b4837a894809413b930026c91e18090b"}, - {file = "coverage-6.4.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e36750fbbc422c1c46c9d13b937ab437138b998fe74a635ec88989afb57a3978"}, - {file = "coverage-6.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:79419370d6a637cb18553ecb25228893966bd7935a9120fa454e7076f13b627c"}, - {file = "coverage-6.4.2-cp39-cp39-win32.whl", hash = "sha256:b5e28db9199dd3833cc8a07fa6cf429a01227b5d429facb56eccd765050c26cd"}, - {file = "coverage-6.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:edfdabe7aa4f97ed2b9dd5dde52d2bb29cb466993bb9d612ddd10d0085a683cf"}, - {file = "coverage-6.4.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:e2618cb2cf5a7cc8d698306e42ebcacd02fb7ef8cfc18485c59394152c70be97"}, - {file = "coverage-6.4.2.tar.gz", hash = "sha256:6c3ccfe89c36f3e5b9837b9ee507472310164f352c9fe332120b764c9d60adbe"}, + {file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"}, + {file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"}, + {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"}, + {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"}, + {file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"}, + {file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"}, + {file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"}, + {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"}, + {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"}, + {file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"}, + {file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"}, + {file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"}, + {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"}, + {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"}, + {file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"}, + {file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"}, + {file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"}, + {file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"}, + {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"}, + {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"}, + {file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"}, + {file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"}, + {file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"}, + {file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"}, + {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"}, + {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"}, + {file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"}, + {file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"}, + {file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"}, + {file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"}, ] crashtest = [ {file = "crashtest-0.3.1-py3-none-any.whl", hash = "sha256:300f4b0825f57688b47b6d70c6a31de33512eb2fa1ac614f780939aa0cf91680"}, {file = "crashtest-0.3.1.tar.gz", hash = "sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd"}, ] cryptography = [ - {file = "cryptography-37.0.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:ef15c2df7656763b4ff20a9bc4381d8352e6640cfeb95c2972c38ef508e75181"}, - {file = "cryptography-37.0.2-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:3c81599befb4d4f3d7648ed3217e00d21a9341a9a688ecdd615ff72ffbed7336"}, - {file = "cryptography-37.0.2-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2bd1096476aaac820426239ab534b636c77d71af66c547b9ddcd76eb9c79e004"}, - {file = "cryptography-37.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:31fe38d14d2e5f787e0aecef831457da6cec68e0bb09a35835b0b44ae8b988fe"}, - {file = "cryptography-37.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:093cb351031656d3ee2f4fa1be579a8c69c754cf874206be1d4cf3b542042804"}, - {file = "cryptography-37.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59b281eab51e1b6b6afa525af2bd93c16d49358404f814fe2c2410058623928c"}, - {file = "cryptography-37.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:0cc20f655157d4cfc7bada909dc5cc228211b075ba8407c46467f63597c78178"}, - {file = "cryptography-37.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f8ec91983e638a9bcd75b39f1396e5c0dc2330cbd9ce4accefe68717e6779e0a"}, - {file = "cryptography-37.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:46f4c544f6557a2fefa7ac8ac7d1b17bf9b647bd20b16decc8fbcab7117fbc15"}, - {file = "cryptography-37.0.2-cp36-abi3-win32.whl", hash = "sha256:731c8abd27693323b348518ed0e0705713a36d79fdbd969ad968fbef0979a7e0"}, - {file = "cryptography-37.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:471e0d70201c069f74c837983189949aa0d24bb2d751b57e26e3761f2f782b8d"}, - {file = "cryptography-37.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a68254dd88021f24a68b613d8c51d5c5e74d735878b9e32cc0adf19d1f10aaf9"}, - {file = "cryptography-37.0.2-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:a7d5137e556cc0ea418dca6186deabe9129cee318618eb1ffecbd35bee55ddc1"}, - {file = "cryptography-37.0.2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aeaba7b5e756ea52c8861c133c596afe93dd716cbcacae23b80bc238202dc023"}, - {file = "cryptography-37.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95e590dd70642eb2079d280420a888190aa040ad20f19ec8c6e097e38aa29e06"}, - {file = "cryptography-37.0.2-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1b9362d34363f2c71b7853f6251219298124aa4cc2075ae2932e64c91a3e2717"}, - {file = "cryptography-37.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e53258e69874a306fcecb88b7534d61820db8a98655662a3dd2ec7f1afd9132f"}, - {file = "cryptography-37.0.2-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:1f3bfbd611db5cb58ca82f3deb35e83af34bb8cf06043fa61500157d50a70982"}, - {file = "cryptography-37.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:419c57d7b63f5ec38b1199a9521d77d7d1754eb97827bbb773162073ccd8c8d4"}, - {file = "cryptography-37.0.2-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:dc26bb134452081859aa21d4990474ddb7e863aa39e60d1592800a8865a702de"}, - {file = "cryptography-37.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b8398b3d0efc420e777c40c16764d6870bcef2eb383df9c6dbb9ffe12c64452"}, - {file = "cryptography-37.0.2.tar.gz", hash = "sha256:f224ad253cc9cea7568f49077007d2263efa57396a2f2f78114066fd54b5c68e"}, + {file = "cryptography-37.0.4-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:549153378611c0cca1042f20fd9c5030d37a72f634c9326e225c9f666d472884"}, + {file = "cryptography-37.0.4-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a958c52505c8adf0d3822703078580d2c0456dd1d27fabfb6f76fe63d2971cd6"}, + {file = "cryptography-37.0.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f721d1885ecae9078c3f6bbe8a88bc0786b6e749bf32ccec1ef2b18929a05046"}, + {file = "cryptography-37.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3d41b965b3380f10e4611dbae366f6dc3cefc7c9ac4e8842a806b9672ae9add5"}, + {file = "cryptography-37.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80f49023dd13ba35f7c34072fa17f604d2f19bf0989f292cedf7ab5770b87a0b"}, + {file = "cryptography-37.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2dcb0b3b63afb6df7fd94ec6fbddac81b5492513f7b0436210d390c14d46ee8"}, + {file = "cryptography-37.0.4-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:b7f8dd0d4c1f21759695c05a5ec8536c12f31611541f8904083f3dc582604280"}, + {file = "cryptography-37.0.4-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:30788e070800fec9bbcf9faa71ea6d8068f5136f60029759fd8c3efec3c9dcb3"}, + {file = "cryptography-37.0.4-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:190f82f3e87033821828f60787cfa42bff98404483577b591429ed99bed39d59"}, + {file = "cryptography-37.0.4-cp36-abi3-win32.whl", hash = "sha256:b62439d7cd1222f3da897e9a9fe53bbf5c104fff4d60893ad1355d4c14a24157"}, + {file = "cryptography-37.0.4-cp36-abi3-win_amd64.whl", hash = "sha256:f7a6de3e98771e183645181b3627e2563dcde3ce94a9e42a3f427d2255190327"}, + {file = "cryptography-37.0.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc95ed67b6741b2607298f9ea4932ff157e570ef456ef7ff0ef4884a134cc4b"}, + {file = "cryptography-37.0.4-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9"}, + {file = "cryptography-37.0.4-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:e007f052ed10cc316df59bc90fbb7ff7950d7e2919c9757fd42a2b8ecf8a5f67"}, + {file = "cryptography-37.0.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bc997818309f56c0038a33b8da5c0bfbb3f1f067f315f9abd6fc07ad359398d"}, + {file = "cryptography-37.0.4-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:d204833f3c8a33bbe11eda63a54b1aad7aa7456ed769a982f21ec599ba5fa282"}, + {file = "cryptography-37.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:75976c217f10d48a8b5a8de3d70c454c249e4b91851f6838a4e48b8f41eb71aa"}, + {file = "cryptography-37.0.4-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:7099a8d55cd49b737ffc99c17de504f2257e3787e02abe6d1a6d136574873441"}, + {file = "cryptography-37.0.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2be53f9f5505673eeda5f2736bea736c40f051a739bfae2f92d18aed1eb54596"}, + {file = "cryptography-37.0.4-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:91ce48d35f4e3d3f1d83e29ef4a9267246e6a3be51864a5b7d2247d5086fa99a"}, + {file = "cryptography-37.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab"}, + {file = "cryptography-37.0.4.tar.gz", hash = "sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82"}, ] deepdiff = [ {file = "deepdiff-5.8.1-py3-none-any.whl", hash = "sha256:e9aea49733f34fab9a0897038d8f26f9d94a97db1790f1b814cced89e9e0d2b7"}, {file = "deepdiff-5.8.1.tar.gz", hash = "sha256:8d4eb2c4e6cbc80b811266419cb71dd95a157094a3947ccf937a94d44943c7b8"}, ] distlib = [ - {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, - {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, + {file = "distlib-0.3.5-py2.py3-none-any.whl", hash = "sha256:b710088c59f06338ca514800ad795a132da19fda270e3ce4affc74abf955a26c"}, + {file = "distlib-0.3.5.tar.gz", hash = "sha256:a7f75737c70be3b25e2bee06288cec4e4c221de18455b2dd037fe2a795cab2fe"}, ] dulwich = [ - {file = "dulwich-0.20.44-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:2f6e35487963296894f2a2fcc49cc1340c24592ea465962f96a33f1527afd3f7"}, - {file = "dulwich-0.20.44-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46273dd4b6fc80f7bd3cdfe35ed1e7ed5cbd9850735b12b1a64f81058f337351"}, - {file = "dulwich-0.20.44-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7a884dd92bbfe66e4662a71d302b22b7910cc694d45f6e32acd1ae5da877183"}, - {file = "dulwich-0.20.44-cp310-cp310-win_amd64.whl", hash = "sha256:61eb4633410ed7e6b49a0ce0f0a4a0604206fc1532ea119b948ff3cf974a0d02"}, - {file = "dulwich-0.20.44-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:6ac93e78eb19f65d958e339818316af07579cdf826257562d3f7310d7535d205"}, - {file = "dulwich-0.20.44-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d18029b40faa09848cb9a9e5a1b5fcc5365f0c959e9fcb3ec63ec78720dfe5e1"}, - {file = "dulwich-0.20.44-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cbe9c167f3a591ac308a8dd54eef901db42cb898dd7f343479ef3badec4b96cc"}, - {file = "dulwich-0.20.44-cp36-cp36m-win_amd64.whl", hash = "sha256:a6a224c28aa47e960c0fa388ad7acc93346bf36cc8bae6f7b4524b14b0c30b7a"}, - {file = "dulwich-0.20.44-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:0e324240007fb2bb5f8c2b92244146cc02a8c451890e3b75257dbc1b14e4fe93"}, - {file = "dulwich-0.20.44-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d97c739bfa8b99dfe40075b5928b16224aa22d739cba57855cccb4d8ee325654"}, - {file = "dulwich-0.20.44-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5f9130827f89bbf013fa169d25fc113503e6536e2759b246db086300bf0caf05"}, - {file = "dulwich-0.20.44-cp37-cp37m-win_amd64.whl", hash = "sha256:63bdfc0b8d762b66053f3dadbbb4b57ac65d201b9863140b6aefc742a4c94814"}, - {file = "dulwich-0.20.44-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f6d9822ce617de1836256808f43dceb80fb343d634d28aef170e87ca47176f83"}, - {file = "dulwich-0.20.44-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:496fa0298285d5e442e858d742ed3fc721a15452b736a03c89124acd08f169a7"}, - {file = "dulwich-0.20.44-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:29f56137a686e956dfa84242f12a79f2c13a0f0840646884de230f3ad07ccc50"}, - {file = "dulwich-0.20.44-cp38-cp38-win_amd64.whl", hash = "sha256:4784e480c6368e1199e5292aca558455b65dbc1b5b0f06341e5702041c5e275a"}, - {file = "dulwich-0.20.44-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:6aa185f04dfba6ab15c36c06ff5f0e8b44f05268011699c25e18b320a76d2d3f"}, - {file = "dulwich-0.20.44-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45a069407630b60d85345da9c9bed07fe9a3d0b55fc3705815ddac1f31ce97be"}, - {file = "dulwich-0.20.44-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:68e46a462d7686f440ef849947b7284412a2715e084090c8f5624d871758bf98"}, - {file = "dulwich-0.20.44-cp39-cp39-win_amd64.whl", hash = "sha256:0a227684997f94518de53041503f4d467ef711319a09b85479a564c751ced65c"}, - {file = "dulwich-0.20.44.tar.gz", hash = "sha256:10e8d73763dd30c86a99a15ade8bfcf3ab8fe96532cdf497e8cb1d11832352b8"}, + {file = "dulwich-0.20.45-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:9b689b05bc7baa5cb20ebff54291085b598a9bdf7caeab23daf93b46421d96ff"}, + {file = "dulwich-0.20.45-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7cf5171034d9d61b928bd5f9c509000e895d1ba29bd6ea850b9e4f93fca0f7"}, + {file = "dulwich-0.20.45-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22d433ba9c776f2b0e19b1186e01e25ca286175e20f4ac422141db94eeaac08b"}, + {file = "dulwich-0.20.45-cp310-cp310-win_amd64.whl", hash = "sha256:6e02babb44bdad17b6c9c50b4f9df42f6e511e3a51555ac07dd85ec904efe0b1"}, + {file = "dulwich-0.20.45-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:042bc206764968b17338e32c52bb6a116154eb87a63651971946917dfa37a359"}, + {file = "dulwich-0.20.45-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e405ac9426288ca782c45e066f816d878b4a529acf4d4b0b2a5bb45a804dfec"}, + {file = "dulwich-0.20.45-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c8c0fc7d2e3b0ad6a4faadf96f0626fa50935ababfd774b9b94edaa28f0668ec"}, + {file = "dulwich-0.20.45-cp36-cp36m-win_amd64.whl", hash = "sha256:35015e43207752cf7924860e85a3c2290c652c0c3ee81e7c95c52d34638f605d"}, + {file = "dulwich-0.20.45-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d89f53a739ac3394b5ef2f178480569b7d36d4fe7b4bb49678582914530ce35b"}, + {file = "dulwich-0.20.45-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abb1b0e1e50192ce7204c4e14f24c989c5920c56de908365f4e66c6e3458945"}, + {file = "dulwich-0.20.45-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eb4189d72a0e2f3070e2abdbd10a05c0e62355cd5496761d6e68f1e865ac6fad"}, + {file = "dulwich-0.20.45-cp37-cp37m-win_amd64.whl", hash = "sha256:efe46167eb02ba85d9c2e993635e7543e1e04bb3261112e9d54daff2385ae5df"}, + {file = "dulwich-0.20.45-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:3f2c137a0003e80e384d116e65b453f8a704c2d393c30a47b447764e7f9c05a1"}, + {file = "dulwich-0.20.45-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334bd7a1d91054516a49f86343e9c2549740bbddebcbb4763c8aacf2aac48c"}, + {file = "dulwich-0.20.45-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5e41044ac51a4b3454d67e5f691808540470deeb6a852d7c5c6ca44c48b4cdc3"}, + {file = "dulwich-0.20.45-cp38-cp38-win_amd64.whl", hash = "sha256:d8b6aae7af8edbfac8038e1777ae820efac33c7c22a8025d3254bbd53ec725b5"}, + {file = "dulwich-0.20.45-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:bb75268cec2f3ae6f6b7addbc0db50db2e9e42b2ad8364e74b9f5b17ab0053b5"}, + {file = "dulwich-0.20.45-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f64870f2f206dda3308cb73563f5f59fdc084179271651a0488d12ab4185b9"}, + {file = "dulwich-0.20.45-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:49852f12c1e1d50039f927e9fdee1bd00a9b428c31b078ba5ba9fc1cf88e9d3e"}, + {file = "dulwich-0.20.45-cp39-cp39-win_amd64.whl", hash = "sha256:3136bcaf7508522a2aa63f856743f06129261bc5a03331aa6a0654fa6d04a4ae"}, + {file = "dulwich-0.20.45.tar.gz", hash = "sha256:70710dd9ca2a442190c7e506892db074c318ac762e221f7529b8ce34802041b7"}, ] execnet = [ {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, ] filelock = [ - {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"}, - {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"}, + {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, + {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, ] flatdict = [ {file = "flatdict-4.0.1.tar.gz", hash = "sha256:cd32f08fd31ed21eb09ebc76f06b6bd12046a24f77beb1fd0281917e47f26742"}, @@ -1099,16 +1121,16 @@ httpretty = [ {file = "httpretty-1.1.4.tar.gz", hash = "sha256:20de0e5dd5a18292d36d928cc3d6e52f8b2ac73daec40d41eb62dee154933b68"}, ] identify = [ - {file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"}, - {file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"}, + {file = "identify-2.5.3-py2.py3-none-any.whl", hash = "sha256:25851c8c1370effb22aaa3c987b30449e9ff0cece408f810ae6ce408fdd20893"}, + {file = "identify-2.5.3.tar.gz", hash = "sha256:887e7b91a1be152b0d46bbf072130235a8117392b9f1828446079a816a05ef44"}, ] 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.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"}, - {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"}, + {file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"}, + {file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, @@ -1119,8 +1141,8 @@ jeepney = [ {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, ] keyring = [ - {file = "keyring-23.5.1-py3-none-any.whl", hash = "sha256:9ef58314bcc823f426b49ec787539a2d73571b37de4cd498f839803b01acff1e"}, - {file = "keyring-23.5.1.tar.gz", hash = "sha256:dee502cdf18a98211bef428eea11456a33c00718b2f08524fd5727c7f424bffd"}, + {file = "keyring-23.8.2-py3-none-any.whl", hash = "sha256:10d2a8639663fe2090705a00b8c47c687cacdf97598ea9c11456679fa974473a"}, + {file = "keyring-23.8.2.tar.gz", hash = "sha256:0d9973f8891850f1ade5f26aafd06bb16865fbbae3fc56b0defb6a14a2624003"}, ] lockfile = [ {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, @@ -1181,37 +1203,37 @@ msgpack = [ {file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"}, ] mypy = [ - {file = "mypy-0.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"}, - {file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"}, - {file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"}, - {file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"}, - {file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"}, - {file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"}, - {file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"}, - {file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"}, - {file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"}, - {file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"}, - {file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"}, - {file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"}, - {file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"}, - {file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"}, - {file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"}, - {file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"}, - {file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"}, - {file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"}, - {file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"}, - {file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"}, - {file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"}, - {file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"}, - {file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"}, + {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, + {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, + {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, + {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, + {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, + {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, + {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, + {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, + {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, + {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, + {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, + {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, + {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, + {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, + {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, + {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, + {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, + {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, + {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, + {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, + {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, + {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, + {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] nodeenv = [ - {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, - {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, ] ordered-set = [ {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, @@ -1226,8 +1248,8 @@ pexpect = [ {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, ] pkginfo = [ - {file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"}, - {file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"}, + {file = "pkginfo-1.8.3-py2.py3-none-any.whl", hash = "sha256:848865108ec99d4901b2f7e84058b6e7660aae8ae10164e015a6dcf5b242a594"}, + {file = "pkginfo-1.8.3.tar.gz", hash = "sha256:a84da4318dd86f870a9447a8c98340aa06216bfc6f2b7bdc4b8766984ae1867c"}, ] platformdirs = [ {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, @@ -1238,16 +1260,16 @@ pluggy = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] poetry-core = [ - {file = "poetry-core-1.1.0b3.tar.gz", hash = "sha256:ea257bb0aab15008d1680cc221a46f3457a3b36f3d463736f552497f0b6b9350"}, - {file = "poetry_core-1.1.0b3-py3-none-any.whl", hash = "sha256:2b65b697e22fc6fc9b60afcadfd4421db796d30d558a003654b5e67e3b262eaa"}, + {file = "poetry-core-1.1.0rc1.tar.gz", hash = "sha256:993ebe45b3fe06deb022a0fd5483d760211f37eef6337122caa098d75d7da1f3"}, + {file = "poetry_core-1.1.0rc1-py3-none-any.whl", hash = "sha256:4a5ae0cda9df52fa6725d6afecca7b3207576c4e896c18b1e20cf3a57e4f513a"}, ] poetry-plugin-export = [ - {file = "poetry-plugin-export-1.0.5.tar.gz", hash = "sha256:e7796292eaafac1316149f3a8070923c2a2214c98d046de1246b4d8eb0b0c84b"}, - {file = "poetry_plugin_export-1.0.5-py3-none-any.whl", hash = "sha256:925088b27c5747c3e0d8cc2bbb692a533eb4569874a676ac0d0f5ab237b15aaa"}, + {file = "poetry-plugin-export-1.0.6.tar.gz", hash = "sha256:af870afceb38e583afa57bcfadfa5cd35ebd74e35aacadcb802bb3a073c13adb"}, + {file = "poetry_plugin_export-1.0.6-py3-none-any.whl", hash = "sha256:55ae87d4560a6a3f96e04eba63c78cadbd0410e9652dee0ee1cde93281e9cb48"}, ] pre-commit = [ - {file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"}, - {file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"}, + {file = "pre_commit-2.20.0-py2.py3-none-any.whl", hash = "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7"}, + {file = "pre_commit-2.20.0.tar.gz", hash = "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959"}, ] psutil = [ {file = "psutil-5.9.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:799759d809c31aab5fe4579e50addf84565e71c1dc9f1c31258f159ff70d3f87"}, @@ -1316,15 +1338,16 @@ pytest-forked = [ {file = "pytest_forked-1.4.0-py3-none-any.whl", hash = "sha256:bbbb6717efc886b9d64537b41fb1497cfaf3c9601276be8da2cccfea5a3c8ad8"}, ] pytest-mock = [ - {file = "pytest-mock-3.7.0.tar.gz", hash = "sha256:5112bd92cc9f186ee96e1a92efc84969ea494939c3aead39c50f421c4cc69534"}, - {file = "pytest_mock-3.7.0-py3-none-any.whl", hash = "sha256:6cff27cec936bf81dc5ee87f07132b807bcda51106b5ec4b90a04331cba76231"}, + {file = "pytest-mock-3.8.2.tar.gz", hash = "sha256:77f03f4554392558700295e05aed0b1096a20d4a60a4f3ddcde58b0c31c8fca2"}, + {file = "pytest_mock-3.8.2-py3-none-any.whl", hash = "sha256:8a9e226d6c0ef09fcf20c94eb3405c388af438a90f3e39687f84166da82d5948"}, ] pytest-randomly = [ {file = "pytest-randomly-3.12.0.tar.gz", hash = "sha256:d60c2db71ac319aee0fc6c4110a7597d611a8b94a5590918bfa8583f00caccb2"}, {file = "pytest_randomly-3.12.0-py3-none-any.whl", hash = "sha256:f4f2e803daf5d1ba036cc22bf4fe9dbbf99389ec56b00e5cba732fb5c1d07fdd"}, ] pytest-sugar = [ - {file = "pytest-sugar-0.9.4.tar.gz", hash = "sha256:b1b2186b0a72aada6859bea2a5764145e3aaa2c1cfbb23c3a19b5f7b697563d3"}, + {file = "pytest-sugar-0.9.5.tar.gz", hash = "sha256:eea78b6f15b635277d3d90280cd386d8feea1cab0f9be75947a626e8b02b477d"}, + {file = "pytest_sugar-0.9.5-py2.py3-none-any.whl", hash = "sha256:3da42de32ce4e1e95b448d61c92804433f5d4058c0a765096991c2e93d5a289f"}, ] pytest-xdist = [ {file = "pytest-xdist-2.5.0.tar.gz", hash = "sha256:4580deca3ff04ddb2ac53eba39d76cb5dd5edeac050cb6fbc768b0dd712b4edf"}, @@ -1370,20 +1393,20 @@ pyyaml = [ {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] requests = [ - {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, - {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] requests-toolbelt = [ {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, ] secretstorage = [ - {file = "SecretStorage-3.3.2-py3-none-any.whl", hash = "sha256:755dc845b6ad76dcbcbc07ea3da75ae54bb1ea529eb72d15f83d26499a5df319"}, - {file = "SecretStorage-3.3.2.tar.gz", hash = "sha256:0a8eb9645b320881c222e827c26f4cfcf55363e8b374a021981ef886657a912f"}, + {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, + {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, ] shellingham = [ - {file = "shellingham-1.4.0-py2.py3-none-any.whl", hash = "sha256:536b67a0697f2e4af32ab176c00a50ac2899c5a05e0d8e2dadac8e58888283f9"}, - {file = "shellingham-1.4.0.tar.gz", hash = "sha256:4855c2458d6904829bd34c299f11fdeed7cfefbf8a2c522e4caea6cd76b3171e"}, + {file = "shellingham-1.5.0-py2.py3-none-any.whl", hash = "sha256:a8f02ba61b69baaa13facdba62908ca8690a94b8119b69f5ec5873ea85f7391b"}, + {file = "shellingham-1.5.0.tar.gz", hash = "sha256:72fb7f5c63103ca2cb91b23dee0c71fe8ad6fbfd46418ef17dbe40db51592dad"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1401,12 +1424,12 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [ - {file = "tomlkit-0.11.1-py3-none-any.whl", hash = "sha256:1c5bebdf19d5051e2e1de6cf70adfc5948d47221f097fcff7a3ffc91e953eaf5"}, - {file = "tomlkit-0.11.1.tar.gz", hash = "sha256:61901f81ff4017951119cd0d1ed9b7af31c821d6845c8c477587bbdcd5e5854e"}, + {file = "tomlkit-0.11.4-py3-none-any.whl", hash = "sha256:25d4e2e446c453be6360c67ddfb88838cfc42026322770ba13d1fbd403a93a5c"}, + {file = "tomlkit-0.11.4.tar.gz", hash = "sha256:3235a9010fae54323e727c3ac06fb720752fe6635b3426e379daec60fbd44a83"}, ] tox = [ - {file = "tox-3.25.0-py2.py3-none-any.whl", hash = "sha256:0805727eb4d6b049de304977dfc9ce315a1938e6619c3ab9f38682bb04662a5a"}, - {file = "tox-3.25.0.tar.gz", hash = "sha256:37888f3092aa4e9f835fc8cc6dadbaaa0782651c41ef359e3a5743fcb0308160"}, + {file = "tox-3.25.1-py2.py3-none-any.whl", hash = "sha256:c38e15f4733683a9cc0129fba078633e07eb0961f550a010ada879e95fb32632"}, + {file = "tox-3.25.1.tar.gz", hash = "sha256:c138327815f53bc6da4fe56baec5f25f00622ae69ef3fe4e1e385720e22486f9"}, ] typed-ast = [ {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, @@ -1435,32 +1458,32 @@ typed-ast = [ {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, ] types-html5lib = [ - {file = "types-html5lib-1.1.7.tar.gz", hash = "sha256:fdb307102ceea52adf52aea0e10255d142ee29d7f169014144a730707a92066a"}, - {file = "types_html5lib-1.1.7-py3-none-any.whl", hash = "sha256:4bc5a1de03b9a697b7cc04b0d03eeed5d36c0073165dd9dc54f2f43d0f23b31f"}, + {file = "types-html5lib-1.1.9.tar.gz", hash = "sha256:a2caebcddb43ba0387579b14c585fe87d53236820e21acff01cac084b0836cb7"}, + {file = "types_html5lib-1.1.9-py3-none-any.whl", hash = "sha256:4a5c1dd200f119f0a226b1c0fe744c8a2a127ff7409c58b1e80115fc3631daec"}, ] types-jsonschema = [ - {file = "types-jsonschema-4.4.8.tar.gz", hash = "sha256:90be58439cb04793b5d359edc2e40a258b9f9409c68ff8e87086420d2b952f7b"}, - {file = "types_jsonschema-4.4.8-py3-none-any.whl", hash = "sha256:601e533d2a9fb851e7ee3a6129362d7d7274dd65b59135471a4afe371fad9e5d"}, + {file = "types-jsonschema-4.9.0.tar.gz", hash = "sha256:b1743257464ba71c80e8c085b4c2a871c98973e4d18e7766bc2b3976bdb7a65b"}, + {file = "types_jsonschema-4.9.0-py3-none-any.whl", hash = "sha256:822221913ff6c8348a6e8af45e70bc223e42767857688a7716795b720de6c214"}, ] types-requests = [ - {file = "types-requests-2.27.30.tar.gz", hash = "sha256:ca8d7cc549c3d10dbcb3c69c1b53e3ffd1270089c1001a65c1e9e1017eb5e704"}, - {file = "types_requests-2.27.30-py3-none-any.whl", hash = "sha256:b9b6cd0a6e5d500e56419b79f44ec96f316e9375ff6c8ee566c39d25e9612621"}, + {file = "types-requests-2.28.8.tar.gz", hash = "sha256:7a9f7b152d594a1c18dd4932cdd2596b8efbeedfd73caa4e4abb3755805b4685"}, + {file = "types_requests-2.28.8-py3-none-any.whl", hash = "sha256:b0421f9f2d0dd0f8df2c75f974686517ca67473f05b466232d4c6384d765ad7a"}, ] types-urllib3 = [ - {file = "types-urllib3-1.26.15.tar.gz", hash = "sha256:c89283541ef92e344b7f59f83ea9b5a295b16366ceee3f25ecfc5593c79f794e"}, - {file = "types_urllib3-1.26.15-py3-none-any.whl", hash = "sha256:6011befa13f901fc934f59bb1fd6973be6f3acf4ebfce427593a27e7f492918f"}, + {file = "types-urllib3-1.26.22.tar.gz", hash = "sha256:b05af90e73889e688094008a97ca95788db8bf3736e2776fd43fb6b171485d94"}, + {file = "types_urllib3-1.26.22-py3-none-any.whl", hash = "sha256:09a8783e1002472e8d1e1f3792d4c5cca1fffebb9b48ee1512aae6d16fe186bc"}, ] typing-extensions = [ - {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, - {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, + {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, + {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, ] urllib3 = [ - {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, - {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, + {file = "urllib3-1.26.11-py2.py3-none-any.whl", hash = "sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc"}, + {file = "urllib3-1.26.11.tar.gz", hash = "sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a"}, ] virtualenv = [ - {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"}, - {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"}, + {file = "virtualenv-20.16.3-py2.py3-none-any.whl", hash = "sha256:4193b7bc8a6cd23e4eb251ac64f29b4398ab2c233531e66e40b19a6b7b0d30c1"}, + {file = "virtualenv-20.16.3.tar.gz", hash = "sha256:d86ea0bb50e06252d79e6c241507cb904fcd66090c3271381372d6221a3970f9"}, ] webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, @@ -1524,6 +1547,6 @@ xattr = [ {file = "xattr-0.9.9.tar.gz", hash = "sha256:09cb7e1efb3aa1b4991d6be4eb25b73dc518b4fe894f0915f5b0dcede972f346"}, ] zipp = [ - {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, - {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, + {file = "zipp-3.8.1-py3-none-any.whl", hash = "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"}, + {file = "zipp-3.8.1.tar.gz", hash = "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2"}, ] diff --git a/pyproject.toml b/pyproject.toml index 9217bbbf6e4..cef867a8e0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,8 +44,8 @@ generate-setup-file = false [tool.poetry.dependencies] python = "^3.7" -poetry-core = "^1.1.0b3" -poetry-plugin-export = "^1.0.5" +poetry-core = "^1.1.0rc1" +poetry-plugin-export = "^1.0.6" cachecontrol = { version = "^0.12.9", extras = ["filecache"] } cachy = "^0.3.0" cleo = "^1.0.0a5" @@ -61,8 +61,9 @@ pkginfo = "^1.5" platformdirs = "^2.5.2" requests = "^2.18" requests-toolbelt = "^0.9.1" -shellingham = "^1.1" -tomlkit = ">=0.11.1,<1.0.0" +shellingham = "^1.5" +# exclude 0.11.2 and 0.11.3 due to https://github.com/sdispater/tomlkit/issues/225 +tomlkit = ">=0.11.1,<1.0.0,!=0.11.2,!=0.11.3" # exclude 20.4.5 - 20.4.6 due to https://github.com/pypa/pip/issues/9953 virtualenv = "(>=20.4.3,<20.4.5 || >=20.4.7)" xattr = { version = "^0.9.7", markers = "sys_platform == 'darwin'" } @@ -83,10 +84,10 @@ httpretty = "^1.0" typing-extensions = { version = "^4.0.0", python = "<3.8" } zipp = { version = "^3.4", python = "<3.8" } flatdict = "^4.0.1" -mypy = ">=0.960" -types-html5lib = ">=1.1.7" -types-jsonschema = ">=4.4.4" -types-requests = ">=2.27.11" +mypy = ">=0.971" +types-html5lib = ">=1.1.9" +types-jsonschema = ">=4.9.0" +types-requests = ">=2.28.8" [tool.poetry.scripts] poetry = "poetry.console.application:main" diff --git a/src/poetry/console/application.py b/src/poetry/console/application.py index c7250cb6c0b..00a9488377b 100644 --- a/src/poetry/console/application.py +++ b/src/poetry/console/application.py @@ -38,13 +38,13 @@ from poetry.poetry import Poetry -def load_command(name: str) -> Callable[[], type[Command]]: - def _load() -> type[Command]: +def load_command(name: str) -> Callable[[], Command]: + def _load() -> Command: words = name.split(" ") module = import_module("poetry.console.commands." + ".".join(words)) command_class = getattr(module, "".join(c.title() for c in words) + "Command") - command_type: type[Command] = command_class() - return command_type + command: Command = command_class() + return command return _load @@ -136,7 +136,8 @@ def poetry(self) -> Poetry: @property def command_loader(self) -> CommandLoader: - command_loader: CommandLoader = self._command_loader + command_loader: CommandLoader | None = self._command_loader + assert command_loader is not None return command_loader def reset_poetry(self) -> None: @@ -333,7 +334,7 @@ def configure_installer_for_command(command: InstallerCommand, io: IO) -> None: installer.use_executor(poetry.config.get("experimental.new-installer", False)) command.set_installer(installer) - def _load_plugins(self, io: IO = None) -> None: + def _load_plugins(self, io: IO | None = None) -> None: if self._plugins_loaded: return diff --git a/src/poetry/console/commands/config.py b/src/poetry/console/commands/config.py index 6c07508161e..03773a5ef0d 100644 --- a/src/poetry/console/commands/config.py +++ b/src/poetry/console/commands/config.py @@ -38,7 +38,8 @@ class ConfigCommand(Command): option("local", None, "Set/Get from the project's local configuration."), ] - help = """This command allows you to edit the poetry config settings and repositories. + help = """\ +This command allows you to edit the poetry config settings and repositories. To add a repository: diff --git a/src/poetry/console/commands/debug/resolve.py b/src/poetry/console/commands/debug/resolve.py index f29aeaca22f..006280021fc 100644 --- a/src/poetry/console/commands/debug/resolve.py +++ b/src/poetry/console/commands/debug/resolve.py @@ -1,16 +1,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING - from cleo.helpers import argument from cleo.helpers import option from cleo.io.outputs.output import Verbosity from poetry.console.commands.init import InitCommand - - -if TYPE_CHECKING: - from poetry.console.commands.show import ShowCommand +from poetry.console.commands.show import ShowCommand class DebugResolveCommand(InitCommand): @@ -94,7 +89,8 @@ def handle(self) -> int: self.line("") if self.option("tree"): - show_command: ShowCommand = self.application.find("show") + show_command = self.application.find("show") + assert isinstance(show_command, ShowCommand) show_command.init_styles(self.io) packages = [op.package for op in ops] diff --git a/src/poetry/console/commands/init.py b/src/poetry/console/commands/init.py index 3817f7ad3c6..e2ebf9cf9b7 100644 --- a/src/poetry/console/commands/init.py +++ b/src/poetry/console/commands/init.py @@ -19,6 +19,7 @@ if TYPE_CHECKING: + from packaging.utils import NormalizedName from poetry.core.packages.package import Package from tomlkit.items import InlineTable @@ -238,7 +239,7 @@ def handle(self) -> int: return 0 def _generate_choice_list( - self, matches: list[Package], canonicalized_name: str + self, matches: list[Package], canonicalized_name: NormalizedName ) -> list[str]: choices = [] matches_names = [p.name for p in matches] diff --git a/src/poetry/console/commands/install.py b/src/poetry/console/commands/install.py index deb3bcbd696..27c35cd4419 100644 --- a/src/poetry/console/commands/install.py +++ b/src/poetry/console/commands/install.py @@ -55,7 +55,8 @@ class InstallCommand(InstallerCommand): ), ] - help = """The install command reads the poetry.lock file from + help = """\ +The install command reads the poetry.lock file from the current directory, processes it, and downloads and installs all the libraries and dependencies outlined in that file. If the file does not exist it will look for pyproject.toml and do the same. diff --git a/src/poetry/console/commands/plugin/add.py b/src/poetry/console/commands/plugin/add.py index d448c7bec4a..b59729bc76d 100644 --- a/src/poetry/console/commands/plugin/add.py +++ b/src/poetry/console/commands/plugin/add.py @@ -45,7 +45,8 @@ def handle(self) -> int: self.line_error(self.deprecation) application = self.get_application() - command: SelfAddCommand = application.find("self add") + command = application.find("self add") + assert isinstance(command, SelfAddCommand) application.configure_installer_for_command(command, self.io) argv: list[str] = ["add", *self.argument("plugins")] diff --git a/src/poetry/console/commands/plugin/remove.py b/src/poetry/console/commands/plugin/remove.py index ed01ac1404e..d50bfaf2ed2 100644 --- a/src/poetry/console/commands/plugin/remove.py +++ b/src/poetry/console/commands/plugin/remove.py @@ -1,17 +1,12 @@ from __future__ import annotations -from typing import TYPE_CHECKING - from cleo.helpers import argument from cleo.helpers import option from cleo.io.inputs.string_input import StringInput from cleo.io.io import IO from poetry.console.commands.command import Command - - -if TYPE_CHECKING: - from poetry.console.commands.self.remove import SelfRemoveCommand +from poetry.console.commands.self.remove import SelfRemoveCommand class PluginRemoveCommand(Command): @@ -43,7 +38,8 @@ def handle(self) -> int: self.line_error(self.help) application = self.get_application() - command: SelfRemoveCommand = application.find("self remove") + command = application.find("self remove") + assert isinstance(command, SelfRemoveCommand) application.configure_installer_for_command(command, self.io) argv: list[str] = ["remove", *self.argument("plugins")] diff --git a/src/poetry/console/commands/plugin/show.py b/src/poetry/console/commands/plugin/show.py index 6dd202e8e35..f04ba7669c8 100644 --- a/src/poetry/console/commands/plugin/show.py +++ b/src/poetry/console/commands/plugin/show.py @@ -1,17 +1,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING - from cleo.io.inputs.string_input import StringInput from cleo.io.io import IO from poetry.console.commands.command import Command -if TYPE_CHECKING: - from poetry.console.commands.self.show.plugins import SelfShowPluginsCommand - - class PluginShowCommand(Command): name = "plugin show" @@ -26,7 +20,7 @@ def handle(self) -> int: self.line_error(self.help) application = self.get_application() - command: SelfShowPluginsCommand = application.find("self show plugins") + command = application.find("self show plugins") exit_code: int = command.run( IO( diff --git a/src/poetry/console/commands/self/update.py b/src/poetry/console/commands/self/update.py index 6bdfd91bb80..f42a3d477d8 100644 --- a/src/poetry/console/commands/self/update.py +++ b/src/poetry/console/commands/self/update.py @@ -1,19 +1,14 @@ from __future__ import annotations -from typing import TYPE_CHECKING - from cleo.helpers import argument from cleo.helpers import option from cleo.io.inputs.string_input import StringInput from cleo.io.io import IO +from poetry.console.commands.add import AddCommand from poetry.console.commands.self.self_command import SelfCommand -if TYPE_CHECKING: - from poetry.console.commands.add import AddCommand - - class SelfUpdateCommand(SelfCommand): name = "self update" description = "Updates Poetry to the latest version." @@ -40,7 +35,8 @@ class SelfUpdateCommand(SelfCommand): def _system_project_handle(self) -> int: self.write("Updating Poetry version ...\n\n") application = self.get_application() - add_command: AddCommand = application.find("add") + add_command = application.find("add") + assert isinstance(add_command, AddCommand) add_command.set_env(self.env) application.configure_installer_for_command(add_command, self.io) diff --git a/src/poetry/console/commands/show.py b/src/poetry/console/commands/show.py index 6216a7fb2cf..1b6463c52ed 100644 --- a/src/poetry/console/commands/show.py +++ b/src/poetry/console/commands/show.py @@ -11,6 +11,7 @@ if TYPE_CHECKING: from cleo.io.io import IO + from packaging.utils import NormalizedName from poetry.core.packages.dependency import Dependency from poetry.core.packages.package import Package from poetry.core.packages.project_package import ProjectPackage @@ -423,7 +424,7 @@ def _display_tree( io: IO, dependency: Dependency, installed_packages: list[Package], - packages_in_tree: list[str], + packages_in_tree: list[NormalizedName], previous_tree_bar: str = "├", level: int = 1, ) -> None: diff --git a/src/poetry/factory.py b/src/poetry/factory.py index fb4b60c5b8e..dfa0a4d63aa 100644 --- a/src/poetry/factory.py +++ b/src/poetry/factory.py @@ -45,6 +45,7 @@ class Factory(BaseFactory): def create_poetry( self, cwd: Path | None = None, + with_groups: bool = True, io: IO | None = None, disable_plugins: bool = False, disable_cache: bool = False, @@ -52,7 +53,7 @@ def create_poetry( if io is None: io = NullIO() - base_poetry = super().create_poetry(cwd) + base_poetry = super().create_poetry(cwd=cwd, with_groups=with_groups) locker = Locker( base_poetry.file.parent / "poetry.lock", base_poetry.local_config diff --git a/src/poetry/installation/executor.py b/src/poetry/installation/executor.py index d39b5dcaf5a..c582b0d9ea7 100644 --- a/src/poetry/installation/executor.py +++ b/src/poetry/installation/executor.py @@ -258,6 +258,7 @@ def _execute_operation(self, operation: Operation) -> None: try: from cleo.ui.exception_trace import ExceptionTrace + io: IO | SectionOutput if not self.supports_fancy_output(): io = self._io else: @@ -534,6 +535,9 @@ def _install_directory(self, operation: Install | Update) -> int: else: req = Path(package.source_url).resolve(strict=False) + if package.source_subdirectory: + req /= package.source_subdirectory + pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) if pyproject.is_poetry_project(): @@ -761,6 +765,8 @@ def _create_git_url_reference(self, package: Package) -> dict[str, Any]: "commit_id": package.source_resolved_reference, }, } + if package.source_subdirectory: + reference["subdirectory"] = package.source_subdirectory return reference diff --git a/src/poetry/installation/installer.py b/src/poetry/installation/installer.py index ccb38d0dc60..b590483bbc5 100644 --- a/src/poetry/installation/installer.py +++ b/src/poetry/installation/installer.py @@ -544,6 +544,7 @@ def _get_extra_packages(self, repo: Repository) -> list[str]: Maybe we just let the solver handle it? """ + extras: dict[str, list[str]] if self._update: extras = {k: [d.name for d in v] for k, v in self._package.extras.items()} else: diff --git a/src/poetry/installation/pip_installer.py b/src/poetry/installation/pip_installer.py index 536f6cdce04..21c0e013771 100644 --- a/src/poetry/installation/pip_installer.py +++ b/src/poetry/installation/pip_installer.py @@ -183,6 +183,9 @@ def requirement(self, package: Package, formatted: bool = False) -> str | list[s f"#egg={package.name}" ) + if package.source_subdirectory: + req += f"&subdirectory={package.source_subdirectory}" + if package.develop: return ["-e", req] @@ -217,6 +220,9 @@ def install_directory(self, package: Package) -> str | int: else: req = Path(package.source_url).resolve(strict=False) + if package.source_subdirectory: + req /= package.source_subdirectory + pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) if pyproject.is_poetry_project(): @@ -278,9 +284,13 @@ def install_git(self, package: Package) -> None: ) # Now we just need to install from the source directory - pkg = Package(package.name, package.version) - pkg._source_type = "directory" - pkg._source_url = str(source.path) - pkg.develop = package.develop + pkg = Package( + name=package.name, + version=package.version, + source_type="directory", + source_url=str(source.path), + source_subdirectory=package.source_subdirectory, + develop=package.develop, + ) self.install_directory(pkg) diff --git a/src/poetry/mixology/partial_solution.py b/src/poetry/mixology/partial_solution.py index 3acb92ff78c..135a765882f 100644 --- a/src/poetry/mixology/partial_solution.py +++ b/src/poetry/mixology/partial_solution.py @@ -4,7 +4,6 @@ from poetry.mixology.assignment import Assignment from poetry.mixology.set_relation import SetRelation -from poetry.mixology.term import Term if TYPE_CHECKING: @@ -12,6 +11,7 @@ from poetry.core.packages.package import Package from poetry.mixology.incompatibility import Incompatibility + from poetry.mixology.term import Term class PartialSolution: @@ -44,7 +44,7 @@ def __init__(self) -> None: # map. # # This is derived from self._assignments. - self._negative: dict[str, dict[str, Term]] = {} + self._negative: dict[str, Term] = {} # The number of distinct solutions that have been attempted so far. self._attempted_solutions = 1 @@ -146,15 +146,6 @@ def _register(self, assignment: Assignment) -> None: """ name = assignment.dependency.complete_name old_positive = self._positive.get(name) - if old_positive is None and assignment.dependency.features: - old_positive_without_features = self._positive.get( - assignment.dependency.name - ) - if old_positive_without_features is not None: - dep = old_positive_without_features.dependency.with_features( - assignment.dependency.features - ) - old_positive = Term(dep, is_positive=True) if old_positive is not None: value = old_positive.intersect(assignment) assert value is not None @@ -162,9 +153,7 @@ def _register(self, assignment: Assignment) -> None: return - ref = assignment.dependency.complete_name - negative_by_ref = self._negative.get(name) - old_negative = None if negative_by_ref is None else negative_by_ref.get(ref) + old_negative = self._negative.get(name) term = ( assignment if old_negative is None else assignment.intersect(old_negative) ) @@ -176,10 +165,7 @@ def _register(self, assignment: Assignment) -> None: self._positive[name] = term else: - if name not in self._negative: - self._negative[name] = {} - - self._negative[name][ref] = term + self._negative[name] = term def satisfier(self, term: Term) -> Assignment: """ @@ -222,11 +208,7 @@ def relation(self, term: Term) -> str: if positive is not None: return positive.relation(term) - by_ref = self._negative.get(term.dependency.complete_name) - if by_ref is None: - return SetRelation.OVERLAPPING - - negative = by_ref[term.dependency.complete_name] + negative = self._negative.get(term.dependency.complete_name) if negative is None: return SetRelation.OVERLAPPING diff --git a/src/poetry/mixology/version_solver.py b/src/poetry/mixology/version_solver.py index 08e7d7bfe86..a5b3961147a 100644 --- a/src/poetry/mixology/version_solver.py +++ b/src/poetry/mixology/version_solver.py @@ -61,7 +61,9 @@ def _search_for(self, dependency: Dependency) -> list[DependencyPackage]: if packages is None: packages = self.provider.search_for(dependency) else: - packages = [p for p in packages if dependency.constraint.allows(p.version)] + packages = [ + p for p in packages if dependency.constraint.allows(p.package.version) + ] self.cache[key] = packages @@ -376,6 +378,12 @@ def _choose_package_version(self) -> str | None: # Prefer packages with as few remaining versions as possible, # so that if a conflict is necessary it's forced quickly. def _get_min(dependency: Dependency) -> tuple[bool, int]: + # Direct origin dependencies must be handled first: we don't want to resolve + # a regular dependency for some package only to find later that we had a + # direct-origin dependency. + if dependency.is_direct_origin(): + return False, -1 + if dependency.name in self._use_latest: # If we're forced to use the latest version of a package, it effectively # only has one version to choose from. @@ -385,16 +393,6 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]: if locked: return not dependency.marker.is_any(), 1 - # VCS, URL, File or Directory dependencies - # represent a single version - if ( - dependency.is_vcs() - or dependency.is_url() - or dependency.is_file() - or dependency.is_directory() - ): - return not dependency.marker.is_any(), 1 - try: return ( not dependency.marker.is_any(), @@ -427,7 +425,12 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]: locked = self._get_locked(dependency, allow_similar=True) if locked is not None: package = next( - (p for p in packages if p.version == locked.version), None + ( + p + for p in packages + if p.package.version == locked.package.version + ), + None, ) if package is None: with suppress(IndexError): @@ -465,7 +468,8 @@ def _get_min(dependency: Dependency) -> tuple[bool, int]: if not conflict: self._solution.decide(package.package) self._log( - f"selecting {package.complete_name} ({package.full_pretty_version})" + f"selecting {package.package.complete_name}" + f" ({package.package.full_pretty_version})" ) complete_name = dependency.complete_name @@ -507,13 +511,12 @@ def _get_locked( return None locked = self._locked.get(dependency.name, []) - for package in locked: - if (allow_similar or dependency.is_same_package_as(package.package)) and ( - dependency.constraint.allows(package.version) - or package.is_prerelease() - and dependency.constraint.allows(package.version.next_patch()) - ): - return DependencyPackage(dependency, package.package) + for dependency_package in locked: + package = dependency_package.package + if ( + allow_similar or dependency.is_same_package_as(package) + ) and dependency.constraint.allows(package.version): + return DependencyPackage(dependency, package) return None def _log(self, text: str) -> None: diff --git a/src/poetry/packages/dependency_package.py b/src/poetry/packages/dependency_package.py index 1cdae4ba4a9..a06d28b65b0 100644 --- a/src/poetry/packages/dependency_package.py +++ b/src/poetry/packages/dependency_package.py @@ -1,7 +1,6 @@ from __future__ import annotations from typing import TYPE_CHECKING -from typing import Any if TYPE_CHECKING: @@ -31,15 +30,6 @@ def with_features(self, features: list[str]) -> DependencyPackage: def without_features(self) -> DependencyPackage: return self.with_features([]) - def __getattr__(self, name: str) -> Any: - return getattr(self._package, name) - - def __setattr__(self, key: str, value: Any) -> None: - if key in {"_dependency", "_package"}: - return super().__setattr__(key, value) - - setattr(self._package, key, value) - def __str__(self) -> str: return str(self._package) diff --git a/src/poetry/packages/locker.py b/src/poetry/packages/locker.py index ec53287b2d1..5460031a820 100644 --- a/src/poetry/packages/locker.py +++ b/src/poetry/packages/locker.py @@ -5,7 +5,6 @@ import os import re -from copy import deepcopy from hashlib import sha256 from pathlib import Path from typing import TYPE_CHECKING @@ -27,20 +26,12 @@ from tomlkit.exceptions import TOMLKitError from tomlkit.items import Array -from poetry.packages import DependencyPackage -from poetry.utils.extras import get_extra_package_names - if TYPE_CHECKING: - from collections.abc import Iterable - from collections.abc import Iterator - from collections.abc import Sequence - from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.vcs_dependency import VCSDependency - from poetry.core.version.markers import BaseMarker from tomlkit.items import Table from tomlkit.toml_document import TOMLDocument @@ -126,6 +117,7 @@ def locked_repository(self) -> Repository: source_url=url, source_reference=source.get("reference"), source_resolved_reference=source.get("resolved_reference"), + source_subdirectory=source.get("subdirectory"), ) package.description = info.get("description", "") package.category = info.get("category", "main") @@ -205,175 +197,6 @@ def locked_repository(self) -> Repository: return packages - @staticmethod - def __get_locked_package( - dependency: Dependency, - packages_by_name: dict[str, list[Package]], - decided: dict[Package, Dependency] | None = None, - ) -> Package | None: - """ - Internal helper to identify corresponding locked package using dependency - version constraints. - """ - decided = decided or {} - - # Get the packages that are consistent with this dependency. - packages = [ - package - for package in packages_by_name.get(dependency.name, []) - if package.python_constraint.allows_all(dependency.python_constraint) - and dependency.constraint.allows(package.version) - ] - - # If we've previously made a choice that is compatible with the current - # requirement, stick with it. - for package in packages: - old_decision = decided.get(package) - if ( - old_decision is not None - and not old_decision.marker.intersect(dependency.marker).is_empty() - ): - return package - - return next(iter(packages), None) - - @classmethod - def __walk_dependencies( - cls, - dependencies: list[Dependency], - packages_by_name: dict[str, list[Package]], - ) -> dict[Package, Dependency]: - nested_dependencies: dict[Package, Dependency] = {} - - visited: set[tuple[Dependency, BaseMarker]] = set() - while dependencies: - requirement = dependencies.pop(0) - if (requirement, requirement.marker) in visited: - continue - visited.add((requirement, requirement.marker)) - - locked_package = cls.__get_locked_package( - requirement, packages_by_name, nested_dependencies - ) - - if not locked_package: - raise RuntimeError(f"Dependency walk failed at {requirement}") - - if requirement.extras: - locked_package = locked_package.with_features(requirement.extras) - - # create dependency from locked package to retain dependency metadata - # if this is not done, we can end-up with incorrect nested dependencies - constraint = requirement.constraint - marker = requirement.marker - requirement = locked_package.to_dependency() - requirement.marker = requirement.marker.intersect(marker) - - requirement.constraint = constraint - - for require in locked_package.requires: - if require.is_optional() and not any( - require in locked_package.extras[feature] - for feature in locked_package.features - ): - continue - - require = deepcopy(require) - require.marker = require.marker.intersect( - requirement.marker.without_extras() - ) - if not require.marker.is_empty(): - dependencies.append(require) - - key = locked_package - if key not in nested_dependencies: - nested_dependencies[key] = requirement - else: - nested_dependencies[key].marker = nested_dependencies[key].marker.union( - requirement.marker - ) - - return nested_dependencies - - @classmethod - def get_project_dependencies( - cls, - project_requires: list[Dependency], - locked_packages: list[Package], - ) -> Iterable[tuple[Package, Dependency]]: - # group packages entries by name, this is required because requirement might use - # different constraints. - packages_by_name: dict[str, list[Package]] = {} - for pkg in locked_packages: - if pkg.name not in packages_by_name: - packages_by_name[pkg.name] = [] - packages_by_name[pkg.name].append(pkg) - - # Put higher versions first so that we prefer them. - for packages in packages_by_name.values(): - packages.sort( - key=lambda package: package.version, - reverse=True, - ) - - nested_dependencies = cls.__walk_dependencies( - dependencies=project_requires, - packages_by_name=packages_by_name, - ) - - return nested_dependencies.items() - - def get_project_dependency_packages( - self, - project_requires: list[Dependency], - project_python_marker: BaseMarker | None = None, - extras: bool | Sequence[str] | None = None, - ) -> Iterator[DependencyPackage]: - # Apply the project python marker to all requirements. - if project_python_marker is not None: - marked_requires: list[Dependency] = [] - for require in project_requires: - require = deepcopy(require) - require.marker = require.marker.intersect(project_python_marker) - marked_requires.append(require) - project_requires = marked_requires - - repository = self.locked_repository() - - # Build a set of all packages required by our selected extras - extra_package_names: set[str] | None = None - - if extras is not True: - extra_package_names = set( - get_extra_package_names( - repository.packages, - self.lock_data.get("extras", {}), - extras or (), - ) - ) - - # If a package is optional and we haven't opted in to it, do not select - selected = [] - for dependency in project_requires: - try: - package = repository.find_packages(dependency=dependency)[0] - except IndexError: - continue - - if extra_package_names is not None and ( - package.optional and package.name not in extra_package_names - ): - # a package is locked as optional, but is not activated via extras - continue - - selected.append(dependency) - - for package, dependency in self.get_project_dependencies( - project_requires=selected, - locked_packages=repository.packages, - ): - yield DependencyPackage(dependency=dependency, package=package) - def set_lock_data(self, root: Package, packages: list[Package]) -> bool: files: dict[str, Any] = table() package_specs = self._lock_packages(packages) @@ -586,13 +409,13 @@ def _dump_package(self, package: Package) -> dict[str, Any]: if package.extras: extras = {} - for name, deps in package.extras.items(): + for name, deps in sorted(package.extras.items()): # TODO: This should use dep.to_pep_508() once this is fixed # https://github.com/python-poetry/poetry-core/pull/102 - extras[name] = [ + extras[name] = sorted( dep.base_pep_508_name if not dep.constraint.is_any() else dep.name for dep in deps - ] + ) data["extras"] = extras @@ -602,7 +425,8 @@ def _dump_package(self, package: Package) -> dict[str, Any]: # The lock file should only store paths relative to the root project url = Path( os.path.relpath( - Path(url).as_posix(), self._lock.path.parent.as_posix() + Path(url).resolve().as_posix(), + Path(self._lock.path.parent).resolve().as_posix(), ) ).as_posix() @@ -619,6 +443,9 @@ def _dump_package(self, package: Package) -> dict[str, Any]: if package.source_resolved_reference: data["source"]["resolved_reference"] = package.source_resolved_reference + if package.source_subdirectory: + data["source"]["subdirectory"] = package.source_subdirectory + if package.source_type in ["directory", "git"]: data["develop"] = package.develop diff --git a/src/poetry/plugins/application_plugin.py b/src/poetry/plugins/application_plugin.py index d1aaf6e1b4f..4dbdb92e5ac 100644 --- a/src/poetry/plugins/application_plugin.py +++ b/src/poetry/plugins/application_plugin.py @@ -23,4 +23,7 @@ def commands(self) -> list[type[Command]]: def activate(self, application: Application) -> None: for command in self.commands: - application.command_loader.register_factory(command.name, lambda: command()) + assert command.name is not None + application.command_loader.register_factory( + command.name, lambda: command() # noqa: B023 + ) diff --git a/src/poetry/publishing/publisher.py b/src/poetry/publishing/publisher.py index df4bb0410d8..cf8515bcf46 100644 --- a/src/poetry/publishing/publisher.py +++ b/src/poetry/publishing/publisher.py @@ -11,8 +11,7 @@ if TYPE_CHECKING: from pathlib import Path - from cleo.io import BufferedIO - from cleo.io import ConsoleIO + from cleo.io.io import IO from poetry.poetry import Poetry @@ -24,7 +23,7 @@ class Publisher: Registers and publishes packages to remote repositories. """ - def __init__(self, poetry: Poetry, io: BufferedIO | ConsoleIO) -> None: + def __init__(self, poetry: Poetry, io: IO) -> None: self._poetry = poetry self._package = poetry.package self._io = io diff --git a/src/poetry/publishing/uploader.py b/src/poetry/publishing/uploader.py index bed6b1f5928..566f50eec5e 100644 --- a/src/poetry/publishing/uploader.py +++ b/src/poetry/publishing/uploader.py @@ -27,7 +27,7 @@ if TYPE_CHECKING: - from cleo.io.null_io import NullIO + from cleo.io.io import IO from poetry.poetry import Poetry @@ -38,7 +38,8 @@ class UploadError(Exception): def __init__(self, error: ConnectionError | HTTPError | str) -> None: if isinstance(error, HTTPError): message = ( - f"HTTP Error {error.response.status_code}: {error.response.reason}" + f"HTTP Error {error.response.status_code}: {error.response.reason} |" + f" {error.response.content!r}" ) elif isinstance(error, ConnectionError): message = ( @@ -51,7 +52,7 @@ def __init__(self, error: ConnectionError | HTTPError | str) -> None: class Uploader: - def __init__(self, poetry: Poetry, io: NullIO) -> None: + def __init__(self, poetry: Poetry, io: IO) -> None: self._poetry = poetry self._package = poetry.package self._io = io diff --git a/src/poetry/puzzle/provider.py b/src/poetry/puzzle/provider.py index ebd7916c903..5896ad178e6 100644 --- a/src/poetry/puzzle/provider.py +++ b/src/poetry/puzzle/provider.py @@ -46,7 +46,6 @@ from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.package import Package - from poetry.core.packages.specification import PackageSpecification from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.vcs_dependency import VCSDependency from poetry.core.semver.version_constraint import VersionConstraint @@ -79,6 +78,7 @@ def _formatter_context(self) -> str: return f" {Indicator.CONTEXT} " def _formatter_elapsed(self) -> str: + assert self._start_time is not None elapsed = time.time() - self._start_time return f"{elapsed:.1f}s" @@ -140,6 +140,7 @@ def __init__( self._load_deferred = True self._source_root: Path | None = None self._installed_packages = installed if installed is not None else [] + self._direct_origin_packages: dict[str, Package] = {} @property def pool(self) -> Pool: @@ -191,11 +192,11 @@ def validate_package_for_dependency( def search_for_installed_packages( self, - specification: PackageSpecification, + dependency: Dependency, ) -> list[Package]: """ - Search for installed packages, when available, that provides the given - specification. + Search for installed packages, when available, that satisfy the given + dependency. This is useful when dealing with packages that are under development, not published on package sources and/or only available via system installations. @@ -205,17 +206,17 @@ def search_for_installed_packages( logger.debug( "Falling back to installed packages to discover metadata for %s", - specification.complete_name, + dependency.complete_name, ) packages = [ package for package in self._installed_packages - if package.provides(specification) + if package.satisfies(dependency, ignore_source_type=True) ] logger.debug( "Found %d compatible packages for %s", len(packages), - specification.complete_name, + dependency.complete_name, ) return packages @@ -268,18 +269,32 @@ def search_for(self, dependency: Dependency) -> list[DependencyPackage]: return PackageCollection(dependency, [self._package]) if dependency.is_direct_origin(): - packages = [self.search_for_direct_origin_dependency(dependency)] + package = self.search_for_direct_origin_dependency(dependency) + self._direct_origin_packages[dependency.name] = package + return PackageCollection(dependency, [package]) - else: - packages = self._pool.find_packages(dependency) - - packages.sort( - key=lambda p: ( - not p.is_prerelease() and not dependency.allows_prereleases(), - p.version, - ), - reverse=True, + # If we've previously found a direct-origin package that meets this dependency, + # use it. + # + # We rely on the VersionSolver resolving direct-origin dependencies first. + direct_origin_package = self._direct_origin_packages.get(dependency.name) + if direct_origin_package is not None: + packages = ( + [direct_origin_package] + if dependency.constraint.allows(direct_origin_package.version) + else [] ) + return PackageCollection(dependency, packages) + + packages = self._pool.find_packages(dependency) + + packages.sort( + key=lambda p: ( + not p.is_prerelease() and not dependency.allows_prereleases(), + p.version, + ), + reverse=True, + ) if not packages: packages = self.search_for_installed_packages(dependency) @@ -426,7 +441,7 @@ def _get_dependencies_with_overrides( return _dependencies def incompatibilities_for( - self, package: DependencyPackage + self, dependency_package: DependencyPackage ) -> list[Incompatibility]: """ Returns incompatibilities that encapsulate a given package's dependencies, @@ -437,6 +452,7 @@ def incompatibilities_for( won't return incompatibilities that have already been returned by a previous call to _incompatibilities_for(). """ + package = dependency_package.package if package.is_root(): dependencies = package.all_requires else: @@ -444,7 +460,7 @@ def incompatibilities_for( if not package.python_constraint.allows_all(self._python_constraint): transitive_python_constraint = get_python_constraint_from_marker( - package.dependency.transitive_marker + dependency_package.dependency.transitive_marker ) intersection = package.python_constraint.intersect( transitive_python_constraint @@ -457,7 +473,7 @@ def incompatibilities_for( if ( transitive_python_constraint.is_any() or self._python_constraint.intersect( - package.dependency.python_constraint + dependency_package.dependency.python_constraint ).is_empty() or intersection.is_empty() or not difference.is_empty() @@ -478,7 +494,9 @@ def incompatibilities_for( and self._python_constraint.allows_any(dep.python_constraint) and (not self._env or dep.marker.validate(self._env.marker_env)) ] - dependencies = self._get_dependencies_with_overrides(_dependencies, package) + dependencies = self._get_dependencies_with_overrides( + _dependencies, dependency_package + ) return [ Incompatibility( @@ -488,39 +506,44 @@ def incompatibilities_for( for dep in dependencies ] - def complete_package(self, package: DependencyPackage) -> DependencyPackage: + def complete_package( + self, dependency_package: DependencyPackage + ) -> DependencyPackage: + package = dependency_package.package + dependency = dependency_package.dependency + if package.is_root(): - package = package.clone() + dependency_package = dependency_package.clone() + package = dependency_package.package + dependency = dependency_package.dependency requires = package.all_requires - elif not package.is_root() and package.source_type not in { + elif package.source_type not in { "directory", "file", "url", "git", }: try: - package = DependencyPackage( - package.dependency, + dependency_package = DependencyPackage( + dependency, self._pool.package( package.name, package.version.text, - extras=list(package.dependency.extras), - repository=package.dependency.source_name, + extras=list(dependency.extras), + repository=dependency.source_name, ), ) except PackageNotFound as e: try: - package = next( - DependencyPackage( - package.dependency, - pkg, - ) - for pkg in self.search_for_installed_packages( - package.dependency - ) + dependency_package = next( + DependencyPackage(dependency, pkg) + for pkg in self.search_for_installed_packages(dependency) ) except StopIteration: raise e from e + + package = dependency_package.package + dependency = dependency_package.dependency requires = package.requires else: requires = package.requires @@ -537,15 +560,19 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage: # If some extras/features were required, we need to # add a special dependency representing the base package # to the current package - if package.dependency.extras: - for extra in package.dependency.extras: + if dependency.extras: + for extra in dependency.extras: extra = safe_extra(extra) if extra not in package.extras: continue optional_dependencies += [d.name for d in package.extras[extra]] - package = package.with_features(list(package.dependency.extras)) + dependency_package = dependency_package.with_features( + list(dependency.extras) + ) + package = dependency_package.package + dependency = dependency_package.dependency _dependencies.append(package.without_features().to_dependency()) for dep in requires: @@ -563,7 +590,7 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage: or ( dep.in_extras and not set(dep.in_extras).intersection( - {safe_extra(extra) for extra in package.dependency.extras} + {safe_extra(extra) for extra in dependency.extras} ) ) ): @@ -571,7 +598,9 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage: _dependencies.append(dep) - dependencies = self._get_dependencies_with_overrides(_dependencies, package) + dependencies = self._get_dependencies_with_overrides( + _dependencies, dependency_package + ) # Searching for duplicate dependencies # @@ -655,10 +684,10 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage: # - {} def fmt_warning(d: Dependency) -> str: - marker = d.marker if not d.marker.is_any() else "*" + dependency_marker = d.marker if not d.marker.is_any() else "*" return ( f"{d.name} ({d.pretty_constraint})" - f" with markers {marker}" + f" with markers {dependency_marker}" ) warnings = ", ".join(fmt_warning(d) for d in deps[:-1]) @@ -727,9 +756,11 @@ def fmt_warning(d: Dependency) -> str: for dep in deps: if not overrides_marker_intersection.intersect(dep.marker).is_empty(): current_overrides = self._overrides.copy() - package_overrides = current_overrides.get(package, {}).copy() + package_overrides = current_overrides.get( + dependency_package, {} + ).copy() package_overrides.update({dep.name: dep}) - current_overrides.update({package: package_overrides}) + current_overrides.update({dependency_package: package_overrides}) overrides.append(current_overrides) if overrides: @@ -738,9 +769,9 @@ def fmt_warning(d: Dependency) -> str: # Modifying dependencies as needed clean_dependencies = [] for dep in dependencies: - if not package.dependency.transitive_marker.without_extras().is_any(): + if not dependency.transitive_marker.without_extras().is_any(): marker_intersection = ( - package.dependency.transitive_marker.without_extras().intersect( + dependency.transitive_marker.without_extras().intersect( dep.marker.without_extras() ) ) @@ -752,9 +783,9 @@ def fmt_warning(d: Dependency) -> str: dep.transitive_marker = marker_intersection - if not package.dependency.python_constraint.is_any(): + if not dependency.python_constraint.is_any(): python_constraint_intersection = dep.python_constraint.intersect( - package.dependency.python_constraint + dependency.python_constraint ) if python_constraint_intersection.is_empty(): # This dependency is not needed under current python constraint. @@ -763,14 +794,13 @@ def fmt_warning(d: Dependency) -> str: clean_dependencies.append(dep) - package = DependencyPackage( - package.dependency, package.with_dependency_groups([], only=True) - ) + package = package.with_dependency_groups([], only=True) + dependency_package = DependencyPackage(dependency, package) for dep in clean_dependencies: package.add_dependency(dep) - return package + return dependency_package def debug(self, message: str, depth: int = 0) -> None: if not (self._io.is_very_verbose() or self._io.is_debug()): diff --git a/src/poetry/repositories/installed_repository.py b/src/poetry/repositories/installed_repository.py index 6cfea588bd7..228df3533f7 100644 --- a/src/poetry/repositories/installed_repository.py +++ b/src/poetry/repositories/installed_repository.py @@ -124,6 +124,7 @@ def create_package_from_distribution( source_url = None source_reference = None source_resolved_reference = None + source_subdirectory = None if is_standard_package: if path.name.endswith(".dist-info"): paths = cls.get_package_paths( @@ -169,6 +170,7 @@ def create_package_from_distribution( source_url=source_url, source_reference=source_reference, source_resolved_reference=source_resolved_reference, + source_subdirectory=source_subdirectory, ) package.description = distribution.metadata.get( # type: ignore[attr-defined] @@ -185,6 +187,7 @@ def create_package_from_pep610(cls, distribution: metadata.Distribution) -> Pack source_url = None source_reference = None source_resolved_reference = None + source_subdirectory = None develop = False url_reference = json.loads( @@ -213,6 +216,7 @@ def create_package_from_pep610(cls, distribution: metadata.Distribution) -> Pack source_reference = url_reference["vcs_info"].get( "requested_revision", source_resolved_reference ) + source_subdirectory = url_reference.get("subdirectory") package = Package( distribution.metadata["name"], @@ -221,6 +225,7 @@ def create_package_from_pep610(cls, distribution: metadata.Distribution) -> Pack source_url=source_url, source_reference=source_reference, source_resolved_reference=source_resolved_reference, + source_subdirectory=source_subdirectory, develop=develop, ) diff --git a/src/poetry/repositories/legacy_repository.py b/src/poetry/repositories/legacy_repository.py index c54b50a79d6..8a280237788 100644 --- a/src/poetry/repositories/legacy_repository.py +++ b/src/poetry/repositories/legacy_repository.py @@ -14,8 +14,9 @@ if TYPE_CHECKING: - from poetry.core.packages.dependency import Dependency + from packaging.utils import NormalizedName from poetry.core.packages.utils.link import Link + from poetry.core.semver.version_constraint import VersionConstraint from poetry.config.config import Config @@ -33,61 +34,6 @@ def __init__( super().__init__(name, url.rstrip("/"), config, disable_cache) - def find_packages(self, dependency: Dependency) -> list[Package]: - packages = [] - constraint, allow_prereleases = self._get_constraints_from_dependency( - dependency - ) - - key = dependency.name - if not constraint.is_any(): - key = f"{key}:{constraint!s}" - - ignored_pre_release_versions = [] - - if self._cache.store("matches").has(key): - versions = self._cache.store("matches").get(key) - else: - page = self._get_page(f"/{dependency.name.replace('.', '-')}/") - if page is None: - return [] - - versions = [] - for version in page.versions(dependency.name): - if version.is_unstable() and not allow_prereleases: - if constraint.is_any(): - # we need this when all versions of the package are pre-releases - ignored_pre_release_versions.append(version) - continue - - if constraint.allows(version): - versions.append(version) - - self._cache.store("matches").put(key, versions, 5) - - for package_versions in (versions, ignored_pre_release_versions): - for version in package_versions: - package = Package( - dependency.name, - version, - source_type="legacy", - source_reference=self.name, - source_url=self._url, - ) - - packages.append(package) - - self._log( - f"{len(packages)} packages found for {dependency.name} {constraint!s}", - level="debug", - ) - - if packages or not constraint.is_any(): - # we have matching packages, or constraint is not (*) - break - - return packages - def package( self, name: str, version: str, extras: list[str] | None = None ) -> Package: @@ -115,14 +61,53 @@ def package( return package def find_links_for_package(self, package: Package) -> list[Link]: - page = self._get_page(f"/{package.name.replace('.', '-')}/") + page = self._get_page(f"/{package.name}/") if page is None: return [] return list(page.links_for_version(package.name, package.version)) + def _find_packages( + self, name: NormalizedName, constraint: VersionConstraint + ) -> list[Package]: + """ + Find packages on the remote server. + """ + versions: list[Version] + + key: str = name + if not constraint.is_any(): + key = f"{key}:{constraint!s}" + + if self._cache.store("matches").has(key): + versions = self._cache.store("matches").get(key) + else: + page = self._get_page(f"/{name}/") + if page is None: + self._log( + f"No packages found for {name}", + level="debug", + ) + return [] + + versions = [ + version for version in page.versions(name) if constraint.allows(version) + ] + self._cache.store("matches").put(key, versions, 5) + + return [ + Package( + name, + version, + source_type="legacy", + source_reference=self.name, + source_url=self._url, + ) + for version in versions + ] + def _get_release_info(self, name: str, version: str) -> dict[str, Any]: - page = self._get_page(f"/{canonicalize_name(name).replace('.', '-')}/") + page = self._get_page(f"/{canonicalize_name(name)}/") if page is None: raise PackageNotFound(f'No package named "{name}"') diff --git a/src/poetry/repositories/pypi_repository.py b/src/poetry/repositories/pypi_repository.py index 142b29d85d2..f61343d7052 100644 --- a/src/poetry/repositories/pypi_repository.py +++ b/src/poetry/repositories/pypi_repository.py @@ -12,6 +12,7 @@ from html5lib.html5parser import parse from poetry.core.packages.package import Package from poetry.core.packages.utils.link import Link +from poetry.core.semver.version import Version from poetry.core.version.exceptions import InvalidVersion from poetry.repositories.exceptions import PackageNotFound @@ -26,7 +27,8 @@ if TYPE_CHECKING: - from poetry.core.packages.dependency import Dependency + from packaging.utils import NormalizedName + from poetry.core.semver.version_constraint import VersionConstraint class PyPiRepository(HTTPRepository): @@ -43,62 +45,6 @@ def __init__( self._base_url = url self._fallback = fallback - def find_packages(self, dependency: Dependency) -> list[Package]: - """ - Find packages on the remote server. - """ - constraint, allow_prereleases = self._get_constraints_from_dependency( - dependency - ) - - try: - info = self.get_package_info(dependency.name) - except PackageNotFound: - self._log( - f"No packages found for {dependency.name} {constraint!s}", - level="debug", - ) - return [] - - packages = [] - ignored_pre_release_packages = [] - - for version, release in info["releases"].items(): - if not release: - # Bad release - self._log( - f"No release information found for {dependency.name}-{version}," - " skipping", - level="debug", - ) - continue - - try: - package = Package(info["info"]["name"], version) - except InvalidVersion: - self._log( - f'Unable to parse version "{version}" for the' - f" {dependency.name} package, skipping", - level="debug", - ) - continue - - if package.is_prerelease() and not allow_prereleases: - if constraint.is_any(): - # we need this when all versions of the package are pre-releases - ignored_pre_release_packages.append(package) - continue - - if constraint.allows(package.version): - packages.append(package) - - self._log( - f"{len(packages)} packages found for {dependency.name} {constraint!s}", - level="debug", - ) - - return packages or ignored_pre_release_packages - def search(self, query: str) -> list[Package]: results = [] @@ -145,7 +91,7 @@ def search(self, query: str) -> list[Package]: return results - def get_package_info(self, name: str) -> dict[str, Any]: + def get_package_info(self, name: NormalizedName) -> dict[str, Any]: """ Return the package information given its name. @@ -160,7 +106,49 @@ def get_package_info(self, name: str) -> dict[str, Any]: ) return package_info - def _get_package_info(self, name: str) -> dict[str, Any]: + def _find_packages( + self, name: NormalizedName, constraint: VersionConstraint + ) -> list[Package]: + """ + Find packages on the remote server. + """ + try: + info = self.get_package_info(name) + except PackageNotFound: + self._log( + f"No packages found for {name} {constraint!s}", + level="debug", + ) + return [] + + packages = [] + + for version_string, release in info["releases"].items(): + if not release: + # Bad release + self._log( + f"No release information found for {name}-{version_string}," + " skipping", + level="debug", + ) + continue + + try: + version = Version.parse(version_string) + except InvalidVersion: + self._log( + f'Unable to parse version "{version_string}" for the' + f" {name} package, skipping", + level="debug", + ) + continue + + if constraint.allows(version): + packages.append(Package(info["info"]["name"], version)) + + return packages + + def _get_package_info(self, name: NormalizedName) -> dict[str, Any]: data = self._get(f"pypi/{name}/json") if data is None: raise PackageNotFound(f"Package [{name}] not found.") diff --git a/src/poetry/repositories/repository.py b/src/poetry/repositories/repository.py index e180a56f2b9..3da801c0434 100644 --- a/src/poetry/repositories/repository.py +++ b/src/poetry/repositories/repository.py @@ -12,6 +12,7 @@ if TYPE_CHECKING: + from packaging.utils import NormalizedName from poetry.core.packages.dependency import Dependency from poetry.core.packages.package import Package from poetry.core.packages.utils.link import Link @@ -35,30 +36,28 @@ def packages(self) -> list[Package]: def find_packages(self, dependency: Dependency) -> list[Package]: packages = [] - ignored_pre_release_packages = [] constraint, allow_prereleases = self._get_constraints_from_dependency( dependency ) + ignored_pre_release_packages = [] - for package in self.packages: - if dependency.name == package.name: - if ( - package.is_prerelease() - and not allow_prereleases - and not package.source_type - ): - # If prereleases are not allowed and the package is a prerelease - # and is a standard package then we skip it - if constraint.is_any(): - # we need this when all versions of the package are pre-releases - ignored_pre_release_packages.append(package) - continue - - if constraint.allows(package.version) or ( - package.is_prerelease() - and constraint.allows(package.version.next_patch()) - ): - packages.append(package) + for package in self._find_packages(dependency.name, constraint): + if ( + package.is_prerelease() + and not allow_prereleases + and not package.is_direct_origin() + ): + if constraint.is_any(): + # we need this when all versions of the package are pre-releases + ignored_pre_release_packages.append(package) + continue + + packages.append(package) + + self._log( + f"{len(packages)} packages found for {dependency.name} {constraint!s}", + level="debug", + ) return packages or ignored_pre_release_packages @@ -114,6 +113,15 @@ def _get_constraints_from_dependency( return constraint, allow_prereleases + def _find_packages( + self, name: NormalizedName, constraint: VersionConstraint + ) -> list[Package]: + return [ + package + for package in self._packages + if package.name == name and constraint.allows(package.version) + ] + def _log(self, msg: str, level: str = "info") -> None: logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}") getattr(logger, level)(f"Source ({self.name}): {msg}") diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index fbcb25ea502..7af9e27121e 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -214,7 +214,7 @@ def request( verify = str(verify) if isinstance(verify, Path) else verify - settings = session.merge_environment_settings( # type: ignore[no-untyped-call] + settings = session.merge_environment_settings( prepared_request.url, proxies, stream, verify, cert ) diff --git a/src/poetry/utils/env.py b/src/poetry/utils/env.py index 35ef45a9f60..092008ac6ef 100644 --- a/src/poetry/utils/env.py +++ b/src/poetry/utils/env.py @@ -648,8 +648,9 @@ def activate(self, python: str, io: IO) -> Env: def deactivate(self, io: IO) -> None: venv_path = self._poetry.config.virtualenvs_path - name = self._poetry.package.name - name = self.generate_env_name(name, str(self._poetry.file.parent)) + name = self.generate_env_name( + self._poetry.package.name, str(self._poetry.file.parent) + ) envs_file = TOMLFile(venv_path / self.ENVS_FILE) if envs_file.exists(): @@ -984,7 +985,8 @@ def create_venv( if venv_prompt is not None: venv_prompt = venv_prompt.format( - project_name=self._poetry.package.name, python_version=python_minor + project_name=self._poetry.package.name or "virtualenv", + python_version=python_minor, ) if not venv.exists(): @@ -1181,7 +1183,7 @@ def get_base_prefix(cls) -> Path: def generate_env_name(cls, name: str, cwd: str) -> str: name = name.lower() sanitized_name = re.sub(r'[ $`!*@"\\\r\n\t]', "_", name)[:42] - normalized_cwd = os.path.normcase(cwd) + normalized_cwd = os.path.normcase(os.path.realpath(cwd)) h_bytes = hashlib.sha256(encode(normalized_cwd)).digest() h_str = base64.urlsafe_b64encode(h_bytes).decode()[:8] @@ -1945,7 +1947,10 @@ def build_environment( """ if not env or poetry.package.build_script: with ephemeral_environment(executable=env.python if env else None) as venv: - overwrite = io and io.output.is_decorated() and not io.is_debug() + overwrite = ( + io is not None and io.output.is_decorated() and not io.is_debug() + ) + if io: if not overwrite: io.write_line("") @@ -1959,6 +1964,7 @@ def build_environment( "Preparing build environment with build-system requirements" f" {', '.join(requires)}" ) + venv.run_pip( "install", "--disable-pip-version-check", @@ -1967,6 +1973,7 @@ def build_environment( ) if overwrite: + assert io is not None io.write_line("") yield venv diff --git a/src/poetry/utils/extras.py b/src/poetry/utils/extras.py index ff7f8a2fc72..e0681d46b76 100644 --- a/src/poetry/utils/extras.py +++ b/src/poetry/utils/extras.py @@ -9,6 +9,7 @@ from collections.abc import Sequence from typing import Mapping + from packaging.utils import NormalizedName from poetry.core.packages.package import Package @@ -43,13 +44,15 @@ def get_extra_package_names( # keep record of packages seen during recursion in order to avoid recursion error seen_package_names = set() - def _extra_packages(package_names: Iterable[str]) -> Iterator[str]: + def _extra_packages( + package_names: Iterable[NormalizedName], + ) -> Iterator[NormalizedName]: """Recursively find dependencies for packages names""" # for each extra package name for package_name in package_names: # Find the actual Package object. A missing key indicates an implicit # dependency (like setuptools), which should be ignored - package = packages_by_name.get(canonicalize_name(package_name)) + package = packages_by_name.get(package_name) if package: if package.name not in seen_package_names: seen_package_names.add(package.name) diff --git a/src/poetry/utils/shell.py b/src/poetry/utils/shell.py index 1a5de3c9cf5..bce274f3700 100644 --- a/src/poetry/utils/shell.py +++ b/src/poetry/utils/shell.py @@ -93,7 +93,7 @@ def activate(self, env: VirtualEnv) -> int | None: self._path, ["-i"], dimensions=(terminal.height, terminal.width) ) - if self._name == "zsh": + if self._name in ["zsh", "nu"]: c.setecho(False) c.sendline(f"{self._get_source_command()} {shlex.quote(str(activate_path))}") @@ -119,13 +119,15 @@ def _get_activate_script(self) -> str: suffix = ".ps1" elif self._name == "cmd": suffix = ".bat" + elif self._name == "nu": + suffix = ".nu" else: suffix = "" return "activate" + suffix def _get_source_command(self) -> str: - if self._name in ("fish", "csh", "tcsh"): + if self._name in ("fish", "csh", "tcsh", "nu"): return "source" return "." diff --git a/tests/compat.py b/tests/compat.py index 411fca199d0..7bcd4e4c6d2 100644 --- a/tests/compat.py +++ b/tests/compat.py @@ -1,12 +1,14 @@ from __future__ import annotations +import sys -try: - import zipp # nopycln: import -except ImportError: - import zipfile as zipp # noqa: F401, TC002 + +if sys.version_info < (3, 8): + import zipp as zipfile # nopycln: import +else: + import zipfile # noqa: F401 try: from typing import Protocol # nopycln: import except ImportError: - from typing_extensions import Protocol # noqa: F401, TC002 + from typing_extensions import Protocol # noqa: F401 diff --git a/tests/console/commands/self/test_add_plugins.py b/tests/console/commands/self/test_add_plugins.py index 0259342a8fd..e8447a32b13 100644 --- a/tests/console/commands/self/test_add_plugins.py +++ b/tests/console/commands/self/test_add_plugins.py @@ -138,6 +138,53 @@ def test_add_with_git_constraint_with_extras( ) +@pytest.mark.parametrize( + "url, rev", + [ + ("git+https://github.com/demo/poetry-plugin2.git#subdirectory=subdir", None), + ( + "git+https://github.com/demo/poetry-plugin2.git@master#subdirectory=subdir", + "master", + ), + ], +) +def test_add_with_git_constraint_with_subdirectory( + url: str, + rev: str | None, + tester: CommandTester, + repo: TestRepository, +): + repo.add_package(Package("pendulum", "2.0.5")) + + tester.execute(url) + + expected = """ +Updating dependencies +Resolving dependencies... + +Writing lock file + +Package operations: 2 installs, 0 updates, 0 removals + + • Installing pendulum (2.0.5) + • Installing poetry-plugin (0.1.2 9cf87a2) +""" + + constraint = { + "git": "https://github.com/demo/poetry-plugin2.git", + "subdirectory": "subdir", + } + + if rev: + constraint["rev"] = rev + + assert_plugin_add_result( + tester, + expected, + constraint, + ) + + def test_add_existing_plugin_warns_about_no_operation( tester: CommandTester, repo: TestRepository, diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 17a6e6977cf..27f803d3915 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -374,6 +374,53 @@ def test_add_git_constraint_with_extras( } +@pytest.mark.parametrize( + "url, rev", + [ + ("git+https://github.com/demo/subdirectories.git#subdirectory=two", None), + ( + "git+https://github.com/demo/subdirectories.git@master#subdirectory=two", + "master", + ), + ], +) +def test_add_git_constraint_with_subdirectory( + url: str, + rev: str | None, + app: PoetryTestApplication, + repo: TestRepository, + tester: CommandTester, + env: MockEnv, +): + tester.execute(url) + + expected = """\ +Updating dependencies +Resolving dependencies... + +Writing lock file + +Package operations: 1 install, 0 updates, 0 removals + + • Installing two (2.0.0 9cf87a2) +""" + assert tester.io.fetch_output().strip() == expected.strip() + assert tester.command.installer.executor.installations_count == 1 + + content = app.poetry.file.read()["tool"]["poetry"] + + constraint = { + "git": "https://github.com/demo/subdirectories.git", + "subdirectory": "two", + } + + if rev: + constraint["rev"] = rev + + assert "two" in content["dependencies"] + assert content["dependencies"]["two"] == constraint + + @pytest.mark.parametrize("editable", [False, True]) def test_add_git_ssh_constraint( editable: bool, diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py index 4ebd8286324..559f58f323f 100644 --- a/tests/console/commands/test_publish.py +++ b/tests/console/commands/test_publish.py @@ -36,7 +36,7 @@ def test_publish_returns_non_zero_code_for_upload_errors( Publishing simple-project (1.2.3) to PyPI """ expected_error_output = """\ -HTTP Error 400: Bad Request +HTTP Error 400: Bad Request | b'Bad Request' """ assert expected_output in app_tester.io.fetch_output() diff --git a/tests/fixtures/git/github.com/demo/poetry-plugin2/subdir/poetry_plugin/__init__.py b/tests/fixtures/git/github.com/demo/poetry-plugin2/subdir/poetry_plugin/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/git/github.com/demo/poetry-plugin2/subdir/pyproject.toml b/tests/fixtures/git/github.com/demo/poetry-plugin2/subdir/pyproject.toml new file mode 100644 index 00000000000..b45d9d976eb --- /dev/null +++ b/tests/fixtures/git/github.com/demo/poetry-plugin2/subdir/pyproject.toml @@ -0,0 +1,18 @@ +[tool.poetry] +name = "poetry-plugin" +version = "0.1.2" +description = "Some description." +authors = [ + "Sébastien Eustace " +] +license = "MIT" + +[tool.poetry.dependencies] +python = "^3.6" +pendulum = "^2.0" +tomlkit = {version = "^0.7.0", optional = true} + +[tool.poetry.extras] +foo = ["tomlkit"] + +[tool.poetry.dev-dependencies] diff --git a/tests/fixtures/git/github.com/demo/subdirectories/one-copy/one/__init__.py b/tests/fixtures/git/github.com/demo/subdirectories/one-copy/one/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/git/github.com/demo/subdirectories/one-copy/pyproject.toml b/tests/fixtures/git/github.com/demo/subdirectories/one-copy/pyproject.toml index 39265efe4a3..1548c3a33a1 100644 --- a/tests/fixtures/git/github.com/demo/subdirectories/one-copy/pyproject.toml +++ b/tests/fixtures/git/github.com/demo/subdirectories/one-copy/pyproject.toml @@ -7,3 +7,7 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.7" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/fixtures/git/github.com/demo/subdirectories/one/one/__init__.py b/tests/fixtures/git/github.com/demo/subdirectories/one/one/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/git/github.com/demo/subdirectories/one/pyproject.toml b/tests/fixtures/git/github.com/demo/subdirectories/one/pyproject.toml index 39265efe4a3..1548c3a33a1 100644 --- a/tests/fixtures/git/github.com/demo/subdirectories/one/pyproject.toml +++ b/tests/fixtures/git/github.com/demo/subdirectories/one/pyproject.toml @@ -7,3 +7,7 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.7" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/fixtures/git/github.com/demo/subdirectories/two/pyproject.toml b/tests/fixtures/git/github.com/demo/subdirectories/two/pyproject.toml index 58fde435649..6a54d8938ff 100644 --- a/tests/fixtures/git/github.com/demo/subdirectories/two/pyproject.toml +++ b/tests/fixtures/git/github.com/demo/subdirectories/two/pyproject.toml @@ -6,4 +6,8 @@ authors = [] license = "MIT" [tool.poetry.dependencies] -python = "^3.7" +python = "~2.7 || ^3.4" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/fixtures/git/github.com/demo/subdirectories/two/two/__init__.py b/tests/fixtures/git/github.com/demo/subdirectories/two/two/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/no_name_project/README.rst b/tests/fixtures/no_name_project/README.rst new file mode 100644 index 00000000000..8b194670930 --- /dev/null +++ b/tests/fixtures/no_name_project/README.rst @@ -0,0 +1,2 @@ +No name project +=============== diff --git a/tests/fixtures/no_name_project/pyproject.toml b/tests/fixtures/no_name_project/pyproject.toml new file mode 100644 index 00000000000..f18fa403c06 --- /dev/null +++ b/tests/fixtures/no_name_project/pyproject.toml @@ -0,0 +1,18 @@ +[tool.poetry] +name = "" +version = "1.2.3" +description = "This project has no name" +authors = [ + "Sébastien Eustace " +] +license = "MIT" + +readme = "README.rst" + + +# Requirements +[tool.poetry.dependencies] +python = "~2.7 || ^3.6" + +[tool.poetry.group.dev.dependencies] +pytest = "~3.4" diff --git a/tests/installation/fixtures/with-pypi-repository.test b/tests/installation/fixtures/with-pypi-repository.test index 27fee8ce755..ac57e43ec7b 100644 --- a/tests/installation/fixtures/with-pypi-repository.test +++ b/tests/installation/fixtures/with-pypi-repository.test @@ -7,7 +7,7 @@ optional = false python-versions = "*" [package.extras] -dev = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope-interface", "sphinx", "zope-interface"] +dev = ["coverage", "hypothesis", "pympler", "pytest", "six", "sphinx", "zope-interface", "zope-interface"] docs = ["sphinx", "zope-interface"] tests = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope-interface"] @@ -72,14 +72,6 @@ pluggy = ">=0.5,<0.7" funcsigs = {"version" = "*", "markers" = "python_version < \"3.0\""} colorama = {"version" = "*", "markers" = "sys_platform == \"win32\""} -[[package]] -name = "six" -version = "1.11.0" -description = "Python 2 and 3 compatibility utilities" -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "setuptools" version = "39.2.0" @@ -92,6 +84,14 @@ python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" certs = ["certifi (==2016.9.26)"] ssl = ["wincertstore (==0.2)"] +[[package]] +name = "six" +version = "1.11.0" +description = "Python 2 and 3 compatibility utilities" +category = "dev" +optional = false +python-versions = "*" + [metadata] python-versions = "*" lock-version = "1.1" diff --git a/tests/installation/test_executor.py b/tests/installation/test_executor.py index 6d67c36770f..7f60905a33c 100644 --- a/tests/installation/test_executor.py +++ b/tests/installation/test_executor.py @@ -553,6 +553,40 @@ def test_executor_should_write_pep610_url_references_for_git( ) +def test_executor_should_write_pep610_url_references_for_git_with_subdirectories( + tmp_venv: VirtualEnv, + pool: Pool, + config: Config, + io: BufferedIO, + mock_file_downloads: None, +): + package = Package( + "two", + "2.0.0", + source_type="git", + source_reference="master", + source_resolved_reference="123456", + source_url="https://github.com/demo/subdirectories.git", + source_subdirectory="two", + ) + + executor = Executor(tmp_venv, pool, config, io) + executor.execute([Install(package)]) + verify_installed_distribution( + tmp_venv, + package, + { + "vcs_info": { + "vcs": "git", + "requested_revision": "master", + "commit_id": "123456", + }, + "url": package.source_url, + "subdirectory": package.source_subdirectory, + }, + ) + + def test_executor_should_use_cached_link_and_hash( tmp_venv: VirtualEnv, pool: Pool, diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py index 2aee63d9701..452ff425da9 100644 --- a/tests/installation/test_installer.py +++ b/tests/installation/test_installer.py @@ -14,7 +14,6 @@ from cleo.io.null_io import NullIO from cleo.io.outputs.buffered_output import BufferedOutput from cleo.io.outputs.output import Verbosity -from deepdiff import DeepDiff from poetry.core.packages.dependency_group import MAIN_GROUP from poetry.core.packages.dependency_group import DependencyGroup from poetry.core.packages.package import Package @@ -1164,7 +1163,7 @@ def test_installer_with_pypi_repository( expected = fixture("with-pypi-repository") - assert not DeepDiff(expected, locker.written_data, ignore_order=True) + assert expected == locker.written_data def test_run_installs_with_local_file( diff --git a/tests/installation/test_installer_old.py b/tests/installation/test_installer_old.py index cdf62563374..baa59649ce9 100644 --- a/tests/installation/test_installer_old.py +++ b/tests/installation/test_installer_old.py @@ -8,7 +8,6 @@ import pytest from cleo.io.null_io import NullIO -from deepdiff import DeepDiff from poetry.core.packages.project_package import ProjectPackage from poetry.core.toml.file import TOMLFile @@ -833,7 +832,7 @@ def test_installer_with_pypi_repository( expected = fixture("with-pypi-repository") - assert not DeepDiff(expected, locker.written_data, ignore_order=True) + assert expected == locker.written_data def test_run_installs_with_local_file( diff --git a/tests/installation/test_pip_installer.py b/tests/installation/test_pip_installer.py index 32a6acc83b1..4763d71bb42 100644 --- a/tests/installation/test_pip_installer.py +++ b/tests/installation/test_pip_installer.py @@ -38,6 +38,20 @@ def package_git() -> Package: return package +@pytest.fixture +def package_git_with_subdirectory() -> Package: + package = Package( + "subdirectories", + "2.0.0", + source_type="git", + source_url="https://github.com/demo/subdirectories.git", + source_reference="master", + source_subdirectory="two", + ) + + return package + + @pytest.fixture def pool() -> Pool: return Pool() @@ -85,6 +99,24 @@ def test_requirement_source_type_url(): assert result == expected +def test_requirement_git_subdirectory( + pool: Pool, package_git_with_subdirectory: Package +) -> None: + null_env = NullEnv() + installer = PipInstaller(null_env, NullIO(), pool) + result = installer.requirement(package_git_with_subdirectory) + expected = ( + "git+https://github.com/demo/subdirectories.git" + "@master#egg=subdirectories&subdirectory=two" + ) + + assert result == expected + installer.install(package_git_with_subdirectory) + assert len(null_env.executed) == 1 + cmd = null_env.executed[0] + assert Path(cmd[-1]).parts[-3:] == ("demo", "subdirectories", "two") + + def test_requirement_git_develop_false(installer: PipInstaller, package_git: Package): package_git.develop = False result = installer.requirement(package_git) diff --git a/tests/mixology/version_solver/test_dependency_cache.py b/tests/mixology/version_solver/test_dependency_cache.py index 423573876ff..c863a9672d6 100644 --- a/tests/mixology/version_solver/test_dependency_cache.py +++ b/tests/mixology/version_solver/test_dependency_cache.py @@ -106,16 +106,19 @@ def test_solver_dependency_cache_respects_subdirectories( package_one = packages_one[0] package_one_copy = packages_one_copy[0] - assert package_one.package.name == package_one_copy.name + assert package_one.package.name == package_one_copy.package.name assert package_one.package.version.text == package_one_copy.package.version.text - assert package_one.package.source_type == package_one_copy.source_type == "git" + assert ( + package_one.package.source_type == package_one_copy.package.source_type == "git" + ) assert ( package_one.package.source_resolved_reference - == package_one_copy.source_resolved_reference + == package_one_copy.package.source_resolved_reference == "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" ) assert ( - package_one.package.source_subdirectory != package_one_copy.source_subdirectory + package_one.package.source_subdirectory + != package_one_copy.package.source_subdirectory ) assert package_one.package.source_subdirectory == "one" assert package_one_copy.package.source_subdirectory == "one-copy" diff --git a/tests/packages/test_locker.py b/tests/packages/test_locker.py index 0e79817d4f3..f41fc2ba056 100644 --- a/tests/packages/test_locker.py +++ b/tests/packages/test_locker.py @@ -2,6 +2,8 @@ import json import logging +import os +import sys import tempfile import uuid @@ -55,6 +57,15 @@ def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage): source_reference="develop", source_resolved_reference="123456", ) + package_git_with_subdirectory = Package( + "git-package-subdir", + "1.2.3", + source_type="git", + source_url="https://github.com/python-poetry/poetry.git", + source_reference="develop", + source_resolved_reference="123456", + source_subdirectory="subdir", + ) package_url_linux = Package( "url-package", "1.0", @@ -72,6 +83,7 @@ def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage): package_a, get_package("B", "1.2"), package_git, + package_git_with_subdirectory, package_url_win32, package_url_linux, ] @@ -124,6 +136,22 @@ def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage): reference = "develop" resolved_reference = "123456" +[[package]] +name = "git-package-subdir" +version = "1.2.3" +description = "" +category = "main" +optional = false +python-versions = "*" +develop = false + +[package.source] +type = "git" +url = "https://github.com/python-poetry/poetry.git" +reference = "develop" +resolved_reference = "123456" +subdirectory = "subdir" + [[package]] name = "url-package" version = "1.0" @@ -161,6 +189,7 @@ def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage): ] B = [] git-package = [] +git-package-subdir = [] url-package = [] """ @@ -342,6 +371,44 @@ def test_locker_properly_loads_extras_legacy(locker: Locker): assert dependency_b.name == "b" +def test_locker_properly_loads_subdir(locker: Locker) -> None: + content = """\ +[[package]] +name = "git-package-subdir" +version = "1.2.3" +description = "" +category = "main" +optional = false +python-versions = "*" +develop = false + +[package.source] +type = "git" +url = "https://github.com/python-poetry/poetry.git" +reference = "develop" +resolved_reference = "123456" +subdirectory = "subdir" + +[metadata] +lock-version = "1.1" +python-versions = "*" +content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8" + +[metadata.files] +git-package-subdir = [] +""" + locker.lock.write(tomlkit.parse(content)) + + repository = locker.locked_repository() + assert len(repository.packages) == 1 + + packages = repository.find_packages(get_dependency("git-package-subdir", "1.2.3")) + assert len(packages) == 1 + + package = packages[0] + assert package.source_subdirectory == "subdir" + + def test_lock_packages_with_null_description(locker: Locker, root: ProjectPackage): package_a = get_package("A", "1.0.0") package_a.description = None @@ -666,6 +733,96 @@ def test_locker_dumps_dependency_information_correctly( assert content == expected +def test_locker_dumps_subdir(locker: Locker, root: ProjectPackage) -> None: + package_git_with_subdirectory = Package( + "git-package-subdir", + "1.2.3", + source_type="git", + source_url="https://github.com/python-poetry/poetry.git", + source_reference="develop", + source_resolved_reference="123456", + source_subdirectory="subdir", + ) + + locker.set_lock_data(root, [package_git_with_subdirectory]) + + with locker.lock.open(encoding="utf-8") as f: + content = f.read() + + expected = """\ +[[package]] +name = "git-package-subdir" +version = "1.2.3" +description = "" +category = "main" +optional = false +python-versions = "*" +develop = false + +[package.source] +type = "git" +url = "https://github.com/python-poetry/poetry.git" +reference = "develop" +resolved_reference = "123456" +subdirectory = "subdir" + +[metadata] +lock-version = "1.1" +python-versions = "*" +content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8" + +[metadata.files] +git-package-subdir = [] +""" + + assert content == expected + + +def test_locker_dumps_dependency_extras_in_correct_order( + locker: Locker, root: ProjectPackage +): + root_dir = Path(__file__).parent.parent.joinpath("fixtures") + package_a = get_package("A", "1.0.0") + Factory.create_dependency("B", "1.0.0", root_dir=root_dir) + Factory.create_dependency("C", "1.0.0", root_dir=root_dir) + package_first = Factory.create_dependency("first", "1.0.0", root_dir=root_dir) + package_second = Factory.create_dependency("second", "1.0.0", root_dir=root_dir) + package_third = Factory.create_dependency("third", "1.0.0", root_dir=root_dir) + + package_a.extras = { + "C": [package_third, package_second, package_first], + "B": [package_first, package_second, package_third], + } + + locker.set_lock_data(root, [package_a]) + + with locker.lock.open(encoding="utf-8") as f: + content = f.read() + + expected = """[[package]] +name = "A" +version = "1.0.0" +description = "" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +B = ["first (==1.0.0)", "second (==1.0.0)", "third (==1.0.0)"] +C = ["first (==1.0.0)", "second (==1.0.0)", "third (==1.0.0)"] + +[metadata] +lock-version = "1.1" +python-versions = "*" +content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8" + +[metadata.files] +A = [] +""" + + assert content == expected + + def test_locked_repository_uses_root_dir_of_package( locker: Locker, mocker: MockerFixture ): @@ -753,3 +910,91 @@ def test_content_hash_with_legacy_is_compatible( content_hash = locker._get_content_hash() assert (content_hash == old_content_hash) or fresh + + +def test_lock_file_resolves_file_url_symlinks(root: ProjectPackage): + """ + Create directories and file structure as follows: + + d1/ + d1/testsymlink -> d1/d2/d3 + d1/d2/d3/lock_file + d1/d4/source_file + + Using the testsymlink as the Locker.lock file path should correctly resolve to + the real physical path of the source_file when calculating the relative path + from the lock_file, i.e. "../../d4/source_file" instead of the unresolved path + from the symlink itself which would have been "../d4/source_file" + + See https://github.com/python-poetry/poetry/issues/5849 + """ + with tempfile.TemporaryDirectory() as d1: + symlink_path = Path(d1).joinpath("testsymlink") + with tempfile.TemporaryDirectory(dir=d1) as d2, tempfile.TemporaryDirectory( + dir=d1 + ) as d4, tempfile.TemporaryDirectory(dir=d2) as d3, tempfile.NamedTemporaryFile( + dir=d4 + ) as source_file, tempfile.NamedTemporaryFile( + dir=d3 + ) as lock_file: + lock_file.close() + try: + os.symlink(Path(d3), symlink_path) + except OSError: + if sys.platform == "win32": + # os.symlink requires either administrative privileges or developer + # mode on Win10, throwing an OSError if neither is active. + # Test is not possible in that case. + return + raise + locker = Locker(str(symlink_path) + os.sep + Path(lock_file.name).name, {}) + + package_local = Package( + "local-package", + "1.2.3", + source_type="file", + source_url=source_file.name, + source_reference="develop", + source_resolved_reference="123456", + ) + packages = [ + package_local, + ] + + locker.set_lock_data(root, packages) + + with locker.lock.open(encoding="utf-8") as f: + content = f.read() + + expected = f"""\ +[[package]] +name = "local-package" +version = "1.2.3" +description = "" +category = "main" +optional = false +python-versions = "*" + +[package.source] +type = "file" +url = "{ + Path( + os.path.relpath( + Path(source_file.name).resolve().as_posix(), + Path(Path(lock_file.name).parent).resolve().as_posix(), + ) + ).as_posix() +}" +reference = "develop" +resolved_reference = "123456" + +[metadata] +lock-version = "1.1" +python-versions = "*" +content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8" + +[metadata.files] +local-package = [] +""" + + assert content == expected diff --git a/tests/publishing/test_uploader.py b/tests/publishing/test_uploader.py index 84581c4ffd4..9a7346825f3 100644 --- a/tests/publishing/test_uploader.py +++ b/tests/publishing/test_uploader.py @@ -32,7 +32,7 @@ def test_uploader_properly_handles_400_errors( with pytest.raises(UploadError) as e: uploader.upload("https://foo.com") - assert str(e.value) == "HTTP Error 400: Bad Request" + assert str(e.value) == "HTTP Error 400: Bad Request | b'Bad request'" def test_uploader_properly_handles_403_errors( @@ -43,7 +43,26 @@ def test_uploader_properly_handles_403_errors( with pytest.raises(UploadError) as e: uploader.upload("https://foo.com") - assert str(e.value) == "HTTP Error 403: Forbidden" + assert str(e.value) == "HTTP Error 403: Forbidden | b'Unauthorized'" + + +def test_uploader_properly_handles_nonstandard_errors( + http: type[httpretty.httpretty], uploader: Uploader +): + # content based off a true story. + # Message changed to protect the ~~innocent~~ guilty. + content = ( + b'{\n "errors": [ {\n ' + b'"status": 400,' + b'"message": "I cant let you do that, dave"\n' + b"} ]\n}" + ) + http.register_uri(http.POST, "https://foo.com", status=400, body=content) + + with pytest.raises(UploadError) as e: + uploader.upload("https://foo.com") + + assert str(e.value) == f"HTTP Error 400: Bad Request | {content}" def test_uploader_properly_handles_301_redirects( diff --git a/tests/puzzle/test_provider.py b/tests/puzzle/test_provider.py index bba585d91f4..60a45e9fca6 100644 --- a/tests/puzzle/test_provider.py +++ b/tests/puzzle/test_provider.py @@ -7,9 +7,12 @@ import pytest from cleo.io.null_io import NullIO +from poetry.core.packages.dependency import Dependency from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.file_dependency import FileDependency +from poetry.core.packages.package import Package from poetry.core.packages.project_package import ProjectPackage +from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.vcs_dependency import VCSDependency from poetry.factory import Factory @@ -27,6 +30,9 @@ from pytest_mock import MockerFixture +SOME_URL = "https://example.com/path.tar.gz" + + class MockEnv(BaseMockEnv): def run(self, bin: str, *args: str) -> None: raise EnvCommandError(CalledProcessError(1, "python", output="")) @@ -55,6 +61,108 @@ def provider(root: ProjectPackage, pool: Pool) -> Provider: return Provider(root, pool, NullIO()) +@pytest.mark.parametrize( + "dependency, expected", + [ + (Dependency("foo", "<2"), [Package("foo", "1")]), + (Dependency("foo", "<2", extras=["bar"]), [Package("foo", "1")]), + (Dependency("foo", ">=1"), [Package("foo", "2"), Package("foo", "1")]), + ( + Dependency("foo", ">=1a"), + [ + Package("foo", "3a"), + Package("foo", "2"), + Package("foo", "2a"), + Package("foo", "1"), + ], + ), + ( + Dependency("foo", ">=1", allows_prereleases=True), + [ + Package("foo", "3a"), + Package("foo", "2"), + Package("foo", "2a"), + Package("foo", "1"), + ], + ), + ], +) +def test_search_for( + provider: Provider, + repository: Repository, + dependency: Dependency, + expected: list[Package], +) -> None: + foo1 = Package("foo", "1") + foo2a = Package("foo", "2a") + foo2 = Package("foo", "2") + foo3a = Package("foo", "3a") + repository.add_package(foo1) + repository.add_package(foo2a) + repository.add_package(foo2) + repository.add_package(foo3a) + assert provider.search_for(dependency) == expected + + +@pytest.mark.parametrize( + "dependency, direct_origin_dependency, expected_before, expected_after", + [ + ( + Dependency("foo", ">=1"), + URLDependency("foo", SOME_URL), + [Package("foo", "3")], + [Package("foo", "2a", source_type="url", source_url=SOME_URL)], + ), + ( + Dependency("foo", ">=2"), + URLDependency("foo", SOME_URL), + [Package("foo", "3")], + [], + ), + ( + Dependency("foo", ">=1", extras=["bar"]), + URLDependency("foo", SOME_URL), + [Package("foo", "3")], + [Package("foo", "2a", source_type="url", source_url=SOME_URL)], + ), + ( + Dependency("foo", ">=1"), + URLDependency("foo", SOME_URL, extras=["baz"]), + [Package("foo", "3")], + [Package("foo", "2a", source_type="url", source_url=SOME_URL)], + ), + ( + Dependency("foo", ">=1", extras=["bar"]), + URLDependency("foo", SOME_URL, extras=["baz"]), + [Package("foo", "3")], + [Package("foo", "2a", source_type="url", source_url=SOME_URL)], + ), + ], +) +def test_search_for_direct_origin_and_extras( + provider: Provider, + repository: Repository, + mocker: MockerFixture, + dependency: Dependency, + direct_origin_dependency: Dependency, + expected_before: list[Package], + expected_after: list[Package], +) -> None: + foo2a_direct_origin = Package("foo", "2a", source_type="url", source_url=SOME_URL) + mocker.patch( + "poetry.puzzle.provider.Provider.search_for_direct_origin_dependency", + return_value=foo2a_direct_origin, + ) + foo2a = Package("foo", "2a") + foo3 = Package("foo", "3") + repository.add_package(foo2a) + repository.add_package(foo3) + + assert provider.search_for(dependency) == expected_before + assert provider.search_for(direct_origin_dependency) == [foo2a_direct_origin] + assert provider.search_for(dependency) == expected_after + + @pytest.mark.parametrize("value", [True, False]) def test_search_for_vcs_retains_develop_flag(provider: Provider, value: bool): dependency = VCSDependency( diff --git a/tests/puzzle/test_solver.py b/tests/puzzle/test_solver.py index b22ff4ed5bd..96b1bf257af 100644 --- a/tests/puzzle/test_solver.py +++ b/tests/puzzle/test_solver.py @@ -1448,9 +1448,9 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved( DependencyPackage(package.to_dependency(), package) ) - assert len(complete_package.all_requires) == 2 + assert len(complete_package.package.all_requires) == 2 - pypi, git = complete_package.all_requires + pypi, git = complete_package.package.all_requires assert isinstance(pypi, Dependency) assert pypi == dependency_pypi @@ -3596,3 +3596,88 @@ def test_solver_direct_origin_dependency_with_extras_requested_by_other_package( assert op.package.version.text == "0.1.2" assert op.package.source_type == "directory" assert op.package.source_url == path + + +def test_solver_incompatible_dependency_with_and_without_extras( + solver: Solver, repo: Repository, package: ProjectPackage +): + """ + The solver first encounters a requirement for google-auth and then later an + incompatible requirement for google-auth[aiohttp]. + + Testcase derived from https://github.com/python-poetry/poetry/issues/6054. + """ + # Incompatible requirements from foo and bar2. + foo = get_package("foo", "1.0.0") + foo.add_dependency(Factory.create_dependency("google-auth", {"version": "^1"})) + + bar = get_package("bar", "1.0.0") + + bar2 = get_package("bar", "2.0.0") + bar2.add_dependency( + Factory.create_dependency( + "google-auth", {"version": "^2", "extras": ["aiohttp"]} + ) + ) + + baz = get_package("baz", "1.0.0") # required by google-auth[aiohttp] + + google_auth = get_package("google-auth", "1.2.3") + google_auth.extras = {"aiohttp": [get_dependency("baz", "^1.0")]} + + google_auth2 = get_package("google-auth", "2.3.4") + google_auth2.extras = {"aiohttp": [get_dependency("baz", "^1.0")]} + + repo.add_package(foo) + repo.add_package(bar) + repo.add_package(bar2) + repo.add_package(baz) + repo.add_package(google_auth) + repo.add_package(google_auth2) + + package.add_dependency(Factory.create_dependency("foo", ">=1")) + package.add_dependency(Factory.create_dependency("bar", ">=1")) + + transaction = solver.solve() + + check_solver_result( + transaction, + [ + {"job": "install", "package": google_auth}, + {"job": "install", "package": bar}, + {"job": "install", "package": foo}, + ], + ) + + +def test_update_with_prerelease_and_no_solution( + solver: Solver, + repo: Repository, + installed: InstalledRepository, + package: ProjectPackage, + locked: Repository, +): + # Locked and installed: cleo which depends on an old version of crashtest. + cleo = get_package("cleo", "1.0.0a5") + crashtest = get_package("crashtest", "0.3.0") + cleo.add_dependency(Factory.create_dependency("crashtest", {"version": "<0.4.0"})) + locked.add_package(cleo) + locked.add_package(crashtest) + + installed.add_package(cleo) + installed.add_package(crashtest) + + # Try to upgrade to a new version of crashtest, this will be disallowed by the + # dependency from cleo. + package.add_dependency(Factory.create_dependency("cleo", "^1.0.0a5")) + package.add_dependency(Factory.create_dependency("crashtest", "^0.4.0")) + + newer_crashtest = get_package("crashtest", "0.4.0") + even_newer_crashtest = get_package("crashtest", "0.4.1") + repo.add_package(cleo) + repo.add_package(crashtest) + repo.add_package(newer_crashtest) + repo.add_package(even_newer_crashtest) + + with pytest.raises(SolverProblemError): + solver.solve() diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610_subdirectory-1.2.3.dist-info/METADATA b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610_subdirectory-1.2.3.dist-info/METADATA new file mode 100644 index 00000000000..551158eb9ba --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610_subdirectory-1.2.3.dist-info/METADATA @@ -0,0 +1,6 @@ +Metadata-Version: 2.1 +Name: git-pep-610-subdirectory +Version: 1.2.3 +Summary: Foo +License: MIT +Requires-Python: >=3.6 diff --git a/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610_subdirectory-1.2.3.dist-info/direct_url.json b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610_subdirectory-1.2.3.dist-info/direct_url.json new file mode 100644 index 00000000000..6b6c93ab265 --- /dev/null +++ b/tests/repositories/fixtures/installed/lib/python3.7/site-packages/git_pep_610_subdirectory-1.2.3.dist-info/direct_url.json @@ -0,0 +1,9 @@ +{ + "url": "https://github.com/demo/git-pep-610-subdirectory.git", + "vcs_info": { + "vcs": "git", + "requested_revision": "my-branch", + "commit_id": "123456" + }, + "subdirectory": "subdir" +} diff --git a/tests/repositories/test_installed_repository.py b/tests/repositories/test_installed_repository.py index e6c36349ec3..87dfe183c8a 100644 --- a/tests/repositories/test_installed_repository.py +++ b/tests/repositories/test_installed_repository.py @@ -9,7 +9,7 @@ from poetry.repositories.installed_repository import InstalledRepository from poetry.utils._compat import metadata from poetry.utils.env import MockEnv as BaseMockEnv -from tests.compat import zipp +from tests.compat import zipfile if TYPE_CHECKING: @@ -27,7 +27,7 @@ metadata.PathDistribution(SITE_PURELIB / "cleo-0.7.6.dist-info"), metadata.PathDistribution(SRC / "pendulum" / "pendulum.egg-info"), metadata.PathDistribution( - zipp.Path(str(SITE_PURELIB / "foo-0.1.0-py3.8.egg"), "EGG-INFO") + zipfile.Path(str(SITE_PURELIB / "foo-0.1.0-py3.8.egg"), "EGG-INFO") ), metadata.PathDistribution(VENDOR_DIR / "attrs-19.3.0.dist-info"), metadata.PathDistribution(SITE_PURELIB / "standard-1.2.3.dist-info"), @@ -39,6 +39,9 @@ metadata.PathDistribution( SITE_PURELIB / "git_pep_610_no_requested_version-1.2.3.dist-info" ), + metadata.PathDistribution( + SITE_PURELIB / "git_pep_610_subdirectory-1.2.3.dist-info" + ), metadata.PathDistribution(SITE_PURELIB / "url_pep_610-1.2.3.dist-info"), metadata.PathDistribution(SITE_PURELIB / "file_pep_610-1.2.3.dist-info"), metadata.PathDistribution(SITE_PURELIB / "directory_pep_610-1.2.3.dist-info"), @@ -238,6 +241,20 @@ def test_load_pep_610_compliant_git_packages_no_requested_version( assert package.source_reference == package.source_resolved_reference +def test_load_pep_610_compliant_git_packages_with_subdirectory( + repository: InstalledRepository, +): + package = get_package_from_repository("git-pep-610-subdirectory", repository) + assert package is not None + assert package.name == "git-pep-610-subdirectory" + assert package.version.text == "1.2.3" + assert package.source_type == "git" + assert package.source_url == "https://github.com/demo/git-pep-610-subdirectory.git" + assert package.source_reference == "my-branch" + assert package.source_resolved_reference == "123456" + assert package.source_subdirectory == "subdir" + + def test_load_pep_610_compliant_url_packages(repository: InstalledRepository): package = get_package_from_repository("url-pep-610", repository) diff --git a/tests/utils/test_dependency_specification.py b/tests/utils/test_dependency_specification.py index c536830af25..95cdffea6bf 100644 --- a/tests/utils/test_dependency_specification.py +++ b/tests/utils/test_dependency_specification.py @@ -35,6 +35,15 @@ "git+https://github.com/demo/demo.git@main", {"git": "https://github.com/demo/demo.git", "name": "demo", "rev": "main"}, ), + ( + "git+https://github.com/demo/subdirectories.git@main#subdirectory=two", + { + "git": "https://github.com/demo/subdirectories.git", + "name": "two", + "rev": "main", + "subdirectory": "two", + }, + ), ("demo", {"name": "demo"}), ("demo@1.0.0", {"name": "demo", "version": "1.0.0"}), ("demo@^1.0.0", {"name": "demo", "version": "^1.0.0"}), diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py index d3ae0624965..9c6aa7c9d36 100644 --- a/tests/utils/test_env.py +++ b/tests/utils/test_env.py @@ -1500,6 +1500,13 @@ def test_generate_env_name_ignores_case_for_case_insensitive_fs( assert venv_name1 != venv_name2 +def test_generate_env_name_uses_real_path(tmp_dir: str, mocker: MockerFixture): + mocker.patch("os.path.realpath", return_value="the_real_dir") + venv_name1 = EnvManager.generate_env_name("simple-project", "the_real_dir") + venv_name2 = EnvManager.generate_env_name("simple-project", "linked_dir") + assert venv_name1 == venv_name2 + + @pytest.fixture() def extended_without_setup_poetry() -> Poetry: poetry = Factory().create_poetry( @@ -1546,3 +1553,43 @@ def test_build_environment_not_called_without_build_script_specified( with build_environment(poetry, project_env) as env: assert env == project_env assert not env.executed + + +def test_create_venv_project_name_empty_sets_correct_prompt( + project_factory: ProjectFactory, + config: Config, + mocker: MockerFixture, + config_virtualenvs_path: Path, +): + if "VIRTUAL_ENV" in os.environ: + del os.environ["VIRTUAL_ENV"] + + fixture = Path(__file__).parent.parent / "fixtures" / "no_name_project" + poetry = project_factory("no", source=fixture) + manager = EnvManager(poetry) + + poetry.package.python_versions = "^3.7" + venv_name = manager.generate_env_name("", str(poetry.file.parent)) + + mocker.patch("sys.version_info", (2, 7, 16)) + mocker.patch( + "subprocess.check_output", + side_effect=check_output_wrapper(Version.parse("3.7.5")), + ) + m = mocker.patch( + "poetry.utils.env.EnvManager.build_venv", side_effect=lambda *args, **kwargs: "" + ) + + manager.create_venv(NullIO()) + + m.assert_called_with( + config_virtualenvs_path / f"{venv_name}-py3.7", + executable="python3", + flags={ + "always-copy": False, + "system-site-packages": False, + "no-pip": False, + "no-setuptools": False, + }, + prompt="virtualenv-py3.7", + ) diff --git a/tests/utils/test_extras.py b/tests/utils/test_extras.py index 9fdc2faeb7d..777016984b0 100644 --- a/tests/utils/test_extras.py +++ b/tests/utils/test_extras.py @@ -63,7 +63,7 @@ def test_get_extra_package_names( extras: dict[str, list[str]], extra_names: list[str], expected_extra_package_names: list[str], -): +) -> None: assert ( list(get_extra_package_names(packages, extras, extra_names)) == expected_extra_package_names