Commit 5a2a3e62 by Sébastien Eustace

Merge branch 'master' into develop

# Conflicts:
#	CHANGELOG.md
#	poetry.lock
#	poetry/__version__.py
#	poetry/installation/installer.py
#	pyproject.toml
#	tests/console/conftest.py
#	tests/installation/test_installer.py
#	tests/masonry/builders/test_builder.py
#	tests/masonry/builders/test_wheel.py
parents 56503817 f2e2ed47
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Packages # Packages
*.egg *.egg
*.egg-info *.egg-info
dist /dist/*
build build
_build _build
.cache .cache
......
...@@ -24,6 +24,24 @@ ...@@ -24,6 +24,24 @@
- Fixed transitive extra dependencies being removed when updating a specific dependency. - Fixed transitive extra dependencies being removed when updating a specific dependency.
## [0.12.12] - 2019-04-11
### Fixed
- Fix lock idempotency.
- Fix markers evaluation for `python_version` with precision < 3.
- Fix permissions of the `dist-info` files.
- Fix `prepare_metadata_for_build_wheel()` missing in the build backend.
- Fix metadata inconsistency between wheels and sdists.
- Fix parsing of `platform_release` markers.
- Fix metadata information when the project has git dependencies.
- Fix error reporting when publishing fails.
- Fix retrieval of `extras_require` in some `setup.py` files. (Thanks to [@asodeur](https://github.com/asodeur))
- Fix wheel compression when building. (Thanks to [@ccosby](https://github.com/ccosby))
- Improve retrieval of information for packages with two python specific wheels.
- Fix request authentication when credentials are included in URLs. (Thanks to [@connorbrinton](https://github.com/connorbrinton))
## [0.12.11] - 2019-01-13 ## [0.12.11] - 2019-01-13
### Fixed ### Fixed
...@@ -643,7 +661,8 @@ Initial release ...@@ -643,7 +661,8 @@ Initial release
[Unreleased]: https://github.com/sdispater/poetry/compare/0.12.11...develop [Unreleased]: https://github.com/sdispater/poetry/compare/0.12.12...develop
[0.12.12]: https://github.com/sdispater/poetry/releases/tag/0.12.12
[0.12.11]: https://github.com/sdispater/poetry/releases/tag/0.12.11 [0.12.11]: https://github.com/sdispater/poetry/releases/tag/0.12.11
[0.12.10]: https://github.com/sdispater/poetry/releases/tag/0.12.10 [0.12.10]: https://github.com/sdispater/poetry/releases/tag/0.12.10
[0.12.9]: https://github.com/sdispater/poetry/releases/tag/0.12.9 [0.12.9]: https://github.com/sdispater/poetry/releases/tag/0.12.9
......
# Contributing to Poetry # Contributing to Poetry
First off, thank for taking the time to contribute! First off, thanks for taking the time to contribute!
The following is a set of guidelines for contributing to Poetry on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. The following is a set of guidelines for contributing to Poetry on GitHub. These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a pull request.
#### Table of Contents #### Table of contents
[How to contribute](#how-to-contribute) [How to contribute](#how-to-contribute)
...@@ -29,7 +29,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r ...@@ -29,7 +29,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
* **Check the [FAQs on the official website](https://poetry.eustace.io)** for a list of common questions and problems. * **Check the [FAQs on the official website](https://poetry.eustace.io)** for a list of common questions and problems.
* **Check that your issue does not already exist in the [issue tracker](https://github.com/sdispater/poetry/issues)**. * **Check that your issue does not already exist in the [issue tracker](https://github.com/sdispater/poetry/issues)**.
#### How do I submit a bug report #### How do I submit a bug report?
Bugs are tracked on the [official issue tracker](https://github.com/sdispater/poetry/issues) where you can create a new one and provide the following information by filling in [the template](https://github.com/sdispater/poetry/blob/master/.github/ISSUE_TEMPLATE/1_Bug_report.md). Bugs are tracked on the [official issue tracker](https://github.com/sdispater/poetry/issues) where you can create a new one and provide the following information by filling in [the template](https://github.com/sdispater/poetry/blob/master/.github/ISSUE_TEMPLATE/1_Bug_report.md).
...@@ -38,7 +38,7 @@ Explain the problem and include additional details to help maintainers reproduce ...@@ -38,7 +38,7 @@ Explain the problem and include additional details to help maintainers reproduce
* **Use a clear and descriptive title** for the issue to identify the problem. * **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. * **Describe the exact steps which reproduce the problem** in as many details as possible.
* **Provide your pyproject.toml file** in a [Gist](https://gist.github.com) after removing potential private information (like private package repositories). * **Provide your pyproject.toml file** in a [Gist](https://gist.github.com) after removing potential private information (like private package repositories).
* **Provide specific examples to demonstrate the steps to reproduce the issue**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. * **Provide specific examples to demonstrate the steps to reproduce the issue**. Include links to files or GitHub projects, or copy-paste-able snippets, which you use in those examples.
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. * **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.** * **Explain which behavior you expected to see instead and why.**
* **If the problem is an unexpected error being raised**, execute the corresponding command in **debug** mode (the `-vvv` option). * **If the problem is an unexpected error being raised**, execute the corresponding command in **debug** mode (the `-vvv` option).
...@@ -115,5 +115,5 @@ will not be merged. ...@@ -115,5 +115,5 @@ will not be merged.
#### Pull requests #### Pull requests
* Fill in [the required template](https://github.com/sdispater/poetry/blob/master/.github/PULL_REQUEST_TEMPLATE.md) * Fill in [the required template](https://github.com/sdispater/poetry/blob/master/.github/PULL_REQUEST_TEMPLATE.md)
* Be sure that you pull request contains tests that cover the changed or added code. * Be sure that your pull request contains tests that cover the changed or added code.
* If you changes warrant a documentation change, the pull request must also update the documentation. * If your changes warrant a documentation change, the pull request must also update the documentation.
...@@ -588,9 +588,9 @@ More identifiers are listed at the [SPDX Open Source License Registry](https://w ...@@ -588,9 +588,9 @@ More identifiers are listed at the [SPDX Open Source License Registry](https://w
#### authors #### authors
The authors of the package. This is a list of authors and should contain at least one author. The authors of the package. **Required**
Authors must be in the form `name <email>`. This is a list of authors and should contain at least one author. Authors must be in the form `name <email>`.
#### readme #### readme
......
...@@ -196,6 +196,16 @@ poetry add my-package --path ../my-package/dist/my-package-0.1.0.tar.gz ...@@ -196,6 +196,16 @@ poetry add my-package --path ../my-package/dist/my-package-0.1.0.tar.gz
poetry add my-package --path ../my-package/dist/my_package-0.1.0.whl poetry add my-package --path ../my-package/dist/my_package-0.1.0.whl
``` ```
Path dependencies pointing to a local directory will be installed in editable mode (i.e. setuptools "develop mode").
It means that changes in the local directory will be reflected directly in environment.
If you don't want the dependency to be installed in editable mode you can specify it in the `pyproject.toml` file:
```
[tool.poetry.dependencies]
my-package = {path = "../my/path", develop = false}
```
### Options ### Options
* `--dev (-D)`: Add package as development dependency. * `--dev (-D)`: Add package as development dependency.
......
...@@ -90,17 +90,23 @@ pip install --user poetry ...@@ -90,17 +90,23 @@ pip install --user poetry
Be aware that it will also install Poetry's dependencies Be aware that it will also install Poetry's dependencies
which might cause conflicts with other packages. which might cause conflicts with other packages.
#### Installing with `pipsi` #### Installing with `pipx`
Using [`pipsi`](https://github.com/mitsuhiko/pipsi) to install Poetry is also possible. Using [`pipx`](https://github.com/cs01/pipx) to install Poetry is also possible. [pipx] is used to install Python CLI applications globally while still isolating them in virtual environments. This allows for clean upgrades and uninstalls. pipx supports Python 3.6 and later. If using an earlier version of Python, consider [pipsi](https://github.com/mitsuhiko/pipsi).
```bash ```bash
pipsi install poetry pipx install poetry
``` ```
Make sure your installed version of `pipsi` is at least version `0.10`, ```bash
otherwise Poetry will not function properly. You can get it from its pipx upgrade poetry
[Github repository](https://github.com/mitsuhiko/pipsi). ```
```bash
pipx uninstall poetry
```
[Github repository](https://github.com/cs01/pipx).
## Updating `poetry` ## Updating `poetry`
......
...@@ -42,9 +42,9 @@ More identifiers are listed at the [SPDX Open Source License Registry](https://w ...@@ -42,9 +42,9 @@ More identifiers are listed at the [SPDX Open Source License Registry](https://w
## authors ## authors
The authors of the package. This is a list of authors and should contain at least one author. The authors of the package. **Required**
Authors must be in the form `name <email>`. This is a list of authors and should contain at least one author. Authors must be in the form `name <email>`.
## readme ## readme
......
...@@ -195,7 +195,7 @@ import glob ...@@ -195,7 +195,7 @@ import glob
import sys import sys
import os import os
lib = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "lib")) lib = os.path.normpath(os.path.join(os.path.realpath(__file__), "../..", "lib"))
sys.path.insert(0, lib) sys.path.insert(0, lib)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
PYTHON_VERSIONS="cp27-cp27m cp34-cp34m cp35-cp35m cp36-cp36m cp37-cp37m" PYTHON_VERSIONS="cp27-cp27m cp34-cp34m cp35-cp35m cp36-cp36m cp37-cp37m"
cd /io cd /io
/opt/python/cp37-cp37m/bin/pip install poetry --pre -U /opt/python/cp37-cp37m/bin/pip install poetry -U
/opt/python/cp37-cp37m/bin/poetry config settings.virtualenvs.create false /opt/python/cp37-cp37m/bin/poetry config settings.virtualenvs.create false
/opt/python/cp37-cp37m/bin/poetry install --no-dev /opt/python/cp37-cp37m/bin/poetry install --no-dev
/opt/python/cp37-cp37m/bin/python sonnet make release \ /opt/python/cp37-cp37m/bin/python sonnet make release \
......
...@@ -12,8 +12,8 @@ category = "dev" ...@@ -12,8 +12,8 @@ category = "dev"
description = "A few extensions to pyyaml." description = "A few extensions to pyyaml."
name = "aspy.yaml" name = "aspy.yaml"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.1.1" version = "1.2.0"
[package.dependencies] [package.dependencies]
pyyaml = "*" pyyaml = "*"
...@@ -24,18 +24,18 @@ description = "Atomic file writes." ...@@ -24,18 +24,18 @@ description = "Atomic file writes."
name = "atomicwrites" name = "atomicwrites"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.2.1" version = "1.3.0"
[[package]] [[package]]
category = "main" category = "main"
description = "Classes Without Boilerplate" description = "Classes Without Boilerplate"
name = "attrs" name = "attrs"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "18.2.0" version = "19.1.0"
[package.extras] [package.extras]
dev = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface", "sphinx", "zope.interface", "pre-commit"] dev = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface", "sphinx", "pre-commit"]
docs = ["sphinx", "zope.interface"] docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface"] tests = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface"]
...@@ -96,15 +96,15 @@ description = "Python package for providing Mozilla's CA Bundle." ...@@ -96,15 +96,15 @@ description = "Python package for providing Mozilla's CA Bundle."
name = "certifi" name = "certifi"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "2018.11.29" version = "2019.3.9"
[[package]] [[package]]
category = "dev" category = "dev"
description = "Validate configuration and produce human readable error messages." description = "Validate configuration and produce human readable error messages."
name = "cfgv" name = "cfgv"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.4.0" version = "1.6.0"
[package.dependencies] [package.dependencies]
six = "*" six = "*"
...@@ -170,12 +170,16 @@ version = "0.4.1" ...@@ -170,12 +170,16 @@ version = "0.4.1"
[[package]] [[package]]
category = "dev" category = "dev"
description = "This library brings the updated configparser from Python 3.5 to Python 2.6-3.5." description = "Updated configparser from Python 3.7 for Python 2.6+."
marker = "python_version < \"3\"" marker = "python_version < \"3\""
name = "configparser" name = "configparser"
optional = false optional = false
python-versions = "*" python-versions = ">=2.6"
version = "3.5.0" version = "3.7.4"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2)", "pytest-flake8"]
[[package]] [[package]]
category = "dev" category = "dev"
...@@ -192,7 +196,7 @@ description = "Code coverage measurement for Python" ...@@ -192,7 +196,7 @@ description = "Code coverage measurement for Python"
name = "coverage" name = "coverage"
optional = false optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4"
version = "4.5.2" version = "4.5.3"
[[package]] [[package]]
category = "main" category = "main"
...@@ -231,12 +235,12 @@ version = "3.2.3-2" ...@@ -231,12 +235,12 @@ version = "3.2.3-2"
[[package]] [[package]]
category = "dev" category = "dev"
description = "Backport of the concurrent.futures package from Python 3.2" description = "Backport of the concurrent.futures package from Python 3"
marker = "python_version < \"3.2\"" marker = "python_version < \"3.2\""
name = "futures" name = "futures"
optional = false optional = false
python-versions = "*" python-versions = ">=2.6, <3"
version = "3.1.1" version = "3.2.0"
[[package]] [[package]]
category = "main" category = "main"
...@@ -268,11 +272,25 @@ lxml = ["lxml"] ...@@ -268,11 +272,25 @@ lxml = ["lxml"]
[[package]] [[package]]
category = "dev" category = "dev"
description = "HTTP client mock for Python"
name = "httpretty"
optional = false
python-versions = "*"
version = "0.9.6"
[package.dependencies]
six = "*"
[[package]]
category = "dev"
description = "File identification library for Python" description = "File identification library for Python"
name = "identify" name = "identify"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.1.8" version = "1.4.1"
[package.extras]
license = ["editdistance"]
[[package]] [[package]]
category = "main" category = "main"
...@@ -288,7 +306,7 @@ description = "Read metadata from Python packages" ...@@ -288,7 +306,7 @@ description = "Read metadata from Python packages"
name = "importlib-metadata" name = "importlib-metadata"
optional = false optional = false
python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3" python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3"
version = "0.8" version = "0.9"
[package.dependencies] [package.dependencies]
zipp = ">=0.3.2" zipp = ">=0.3.2"
...@@ -305,6 +323,9 @@ version = "*" ...@@ -305,6 +323,9 @@ version = "*"
python = "<3" python = "<3"
version = "*" version = "*"
[package.extras]
docs = ["sphinx", "docutils (0.12)", "rst.linker"]
[[package]] [[package]]
category = "dev" category = "dev"
description = "Read resources from Python packages" description = "Read resources from Python packages"
...@@ -330,7 +351,7 @@ marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_v ...@@ -330,7 +351,7 @@ marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_v
name = "jinja2" name = "jinja2"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "2.10" version = "2.10.1"
[package.dependencies] [package.dependencies]
MarkupSafe = ">=0.23" MarkupSafe = ">=0.23"
...@@ -344,7 +365,7 @@ description = "An implementation of JSON Schema validation for Python" ...@@ -344,7 +365,7 @@ description = "An implementation of JSON Schema validation for Python"
name = "jsonschema" name = "jsonschema"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "3.0.0a4" version = "3.0.1"
[package.dependencies] [package.dependencies]
attrs = ">=17.4.0" attrs = ">=17.4.0"
...@@ -391,12 +412,26 @@ version = "3.0.1" ...@@ -391,12 +412,26 @@ version = "3.0.1"
[[package]] [[package]]
category = "dev" category = "dev"
description = "Python implementation of Markdown."
name = "markdown"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
version = "3.1"
[package.dependencies]
setuptools = ">=36"
[package.extras]
testing = ["coverage", "pyyaml"]
[[package]]
category = "dev"
description = "Safely add untrusted strings to HTML/XML markup." description = "Safely add untrusted strings to HTML/XML markup."
marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_version >= \"3.4\" and python_version < \"4.0\"" marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_version >= \"3.4\" and python_version < \"4.0\""
name = "markupsafe" name = "markupsafe"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "1.1.0" version = "1.1.1"
[[package]] [[package]]
category = "dev" category = "dev"
...@@ -439,6 +474,7 @@ test = ["unittest2 (>=1.1.0)"] ...@@ -439,6 +474,7 @@ test = ["unittest2 (>=1.1.0)"]
[[package]] [[package]]
category = "dev" category = "dev"
description = "More routines for operating on iterables, beyond itertools" description = "More routines for operating on iterables, beyond itertools"
marker = "python_version <= \"2.7\""
name = "more-itertools" name = "more-itertools"
optional = false optional = false
python-versions = "*" python-versions = "*"
...@@ -448,12 +484,21 @@ version = "5.0.0" ...@@ -448,12 +484,21 @@ version = "5.0.0"
six = ">=1.0.0,<2.0.0" six = ">=1.0.0,<2.0.0"
[[package]] [[package]]
category = "dev"
description = "More routines for operating on iterables, beyond itertools"
marker = "python_version > \"2.7\""
name = "more-itertools"
optional = false
python-versions = ">=3.4"
version = "7.0.0"
[[package]]
category = "main" category = "main"
description = "MessagePack (de)serializer." description = "MessagePack (de)serializer."
name = "msgpack" name = "msgpack"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "0.6.0" version = "0.6.1"
[[package]] [[package]]
category = "dev" category = "dev"
...@@ -469,7 +514,7 @@ description = "Core utilities for Python packages" ...@@ -469,7 +514,7 @@ description = "Core utilities for Python packages"
name = "packaging" name = "packaging"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "18.0" version = "19.0"
[package.dependencies] [package.dependencies]
pyparsing = ">=2.0.2" pyparsing = ">=2.0.2"
...@@ -506,7 +551,7 @@ marker = "python_version < \"3.0\"" ...@@ -506,7 +551,7 @@ marker = "python_version < \"3.0\""
name = "pbr" name = "pbr"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "5.1.1" version = "5.1.3"
[[package]] [[package]]
category = "main" category = "main"
...@@ -525,7 +570,7 @@ description = "plugin and hook calling mechanisms for python" ...@@ -525,7 +570,7 @@ description = "plugin and hook calling mechanisms for python"
name = "pluggy" name = "pluggy"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.8.1" version = "0.9.0"
[package.extras] [package.extras]
dev = ["pre-commit", "tox"] dev = ["pre-commit", "tox"]
...@@ -535,8 +580,8 @@ category = "dev" ...@@ -535,8 +580,8 @@ category = "dev"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
name = "pre-commit" name = "pre-commit"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.14.2" version = "1.15.1"
[package.dependencies] [package.dependencies]
"aspy.yaml" = "*" "aspy.yaml" = "*"
...@@ -547,7 +592,7 @@ nodeenv = ">=0.11.1" ...@@ -547,7 +592,7 @@ nodeenv = ">=0.11.1"
pyyaml = "*" pyyaml = "*"
six = "*" six = "*"
toml = "*" toml = "*"
virtualenv = "*" virtualenv = ">=15.2"
[package.dependencies.futures] [package.dependencies.futures]
python = "<3.2" python = "<3.2"
...@@ -563,7 +608,7 @@ description = "library with cross-python path, ini-parsing, io, code, log facili ...@@ -563,7 +608,7 @@ description = "library with cross-python path, ini-parsing, io, code, log facili
name = "py" name = "py"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.7.0" version = "1.8.0"
[[package]] [[package]]
category = "dev" category = "dev"
...@@ -608,8 +653,8 @@ category = "main" ...@@ -608,8 +653,8 @@ category = "main"
description = "Python parsing module" description = "Python parsing module"
name = "pyparsing" name = "pyparsing"
optional = false optional = false
python-versions = "*" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
version = "2.3.1" version = "2.4.0"
[[package]] [[package]]
category = "main" category = "main"
...@@ -617,7 +662,7 @@ description = "Persistent/Functional/Immutable data structures" ...@@ -617,7 +662,7 @@ description = "Persistent/Functional/Immutable data structures"
name = "pyrsistent" name = "pyrsistent"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "0.14.9" version = "0.14.11"
[package.dependencies] [package.dependencies]
six = "*" six = "*"
...@@ -628,28 +673,35 @@ description = "pytest: simple powerful testing with Python" ...@@ -628,28 +673,35 @@ description = "pytest: simple powerful testing with Python"
name = "pytest" name = "pytest"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "4.1.1" version = "4.4.0"
[package.dependencies] [package.dependencies]
atomicwrites = ">=1.0" atomicwrites = ">=1.0"
attrs = ">=17.4.0" attrs = ">=17.4.0"
colorama = "*" colorama = "*"
more-itertools = ">=4.0.0" pluggy = ">=0.9"
pluggy = ">=0.7"
py = ">=1.5.0" py = ">=1.5.0"
setuptools = "*" setuptools = "*"
six = ">=1.10.0" six = ">=1.10.0"
[[package.dependencies.more-itertools]]
python = "<2.8"
version = ">=4.0.0,<6.0.0"
[[package.dependencies.more-itertools]]
python = ">=2.8"
version = ">=4.0.0"
[package.dependencies.funcsigs] [package.dependencies.funcsigs]
python = "<3.0" python = "<3.0"
version = "*" version = ">=1.0"
[package.dependencies.pathlib2] [package.dependencies.pathlib2]
python = "<3.6" python = "<3.6"
version = ">=2.2.0" version = ">=2.2.0"
[package.extras] [package.extras]
testing = ["hypothesis (>=3.56)", "nose", "requests", "mock"] testing = ["argcomplete", "hypothesis (>=3.56)", "nose", "requests", "mock"]
[[package]] [[package]]
category = "dev" category = "dev"
...@@ -669,7 +721,7 @@ description = "Thin-wrapper around the mock package for easier use with py.test" ...@@ -669,7 +721,7 @@ description = "Thin-wrapper around the mock package for easier use with py.test"
name = "pytest-mock" name = "pytest-mock"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.10.0" version = "1.10.3"
[package.dependencies] [package.dependencies]
pytest = ">=2.7" pytest = ">=2.7"
...@@ -678,6 +730,9 @@ pytest = ">=2.7" ...@@ -678,6 +730,9 @@ pytest = ">=2.7"
python = "<3.0" python = "<3.0"
version = "*" version = "*"
[package.extras]
dev = ["pre-commit", "tox"]
[[package]] [[package]]
category = "dev" category = "dev"
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)." 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)."
...@@ -696,8 +751,8 @@ category = "dev" ...@@ -696,8 +751,8 @@ category = "dev"
description = "YAML parser and emitter for Python" description = "YAML parser and emitter for Python"
name = "pyyaml" name = "pyyaml"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "3.13" version = "5.1"
[[package]] [[package]]
category = "main" category = "main"
...@@ -735,7 +790,7 @@ marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_versi ...@@ -735,7 +790,7 @@ marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_versi
name = "scandir" name = "scandir"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "1.9.0" version = "1.10.0"
[[package]] [[package]]
category = "main" category = "main"
...@@ -743,7 +798,7 @@ description = "Tool to Detect Surrounding Shell" ...@@ -743,7 +798,7 @@ description = "Tool to Detect Surrounding Shell"
name = "shellingham" name = "shellingham"
optional = false optional = false
python-versions = ">=2.6,!=3.0,!=3.1,!=3.2,!=3.3" python-versions = ">=2.6,!=3.0,!=3.1,!=3.2,!=3.3"
version = "1.2.8" version = "1.3.1"
[[package]] [[package]]
category = "main" category = "main"
...@@ -801,11 +856,11 @@ version = "5.1.1" ...@@ -801,11 +856,11 @@ version = "5.1.1"
[[package]] [[package]]
category = "dev" category = "dev"
description = "virtualenv-based automation of test activities" description = "tox is a generic virtualenv management and test command line tool"
name = "tox" name = "tox"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "3.7.0" version = "3.8.6"
[package.dependencies] [package.dependencies]
filelock = ">=3.0.0,<4" filelock = ">=3.0.0,<4"
...@@ -818,7 +873,7 @@ virtualenv = ">=1.11.2" ...@@ -818,7 +873,7 @@ virtualenv = ">=1.11.2"
[package.extras] [package.extras]
docs = ["sphinx (>=1.8.0,<2)", "towncrier (>=18.5.0)", "pygments-github-lexers (>=0.0.5)", "sphinxcontrib-autoprogram (>=0.1.5)"] docs = ["sphinx (>=1.8.0,<2)", "towncrier (>=18.5.0)", "pygments-github-lexers (>=0.0.5)", "sphinxcontrib-autoprogram (>=0.1.5)"]
testing = ["freezegun (>=0.3.11)", "pytest (>=3.0.0,<4)", "pytest-cov (>=2.5.1,<3)", "pytest-mock (>=1.10.0,<2)", "pytest-timeout (>=1.3.0,<2)", "pytest-xdist (>=1.22.2,<2)", "pytest-randomly (>=1.2.3,<2)"] testing = ["freezegun (>=0.3.11,<1)", "pathlib2 (>=2.3.3,<3)", "pytest (>=3.0.0,<5)", "pytest-cov (>=2.5.1,<3)", "pytest-mock (>=1.10.0,<2)", "pytest-timeout (>=1.3.0,<2)", "pytest-xdist (>=1.22.2,<2)", "pytest-randomly (>=1.2.3,<2)", "psutil (>=5.6.1,<6)"]
[[package]] [[package]]
category = "main" category = "main"
...@@ -847,14 +902,11 @@ description = "Virtual Python Environment builder" ...@@ -847,14 +902,11 @@ description = "Virtual Python Environment builder"
name = "virtualenv" name = "virtualenv"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "16.2.0" version = "16.4.3"
[package.dependencies]
setuptools = ">=18.0.0"
[package.extras] [package.extras]
docs = ["sphinx (>=1.8.0,<2)", "towncrier (>=18.5.0)", "sphinx-rtd-theme (>=0.4.2,<1)"] docs = ["sphinx (>=1.8.0,<2)", "towncrier (>=18.5.0)", "sphinx-rtd-theme (>=0.4.2,<1)"]
testing = ["pytest (>=4.0.0,<5)", "coverage (>=4.5.0,<5)", "six (>=1.10.0,<2)", "pytest-timeout (>=1.3.0,<2)", "pytest-xdist", "mock", "xonsh"] testing = ["pytest (>=4.0.0,<5)", "coverage (>=4.5.0,<5)", "six (>=1.10.0,<2)", "pytest-localserver", "pypiserver", "pytest-timeout (>=1.3.0,<2)", "pytest-xdist", "mock", "xonsh"]
[[package]] [[package]]
category = "main" category = "main"
...@@ -877,80 +929,81 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] ...@@ -877,80 +929,81 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs", "pytest-flake8", "pathlib2"] testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs", "pytest-flake8", "pathlib2"]
[metadata] [metadata]
content-hash = "0d0969aacd81c55841c170dd6107cfa332670e32e5cfce2779a796e895273ee5" content-hash = "0c8dacc601bb5dc9b87338e0162891afed269977065ee01f960ae7342a17d863"
python-versions = "~2.7 || ^3.4" python-versions = "~2.7 || ^3.4"
[metadata.hashes] [metadata.hashes]
appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"] appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"]
"aspy.yaml" = ["04d26279513618f1024e1aba46471db870b3b33aef204c2d09bcf93bea9ba13f", "0a77e23fafe7b242068ffc0252cee130d3e509040908fc678d9d1060e7494baa"] "aspy.yaml" = ["ae249074803e8b957c83fdd82a99160d0d6d26dff9ba81ba608b42eebd7d8cd3", "c7390d79f58eb9157406966201abf26da0d56c07e0ff0deadc39c8f4dbc13482"]
atomicwrites = ["0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", "ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"] atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"]
attrs = ["10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", "ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"] attrs = ["69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", "f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"]
black = ["817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739", "e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"] black = ["817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739", "e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"]
cachecontrol = ["cef77effdf51b43178f6a2d3b787e3734f98ade253fa3187f3bb7315aaa42ff7"] cachecontrol = ["cef77effdf51b43178f6a2d3b787e3734f98ade253fa3187f3bb7315aaa42ff7"]
cachy = ["b71513e5a38ce90c1280c02b7d8d6bb3fdf64666c9cc0584f2479afea097d56c", "b71e8e7ddb5b386e23e81befdfac8a93885406139b8681bedc17b3444fcb8fca"] cachy = ["b71513e5a38ce90c1280c02b7d8d6bb3fdf64666c9cc0584f2479afea097d56c", "b71e8e7ddb5b386e23e81befdfac8a93885406139b8681bedc17b3444fcb8fca"]
certifi = ["47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", "993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"] certifi = ["59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", "b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"]
cfgv = ["39d9055c47e3932908fe25abd5807e21dc002630db01c7a5f05738d027e2b706", "41d22dd864c474f919ecb88900000d2410d640315f75bdb79b3abf9347089641"] cfgv = ["6e9f2feea5e84bc71e56abd703140d7a2c250fc5ba38b8702fd6a68ed4e3b2ef", "e7f186d4a36c099a9e20b04ac3108bd8bb9b9257e692ce18c8c3764d5cb12172"]
chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"] chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
cleo = ["7a5000de616de42fd78f968192651b9174bf333a9079fc9d68ccc672ddfd3624", "a39fa806fd3f64ff0ae4e3a55bb80c8ce60ca73634e13619731d63a04a63be69"] cleo = ["7a5000de616de42fd78f968192651b9174bf333a9079fc9d68ccc672ddfd3624", "a39fa806fd3f64ff0ae4e3a55bb80c8ce60ca73634e13619731d63a04a63be69"]
click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"] click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"]
clikit = ["7bbd38fcb912058c689a03f487a66f8d1eb1f486bc5cf68d4a5798093bd0217f", "e23ac911afb7079ae0e4d89af73ee0d31c8952c64ef4fcf76bcd46bfde9aabaa"] clikit = ["7bbd38fcb912058c689a03f487a66f8d1eb1f486bc5cf68d4a5798093bd0217f", "e23ac911afb7079ae0e4d89af73ee0d31c8952c64ef4fcf76bcd46bfde9aabaa"]
colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"] colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
configparser = ["5308b47021bc2340965c371f0f058cc6971a04502638d4244225c49d80db273a"] configparser = ["8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32", "da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75"]
contextlib2 = ["509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", "f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"] contextlib2 = ["509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", "f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"]
coverage = ["06123b58a1410873e22134ca2d88bd36680479fe354955b3579fb8ff150e4d27", "09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", "0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", "0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", "0d34245f824cc3140150ab7848d08b7e2ba67ada959d77619c986f2062e1f0e8", "10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", "1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", "1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", "258b21c5cafb0c3768861a6df3ab0cfb4d8b495eee5ec660e16f928bf7385390", "2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", "3ad59c84c502cd134b0088ca9038d100e8fb5081bbd5ccca4863f3804d81f61d", "447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", "46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", "4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", "510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", "5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", "5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", "5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", "6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", "6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", "71afc1f5cd72ab97330126b566bbf4e8661aab7449f08895d21a5d08c6b051ff", "7349c27128334f787ae63ab49d90bf6d47c7288c63a0a5dfaa319d4b4541dd2c", "77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", "828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", "859714036274a75e6e57c7bab0c47a4602d2a8cfaaa33bbdb68c8359b2ed4f5c", "85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", "869ef4a19f6e4c6987e18b315721b8b971f7048e6eaea29c066854242b4e98d9", "8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", "977e2d9a646773cc7428cdd9a34b069d6ee254fadfb4d09b3f430e95472f3cf3", "99bd767c49c775b79fdcd2eabff405f1063d9d959039c0bdd720527a7738748a", "a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", "aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", "ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", "b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", "bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", "c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", "d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", "d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", "da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", "ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", "ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9"] coverage = ["0c5fe441b9cfdab64719f24e9684502a59432df7570521563d7b1aff27ac755f", "2b412abc4c7d6e019ce7c27cbc229783035eef6d5401695dccba80f481be4eb3", "3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", "39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", "3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", "42692db854d13c6c5e9541b6ffe0fe921fe16c9c446358d642ccae1462582d3b", "465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", "48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", "4ec30ade438d1711562f3786bea33a9da6107414aed60a5daa974d50a8c2c351", "5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", "5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", "6899797ac384b239ce1926f3cb86ffc19996f6fa3a1efbb23cb49e0c12d8c18c", "68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", "6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", "7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", "7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", "839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", "8e679d1bde5e2de4a909efb071f14b472a678b788904440779d2c449c0355b27", "8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", "932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", "93f965415cc51604f571e491f280cff0f5be35895b4eb5e55b47ae90c02a497b", "988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", "998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", "9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", "9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", "a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", "a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", "a9abc8c480e103dc05d9b332c6cc9fb1586330356fc14f1aa9c0ca5745097d19", "aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", "bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", "bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", "c22ab9f96cbaff05c6a84e20ec856383d27eae09e511d3e6ac4479489195861d", "c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", "c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", "c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", "ca58eba39c68010d7e87a823f22a081b5290e3e3c64714aac3c91481d8b34d22", "df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", "f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", "f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", "f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", "fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a"]
enum34 = ["2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", "644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", "6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", "8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"] enum34 = ["2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", "644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", "6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", "8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"]
filelock = ["b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633", "d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6"] filelock = ["b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633", "d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6"]
funcsigs = ["330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", "a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"] funcsigs = ["330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", "a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"]
functools32 = ["89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", "f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d"] functools32 = ["89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", "f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d"]
futures = ["51ecb45f0add83c806c68e4b06106f90db260585b25ef2abfcda0bd95c0132fd", "c4884a65654a7c45435063e14ae85280eb1f111d94e542396717ba9828c4337f"] futures = ["9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265", "ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1"]
glob2 = ["f5b0a686ff21f820c4d3f0c4edd216704cea59d79d00fa337e244a2f2ff83ed6"] glob2 = ["f5b0a686ff21f820c4d3f0c4edd216704cea59d79d00fa337e244a2f2ff83ed6"]
html5lib = ["20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3", "66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"] html5lib = ["20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3", "66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"]
identify = ["08826e68e39e7de53cc2ddd8f6228a4e463b4bacb20565e5301c3ec690e68d27", "2364e24a7699fea0dc910e90740adbab43eef3746eeea4e016029c34123ce66d"] httpretty = ["01b52d45077e702eda491f4fe75328d3468fd886aed5dcc530003e7b2b5939dc"]
identify = ["244e7864ef59f0c7c50c6db73f58564151d91345cd9b76ed793458953578cadd", "8ff062f90ad4b09cfe79b5dfb7a12e40f19d2e68a5c9598a49be45f16aba7171"]
idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"] idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"]
importlib-metadata = ["a17ce1a8c7bff1e8674cb12c992375d8d0800c9190177ecf0ad93e0097224095", "b50191ead8c70adfa12495fba19ce6d75f2e0275c14c5a7beb653d6799b512bd"] importlib-metadata = ["46fc60c34b6ed7547e2a723fc8de6dc2e3a1173f8423246b3ce497f064e9c3de", "bc136180e961875af88b1ab85b4009f4f1278f8396a60526c0009f503a1a96ca"]
importlib-resources = ["6e2783b2538bd5a14678284a3962b0660c715e5a0f10243fd5e00a4b5974f50b", "d3279fd0f6f847cced9f7acc19bd3e5df54d34f93a2e7bb5f238f81545787078"] importlib-resources = ["6e2783b2538bd5a14678284a3962b0660c715e5a0f10243fd5e00a4b5974f50b", "d3279fd0f6f847cced9f7acc19bd3e5df54d34f93a2e7bb5f238f81545787078"]
jinja2 = ["74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", "f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"] jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"]
jsonschema = ["5695bc362157eab16513b27d5ec221048220ceacbceaf35ec235b5993deb9090", "8937b03883c17c999a45a1ec70c46690ef454181f09ebcbcb21694153b9e39c8"] jsonschema = ["0c0a81564f181de3212efa2d17de1910f8732fa1b71c42266d983cd74304e20d", "a5f6559964a3851f59040d3b961de5e68e70971afb88ba519d27e6a039efff1a"]
livereload = ["29cadfabcedd12eed792e0131991235b9d4764d4474bed75cf525f57109ec0a2", "e632a6cd1d349155c1d7f13a65be873b38f43ef02961804a1bba8d817fa649a7"] livereload = ["29cadfabcedd12eed792e0131991235b9d4764d4474bed75cf525f57109ec0a2", "e632a6cd1d349155c1d7f13a65be873b38f43ef02961804a1bba8d817fa649a7"]
lockfile = ["6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", "6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"] lockfile = ["6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", "6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"]
markdown = ["c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa", "d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c"] markdown = ["c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa", "d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c", "fc4a6f69a656b8d858d7503bda633f4dd63c2d70cf80abdc6eafa64c4ae8c250", "fe463ff51e679377e3624984c829022e2cfb3be5518726b06f608a07a3aad680"]
markupsafe = ["048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", "130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", "19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", "1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", "1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", "1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", "1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", "31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", "3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", "4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", "525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", "52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", "52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", "5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", "5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", "5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", "7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", "83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", "857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", "98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", "bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", "d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", "e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", "edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", "efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", "f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", "f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", "fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"] markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"]
mkdocs = ["17d34329aad75d5de604b9ed4e31df3a4d235afefdc46ce7b1964fddb2e1e939", "8cc8b38325456b9e942c981a209eaeb1e9f3f77b493ad755bfef889b9c8d356a"] mkdocs = ["17d34329aad75d5de604b9ed4e31df3a4d235afefdc46ce7b1964fddb2e1e939", "8cc8b38325456b9e942c981a209eaeb1e9f3f77b493ad755bfef889b9c8d356a"]
mock = ["5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", "b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"] mock = ["5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", "b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"]
more-itertools = ["38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", "c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", "fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"] more-itertools = ["38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", "c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", "fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9", "2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7", "c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"]
msgpack = ["102802a9433dcf36f939b632cce9dea87310b2f163bb37ffc8bc343677726e88", "3055c44f39833b6edb27fd48028dc7822d1fd75bfeef8a2434caed8d62bb24ee", "3b7fd45c8e9e537640f541d3699b1773cf5cb9345d4a75f93baa8f055084e59c", "64abc6bf3a2ac301702f5760f4e6e227d0fd4d84d9014ef9a40faa9d43365259", "6e962c4adc7970af5a3d6a4f9bb87c617b1bd041fd9ab42355a263d421017ed9", "72259661a83f8b08ef6ee83927ce4937f841226735824af5b10a536d886eeb36", "78e297c3996fd9f35090fbddd1c148c2a71e0d6024500bcf3af90a4b9698bc19", "85f1342b9d7549dd3daf494100d47a3dc7daae703cdbfc2c9ee7bbdc8a492cba", "8ce9f88b6cb75d74eda2a5522e5c2e5ec0f17fd78605d6502abb61f46b306865", "8d0af8d64198e4b4f942a15ea9cb0dd9c4a0bd3e4e2ba57425e108bdbd4c3a0f", "9936ce3a530ca78db60b6631003b5f4ba383cfb1d9830a27d1b5c61857226e2f", "b688721df31c4bad6f508fb262719eb7e4a3532024c66d3c44ad6a4704519dda", "c28478328e9cd868ce54e8465eae9fa3605790450c66cc7e8bc416526917ef6e", "cb4e228f3d93779a1d77a1e9d72759b79dfa2975c1a5bd2a090eaa98239fa4b1", "d03d0b6e4adf5bd1cbf7a81a20a56c883351947a57b7b85235181b057adf1120", "d2b179faebd278e5f4e255a6bbc7ccb467f02ed5c4c00c8a68dc926002223a20", "f1a8f7bd84be103979a73da57be3cb929d702a656162ee466597b816fa9eec97"] msgpack = ["26cb40116111c232bc235ce131cc3b4e76549088cb154e66a2eb8ff6fcc907ec", "300fd3f2c664a3bf473d6a952f843b4a71454f4c592ed7e74a36b205c1782d28", "3129c355342853007de4a2a86e75eab966119733eb15748819b6554363d4e85c", "31f6d645ee5a97d59d3263fab9e6be76f69fa131cddc0d94091a3c8aca30d67a", "3ce7ef7ee2546c3903ca8c934d09250531b80c6127e6478781ae31ed835aac4c", "4008c72f5ef2b7936447dcb83db41d97e9791c83221be13d5e19db0796df1972", "62bd8e43d204580308d477a157b78d3fee2fb4c15d32578108dc5d89866036c8", "70cebfe08fb32f83051971264466eadf183101e335d8107b80002e632f425511", "72cb7cf85e9df5251abd7b61a1af1fb77add15f40fa7328e924a9c0b6bc7a533", "7c55649965c35eb32c499d17dadfb8f53358b961582846e1bc06f66b9bccc556", "86b963a5de11336ec26bc4f839327673c9796b398b9f1fe6bb6150c2a5d00f0f", "8c73c9bcdfb526247c5e4f4f6cf581b9bb86b388df82cfcaffde0a6e7bf3b43a", "8e68c76c6aff4849089962d25346d6784d38e02baa23ffa513cf46be72e3a540", "97ac6b867a8f63debc64f44efdc695109d541ecc361ee2dce2c8884ab37360a1", "9d4f546af72aa001241d74a79caec278bcc007b4bcde4099994732e98012c858", "a28e69fe5468c9f5251c7e4e7232286d71b7dfadc74f312006ebe984433e9746", "fd509d4aa95404ce8d86b4e32ce66d5d706fd6646c205e1c2a715d87078683a2"]
nodeenv = ["ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"] nodeenv = ["ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"]
packaging = ["0886227f54515e592aaa2e5a553332c73962917f2831f1b0f9b9f4380a4b9807", "f95a1e147590f204328170981833854229bb2912ac3d5f89e2a8ccd2834800c9"] packaging = ["0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", "9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3"]
pastel = ["3108af417ec0fa6d0a620e676ec4f02c839ca13e10611586e5d2174b46aa0bc3", "d1fee8079534f99f1805a044fef946d23eee6d6a7cd34292c30e6c16be9a80b9"] pastel = ["3108af417ec0fa6d0a620e676ec4f02c839ca13e10611586e5d2174b46aa0bc3", "d1fee8079534f99f1805a044fef946d23eee6d6a7cd34292c30e6c16be9a80b9"]
pathlib2 = ["25199318e8cc3c25dcb45cbe084cc061051336d5a9ea2a12448d3d8cb748f742", "5887121d7f7df3603bca2f710e7219f3eca0eb69e0b7cc6e0a022e155ac931a7"] pathlib2 = ["25199318e8cc3c25dcb45cbe084cc061051336d5a9ea2a12448d3d8cb748f742", "5887121d7f7df3603bca2f710e7219f3eca0eb69e0b7cc6e0a022e155ac931a7"]
pbr = ["f59d71442f9ece3dffc17bc36575768e1ee9967756e6b6535f0ee1f0054c3d68", "f6d5b23f226a2ba58e14e49aa3b1bfaf814d0199144b95d78458212444de1387"] pbr = ["8257baf496c8522437e8a6cfe0f15e00aedc6c0e0e7c9d55eeeeab31e0853843", "8c361cc353d988e4f5b998555c88098b9d5964c2e11acf7b0d21925a66bb5824"]
pkginfo = ["7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", "a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32"] pkginfo = ["7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", "a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32"]
pluggy = ["8ddc32f03971bfdf900a81961a48ccf2fb677cf7715108f85295c67405798616", "980710797ff6a041e9a73a5787804f848996ecaa6f8a1b1e08224a5894f2074a"] pluggy = ["19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f", "84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746"]
pre-commit = ["2cb7a588fdc78e4ec4e624932765e65d285159f4b3425121106cbd9060e40e04", "74ee5779a17ef540efdf9a832911fe9057b1bb57d5d0152eace6534a228a863b"] pre-commit = ["75a9110eae00d009c913616c0fc8a6a02e7716c4a29a14cac9b313d2c7338ab0", "f882c65316eb5b705fe4613e92a7c91055c1800102e4d291cfd18912ec9cf90e"]
py = ["bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", "e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"] py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"]
pygments = ["5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", "e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"] pygments = ["5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", "e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"]
pygments-github-lexers = ["0f9e9fb607d351c127a1e55e82a6eb491ed1fc11b2d6a0444ba217dc6d1f82c1", "aaca57e77cd6fcfce8d6ee97a998962eebf7fbb810519a8ebde427c62823e133"] pygments-github-lexers = ["0f9e9fb607d351c127a1e55e82a6eb491ed1fc11b2d6a0444ba217dc6d1f82c1", "aaca57e77cd6fcfce8d6ee97a998962eebf7fbb810519a8ebde427c62823e133"]
pylev = ["063910098161199b81e453025653ec53556c1be7165a9b7c50be2f4d57eae1c3", "1d29a87beb45ebe1e821e7a3b10da2b6b2f4c79b43f482c2df1a1f748a6e114e"] pylev = ["063910098161199b81e453025653ec53556c1be7165a9b7c50be2f4d57eae1c3", "1d29a87beb45ebe1e821e7a3b10da2b6b2f4c79b43f482c2df1a1f748a6e114e"]
pymdown-extensions = ["25b0a7967fa697b5035e23340a48594e3e93acb10b06d74574218ace3347d1df", "6cf0cf36b5a03b291ace22dc2f320f4789ce56fbdb6635a3be5fadbf5d7694dd"] pymdown-extensions = ["25b0a7967fa697b5035e23340a48594e3e93acb10b06d74574218ace3347d1df", "6cf0cf36b5a03b291ace22dc2f320f4789ce56fbdb6635a3be5fadbf5d7694dd"]
pyparsing = ["66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", "f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3"] pyparsing = ["1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", "9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"]
pyrsistent = ["5a3827d57ad3e46820e5ee4ed5b9e0ee7bc4686df6634a7368bc1863a5c48a77"] pyrsistent = ["3ca82748918eb65e2d89f222b702277099aca77e34843c5eb9d52451173970e2"]
pytest = ["41568ea7ecb4a68d7f63837cf65b92ce8d0105e43196ff2b26622995bb3dc4b2", "c3c573a29d7c9547fb90217ece8a8843aa0c1328a797e200290dc3d0b4b823be"] pytest = ["13c5e9fb5ec5179995e9357111ab089af350d788cbc944c628f3cde72285809b", "f21d2f1fb8200830dcbb5d8ec466a9c9120e20d8b53c7585d180125cce1d297a"]
pytest-cov = ["0ab664b25c6aa9716cbf203b17ddb301932383046082c081b9848a0edf5add33", "230ef817450ab0699c6cc3c9c8f7a829c34674456f2ed8df1fe1d39780f7c87f"] pytest-cov = ["0ab664b25c6aa9716cbf203b17ddb301932383046082c081b9848a0edf5add33", "230ef817450ab0699c6cc3c9c8f7a829c34674456f2ed8df1fe1d39780f7c87f"]
pytest-mock = ["53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928", "d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0"] pytest-mock = ["330bfa1a71c9b6e84e2976f01d70d8a174f755e7f9dc5b22f4b7335992e1e98b", "cea3983a1ebc88bf7c0fa1ed8c84e67b898bf71a320a49605bcb74f31e6cfd6a"]
pytest-sugar = ["26cf8289fe10880cbbc130bd77398c4e6a8b936d8393b116a5c16121d95ab283", "fcd87a74b2bce5386d244b49ad60549bfbc4602527797fac167da147983f58ab"] pytest-sugar = ["26cf8289fe10880cbbc130bd77398c4e6a8b936d8393b116a5c16121d95ab283", "fcd87a74b2bce5386d244b49ad60549bfbc4602527797fac167da147983f58ab"]
pyyaml = ["3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", "3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", "40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", "558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", "a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", "aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", "bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", "d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", "d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", "e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", "e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"] pyyaml = ["1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c", "436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95", "460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2", "5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4", "7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad", "9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba", "a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1", "aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e", "c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673", "c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13", "e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19"]
requests = ["502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", "7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"] requests = ["502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", "7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"]
requests-toolbelt = ["42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", "f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"] requests-toolbelt = ["42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", "f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"]
scandir = ["04b8adb105f2ed313a7c2ef0f1cf7aff4871aa7a1883fa4d8c44b5551ab052d6", "1444134990356c81d12f30e4b311379acfbbcd03e0bab591de2696a3b126d58e", "1b5c314e39f596875e5a95dd81af03730b338c277c54a454226978d5ba95dbb6", "346619f72eb0ddc4cf355ceffd225fa52506c92a2ff05318cfabd02a144e7c4e", "44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064", "61859fd7e40b8c71e609c202db5b0c1dbec0d5c7f1449dec2245575bdc866792", "a5e232a0bf188362fa00123cc0bb842d363a292de7126126df5527b6a369586a", "c14701409f311e7a9b7ec8e337f0815baf7ac95776cc78b419a1e6d49889a383", "c7708f29d843fc2764310732e41f0ce27feadde453261859ec0fca7865dfc41b", "c9009c527929f6e25604aec39b0a43c3f831d2947d89d6caaab22f057b7055c8", "f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd"] scandir = ["2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e", "2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022", "2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f", "2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f", "4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae", "67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173", "7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4", "8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32", "92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188", "b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d", "cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac"]
shellingham = ["56e6c7f043661a82b276c241c8e62da62cdf710437164cdef75b3f3ac50fb384", "f24a5a01e6c81d04e252fa2ebaa37710af27e7ec9b54692bcddb9303f899101b"] shellingham = ["77d37a4fd287c1e663006f7ecf1b9deca9ad492d0082587bd813c44eb49e4e62", "985b23bbd1feae47ca6a6365eacd314d93d95a8a16f8f346945074c28fe6f3e0"]
six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"] six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
termcolor = ["1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"] termcolor = ["1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"]
toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"] toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"]
tomlkit = ["d6506342615d051bc961f70bfcfa3d29b6616cc08a3ddfd4bc24196f16fd4ec2", "f077456d35303e7908cc233b340f71e0bec96f63429997f38ca9272b7d64029e"] tomlkit = ["d6506342615d051bc961f70bfcfa3d29b6616cc08a3ddfd4bc24196f16fd4ec2", "f077456d35303e7908cc233b340f71e0bec96f63429997f38ca9272b7d64029e"]
tornado = ["0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d", "4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409", "732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f", "8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f", "8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5", "d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb", "e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"] tornado = ["0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d", "4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409", "732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f", "8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f", "8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5", "d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb", "e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"]
tox = ["04f8f1aa05de8e76d7a266ccd14e0d665d429977cd42123bc38efa9b59964e9e", "25ef928babe88c71e3ed3af0c464d1160b01fca2dd1870a5bb26c2dea61a17fc"] tox = ["69620e19de33a6b7ee8aeda5478791b3618ff58f0b869dbd0319fb71aa903deb", "e5cdb1653aa27b3e46b5c390de6b6d51d31afcfdbd9d1222d82d76b82ad03d9b"]
typing = ["4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", "57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", "a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"] typing = ["4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", "57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", "a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"]
urllib3 = ["61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"] urllib3 = ["61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"]
virtualenv = ["34b9ae3742abed2f95d3970acf4d80533261d6061b51160b197f84e5b4c98b4c", "fa736831a7b18bd2bfeef746beb622a92509e9733d645952da136b0639cd40cd"] virtualenv = ["6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417", "984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39"]
webencodings = ["a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", "b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"] webencodings = ["a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", "b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"]
zipp = ["55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478", "682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4"] zipp = ["55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478", "682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4"]
...@@ -23,7 +23,6 @@ the current directory, processes it, and locks the depdencies in the <comment>po ...@@ -23,7 +23,6 @@ the current directory, processes it, and locks the depdencies in the <comment>po
self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
) )
installer.update(True) installer.lock()
installer.execute_operations(False)
return installer.run() return installer.run()
...@@ -45,6 +45,7 @@ class Installer: ...@@ -45,6 +45,7 @@ class Installer:
self._dev_mode = True self._dev_mode = True
self._develop = [] self._develop = []
self._execute_operations = True self._execute_operations = True
self._lock = False
self._whitelist = [] self._whitelist = []
...@@ -109,6 +110,16 @@ class Installer: ...@@ -109,6 +110,16 @@ class Installer:
return self return self
def lock(self): # type: () -> Installer
"""
Prepare the installer for locking only.
"""
self.update()
self.execute_operations(False)
self._lock = True
return self
def is_updating(self): # type: () -> bool def is_updating(self): # type: () -> bool
return self._update return self._update
...@@ -130,7 +141,7 @@ class Installer: ...@@ -130,7 +141,7 @@ class Installer:
def _do_install(self, local_repo): def _do_install(self, local_repo):
locked_repository = Repository() locked_repository = Repository()
if self._update: if self._update:
if self._locker.is_locked(): if self._locker.is_locked() and not self._lock:
locked_repository = self._locker.locked_repository(True) locked_repository = self._locker.locked_repository(True)
# If no packages have been whitelisted (The ones we want to update), # If no packages have been whitelisted (The ones we want to update),
...@@ -178,7 +189,14 @@ class Installer: ...@@ -178,7 +189,14 @@ class Installer:
# currently installed # currently installed
ops = self._get_operations_from_lock(locked_repository) ops = self._get_operations_from_lock(locked_repository)
self._populate_local_repo(local_repo, ops, locked_repository) self._populate_local_repo(local_repo, ops)
if self._update:
self._write_lock_file(local_repo)
if self._lock:
# If we are only in lock mode, no need to go any further
return 0
root = self._package root = self._package
if not self.is_dev_mode(): if not self.is_dev_mode():
...@@ -270,20 +288,18 @@ class Installer: ...@@ -270,20 +288,18 @@ class Installer:
) )
) )
# Writing lock before installing self._io.write_line("")
for op in ops:
self._execute(op)
def _write_lock_file(self, repo): # type: (Repository) -> None
if self._update and self._write_lock: if self._update and self._write_lock:
updated_lock = self._locker.set_lock_data( updated_lock = self._locker.set_lock_data(self._package, repo.packages)
self._package, local_repo.packages
)
if updated_lock: if updated_lock:
self._io.write_line("") self._io.write_line("")
self._io.write_line("<info>Writing lock file</>") self._io.write_line("<info>Writing lock file</>")
self._io.write_line("")
for op in ops:
self._execute(op)
def _execute(self, operation): # type: (Operation) -> None def _execute(self, operation): # type: (Operation) -> None
""" """
Execute a given operation. Execute a given operation.
...@@ -372,36 +388,15 @@ class Installer: ...@@ -372,36 +388,15 @@ class Installer:
self._installer.remove(operation.package) self._installer.remove(operation.package)
def _populate_local_repo(self, local_repo, ops, locked_repository): def _populate_local_repo(self, local_repo, ops):
# We walk through all operations and add/remove/update accordingly
for op in ops: for op in ops:
if isinstance(op, Update): if isinstance(op, Uninstall):
continue
elif isinstance(op, Update):
package = op.target_package package = op.target_package
else: else:
package = op.package package = op.package
acted_on = False
for pkg in locked_repository.packages:
if pkg.name == package.name:
# The package we operate on is in the local repo
if op.job_type == "update":
if pkg.version == package.version:
break
local_repo.remove_package(pkg)
local_repo.add_package(op.target_package)
elif op.job_type == "uninstall":
local_repo.remove_package(op.package)
else:
# Even though the package already exists
# in the lock file we will prefer the new one
# to force updates
local_repo.remove_package(pkg)
local_repo.add_package(package)
acted_on = True
if not acted_on:
if not local_repo.has_package(package): if not local_repo.has_package(package):
local_repo.add_package(package) local_repo.add_package(package)
......
from cleo.io.io_mixin import IOMixin
from clikit.io import NullIO as BaseNullIO
class NullIO(IOMixin, BaseNullIO):
"""
A wrapper around CliKit's NullIO.
"""
def __init__(self, *args, **kwargs):
super(NullIO, self).__init__(*args, **kwargs)
...@@ -32,6 +32,26 @@ def get_requires_for_build_wheel(config_settings=None): ...@@ -32,6 +32,26 @@ def get_requires_for_build_wheel(config_settings=None):
get_requires_for_build_sdist = get_requires_for_build_wheel get_requires_for_build_sdist = get_requires_for_build_wheel
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
poetry = Poetry.create(".")
builder = WheelBuilder(poetry, SystemEnv(Path(sys.prefix)), NullIO())
dist_info = Path(metadata_directory, builder.dist_info)
dist_info.mkdir()
if "scripts" in poetry.local_config or "plugins" in poetry.local_config:
with (dist_info / "entry_points.txt").open("w") as f:
builder._write_entry_points(f)
with (dist_info / "WHEEL").open("w") as f:
builder._write_wheel_file(f)
with (dist_info / "METADATA").open("w") as f:
builder._write_metadata_file(f)
return dist_info.name
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
"""Builds a wheel, places it in wheel_directory""" """Builds a wheel, places it in wheel_directory"""
poetry = Poetry.create(".") poetry = Poetry.create(".")
......
...@@ -15,6 +15,7 @@ from poetry.utils._compat import Path ...@@ -15,6 +15,7 @@ from poetry.utils._compat import Path
from poetry.utils._compat import basestring from poetry.utils._compat import basestring
from poetry.utils._compat import glob from poetry.utils._compat import glob
from poetry.utils._compat import lru_cache from poetry.utils._compat import lru_cache
from poetry.utils._compat import to_str
from poetry.vcs import get_vcs from poetry.vcs import get_vcs
from ..metadata import Metadata from ..metadata import Metadata
...@@ -24,6 +25,13 @@ from ..utils.package_include import PackageInclude ...@@ -24,6 +25,13 @@ from ..utils.package_include import PackageInclude
AUTHOR_REGEX = re.compile(r"(?u)^(?P<name>[- .,\w\d'’\"()]+) <(?P<email>.+?)>$") AUTHOR_REGEX = re.compile(r"(?u)^(?P<name>[- .,\w\d'’\"()]+) <(?P<email>.+?)>$")
METADATA_BASE = """\
Metadata-Version: 2.1
Name: {name}
Version: {version}
Summary: {summary}
"""
class Builder(object): class Builder(object):
...@@ -147,6 +155,54 @@ class Builder(object): ...@@ -147,6 +155,54 @@ class Builder(object):
return sorted(to_add) return sorted(to_add)
def get_metadata_content(self): # type: () -> bytes
content = METADATA_BASE.format(
name=self._meta.name,
version=self._meta.version,
summary=to_str(self._meta.summary),
)
# Optional fields
if self._meta.home_page:
content += "Home-page: {}\n".format(self._meta.home_page)
if self._meta.license:
content += "License: {}\n".format(self._meta.license)
if self._meta.keywords:
content += "Keywords: {}\n".format(self._meta.keywords)
if self._meta.author:
content += "Author: {}\n".format(to_str(self._meta.author))
if self._meta.author_email:
content += "Author-email: {}\n".format(to_str(self._meta.author_email))
if self._meta.requires_python:
content += "Requires-Python: {}\n".format(self._meta.requires_python)
for classifier in self._meta.classifiers:
content += "Classifier: {}\n".format(classifier)
for extra in sorted(self._meta.provides_extra):
content += "Provides-Extra: {}\n".format(extra)
for dep in sorted(self._meta.requires_dist):
content += "Requires-Dist: {}\n".format(dep)
for url in sorted(self._meta.project_urls, key=lambda u: u[0]):
content += "Project-URL: {}\n".format(to_str(url))
if self._meta.description_content_type:
content += "Description-Content-Type: {}\n".format(
self._meta.description_content_type
)
if self._meta.description is not None:
content += "\n" + to_str(self._meta.description) + "\n"
return content
def convert_entry_points(self): # type: () -> dict def convert_entry_points(self): # type: () -> dict
result = defaultdict(list) result = defaultdict(list)
......
...@@ -41,17 +41,6 @@ setup(**setup_kwargs) ...@@ -41,17 +41,6 @@ setup(**setup_kwargs)
""" """
PKG_INFO = """\
Metadata-Version: 2.1
Name: {name}
Version: {version}
Summary: {summary}
Home-page: {home_page}
Author: {author}
Author-email: {author_email}
"""
class SdistBuilder(Builder): class SdistBuilder(Builder):
def build(self, target_dir=None): # type: (Path) -> Path def build(self, target_dir=None): # type: (Path) -> Path
self._io.write_line(" - Building <info>sdist</info>") self._io.write_line(" - Building <info>sdist</info>")
...@@ -195,34 +184,7 @@ class SdistBuilder(Builder): ...@@ -195,34 +184,7 @@ class SdistBuilder(Builder):
) )
def build_pkg_info(self): def build_pkg_info(self):
pkg_info = PKG_INFO.format( return encode(self.get_metadata_content())
name=self._meta.name,
version=self._meta.version,
summary=self._meta.summary,
home_page=self._meta.home_page,
author=to_str(self._meta.author),
author_email=to_str(self._meta.author_email),
)
if self._meta.keywords:
pkg_info += "Keywords: {}\n".format(self._meta.keywords)
if self._meta.requires_python:
pkg_info += "Requires-Python: {}\n".format(self._meta.requires_python)
for classifier in self._meta.classifiers:
pkg_info += "Classifier: {}\n".format(classifier)
for extra in sorted(self._meta.provides_extra):
pkg_info += "Provides-Extra: {}\n".format(extra)
for dep in sorted(self._meta.requires_dist):
pkg_info += "Requires-Dist: {}\n".format(dep)
for url in sorted(self._meta.project_urls, key=lambda u: u[0]):
pkg_info += "Project-URL: {}\n".format(url)
return encode(pkg_info)
def find_packages(self, include): def find_packages(self, include):
""" """
......
...@@ -17,6 +17,7 @@ from clikit.api.io.flags import VERY_VERBOSE ...@@ -17,6 +17,7 @@ from clikit.api.io.flags import VERY_VERBOSE
from poetry.__version__ import __version__ from poetry.__version__ import __version__
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
from poetry.utils._compat import decode
from ..utils.helpers import normalize_file_permissions from ..utils.helpers import normalize_file_permissions
from ..utils.package_include import PackageInclude from ..utils.package_include import PackageInclude
...@@ -259,7 +260,7 @@ class WheelBuilder(Builder): ...@@ -259,7 +260,7 @@ class WheelBuilder(Builder):
hashsum.update(buf) hashsum.update(buf)
src.seek(0) src.seek(0)
wheel.writestr(zinfo, src.read()) wheel.writestr(zinfo, src.read(), compress_type=zipfile.ZIP_DEFLATED)
size = os.stat(full_path).st_size size = os.stat(full_path).st_size
hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=")
...@@ -276,6 +277,7 @@ class WheelBuilder(Builder): ...@@ -276,6 +277,7 @@ class WheelBuilder(Builder):
# give you the exact same result. # give you the exact same result.
date_time = (2016, 1, 1, 0, 0, 0) date_time = (2016, 1, 1, 0, 0, 0)
zi = zipfile.ZipInfo(rel_path, date_time) zi = zipfile.ZipInfo(rel_path, date_time)
zi.external_attr = (0o644 & 0xFFFF) << 16 # Unix attributes
b = sio.getvalue().encode("utf-8") b = sio.getvalue().encode("utf-8")
hashsum = hashlib.sha256(b) hashsum = hashlib.sha256(b)
hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=")
...@@ -309,43 +311,4 @@ class WheelBuilder(Builder): ...@@ -309,43 +311,4 @@ class WheelBuilder(Builder):
""" """
Write out metadata in the 2.x format (email like) Write out metadata in the 2.x format (email like)
""" """
fp.write("Metadata-Version: 2.1\n") fp.write(decode(self.get_metadata_content()))
fp.write("Name: {}\n".format(self._meta.name))
fp.write("Version: {}\n".format(self._meta.version))
fp.write("Summary: {}\n".format(self._meta.summary))
fp.write("Home-page: {}\n".format(self._meta.home_page or "UNKNOWN"))
fp.write("License: {}\n".format(self._meta.license or "UNKNOWN"))
# Optional fields
if self._meta.keywords:
fp.write("Keywords: {}\n".format(self._meta.keywords))
if self._meta.author:
fp.write("Author: {}\n".format(self._meta.author))
if self._meta.author_email:
fp.write("Author-email: {}\n".format(self._meta.author_email))
if self._meta.requires_python:
fp.write("Requires-Python: {}\n".format(self._meta.requires_python))
for classifier in self._meta.classifiers:
fp.write("Classifier: {}\n".format(classifier))
for extra in sorted(self._meta.provides_extra):
fp.write("Provides-Extra: {}\n".format(extra))
for dep in sorted(self._meta.requires_dist):
fp.write("Requires-Dist: {}\n".format(dep))
for url in sorted(self._meta.project_urls, key=lambda u: u[0]):
fp.write("Project-URL: {}\n".format(url))
if self._meta.description_content_type:
fp.write(
"Description-Content-Type: "
"{}\n".format(self._meta.description_content_type)
)
if self._meta.description is not None:
fp.write("\n" + self._meta.description + "\n")
import hashlib import hashlib
import io import io
import math
import re import re
from typing import List from typing import List
...@@ -22,6 +23,15 @@ from ..metadata import Metadata ...@@ -22,6 +23,15 @@ from ..metadata import Metadata
_has_blake2 = hasattr(hashlib, "blake2b") _has_blake2 = hasattr(hashlib, "blake2b")
class UploadError(Exception):
def __init__(self, error): # type: (HTTPError) -> None
super(UploadError, self).__init__(
"HTTP Error {}: {}".format(
error.response.status_code, error.response.reason
)
)
class Uploader: class Uploader:
def __init__(self, poetry, io): def __init__(self, poetry, io):
self._poetry = poetry self._poetry = poetry
...@@ -175,18 +185,15 @@ class Uploader: ...@@ -175,18 +185,15 @@ class Uploader:
self._do_upload(session, url) self._do_upload(session, url)
except HTTPError as e: except HTTPError as e:
if ( if (
e.response.status_code not in (403, 400) e.response.status_code == 400
or e.response.status_code == 400 and "was ever registered" in e.response.text
and "was ever registered" not in e.response.text
): ):
raise
# It may be the first time we publish the package
# We'll try to register it and go from there
try: try:
self._register(session, url) self._register(session, url)
except HTTPError: except HTTPError as e:
raise raise UploadError(e)
raise UploadError(e)
def _do_upload(self, session, url): def _do_upload(self, session, url):
for file in self.files: for file in self.files:
...@@ -235,7 +242,14 @@ class Uploader: ...@@ -235,7 +242,14 @@ class Uploader:
self._io.write_line("") self._io.write_line("")
else: else:
self._io.overwrite("") if self._io.output.supports_ansi():
self._io.overwrite(
" - Uploading <info>{0}</> <error>{1}%</>".format(
file.name, int(math.floor(bar._percent * 100))
)
)
else:
self._io.write_line("")
return resp return resp
...@@ -263,6 +277,8 @@ class Uploader: ...@@ -263,6 +277,8 @@ class Uploader:
headers={"Content-Type": encoder.content_type}, headers={"Content-Type": encoder.content_type},
) )
resp.raise_for_status()
return resp return resp
def _prepare_data(self, data): def _prepare_data(self, data):
......
import os import os
import re import re
from poetry.semver import Version
from poetry.version.requirements import Requirement from poetry.version.requirements import Requirement
from .dependency import Dependency from .dependency import Dependency
...@@ -105,6 +106,22 @@ def dependency_from_pep_508(name): ...@@ -105,6 +106,22 @@ def dependency_from_pep_508(name):
op = "" op = ""
elif op == "!=": elif op == "!=":
version += ".*" version += ".*"
elif op in ("<=", ">"):
parsed_version = Version.parse(version)
if parsed_version.precision == 1:
if op == "<=":
op = "<"
version = parsed_version.next_major.text
elif op == ">":
op = ">="
version = parsed_version.next_major.text
elif parsed_version.precision == 2:
if op == "<=":
op = "<"
version = parsed_version.next_minor.text
elif op == ">":
op = ">="
version = parsed_version.next_minor.text
elif op in ("in", "not in"): elif op in ("in", "not in"):
versions = [] versions = []
for v in re.split("[ ,]+", version): for v in re.split("[ ,]+", version):
......
...@@ -127,6 +127,24 @@ class Dependency(object): ...@@ -127,6 +127,24 @@ class Dependency(object):
def in_extras(self): # type: () -> list def in_extras(self): # type: () -> list
return self._in_extras return self._in_extras
@property
def base_pep_508_name(self): # type: () -> str
requirement = self.pretty_name
if self.extras:
requirement += "[{}]".format(",".join(self.extras))
if isinstance(self.constraint, VersionUnion):
requirement += " ({})".format(
",".join([str(c).replace(" ", "") for c in self.constraint.ranges])
)
elif isinstance(self.constraint, Version):
requirement += " (=={})".format(self.constraint.text)
elif not self.constraint.is_any():
requirement += " ({})".format(str(self.constraint).replace(" ", ""))
return requirement
def allows_prereleases(self): def allows_prereleases(self):
return self._allows_prereleases return self._allows_prereleases
...@@ -156,19 +174,7 @@ class Dependency(object): ...@@ -156,19 +174,7 @@ class Dependency(object):
) )
def to_pep_508(self, with_extras=True): # type: (bool) -> str def to_pep_508(self, with_extras=True): # type: (bool) -> str
requirement = self.pretty_name requirement = self.base_pep_508_name
if self.extras:
requirement += "[{}]".format(",".join(self.extras))
if isinstance(self.constraint, VersionUnion):
requirement += " ({})".format(
",".join([str(c).replace(" ", "") for c in self.constraint.ranges])
)
elif isinstance(self.constraint, Version):
requirement += " (=={})".format(self.constraint.text)
elif not self.constraint.is_any():
requirement += " ({})".format(str(self.constraint).replace(" ", ""))
markers = [] markers = []
if not self.marker.is_any(): if not self.marker.is_any():
......
...@@ -62,6 +62,17 @@ class VCSDependency(Dependency): ...@@ -62,6 +62,17 @@ class VCSDependency(Dependency):
return "{} {}".format(what, version) return "{} {}".format(what, version)
@property
def base_pep_508_name(self): # type: () -> str
requirement = self.pretty_name
if self.extras:
requirement += "[{}]".format(",".join(self.extras))
requirement += " @ {}+{}@{}".format(self._vcs, self._source, self.reference)
return requirement
def is_vcs(self): # type: () -> bool def is_vcs(self): # type: () -> bool
return True return True
......
...@@ -282,6 +282,10 @@ class SetupReader(object): ...@@ -282,6 +282,10 @@ class SetupReader(object):
if isinstance(value, ast.Dict): if isinstance(value, ast.Dict):
for key, val in zip(value.keys, value.values): for key, val in zip(value.keys, value.values):
if isinstance(val, ast.Name):
val = self._find_variable_in_body(body, val.id)
if isinstance(val, ast.List):
extras_require[key.s] = [e.s for e in val.elts] extras_require[key.s] = [e.s for e in val.elts]
elif isinstance(value, ast.Name): elif isinstance(value, ast.Name):
variable = self._find_variable_in_body(body, value.id) variable = self._find_variable_in_body(body, value.id)
...@@ -290,6 +294,10 @@ class SetupReader(object): ...@@ -290,6 +294,10 @@ class SetupReader(object):
return extras_require return extras_require
for key, val in zip(variable.keys, variable.values): for key, val in zip(variable.keys, variable.values):
if isinstance(val, ast.Name):
val = self._find_variable_in_body(body, val.id)
if isinstance(val, ast.List):
extras_require[key.s] = [e.s for e in val.elts] extras_require[key.s] = [e.s for e in val.elts]
return extras_require return extras_require
......
...@@ -230,6 +230,7 @@ class EmptyMarker(BaseMarker): ...@@ -230,6 +230,7 @@ class EmptyMarker(BaseMarker):
class SingleMarker(BaseMarker): class SingleMarker(BaseMarker):
_CONSTRAINT_RE = re.compile(r"(?i)^(~=|!=|>=?|<=?|==?|in|not in)?\s*(.+)$") _CONSTRAINT_RE = re.compile(r"(?i)^(~=|!=|>=?|<=?|==?|in|not in)?\s*(.+)$")
_VERSION_LIKE_MARKER_NAME = {"python_version", "platform_release"}
def __init__(self, name, constraint): def __init__(self, name, constraint):
from poetry.packages.constraints import ( from poetry.packages.constraints import (
...@@ -248,10 +249,10 @@ class SingleMarker(BaseMarker): ...@@ -248,10 +249,10 @@ class SingleMarker(BaseMarker):
self._value = m.group(2) self._value = m.group(2)
self._parser = parse_generic_constraint self._parser = parse_generic_constraint
if self._name == "python_version":
if name in self._VERSION_LIKE_MARKER_NAME:
self._parser = parse_constraint self._parser = parse_constraint
if name == "python_version":
if self._operator in {"in", "not in"}: if self._operator in {"in", "not in"}:
versions = [] versions = []
for v in re.split("[ ,]+", self._value): for v in re.split("[ ,]+", self._value):
......
...@@ -174,8 +174,8 @@ MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") ...@@ -174,8 +174,8 @@ MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
MARKER_EXPR.setParseAction( MARKER_EXPR.setParseAction(
lambda s, l, t: parse_marker(s[t._original_start : t._original_end]) lambda s, l, t: parse_marker(s[t._original_start : t._original_end])
) )
MARKER_SEPERATOR = SEMICOLON MARKER_SEPARATOR = SEMICOLON
MARKER = MARKER_SEPERATOR + MARKER_EXPR MARKER = MARKER_SEPARATOR + MARKER_EXPR
VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
URL_AND_MARKER = URL + Optional(MARKER) URL_AND_MARKER = URL + Optional(MARKER)
......
...@@ -60,6 +60,7 @@ black = { version = "^18.3-alpha.0", python = "^3.6" } ...@@ -60,6 +60,7 @@ black = { version = "^18.3-alpha.0", python = "^3.6" }
pre-commit = "^1.10" pre-commit = "^1.10"
tox = "^3.0" tox = "^3.0"
pytest-sugar = "^0.9.2" pytest-sugar = "^0.9.2"
httpretty = "^0.9.6"
[tool.poetry.scripts] [tool.poetry.scripts]
......
...@@ -68,6 +68,7 @@ class MakeReleaseCommand(Command): ...@@ -68,6 +68,7 @@ class MakeReleaseCommand(Command):
else: else:
vcs_excluded = [] vcs_excluded = []
created_files = []
with temporary_directory() as tmp_dir: with temporary_directory() as tmp_dir:
# Copy poetry to tmp dir # Copy poetry to tmp dir
poetry_dir = os.path.join(tmp_dir, "poetry") poetry_dir = os.path.join(tmp_dir, "poetry")
...@@ -78,6 +79,13 @@ class MakeReleaseCommand(Command): ...@@ -78,6 +79,13 @@ class MakeReleaseCommand(Command):
set([os.path.join(dir_, name) for name in names]) set([os.path.join(dir_, name) for name in names])
), ),
) )
created_files += [
p.relative_to(Path(tmp_dir))
for p in Path(poetry_dir).glob("**/*")
if p.is_file()
and p.suffix != ".pyc"
and str(p.relative_to(Path(tmp_dir))) not in vcs_excluded
]
for version, python in sorted(pythons.items()): for version, python in sorted(pythons.items()):
self.line( self.line(
"<info>Preparing files for Python <comment>{}</comment></info>".format( "<info>Preparing files for Python <comment>{}</comment></info>".format(
...@@ -91,6 +99,16 @@ class MakeReleaseCommand(Command): ...@@ -91,6 +99,16 @@ class MakeReleaseCommand(Command):
self.vendorize_for_python( self.vendorize_for_python(
python, [op.package for op in ops], poetry_dir, version python, [op.package for op in ops], poetry_dir, version
) )
vendor_dir = Path(
os.path.join(poetry_dir, "_vendor", "py{}".format(python))
)
created_files += [
p.relative_to(Path(tmp_dir))
for p in vendor_dir.glob("**/*")
if p.is_file()
and p.suffix != ".pyc"
and str(p.relative_to(Path(tmp_dir))) not in vcs_excluded
]
self.line("") self.line("")
...@@ -130,6 +148,22 @@ class MakeReleaseCommand(Command): ...@@ -130,6 +148,22 @@ class MakeReleaseCommand(Command):
finally: finally:
gz.close() gz.close()
self.line("<info>Checking release file</info>")
missing_files = []
with tarfile.open(os.path.join(tmp_dir2, name), "r") as tar:
names = tar.getnames()
for created_file in created_files:
if created_file.as_posix() not in names:
missing_files.append(created_file.as_posix())
if missing_files:
self.line("<error>Some files are missing:</error>")
for missing_file in missing_files:
self.line("<error> - {}</error>".format(missing_file))
return 1
releases_dir = os.path.join(os.path.dirname(__file__), "releases") releases_dir = os.path.join(os.path.dirname(__file__), "releases")
if not os.path.exists(releases_dir): if not os.path.exists(releases_dir):
os.mkdir(releases_dir) os.mkdir(releases_dir)
......
import httpretty
import os import os
import pytest import pytest
import shutil import shutil
...@@ -72,3 +73,12 @@ def git_mock(mocker): ...@@ -72,3 +73,12 @@ def git_mock(mocker):
mocker.patch("poetry.vcs.git.Git.checkout", new=lambda *_: None) mocker.patch("poetry.vcs.git.Git.checkout", new=lambda *_: None)
p = mocker.patch("poetry.vcs.git.Git.rev_parse") p = mocker.patch("poetry.vcs.git.Git.rev_parse")
p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
@pytest.fixture
def http():
httpretty.enable()
yield httpretty
httpretty.disable()
...@@ -21,10 +21,10 @@ Using version ^0.2.0 for cachy ...@@ -21,10 +21,10 @@ Using version ^0.2.0 for cachy
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 1 install, 0 updates, 0 removals
Writing lock file Package operations: 1 install, 0 updates, 0 removals
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
...@@ -53,10 +53,10 @@ def test_add_constraint(app, repo, installer): ...@@ -53,10 +53,10 @@ def test_add_constraint(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 1 install, 0 updates, 0 removals
Writing lock file Package operations: 1 install, 0 updates, 0 removals
- Installing cachy (0.1.0) - Installing cachy (0.1.0)
""" """
...@@ -85,11 +85,11 @@ def test_add_constraint_dependencies(app, repo, installer): ...@@ -85,11 +85,11 @@ def test_add_constraint_dependencies(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 2 installs, 0 updates, 0 removals Package operations: 2 installs, 0 updates, 0 removals
Writing lock file
- Installing msgpack-python (0.5.3) - Installing msgpack-python (0.5.3)
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
...@@ -113,10 +113,10 @@ def test_add_git_constraint(app, repo, installer): ...@@ -113,10 +113,10 @@ def test_add_git_constraint(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
Writing lock file Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4) - Installing pendulum (1.4.4)
- Installing demo (0.1.2 9cf87a2) - Installing demo (0.1.2 9cf87a2)
...@@ -147,10 +147,10 @@ def test_add_git_constraint_with_poetry(app, repo, installer): ...@@ -147,10 +147,10 @@ def test_add_git_constraint_with_poetry(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
Writing lock file Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4) - Installing pendulum (1.4.4)
- Installing demo (0.1.2 9cf87a2) - Installing demo (0.1.2 9cf87a2)
...@@ -174,11 +174,11 @@ def test_add_file_constraint_wheel(app, repo, installer): ...@@ -174,11 +174,11 @@ def test_add_file_constraint_wheel(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 2 installs, 0 updates, 0 removals Package operations: 2 installs, 0 updates, 0 removals
Writing lock file
- Installing pendulum (1.4.4) - Installing pendulum (1.4.4)
- Installing demo (0.1.0 ../distributions/demo-0.1.0-py2.py3-none-any.whl) - Installing demo (0.1.0 ../distributions/demo-0.1.0-py2.py3-none-any.whl)
""" """
...@@ -208,10 +208,10 @@ def test_add_file_constraint_sdist(app, repo, installer): ...@@ -208,10 +208,10 @@ def test_add_file_constraint_sdist(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
Writing lock file Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4) - Installing pendulum (1.4.4)
- Installing demo (0.1.0 ../distributions/demo-0.1.0.tar.gz) - Installing demo (0.1.0 ../distributions/demo-0.1.0.tar.gz)
...@@ -249,10 +249,10 @@ def test_add_constraint_with_extras(app, repo, installer): ...@@ -249,10 +249,10 @@ def test_add_constraint_with_extras(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
Writing lock file Package operations: 2 installs, 0 updates, 0 removals
- Installing msgpack-python (0.5.3) - Installing msgpack-python (0.5.3)
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
...@@ -287,11 +287,11 @@ def test_add_constraint_with_python(app, repo, installer): ...@@ -287,11 +287,11 @@ def test_add_constraint_with_python(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 1 install, 0 updates, 0 removals Package operations: 1 install, 0 updates, 0 removals
Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
...@@ -322,10 +322,10 @@ def test_add_constraint_with_platform(app, repo, installer): ...@@ -322,10 +322,10 @@ def test_add_constraint_with_platform(app, repo, installer):
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 1 install, 0 updates, 0 removals
Writing lock file Package operations: 1 install, 0 updates, 0 removals
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
...@@ -358,10 +358,10 @@ Using version ^0.2.0 for cachy ...@@ -358,10 +358,10 @@ Using version ^0.2.0 for cachy
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 1 install, 0 updates, 0 removals
Writing lock file Package operations: 1 install, 0 updates, 0 removals
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
...@@ -391,11 +391,11 @@ Using version ^3.13 for pyyaml ...@@ -391,11 +391,11 @@ Using version ^3.13 for pyyaml
Updating dependencies Updating dependencies
Resolving dependencies... Resolving dependencies...
Writing lock file
Package operations: 1 install, 0 updates, 0 removals Package operations: 1 install, 0 updates, 0 removals
Writing lock file
- Installing pyyaml (3.13) - Installing pyyaml (3.13)
""" """
......
def test_publish_returns_non_zero_code_for_upload_errors(app, app_tester, http):
http.register_uri(
http.POST, "https://upload.pypi.org/legacy/", status=400, body="Bad Request"
)
exit_code = app_tester.execute("publish --username foo --password bar")
assert 1 == exit_code
expected = """
Publishing simple-project (1.2.3) to PyPI
[UploadError]
HTTP Error 400: Bad Request
"""
assert app_tester.io.fetch_output() == expected
...@@ -7,6 +7,7 @@ try: ...@@ -7,6 +7,7 @@ try:
except ImportError: except ImportError:
import urlparse import urlparse
from cleo import ApplicationTester
from tomlkit import document from tomlkit import document
from poetry.config import Config as BaseConfig from poetry.config import Config as BaseConfig
...@@ -139,6 +140,7 @@ class Poetry(BasePoetry): ...@@ -139,6 +140,7 @@ class Poetry(BasePoetry):
self._local_config = local_config self._local_config = local_config
self._locker = Locker(locker.lock.path, locker._local_config) self._locker = Locker(locker.lock.path, locker._local_config)
self._config = Config.create("config.toml") self._config = Config.create("config.toml")
self._auth_config = Config.create("auth.toml")
# Configure sources # Configure sources
self._pool = Pool() self._pool = Pool()
...@@ -184,4 +186,12 @@ def poetry(repo, project_directory): ...@@ -184,4 +186,12 @@ def poetry(repo, project_directory):
@pytest.fixture @pytest.fixture
def app(poetry): def app(poetry):
return Application(poetry) app_ = Application(poetry)
app_.config.set_terminate_after_run(False)
return app_
@pytest.fixture
def app_tester(app):
return ApplicationTester(app)
[[package]]
name = "A"
version = "1.0"
description = ""
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
B = ">=1.0.1"
C = [
{version = "^1.0", python = ">=2.7,<2.8"},
{version = "^2.0", python = ">=3.4,<4.0"},
]
[[package]]
name = "B"
version = "1.0.1"
description = ""
category = "main"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
[[package]]
name = "B"
version = "1.1.0"
description = ""
category = "main"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
[[package]]
name = "C"
version = "1.0"
description = ""
category = "main"
optional = false
marker = "python_version >= \"2.7\" and python_version < \"2.8\""
python-versions = "*"
[[package]]
name = "C"
version = "2.0"
description = ""
category = "main"
optional = false
marker = "python_version >= \"3.4\" and python_version < \"4.0\""
python-versions = "*"
[metadata]
python-versions = "~2.7 || ^3.4"
content-hash = "123456789"
[metadata.hashes]
A = []
B = []
C = []
...@@ -1396,3 +1396,78 @@ def test_installer_required_extras_should_be_installed( ...@@ -1396,3 +1396,78 @@ def test_installer_required_extras_should_be_installed(
assert len(installer.installer.installs) == 2 assert len(installer.installer.installs) == 2
assert len(installer.installer.updates) == 0 assert len(installer.installer.updates) == 0
assert len(installer.installer.removals) == 0 assert len(installer.installer.removals) == 0
def test_update_multiple_times_with_split_dependencies_is_idempotent(
installer, locker, repo, package
):
locker.locked(True)
locker.mock_lock_data(
{
"package": [
{
"name": "A",
"version": "1.0",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
"dependencies": {"B": ">=1.0"},
},
{
"name": "B",
"version": "1.0.1",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
"checksum": [],
"dependencies": {},
},
],
"metadata": {
"python-versions": "*",
"platform": "*",
"content-hash": "123456789",
"hashes": {"A": [], "B": []},
},
}
)
package.python_versions = "~2.7 || ^3.4"
package.add_dependency("A", "^1.0")
a = get_package("A", "1.0")
a.add_dependency("B", ">=1.0.1")
a.add_dependency("C", {"version": "^1.0", "python": "~2.7"})
a.add_dependency("C", {"version": "^2.0", "python": "^3.4"})
b101 = get_package("B", "1.0.1")
b101.python_versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
b110 = get_package("B", "1.1.0")
b110.python_versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
repo.add_package(a)
repo.add_package(b101)
repo.add_package(b110)
repo.add_package(get_package("C", "1.0"))
repo.add_package(get_package("C", "2.0"))
expected = fixture("with-multiple-updates")
installer.update(True)
installer.run()
assert expected == locker.written_data
locker.mock_lock_data(locker.written_data)
installer.update(True)
installer.run()
assert expected == locker.written_data
locker.mock_lock_data(locker.written_data)
installer.update(True)
installer.run()
assert expected == locker.written_data
...@@ -5,12 +5,9 @@ description = "Some description." ...@@ -5,12 +5,9 @@ description = "Some description."
authors = [ authors = [
"Sébastien Eustace <sebastien@eustace.io>" "Sébastien Eustace <sebastien@eustace.io>"
] ]
license = "MIT"
readme = "README.rst" readme = "README.rst"
homepage = "https://poetry.eustace.io/"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "3.6" python = "3.6"
[tool.poetry]
name = "with-vcs-dependency"
version = "1.2.3"
description = "Some description."
authors = [
"Sébastien Eustace <sebastien@eustace.io>"
]
license = "MIT"
homepage = "https://poetry.eustace.io/"
repository = "https://github.com/sdispater/poetry"
documentation = "https://poetry.eustace.io/docs"
keywords = ["packaging", "dependency", "poetry"]
classifiers = [
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules"
]
# Requirements
[tool.poetry.dependencies]
python = "^3.6"
cleo = { git = "https://github.com/sdispater/cleo.git", branch = "master" }
# -*- coding: utf-8 -*-
from clikit.io import NullIO from clikit.io import NullIO
from email.parser import Parser
from poetry.masonry.builders.builder import Builder from poetry.masonry.builders.builder import Builder
from poetry.poetry import Poetry from poetry.poetry import Poetry
...@@ -53,3 +55,79 @@ def test_builder_find_invalid_case_sensitive_excluded_files(mocker): ...@@ -53,3 +55,79 @@ def test_builder_find_invalid_case_sensitive_excluded_files(mocker):
) )
assert {"my_package/Bar/foo/bar/Foo.py"} == builder.find_excluded_files() assert {"my_package/Bar/foo/bar/Foo.py"} == builder.find_excluded_files()
def test_get_metadata_content():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "complete"),
NullEnv(),
NullIO(),
)
metadata = builder.get_metadata_content()
p = Parser()
parsed = p.parsestr(metadata)
assert parsed["Metadata-Version"] == "2.1"
assert parsed["Name"] == "my-package"
assert parsed["Version"] == "1.2.3"
assert parsed["Summary"] == "Some description."
assert parsed["Author"] == "Sébastien Eustace"
assert parsed["Author-email"] == "sebastien@eustace.io"
assert parsed["Keywords"] == "packaging,dependency,poetry"
assert parsed["Requires-Python"] == ">=3.6,<4.0"
assert parsed["License"] == "MIT"
assert parsed["Home-page"] == "https://poetry.eustace.io/"
classifiers = parsed.get_all("Classifier")
assert classifiers == [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules",
]
extras = parsed.get_all("Provides-Extra")
assert extras == ["time"]
requires = parsed.get_all("Requires-Dist")
assert requires == [
"cachy[msgpack] (>=0.2.0,<0.3.0)",
"cleo (>=0.6,<0.7)",
'pendulum (>=1.4,<2.0); extra == "time"',
]
urls = parsed.get_all("Project-URL")
assert urls == [
"Documentation, https://poetry.eustace.io/docs",
"Repository, https://github.com/sdispater/poetry",
]
def test_metadata_homepage_default():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "simple_version"),
NullEnv(),
NullIO(),
)
metadata = Parser().parsestr(builder.get_metadata_content())
assert metadata["Home-page"] is None
def test_metadata_with_vcs_dependencies():
builder = Builder(
Poetry.create(Path(__file__).parent / "fixtures" / "with_vcs_dependency"),
NullEnv(),
NullIO(),
)
metadata = Parser().parsestr(builder.get_metadata_content())
requires_dist = metadata["Requires-Dist"]
assert "cleo @ git+https://github.com/sdispater/cleo.git@master" == requires_dist
...@@ -11,6 +11,7 @@ from clikit.io import NullIO ...@@ -11,6 +11,7 @@ from clikit.io import NullIO
from poetry.masonry.builders.sdist import SdistBuilder from poetry.masonry.builders.sdist import SdistBuilder
from poetry.masonry.utils.package_include import PackageInclude from poetry.masonry.utils.package_include import PackageInclude
from poetry.packages import Package from poetry.packages import Package
from poetry.packages.vcs_dependency import VCSDependency
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import to_str from poetry.utils._compat import to_str
...@@ -49,9 +50,15 @@ def test_convert_dependencies(): ...@@ -49,9 +50,15 @@ def test_convert_dependencies():
get_dependency("A", "^1.0"), get_dependency("A", "^1.0"),
get_dependency("B", "~1.0"), get_dependency("B", "~1.0"),
get_dependency("C", "1.2.3"), get_dependency("C", "1.2.3"),
VCSDependency("D", "git", "https://github.com/sdispater/d.git"),
], ],
) )
main = ["A>=1.0,<2.0", "B>=1.0,<1.1", "C==1.2.3"] main = [
"A>=1.0,<2.0",
"B>=1.0,<1.1",
"C==1.2.3",
"D @ git+https://github.com/sdispater/d.git@master",
]
extras = {} extras = {}
assert result == (main, extras) assert result == (main, extras)
...@@ -129,48 +136,16 @@ def test_make_setup(): ...@@ -129,48 +136,16 @@ def test_make_setup():
assert ns["extras_require"] == {"time": ["pendulum>=1.4,<2.0"]} assert ns["extras_require"] == {"time": ["pendulum>=1.4,<2.0"]}
def test_make_pkg_info(): def test_make_pkg_info(mocker):
get_metadata_content = mocker.patch(
"poetry.masonry.builders.builder.Builder.get_metadata_content"
)
poetry = Poetry.create(project("complete")) poetry = Poetry.create(project("complete"))
builder = SdistBuilder(poetry, NullEnv(), NullIO()) builder = SdistBuilder(poetry, NullEnv(), NullIO())
pkg_info = builder.build_pkg_info() builder.build_pkg_info()
p = Parser()
parsed = p.parsestr(to_str(pkg_info))
assert parsed["Metadata-Version"] == "2.1"
assert parsed["Name"] == "my-package"
assert parsed["Version"] == "1.2.3"
assert parsed["Summary"] == "Some description."
assert parsed["Author"] == "Sébastien Eustace"
assert parsed["Author-email"] == "sebastien@eustace.io"
assert parsed["Keywords"] == "packaging,dependency,poetry"
assert parsed["Requires-Python"] == ">=3.6,<4.0"
classifiers = parsed.get_all("Classifier")
assert classifiers == [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules",
]
extras = parsed.get_all("Provides-Extra") assert get_metadata_content.called
assert extras == ["time"]
requires = parsed.get_all("Requires-Dist")
assert requires == [
"cachy[msgpack] (>=0.2.0,<0.3.0)",
"cleo (>=0.6,<0.7)",
'pendulum (>=1.4,<2.0); extra == "time"',
]
urls = parsed.get_all("Project-URL")
assert urls == [
"Documentation, https://poetry.eustace.io/docs",
"Repository, https://github.com/sdispater/poetry",
]
def test_make_pkg_info_any_python(): def test_make_pkg_info_any_python():
......
# -*- coding: utf-8 -*-
import pytest import pytest
import shutil import shutil
import zipfile import zipfile
...@@ -8,7 +9,6 @@ from poetry.masonry.builders import WheelBuilder ...@@ -8,7 +9,6 @@ from poetry.masonry.builders import WheelBuilder
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.env import NullEnv from poetry.utils.env import NullEnv
from poetry.packages import ProjectPackage
fixtures_dir = Path(__file__).parent / "fixtures" fixtures_dir = Path(__file__).parent / "fixtures"
...@@ -127,21 +127,24 @@ def test_package_with_include(mocker): ...@@ -127,21 +127,24 @@ def test_package_with_include(mocker):
assert "package_with_include/__init__.py" in names assert "package_with_include/__init__.py" in names
def test_write_metadata_file_license_homepage_default(mocker): def test_dist_info_file_permissions():
# Preparation module_path = fixtures_dir / "complete"
mocked_poetry = mocker.Mock() WheelBuilder.make(Poetry.create(str(module_path)), NullEnv(), NullIO())
mocked_poetry.file.parent = Path(".")
mocked_poetry.package = ProjectPackage("pkg_name", "1.0.0") whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
mocked_file = mocker.Mock()
mocked_venv = mocker.Mock() with zipfile.ZipFile(str(whl)) as z:
mocked_io = mocker.Mock() assert (
# patch Module init inside Builder class z.getinfo("my_package-1.2.3.dist-info/WHEEL").external_attr == 0o644 << 16
mocker.patch("poetry.masonry.builders.builder.Module") )
w = WheelBuilder(mocked_poetry, mocked_venv, mocked_io) assert (
z.getinfo("my_package-1.2.3.dist-info/METADATA").external_attr
# Action == 0o644 << 16
w._write_metadata_file(mocked_file) )
assert (
# Assertion z.getinfo("my_package-1.2.3.dist-info/RECORD").external_attr == 0o644 << 16
mocked_file.write.assert_any_call("Home-page: UNKNOWN\n") )
mocked_file.write.assert_any_call("License: UNKNOWN\n") assert (
z.getinfo("my_package-1.2.3.dist-info/entry_points.txt").external_attr
== 0o644 << 16
)
import pytest
from poetry.io.null_io import NullIO
from poetry.masonry.publishing.uploader import UploadError
from poetry.masonry.publishing.uploader import Uploader
from poetry.poetry import Poetry
from poetry.utils._compat import Path
fixtures_dir = Path(__file__).parent.parent.parent / "fixtures"
def project(name):
return fixtures_dir / name
def test_uploader_properly_handles_400_errors(http):
http.register_uri(http.POST, "https://foo.com", status=400, body="Bad request")
uploader = Uploader(Poetry.create(project("simple_project")), NullIO())
with pytest.raises(UploadError) as e:
uploader.upload("https://foo.com")
assert "HTTP Error 400: Bad Request" == str(e.value)
def test_uploader_properly_handles_403_errors(http):
http.register_uri(http.POST, "https://foo.com", status=403, body="Unauthorized")
uploader = Uploader(Poetry.create(project("simple_project")), NullIO())
with pytest.raises(UploadError) as e:
uploader.upload("https://foo.com")
assert "HTTP Error 403: Forbidden" == str(e.value)
def test_uploader_registers_for_appropriate_400_errors(mocker, http):
register = mocker.patch("poetry.masonry.publishing.uploader.Uploader._register")
http.register_uri(
http.POST, "https://foo.com", status=400, body="No package was ever registered"
)
uploader = Uploader(Poetry.create(project("simple_project")), NullIO())
with pytest.raises(UploadError):
uploader.upload("https://foo.com")
assert 1 == register.call_count
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os import os
import tarfile import tarfile
import zipfile import zipfile
from contextlib import contextmanager from contextlib import contextmanager
from poetry import __version__
from poetry.masonry import api from poetry.masonry import api
from poetry.utils._compat import Path
from poetry.utils._compat import decode
from poetry.utils.helpers import temporary_directory from poetry.utils.helpers import temporary_directory
...@@ -53,3 +59,69 @@ def test_build_sdist(): ...@@ -53,3 +59,69 @@ def test_build_sdist():
namelist = tar.getnames() namelist = tar.getnames()
assert "my-package-1.2.3/LICENSE" in namelist assert "my-package-1.2.3/LICENSE" in namelist
def test_prepare_metadata_for_build_wheel():
entry_points = """\
[console_scripts]
extra-script=my_package.extra:main[time]
my-2nd-script=my_package:main2
my-script=my_package:main
"""
wheel_data = """\
Wheel-Version: 1.0
Generator: poetry {}
Root-Is-Purelib: true
Tag: py3-none-any
""".format(
__version__
)
metadata = """\
Metadata-Version: 2.1
Name: my-package
Version: 1.2.3
Summary: Some description.
Home-page: https://poetry.eustace.io/
License: MIT
Keywords: packaging,dependency,poetry
Author: Sébastien Eustace
Author-email: sebastien@eustace.io
Requires-Python: >=3.6,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Provides-Extra: time
Requires-Dist: cachy[msgpack] (>=0.2.0,<0.3.0)
Requires-Dist: cleo (>=0.6,<0.7)
Requires-Dist: pendulum (>=1.4,<2.0); extra == "time"
Project-URL: Documentation, https://poetry.eustace.io/docs
Project-URL: Repository, https://github.com/sdispater/poetry
Description-Content-Type: text/x-rst
My Package
==========
"""
with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "complete")):
dirname = api.prepare_metadata_for_build_wheel(tmp_dir)
assert "my_package-1.2.3.dist-info" == dirname
dist_info = Path(tmp_dir, dirname)
assert (dist_info / "entry_points.txt").exists()
assert (dist_info / "WHEEL").exists()
assert (dist_info / "METADATA").exists()
with (dist_info / "entry_points.txt").open() as f:
assert entry_points == decode(f.read())
with (dist_info / "WHEEL").open() as f:
assert wheel_data == decode(f.read())
with (dist_info / "METADATA").open() as f:
assert metadata == decode(f.read())
from poetry.packages.vcs_dependency import VCSDependency
def test_to_pep_508():
dependency = VCSDependency(
"poetry", "git", "https://github.com/sdispater/poetry.git"
)
expected = "poetry @ git+https://github.com/sdispater/poetry.git@master"
assert expected == dependency.to_pep_508()
def test_to_pep_508_with_extras():
dependency = VCSDependency(
"poetry", "git", "https://github.com/sdispater/poetry.git"
)
dependency.extras.append("foo")
expected = "poetry[foo] @ git+https://github.com/sdispater/poetry.git@master"
assert expected == dependency.to_pep_508()
from setuptools import setup
tests_require = ["pytest"]
setup(
name="extras_require_with_vars",
version="0.0.1",
description="test setup_reader.py",
install_requires=[],
extras_require={"test": tests_require},
)
...@@ -149,3 +149,20 @@ def test_setup_reader_read_setup_call_in_main(setup): ...@@ -149,3 +149,20 @@ def test_setup_reader_read_setup_call_in_main(setup):
assert expected_install_requires == result["install_requires"] assert expected_install_requires == result["install_requires"]
assert expected_extras_require == result["extras_require"] assert expected_extras_require == result["extras_require"]
assert expected_python_requires == result["python_requires"] assert expected_python_requires == result["python_requires"]
@pytest.mark.skipif(not PY35, reason="AST parsing does not work for Python <3.4")
def test_setup_reader_read_extras_require_with_variables(setup):
result = SetupReader.read_from_directory(setup("extras_require_with_vars"))
expected_name = "extras_require_with_vars"
expected_version = "0.0.1"
expected_install_requires = []
expected_extras_require = {"test": ["pytest"]}
expected_python_requires = None
assert expected_name == result["name"]
assert expected_version == result["version"]
assert expected_install_requires == result["install_requires"]
assert expected_extras_require == result["extras_require"]
assert expected_python_requires == result["python_requires"]
...@@ -423,3 +423,18 @@ def test_validate(marker_string, environment, expected): ...@@ -423,3 +423,18 @@ def test_validate(marker_string, environment, expected):
m = parse_marker(marker_string) m = parse_marker(marker_string)
assert m.validate(environment) is expected assert m.validate(environment) is expected
@pytest.mark.parametrize(
"marker, env",
[
(
'platform_release >= "9.0" and platform_release < "11.0"',
{"platform_release": "10.0"},
)
],
)
def test_parse_version_like_markers(marker, env):
m = parse_marker(marker)
assert m.validate(env)
...@@ -6,5 +6,5 @@ envlist = py27, py34, py35, py36, py37 ...@@ -6,5 +6,5 @@ envlist = py27, py34, py35, py36, py37
whitelist_externals = poetry whitelist_externals = poetry
skip_install = true skip_install = true
commands = commands =
poetry install -v poetry install -vvv
poetry run pytest tests/ poetry run pytest tests/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment